Sign inGet Started

Reply through the Apple Messages API

Send a text reply to an existing Apple Messages conversation using the public Bird API, then inspect its processing status and receive customer replies.

Prepare the workspace and credential

Complete the dashboard first-conversation quickstart to connect a business and open a test conversation. A Draft business can send test messages before approval. Ordinary replies use the customer's Apple opaque identifier; a phone number cannot replace it.

Create a workspace API key with amb:read, amb:write, and amb_management:read. Use Bash with curl, jq, and uuidgen. Run the following blocks in one Bash script or shell. The error settings stop the walkthrough if a request or validation fails. Keep credentials in your environment rather than source files:

Code example
set -euo pipefail
read -r -s -p "Bird API key: " BIRD_API_KEY
printf '\n'
export BIRD_API_KEY
case "$BIRD_API_KEY" in
  bk_eu1_*) BIRD_API_URL=https://eu1.platform.bird.com ;;
  bk_us1_*) BIRD_API_URL=https://us1.platform.bird.com ;;
  *) printf 'Use a workspace key for a supported region.\n' >&2; exit 1 ;;
esac

The key supplies the workspace context. See regions if you receive a region mismatch.

Select the business and conversation

List businesses and conversations:

Code example
curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/business-accounts" \
  -H "Authorization: Bearer $BIRD_API_KEY" | jq .
curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/conversations" \
  -H "Authorization: Bearer $BIRD_API_KEY" | jq .
read -r -p "Bird business record ID: " BUSINESS_ID
read -r -p "Bird conversation record ID: " CONVERSATION_ID
BUSINESS=$(curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/business-accounts/$BUSINESS_ID" \
  -H "Authorization: Bearer $BIRD_API_KEY")
CONVERSATION=$(curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/conversations/$CONVERSATION_ID" \
  -H "Authorization: Bearer $BIRD_API_KEY")
printf '%s' "$BUSINESS" | jq -e '.status == "pending" or .status == "active"'
printf '%s' "$CONVERSATION" | jq -e --arg business "$BUSINESS_ID" \
  '.status == "open" and .business_account_id == $business'

This example is for an authorized test conversation; a Draft status does not authorize public launch. Stop if either check returns false or a request fails. Select records from the same business. For more results, follow cursor pagination; a first page is not the complete inventory.

Review and send the reply

Build the request using apple_business_id as from and opaque_user_id as to:

Code example
APPLE_BUSINESS_ID=$(printf '%s' "$BUSINESS" | jq -er '.apple_business_id')
OPAQUE_USER_ID=$(printf '%s' "$CONVERSATION" | jq -er '.opaque_user_id')
REQUEST=$(jq -n --arg from "$APPLE_BUSINESS_ID" --arg to "$OPAQUE_USER_ID" \
  '{from:$from,to:$to,content:{type:"text",body:"We can help arrange your visit. Which day works for you?"}}')
printf '%s\n' "$REQUEST" | jq .

Review the business, recipient, and text. The next request queues a real, potentially billable message:

Code example
REQUEST_ID=$(uuidgen)
RESPONSE=$(curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/messages" \
  -H "Authorization: Bearer $BIRD_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $REQUEST_ID" \
  --data "$REQUEST")
printf '%s\n' "$RESPONSE" | jq .
MESSAGE_ID=$(printf '%s' "$RESPONSE" | jq -er '.id')

A 202 response confirms acceptance for asynchronous processing. Retain REQUEST_ID and the unchanged body when retrying that logical request; generating another key can create another message. See idempotency.

Inspect processing and receive replies

Use Get message and List message events:

Code example
curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/messages/$MESSAGE_ID" \
  -H "Authorization: Bearer $BIRD_API_KEY" | jq .
curl --fail-with-body -sS "$BIRD_API_URL/v1/amb/messages/$MESSAGE_ID/events" \
  -H "Authorization: Bearer $BIRD_API_KEY" | jq .

For asynchronous updates, configure webhooks for amb.accepted, amb.sent, amb.send_failed, amb.rejected, amb.received, and the required conversation lifecycle events. Verify signatures, deduplicate webhook deliveries, and tolerate out-of-order events. Fetch the message when reconciling an uncertain state.

For amb.received, inspect the incoming content and match the conversation to your pending customer task. Process native answers using the sent identifiers where available; a time-picker reply can contain a selected label. Check the booking, order, or case system before taking an irreversible action or confirming its result.

Extend the message content

The Send message reference defines text, rich_link, and interactive content. Interactive messages include quick replies, lists, time pickers, forms, and custom iMessage apps. Use native-message design guidance for the customer experience.

For Apple-generated previews, use the supported dashboard link workflow. Media source URLs are fetched during processing and can fail after acceptance; use the media requirements.

CLI or MCP installations that expose bird amb or the corresponding amb_* tools use the same addressing and status semantics. Check the installed command or tool schema before using it; this walkthrough depends directly on the public HTTP contract.

Resolve errors

A 404 can indicate an unknown conversation or the wrong workspace. A 403 requires the operation's scope. A closed conversation or unsupported native interaction can return 422; the customer must reopen a closed conversation. For 429, follow Retry-After and the shared rate-limit guidance.

After acceptance, inspect message events and statuses for a processing or billing failure. Sent is Apple gateway acceptance; it does not provide a device-delivery or read receipt. Measure business outcomes separately.