POST /v1/handle-check
Ask the transport behind a line whether an address can receive on its channel, before you try to send.
POST /v1/handle-checkAsks the transport behind a line whether an address can receive on its channel — on an iMessage line, Apple's directory. Use it to avoid sending into a void: a number that is Android-only, or an Apple ID that does not exist.
Unlike commands, this is a synchronous read. The answer is in the HTTP response; nothing arrives on the stream. A check is not a send: it does not assign the address to a line or spend a slot on a person you never message.
Request
Prop
Type
curl https://api.mapier.ai/v1/handle-check \
-H "Authorization: Bearer $MAPIER_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "address": "+14155550100", "channel": "imessage" }'Response
{ "address": "+14155550100", "channel": "imessage", "available": true, "reason": null }{ "address": "+14155550100", "channel": "imessage", "available": false, "reason": "not_reachable" }On an iMessage line, available: false means Apple's directory said the
address is not on iMessage. When Apple's lookup cannot give an answer for the
address, the check does not answer false: it fails with
503 line_unavailable — see When the check cannot run.
Prop
Type
When the check cannot run
A 503 line_unavailable carries details.reason. No reason is an answer
about reachability — the question either never reached the transport or came
back unusable. The words this platform mints are listed under
Error codes; on an iMessage line the transport may answer with
its own, which reach you as details.reason unchanged:
{
"error": { "code": "line_unavailable", "message": "…", "details": { "reason": "read_in_flight" } }
}On an iMessage line, an address Apple's directory holds no current answer for
is looked up again; when that lookup still gives no answer, the check fails
here with details.reason read_failed rather than answering
available: false. Ask again later.
Reads run one at a time per line, so read_in_flight is common under concurrency. Check addresses
serially, or cache the result — reachability rarely changes.
Errors
| Status | Code | Cause |
|---|---|---|
400 | bad_request | The body is not JSON, or the transport refused the request as malformed (details.reason is its word) |
401 | invalid_credentials | No key, or one that is unknown, revoked or expired |
404 | not_found | The transport's own not-found, with its word in details.reason; a project with no line to ask is the 503 no_line below |
409 | project_archived | The project is archived |
413 | payload_too_large | Body over 65,536 bytes |
422 | validation_failed | address is missing or not a form the channel accepts |
429 | rate_limited | 30 requests per minute, per key; the Retry-After header says how long to wait (a transport's own rate limit may give details.retryAfter instead) |
500 | internal_error | An unhandled failure, reported; details.requestId names the log line when present |
503 | no_line · line_unavailable · upstream_unavailable | No line, the line cannot ask right now (see When the check cannot run), or the transport did not answer |
503 | service_busy | The platform had no database connection free in time and did nothing; wait details.retryAfter seconds and ask again |