---
seo_title: CSV to JSON API for Converting CSV Files to JSON | EnConvert
meta_desc: Convert CSV to JSON with POST /v1/convert/csv-to-json. First row becomes the keys, each row a JSON object; all values stay strings, no type inference.
keywords: csv to json api, convert csv to json rest api, csv to json converter api, csv file to json array api, csv rows to json objects, parse csv to json online api, upload csv convert to json, csv to json endpoint
---

# CSV to JSON API

Convert a CSV file to a JSON array with a single request to `POST /v1/convert/csv-to-json`. The first row is used as column headers and each subsequent row becomes a JSON object in the output array, with all values kept as strings (no type inference). Responses return raw JSON bytes by default, or metadata with a presigned download URL when `direct_download=false`.

---

## Endpoint

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

**Content-Type:** `multipart/form-data`

**Accepted input:** `.csv` files (UTF-8 encoded)

**Output format:** `.json` (`application/json`)

---

## Authentication

Requires either a private API key or a JWT token from a public key.

```
X-API-Key: sk_your_private_key
```

Or:

```
Authorization: Bearer <jwt_token>
```

---

## Request Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `file` | file | Yes | -- | The `.csv` file to convert. First row must be column headers. UTF-8 encoded. |
| `output_filename` | `string` | No | Input filename | Custom output filename. The `.json` extension is added automatically. |
| `direct_download` | `boolean` | No | `true` | When `true`, returns raw JSON bytes. When `false`, returns metadata with a presigned download URL. |

---

## Conversion Rules

```csv
name,age,city
Alice,30,London
Bob,25,Paris
```

Becomes:

```json
[
  {"name": "Alice", "age": "30", "city": "London"},
  {"name": "Bob", "age": "25", "city": "Paris"}
]
```

- First row is treated as column headers
- Delimiter is comma (not configurable)
- **All values remain as strings** in the JSON output -- no type inference is performed. The number `30` in CSV becomes `"30"` in JSON, not `30`.
- Output is pretty-printed JSON with 2-space indentation

---

## Response

### Direct Download (`direct_download=true`, default)

```
HTTP 200 OK
Content-Type: application/json
Content-Disposition: inline; filename="data_20260405_123456789.json"
```

### Metadata Response (`direct_download=false`)

```json
{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/csv-to-json/data_20260405_123456789.json",
    "filename": "data_20260405_123456789.json",
    "file_size": 1234,
    "conversion_time_seconds": 0.03
}
```

---

## Code Examples

### Python

```python
import requests

with open("data.csv", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/csv-to-json",
        headers={"X-API-Key": "sk_your_private_key"},
        files={"file": ("data.csv", f, "text/csv")}
    )

with open("data.json", "wb") as out:
    out.write(response.content)
```

### Node.js

```javascript
const form = new FormData();
form.append("file", fs.createReadStream("data.csv"));

const response = await fetch("https://api.enconvert.com/v1/convert/csv-to-json", {
    method: "POST",
    headers: { "X-API-Key": "sk_your_private_key" },
    body: form
});

const json = await response.json();
```

### PHP

```php
$ch = curl_init("https://api.enconvert.com/v1/convert/csv-to-json");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_your_private_key"],
    CURLOPT_POSTFIELDS => ["file" => new CURLFile("data.csv", "text/csv")]
]);
$json = curl_exec($ch);
curl_close($ch);
```

### Go

```go
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "data.csv")
file, _ := os.Open("data.csv")
io.Copy(part, file)
writer.Close()

req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/csv-to-json", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_your_private_key")
resp, _ := http.DefaultClient.Do(req)
```

---

## Error Responses

| Status | Condition |
|--------|-----------|
| `400 Bad Request` | File is not a `.csv` file |
| `400 Bad Request` | CSV file is empty or has no valid rows |
| `400 Bad Request` | Invalid CSV encoding (expected UTF-8) |
| `401 Unauthorized` | Missing or invalid API key / JWT token |
| `402 Payment Required` | Monthly ops allowance exhausted |
| `413 Payload Too Large` | File exceeds plan's maximum file size |

---

## Limits

| Limit | Value |
|-------|-------|
| Max file size | Plan-dependent (Founding: 5 MB) |
| Input encoding | UTF-8 only |
| Type inference | None (all values are strings) |
| Monthly conversions | Plan-dependent |

## Frequently asked questions

### How do I convert CSV to JSON with a REST API?

Send a `multipart/form-data` POST request to `/v1/convert/csv-to-json` with your `.csv` file in the `file` field, authenticated with an `X-API-Key` header or a JWT `Authorization: Bearer` token. The first row must contain column headers.

### Why are numbers in my CSV returned as strings in the JSON?

No type inference is performed, so all values remain strings in the JSON output. The number `30` in CSV becomes `"30"` in JSON, not `30`.

### Can I use a delimiter other than a comma?

No. The delimiter is always a comma and is not configurable.

### Can I get a presigned download URL instead of raw JSON bytes?

Yes. Set `direct_download=false` to receive metadata with a `presigned_url`, `object_key`, `filename`, `file_size`, and `conversion_time_seconds`.

### Why does the CSV to JSON API return 400 Bad Request?

A `400` is returned when the file is not a `.csv` file, the CSV is empty or has no valid rows, or the encoding is not UTF-8. Oversized files return `413 Payload Too Large`.
