Realtime Single Check
POST/v1/realtime/check/phone
Synchronously check one phone number against one to ten realtime products in a single call — the same contract the console uses. Products are addressed by realtime product IDs, never by batch product slugs.
Parameters
Section titled “Parameters”| Field | Type | Required | Description |
|---|---|---|---|
identifier | string | Yes | One E.164 phone number, for example +8613800138000. |
country | string | No | Optional for a complete E.164 number; a national number requires a matching ISO country code. |
product_ids | array<int> | Yes | An array of 1 to 10 realtime product IDs. |
Choosing the products to check
Section titled “Choosing the products to check”Product IDs are not guessed. Read them from the realtime product list, which is backed by GET /v1/products: take the id of an entry whose mode is realtime. Bulk products are addressed by slug instead, so a slug never works on this endpoint — the catalog prints realtime IDs with a # prefix for exactly this reason.
One call checks one phone number against one to ten realtime products. You get a single request_id, one entry per product in results, and each entry is billed on its own — which is why status can come back partial_succeeded. More than ten IDs is rejected as invalid_realtime_request; the console submits through this same endpoint and enforces the same ceiling.
Response Example
Section titled “Response Example”{ "request_id": "8c1e4f91-7bd8-4d7e-a3ae-3d7e5b0c6c11", "identifier": "+8613800138000", "series": "phone", "status": "succeeded", "request_status": "completed", "replayed": false, "total_reserved": 0.004000, "total_charged": 0.004000, "total_refunded": 0.000000, "charged_amount": 0.004000, "refunded_amount": 0.000000, "results": [ { "product_id": 47, "product": "wavalid-realtime", "result": "valid", "cached": false, "billing_status": "charged", "charged_amount": 0.002000, "refunded_amount": 0.000000, "checked_at": "2026-09-05T10:00:00Z", "error_code": null }, { "product_id": 50, "product": "tgValid-rt", "result": "invalid", "cached": false, "billing_status": "charged", "charged_amount": 0.002000, "refunded_amount": 0.000000, "checked_at": "2026-09-05T10:00:01Z", "error_code": null } ]}request_id is a UUID. replayed is true when an Idempotency-Key replay returned a stored result instead of talking to a supplier — a replay never moves money.
Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
request_id | string (UUID) | Identifies this submission. Quote it in support requests. |
identifier | string | The identifier that was checked, echoed back. |
series | string | phone or email. |
status | string | succeeded, partial_succeeded or failed — derived from how many results were charged. |
request_status | string | Internal lifecycle state of the request. |
total_reserved | number | Amount reserved before the checks ran. |
total_charged | number | Total charged across every product in the combo. |
total_refunded | number | Total refunded for items that could not be resolved. |
charged_amount | number | Net charge. Always equals total_charged. |
refunded_amount | number | Net refund. Always equals total_refunded. |
replayed | boolean | true when an Idempotency-Key replay returned a stored result. |
results | array | One entry per requested product, in the order the products were requested. |
Each entry in results carries its own state:
| Field | Type | Description |
|---|---|---|
product_id | integer | Realtime product ID from the catalog. |
product | string | Product slug that ID resolves to. |
result | string | valid, invalid or unknown — whether the identifier is registered. |
cached | boolean | true when the verdict came from cache. A cache hit is still charged. |
billing_status | string | charged or refunded. |
charged_amount | number | Amount charged for this product. |
refunded_amount | number | Amount refunded for this product. |
checked_at | string (ISO 8601) | When the verdict was produced, in UTC. |
error_code | string | null | Why the item could not be resolved, or null when it succeeded. |
cURL Example
Section titled “cURL Example”curl -X POST "https://api.zelnum.com/api/v1/realtime/check/phone" \ -H "X-API-Key: YOUR_KEY_HERE" \ -H "Idempotency-Key: UNIQUE_REQUEST_ID" \ -H "Content-Type: application/json" \ -d '{"identifier":"+8613800138000","country":"CN","product_ids":[47,50]}'Billing & Semantics
Section titled “Billing & Semantics”- Billing: each product uses its snapshotted per-check price, including cache hits. Only
validandinvalidresults are charged;unknown, timeout and busy items are refunded.total_reserved = total_charged + total_refunded;charged_amountis the net charge. - Partial success: a partially successful combo returns HTTP 200 with
status=partial_succeeded; all failed returnsstatus=failed. Inspect eachbilling_statusanderror_codeinstead of relying on HTTP 200 alone. - Replay:
Idempotency-Keyis limited to 191 bytes and scoped to the user. After a timeout or HTTP 500, retry the original content with the original key. In-flight replays return409/request_in_progress. Logs and replay results are retained for 30 days by default.
HTTP Error Handling
Section titled “HTTP Error Handling”| HTTP | code | Meaning / action |
|---|---|---|
| 400 | invalid_realtime_request / idempotency_key_required | Fix the number, products or request key; no prepayment. |
| 401 / 403 | unauthorized / account_banned / realtime_disabled | Check the key, account status and realtime access; no prepayment. |
| 402 | insufficient_balance | Insufficient balance; no combo item starts. |
| 409 | request_in_progress / idempotency_conflict | Retry an in-flight request after Retry-After; a conflicting payload cannot reuse the key. |
| 429 | realtime_rate_limited | Wait for Retry-After; no prepayment. |
| 503 | realtime_route_unavailable / realtime_fact_cache_unavailable / realtime_rate_limiter_unavailable | The route, cache or limiter is unavailable; no prepayment. Retry later. |
| 500 | internal_error | The outcome is uncertain. Retry with the original key; do not blindly submit a new key. |
Item error_code values identify provider, channel-capacity, deadline, cache or concurrency-protection failures. Failed items are not charged.