Error codes

Every HTTP error code and every asynchronous settlement code, with what to do about each.

Errors reach you in two places, and the difference matters.

Synchronous errors are HTTP responses to your request. The command was never queued. The body is { "error": "<code>" }.

Asynchronous errors arrive later on the response stream as a command event with status: "failed" and an errorCode. The command was queued, dispatched, and then something went wrong on the way to iMessage.

A client that only handles the first kind will believe every message was delivered.

HTTP errors

400 — the request was malformed

CodeMeaningWhat to do
invalid_urlThe request target could not be parsed.Fix the URL.
body_too_largeBody exceeded 65,536 bytes.Shorten the payload. Text itself is capped at 64 KiB.
body_not_objectBody parsed as JSON but was not an object.Send {...}, not an array or scalar.
target_and_payload_requiredtarget or payload missing, or not an object.Include both as objects. payload may be {} where the command takes none.
invalid_conversationIdconversationId is not a UUID.Use the conversationId from an inbound message event, not an iMessage GUID.
recipient_send_requires_recipientExternalId_and_textA recipient-target send was missing an address or text.Recipient sends accept { "text": "..." } only — no rich kinds.
group_create_requires_new_group_target_and_firstMessagegroup.create had the wrong target kind or no firstMessage.Use a new_group target and a non-empty firstMessage.
group_command_requires_group_conversationA group verb was aimed at a DM.Group commands need a group conversationId.
invalid_idAttachment id could not be decoded.Use an id from an inbound message's attachmentIds.
invalid_addressHandle-check address failed validation.E.164 (+14155550100) or a lowercase email.

401 — not authenticated

CodeMeaningWhat to do
unauthenticatedNo credential was presented.See Authentication.

404 — not found

CodeMeaningWhat to do
unknown_commandThe :type segment is not a known command. Body includes command.Check the spelling against the command list.
conversation_not_foundNo such conversation, or it belongs to another account.The two cases are deliberately indistinguishable. Verify the id came from your own stream.
not_foundNo such attachment, or it belongs to another account.Same reasoning as above.
no_connectorYour account has no Mac connector.Contact Mapier — this is provisioning, not something you can fix in code.

A request to a path that matches no route returns a bare 404 with no body.

405 — wrong method

CodeMeaningWhat to do
method_not_allowedRight path, wrong verb.Commands and handle-check are POST; the stream and attachments are GET.

422 — rejected by validation

CodeMeaningWhat to do
recipient_not_allowedA recipient-target send addressed something that is not an E.164 phone number.Use a phone number, or send into a conversation target instead.
invalid_participantsgroup.create had fewer than two participants, or a duplicate.Deduplicate the list and check it has at least two entries.
invalid_textA recipient send's text or a group.create firstMessage was empty or over 16,384 bytes.Trim, and split anything longer across several messages.

422 fires only for the handful of checks the queueing layer performs on admin-path commands — address grammar, participant lists and those two text fields. It does not fire for a malformed command payload, which is accepted with 202 and fails asynchronously instead. This is sometimes described as 422 being the general "invalid payload" response; that is not what the service does.

429 — rate limited

CodeMeaningWhat to do
rate_limitedToo many requests. Body includes retryAfter in seconds; a Retry-After header carries the same value.Wait, then retry. See Rate limits.

500 — server error

CodeMeaningWhat to do
internalPersistence or an unhandled failure.Retry with the same Idempotency-Key. If it persists, send it in.

503 — temporarily unavailable

CodeMeaningWhat to do
no_live_connectorNo Mac holds a live lease. The agent-turn path's wording for it.Transient. Retry with backoff.
connector_unavailableThe same condition on the admin path — the two paths report it under different names.Transient. Retry with backoff.
outbound_pausedSending is administratively paused.Do not retry in a tight loop; this clears operationally.
stream_unavailableThe response-stream watcher is not configured.Contact Mapier.
handle_check_unavailableHandle check could not run. Body includes reason.See the reason table on handle check. No reason is a verdict on the address.

Settlement error codes

These appear as errorCode on a command event with status: "failed", and also on ambiguous, cancelled and expired. Grouped by what you should do.

Fix the request and resend

errorCodeMeaning
invalid_targetThe target does not resolve on the Mac.
stale_targetThe referenced message or participant set no longer matches. Common after a group's membership changes — wait for a new message in the group, then use the fresh conversationId.
payload_conflictThe payload contradicts the recorded command identity.
unsupported_capabilityThe Mac does not support this operation.
capability_not_negotiatedThe capability was not agreed at handshake.
capability_constraint_violationThe capability exists but a parameter is out of its declared bounds.
invalid_session_capabilitiesThe session advertised an unusable capability set.

Retry — the effect did not happen

errorCodeMeaning
gateway_rejectediMessage refused the operation.
send_returned_not_okThe send call returned a failure.
preparation_dispatch_exhaustedDispatch attempts were exhausted before execution.
command_claim_invalidThe claim was not valid when execution began.
stale_fenceA newer session superseded this one.
expiredThe command passed its deadline before dispatch.
command_expired_before_executionThe expiry sweep terminated it. The usual companion of an expired status.
outbound_pausedSending was paused before the command ran.

Investigate — the effect may or may not have happened

These settle ambiguous more often than failed. Do not blindly resend; you may duplicate a message that was in fact delivered.

errorCodeMeaning
outbound_echo_unconfirmediMessage accepted the send but no echo confirmed it.
connector_crash_after_effect_startThe connector died mid-effect.
gateway_timeoutNo answer within the deadline.
gateway_response_lostThe response was lost in transit.
reaction_unverified · tapback_unverifiedThe reaction could not be verified afterwards.
poll_vote_unverifiedThe vote could not be verified.
group_content_unverified · group_update_unverified · group_leave_unverifiedThe group operation could not be verified.
moderation_unverifiedThe moderation action could not be verified.
journal_corruptThe durability journal was unreadable.

Not an error

errorCodeMeaning
operator_cancelledA human cancelled the command.

Unconfirmed

This list is assembled from the service's source rather than a published registry, and it is not a closed set. Treat an unrecognised errorCode as a generic failure rather than assuming it cannot occur — new codes can appear without a version change.

Retry rules of thumb

  • 429 — honour Retry-After.
  • 503 — exponential backoff; these are genuinely transient.
  • 500 — retry once with the same Idempotency-Key, then escalate.
  • Any other 4xx — do not retry. The request will fail identically.
  • A failed settlement — consult the tables above. Only the first two categories are safe to resend, and always under a new idempotency key, whether or not you changed the payload. A key stays bound to its command once that command has settled, so a same-key resend is adopted, returns 202 carrying the old terminal status, and sends nothing.

Retries are only safe from double-sending if you supply an Idempotency-Key and the command uses the idempotent routing path. See Idempotency and retries — this is a real trap, and it does not apply to every command.

On this page