Submit
Kick off a job. Returns 202 Accepted with a job_id plus status_url and result_url. Credits are held at submit time and reconciled when the job finishes — unused rows are refunded automatically.
Endpoint
Method: POST
Path: /data-enrichment/submit/
Full URL: https://backend.ecoreservice.com/api/v1/data-enrichment/submit/
Auth: Authorization: Token YOUR_API_TOKEN (or Bearer) — see Authentication
Accepts either a JSON body (rows) or a multipart file upload (file + meta).
JSON submission
POST /api/v1/data-enrichment/submit/
Authorization: Token sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"selected_layers": ["L1", "L2"],
"rows": [
{ "first_name": "Jane", "last_name": "Doe", "company_name": "Acme Corp", "email": "jane@acme.com" },
{ "first_name": "John", "last_name": "Smith", "company_name": "Globex", "email": "john@globex.com" }
],
"title": "Q1 renewal list",
"field_mapping": { "first_name": "First Name", "last_name": "Last Name", "company_name": "Company", "email": "Email" },
"import_columns": ["first_name", "last_name", "company_name", "email"]
}
| Field | Type | Required | Notes |
|---|---|---|---|
selected_layers | "full" or string[] | yes | Layer codes or "full". Must be an in-order prefix (["L1"], ["L1","L2"], …), optionally plus "MPA". See Choosing layers. |
rows | object[] | yes (JSON path) | One object per contact. Keys are your column names; use field_mapping to map them to the enrichment schema. |
title | string | no | Shown in your DataCore history. |
file_name | string | no | Used as the download filename. |
field_mapping | { src: dest } | no | Maps your column names to canonical fields (first_name, last_name, email, company_name, linkedin_url, title). |
import_columns | string[] | no | Columns to pass through verbatim onto the output. |
suppression_list_id | uuid | no | Skip contacts that appear on this suppression list. |
campaign_name | string | no | Optional campaign tag. |
Multipart (CSV) submission
POST /api/v1/data-enrichment/submit/
Authorization: Token sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: multipart/form-data
Form parts:
| Part | Type | Required | Notes |
|---|---|---|---|
file | file (text/csv) | yes | The contact CSV. First row = headers. |
meta | string (JSON) | yes | JSON with the same fields as the JSON body, minus rows. |
Response (202 Accepted for both paths)
{
"success": true,
"data": {
"job_id": "6b4c9f70-5a2b-4a0e-9a1b-9c2a3d4e5f61",
"status": "queued",
"ready": false,
"row_count": 1500,
"credits_held": "1125.0000",
"estimated_credits": "1125.0000",
"status_url": "https://backend.ecoreservice.com/api/v1/data-enrichment/status/6b4c9f70-5a2b-4a0e-9a1b-9c2a3d4e5f61/",
"result_url": "https://backend.ecoreservice.com/api/v1/data-enrichment/result/6b4c9f70-5a2b-4a0e-9a1b-9c2a3d4e5f61/"
}
}
Submit errors
| HTTP | error | When |
|---|---|---|
400 | validation_error | Bad selected_layers value (unknown code, skipped layer, or MPA alone) or empty payload. |
400 | bad_meta / bad_layers / bad_rows | Multipart meta missing, not JSON, or selected_layers/rows missing. |
402 | insufficient_credits | Your wallet can't cover the hold. |
402 | upstream_insufficient_credits | DataForge rejected the submission. Credits are released. |
502 | dataforge_error | Transient upstream failure. Credits are released. Safe to retry. |