Task Status
GET/v1/tasks/{token}
Poll the task until status is completed or failed. The recommended interval is 3–5 seconds; a 5,000-row task typically settles in well under a minute.
The route parameter is {token}, and it takes the value the submission returned as task_id.
Response Example
Section titled “Response Example”{ "task_id": "xKj9aP3qLm7v", "status": "completed", "progress": 100, "product": "YOUR_PRODUCT_SLUG", "country": "CN", "submitted": 5000, "prefiltered": 0, "deduped": 0, "total": 5000, "processed": 5000, "valid": 3800, "invalid": 1200, "unknown": 0, "unknown_processed": 0, "unknown_unprocessed": 0, "stage": "completed", "stage_seconds": 12, "last_progress_at": "2026-09-05T10:00:12+00:00", "failure_message": null, "cost_deducted": "0.500000", "cost_refunded": "0.000000", "result_available": true, "result_expires_at": "2026-05-02T10:00:00+00:00", "created_at": "2026-05-01T10:00:00+00:00"}Task Status Values
Section titled “Task Status Values”| status | Description |
|---|---|
pending | Queued and waiting for resources. |
processing | Detection is in progress. |
completed | Completed. The result is ready to download. |
failed | Execution failed. failure_message says why. |
Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
task_id | string | The task token, echoed back. |
status | string | pending, processing, completed or failed. |
progress | integer | Percentage complete, 0 to 100. |
product | string | Product slug the task was submitted with — see the bulk product list. |
country | string | null | Country the task was submitted with; null for email products. |
submitted | integer | Rows received in the submission. |
prefiltered | integer | Rows dropped before detection — malformed lines, for example. |
deduped | integer | Duplicate rows removed. |
total | integer | Rows actually queued for detection, after prefiltering and deduplication. |
processed | integer | Rows the upstream channel has finished. |
valid | integer | Rows confirmed as registered. |
invalid | integer | Rows confirmed as not registered. |
unknown | integer | Rows the provider could not resolve. |
unknown_processed | integer | Unknown rows that were retried and settled. |
unknown_unprocessed | integer | Unknown rows still unresolved. These are refunded. |
stage | string | null | Internal stage name while the task is running. Diagnostic only — do not branch on it. |
stage_seconds | integer | null | Seconds spent in the current stage. |
last_progress_at | string (ISO 8601) | null | When progress last advanced. A timestamp that stops moving means the task is stuck, not merely slow. |
failure_message | string | null | Why the task failed, or null. |
cost_deducted | string | Amount deducted for the task, as a string. |
cost_refunded | string | Amount refunded for rows that were never checked, as a string. |
result_available | boolean | true when the result file can be downloaded. |
result_expires_at | string (ISO 8601) | null | When the result file stops being downloadable. |
created_at | string (ISO 8601) | When the task was created. |
Reading the counts
Section titled “Reading the counts”submitted is what you sent; total is what was actually checked. They differ whenever rows were malformed or duplicated, and the gap is exactly prefiltered + deduped.
cost_deducted is charged on total, and cost_refunded covers rows that never resolved — the unknown_unprocessed bucket. Only valid and invalid verdicts are billed.
Polling
Section titled “Polling”# Poll until the task leaves pending/processing. `last_progress_at` going# stale is the real failure signal, not elapsed time.for i in $(seq 1 120); do body=$(curl -s -X GET "https://api.zelnum.com/api/v1/tasks/xKj9aP3qLm7v" \ -H "X-API-Key: YOUR_KEY_HERE") status=$(printf '%s' "$body" | jq -r '.status') printf '%s %s%%\n' "$status" "$(printf '%s' "$body" | jq -r '.progress')" case "$status" in completed) printf '%s' "$body" | jq .; break ;; failed) printf '%s' "$body" | jq .; exit 1 ;; esac sleep 5done- Download the results once
result_availableistrue