typing.start

Show the typing bubble on a contact's phone, in a one-to-one conversation they have written into — fire-and-forget, about twelve seconds, never retried.

POST /v1/commands/typing.start

Shows the typing dots on the other person's phone — the bubble Messages draws while somebody is writing — in a one-to-one conversation the contact has written into. Takes no arguments: payload is {} or absent.

It is not a queued command. On an iMessage line the relay serves typing as a route of its own, fire-and-forget — nothing is journaled or replayed — and the platform settles the command itself from that route's answer. So the 202 is followed within the second by a command frame, type: "typing.start", messageId: null.

On a live line Idempotency-Key is ignored, as on group.create: the presence route takes no key, so a repeat under the same key is a second request. What coalesces repeats is time — a second signal to the same conversation within five seconds settles succeeded and posts nothing; one after that shows the dots again, which is harmless. In test the sandbox honours the key.

Target

Prop

Type

On an iMessage line, live or test, the conversation at target.conversationId must be one the transport has named and confirmed is with that one person — which it does when it reports the conversation, the first time the contact writes into it. A group, a conversation the transport has never named, and one it has named but not confirmed are each 422 validation_failed at target.conversationId before anything is sent; the unconfirmed case carries reason: conversation_not_confirmed. Send the person a text first.

What happens

The 202 says the signal was accepted. What the command frame then says:

  • succeeded once the transport took the signal — never a promise that the phone drew it.
  • failed, with the code of what the transport answered instead: not_found, rate_limited (the relay's own cap on typing, twelve a minute per conversation) or upstream_unavailable (the Mac behind the line is offline). It is never retried.

The bubble shows for about twelve seconds, or until the line sends into the conversation. There is no call that takes it down; to hold it up, send typing.start again.

At most one signal per conversation per five seconds is sent. Another inside that window is accepted and settles succeeded without being sent again — the bubble the first one raised is still up. So a loop that signals every few seconds while an answer is being written costs one relay call per five seconds, whatever its cadence.

Typing the contact does is not carried: no frame, event or webhook says a person is typing. The signal only ever goes out.

In test

A test iMessage line accepts typing.start after the same refusals and settles it succeeded, with nothing drawn: the sandbox phone shows no bubble, and the five-second window is not rehearsed there.

Request

curl https://api.mapier.ai/v1/commands/typing.start \
  -H "Authorization: Bearer $MAPIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target": {
      "kind": "conversation",
      "conversationId": "a0000000-0000-4000-8000-000000000001"
    }
  }'

A common shape: signal once when the model starts, send the answer when it is ready. For an answer that takes longer than the bubble lasts, signal again every ten seconds or so until the send goes out.

Response

202 Accepted
{ "commandId": "cmd-9", "status": "queued", "disposition": "queued" }

Then, on the response stream:

event: command — succeeded
{
  "commandId": "cmd-9",
  "logicalActionId": "…",
  "status": "succeeded",
  "errorCode": null,
  "conversationId": "a0000000-0000-4000-8000-000000000001",
  "type": "typing.start",
  "messageId": null,
  "failureClass": null
}

Errors

A command answers the one set of HTTP refusals POST /v1/commands/{type} publishes, so that table is the one to handle. What is particular to this type:

  • 422 validation_failed at target.conversationId for a group, a conversation the transport has never named, or one it has not confirmed — the last with reason: conversation_not_confirmed.
  • 404 unsupported_command with reason: not_on_channel on a line whose channel does not carry it.

Settlement codes you will see for this command: not_found, rate_limited, upstream_unavailable. See Error codes.

On this page