Skip to content
Documentation for: Echo
HUuptools.io
Markdown

Import through the API

For a few subscribers at a time (a sign-up, a checkout) use POST /subscribers. For a list, use the bulk import: it runs in the background, exactly like a file import in the app, and shows up on the History tab under Subscribers.

POST /groups/{id}/import-subscribers imports 1 to 50,000 subscribers into one group. It needs Subscribers: manage.

Key Meaning
subscribers The rows. Each row is an object with email (required) and fields (values by field key). No other keys.
Terminal window
curl -X POST "$ECHO_API/groups/257e83a2-d55e-4a8c-b9a4-b3e939c151cc/import-subscribers" \
-H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \
-d '{"subscribers":[
{"email":"[email protected]","fields":{"name":"Bence","city":"Győr"}},
{"email":"[email protected]","fields":{"name":"Réka","rendelesek_szama":5}},
{"email":"hibas-cim"}
]}'
HTTP/1.1 202 Accepted
Content-Type: application/json
X-Ratelimit-Limit: 5
X-Ratelimit-Remaining: 4
{"data":{"import_id":"df745729-be25-495c-a5b1-8a070dbd18cb"}}

The rate limit headers of this answer show the import bucket (5 a minute), see Errors and limits.

Every field key used in any row must exist in the workspace; otherwise nothing is imported:

{"error":{"code":"validation","message":"Please check the highlighted fields.","fields":{"fields.kedvenc_szin":"Unknown field."}}}

An unknown group is 404 not_found; an empty list or more than 50,000 rows is 422 with fields.subscribers.

GET /subscribers/import/{import_id} (Subscribers: view) shows the progress and the result. Poll it every few seconds until status is done, failed or canceled.

Terminal window
curl -H "Authorization: Bearer $ECHO_TOKEN" "$ECHO_API/subscribers/import/df745729-be25-495c-a5b1-8a070dbd18cb"
{"data":{"id":"df745729-be25-495c-a5b1-8a070dbd18cb","kind":"csv","status":"done","filename":"api-import.csv","size_bytes":115,"encoding":"utf-8","delimiter":",","has_header":true,"preview":{"headers":[],"rows":[],"columns":0},"mapping":["email","city","name","rendelesek_szama"],"groups":[{"id":"257e83a2-d55e-4a8c-b9a4-b3e939c151cc","name":"Webshop vásárlók"}],"start_automations":false,"processed_rows":3,"added":2,"updated":0,"failed":1,"error":"","created_at":"2026-10-22T08:52:08.576581Z","started_at":"2026-10-22T08:52:08.759366Z","finished_at":"2026-10-22T08:52:08.810755Z","failed_rows":[{"row":3,"email":"hibas-cim","reason":"invalid_email","detail":""}]}}
Key Meaning
status queued (waiting for an earlier import), processing, done, failed or canceled.
processed_rows Rows handled so far.
added, updated, failed New subscribers, updated subscribers, rows left out.
error parse_error or internal when the whole import failed, otherwise empty.
mapping The columns: email, then the field keys used (in alphabetical order).
start_automations Always false for API imports.
failed_rows The first 100 rows left out: row (the row’s position in your subscribers array, from 1), email as sent (empty when missing), reason and detail (the field, when a value was refused).

The API import is stored as a CSV named api-import.csv, so kind, filename, encoding, delimiter and has_header describe that file. failed counts every row left out, failed_rows lists the first 100. reason is one of missing_email, invalid_email, duplicate, role_address, short_gmail, suppressed, invalid_number, invalid_date, value_too_long or invalid_text. The import’s result page in the app (History tab, View) shows the same rows.

  • New addresses become active subscribers with the source import, in the group. Imported subscribers get no confirmation email, so only import people who agreed to receive your emails.
  • Existing addresses are updated and added to the group; their status doesn’t change, so an unsubscribed subscriber stays unsubscribed.
  • An empty value doesn’t erase a stored value.
  • Rows fail for the same reasons as in the app: an invalid or missing address, a role address, an address on the suppression list, an address twice in the list, or a value that doesn’t fit the field type (numbers for number fields, YYYY-MM-DD for dates).
  • Imports don’t start automation workflows.
  • Imports run one at a time per workspace; a second one waits as queued.
  • When the import finishes, the workspace’s notification bell shows it; no email notification is sent for API imports.
Limit Value
Rows per request 1 to 50,000
Request body 10 MB (413 too_large above it)
Imports per token 5 a minute, on top of the 120 requests a minute