Upload
Start an email generation job from a CSV. Processing runs in the background — the response returns a job_id you poll for progress.
Endpoint
Method: POST
Path: /email-generation/upload/
Full URL: https://backend.ecoreservice.com/api/v1/email-generation/upload/
Auth: Authorization: Bearer <JWT>
Content-Type: application/json (JSON array) or multipart/form-data (file upload)
Request
Submit contacts either as a file or as a JSON array — same contact fields as Validate (first_name, last_name, company_domain required).
Option A — File upload (multipart/form-data)
| Field | Type | Required | Notes |
|---|---|---|---|
csv_file | file | Yes | CSV/Excel of contacts |
list_name | string | No | Display label. Defaults to the file name. |
Option B — JSON body (application/json)
A JSON array of contact objects:
[
{ "first_name": "Jane", "last_name": "Doe", "company_domain": "acme.com" },
{ "first_name": "John", "last_name": "Roe", "company_domain": "globex.com", "ec_id": "1002" }
]
Successful Response — 201 Created
{ "job_id": 123, "uuid": "…", "list_name": "Q3 prospects", "total_records": 4000, "status": "Uploading" }
| Field | Type | Description |
|---|---|---|
job_id | integer | Use this in the Job Status, Records, and Download paths |
uuid | string | UUID4 |
list_name | string | Display label |
total_records | integer | Contacts accepted for processing |
status | string | "Uploading" immediately on creation |
Keep the job_id and poll the job. Credits (total_records × 5) are charged upfront and refunded for contacts with no email found.
Error Responses
| HTTP | When | Body |
|---|---|---|
| 400 | Missing/invalid file, missing required columns, or empty file | { "error": "..." } |
| 402 | Wallet can't cover total_records × 5 | { "error": "Insufficient credits. You need 20000 credits but have 5000.", "required": 20000, "balance": 5000 } |
See Error Codes for the full list.