# Write an array of objects as CSV text

`POST /v1/convert/json/to/csv`

Turns a JSON array of objects into CSV text with the columns, order and header labels you choose. Values with commas, quotes or line breaks are quoted correctly; the separator, the quoting policy (minimal or all), the line ending and a byte order mark for Excel are options. Objects and arrays inside a record are written as JSON in one cell, or flattened into columns like owner.name. Values written here read back unchanged through the parse operation.

## Request body

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| records | array of object | yes | The rows, one object each |
| columns | array of string | no | Columns to write and their order. Default: every key, in the order first seen |
| header_labels | object | no | Header text per column name. Columns without a label keep their name |
| include_header | boolean | no | False writes the data rows only (default `true`) |
| delimiter | string | no | The one character between fields (default `","`) |
| quoting | one of: minimal, all | no | minimal or all (default `"minimal"`) |
| line_ending | one of: crlf, lf | no | crlf or lf (default `"crlf"`) |
| byte_order_mark | boolean | no | True starts the file with a byte order mark so Excel reads UTF-8 (default `false`) |
| nested | one of: json, flatten | no | json or flatten (default `"json"`) |

## Example request

A request body that works, as JSON.

```json
{
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}
```

## Code samples

Replace YOUR_TOKEN with your access token.

### curl

```shell
curl -X POST 'https://api.skillfulsardine.com/v1/convert/json/to/csv' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}'
```

### PowerShell

```powershell
$body = @'
{
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}
'@
$response = Invoke-RestMethod -Method Post -Uri 'https://api.skillfulsardine.com/v1/convert/json/to/csv' `
  -Headers @{ Authorization = 'Bearer YOUR_TOKEN' } `
  -ContentType 'application/json; charset=utf-8' `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$response | ConvertTo-Json -Depth 10
```

### Python

```python
import requests

payload = {
    "records": [
        {
            "name": "Ana",
            "city": "Porto",
            "note": "Likes coffee, black",
        },
        {
            "name": "João",
            "city": "Lisboa",
            "note": "",
        },
    ],
    "columns": [
        "name",
        "city",
        "note",
    ],
    "header_labels": {
        "name": "Name",
        "city": "City",
        "note": "Note",
    },
}

response = requests.post(
    "https://api.skillfulsardine.com/v1/convert/json/to/csv",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json=payload,
    timeout=30,
)
print(response.json())
```

### JavaScript

```javascript
const response = await fetch("https://api.skillfulsardine.com/v1/convert/json/to/csv", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}),
});
const result = await response.json();
console.log(result);
```

### Node

```javascript
// Node 18 or later. Save as call.mjs and run: API_TOKEN=... node call.mjs
const token = process.env.API_TOKEN;

const response = await fetch("https://api.skillfulsardine.com/v1/convert/json/to/csv", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}),
});
const result = await response.json();
console.log(result);
```

### Rust

```rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let body: serde_json::Value = serde_json::from_str(r#"{
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}"#)?;
    let response = reqwest::blocking::Client::new()
        .post("https://api.skillfulsardine.com/v1/convert/json/to/csv")
        .bearer_auth("YOUR_TOKEN")
        .json(&body)
        .send()?;
    println!("{}", response.text()?);
    Ok(())
}
```

### Swift

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.skillfulsardine.com/v1/convert/json/to/csv")!)
request.httpMethod = "POST"
request.setValue("Bearer YOUR_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(#"""
{
  "records": [
    {
      "name": "Ana",
      "city": "Porto",
      "note": "Likes coffee, black"
    },
    {
      "name": "João",
      "city": "Lisboa",
      "note": ""
    }
  ],
  "columns": [
    "name",
    "city",
    "note"
  ],
  "header_labels": {
    "name": "Name",
    "city": "City",
    "note": "Note"
  }
}
"""#.utf8)

let (data, _) = try await URLSession.shared.data(for: request)
print(String(decoding: data, as: UTF8.self))
```

## Response

The fields inside `data` of a successful response.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| content | string | yes | The CSV text |
| columns | array of string | yes | Column names written, in order (before header labels) |
| row_count | integer | yes | Number of data rows |

## Example response

A real answer from the operation, as JSON. The fields in the table above are inside `data`.

```json
{
  "data": {
    "content": "Name,City,Note\r\nAna,Porto,\"Likes coffee, black\"\r\nJoão,Lisboa,\r\n",
    "columns": [
      "name",
      "city",
      "note"
    ],
    "row_count": 2
  },
  "errors": null,
  "meta": {
    "request_id": "fc5977a6-81bb-47ca-9343-ae362fa4e850",
    "timestamp": "2026-10-27T07:19:42.024838Z",
    "version": "2026-03-26"
  },
  "pagination": null
}
```

## Responses

| Status | When it happens |
| --- | --- |
| 200 | Successful Response |
| 400 | The body respects the operation schema, but the use case rejected it. Each problem is one ApiError entry |
| 413 | The request is larger than the request size limit of the API allows |
| 422 | The body does not respect the operation schema. Each problem is one ApiError entry with the code validation_error |
| 500 | Something failed inside the server and was not an input problem. The same envelope, errors may be empty |

---
Source: https://skillfulsardine.com/developers/api/write-csv/