Troubleshooting: Apple Messages for Business onboarding and send failures
Apple Messages for Business (AMB) failures split into two moments: onboarding (the agent never reachesapproved, or the webhook secret no longer verifies) and sending (a 422 naming a missing *Json metadata key, or a capability the agent does not hold). Both are deterministic, and neither is fixed by resending the same request. This page walks the failure surfaces the Apple Messages for Business channel page exposes, in triage order.
Symptom map
Agent stuck in pending — Apple-side clearance has not landed
A fresh registration returns201 with status: "pending". Orbit cannot speed up Apple’s review: the agent flips to approved only when Apple clears the business on their side. The channel page’s polling pattern (re-fetch GET /api/v1/channels/amb/agents/{id} with exponential backoff) is the correct way to wait. Do not route live conversations to a pending agent.
When the status never flips:
- Check Apple Business Register for an open action on the business entry. A missing document or a failed review keeps the agent
pendingno matter what Orbit does. - Confirm the
business_idyou passed at create time is the approved identity, not a draft or sandbox one. - Keep polling with backoff. No retry from your side moves the status.
- If the register shows the business as approved but the agent still reads
pending, escalate: the MSP-side handoff is the remaining leg, and support can check it with your agent ID andbusiness_id.
Suspended means repair or re-register
suspended is not a pause. Apple took the agent down after approval, for a policy or registration issue on their side. Treat any status regression as out-of-routing-set: resolve the cause in Apple Business Register, then repair the agent or re-register it before the next send. The onboarding guide’s polling loop throws on suspended for exactly this reason.
422 on a send: the missing *Json metadata key
An interactive send is a normal unified send withchannel: "amb" and msgType: "interactive"; the Apple payload travels as a serialized JSON string in the matching metadata key: listPickerJson for list pickers, formJson for forms, timePickerJson for time pickers. A send missing the matching *Json metadata key is rejected with 422 naming the key. Fix the template and resend; nothing queues.
Full-error sample, from a list-picker send that carried msgType: "interactive" but no listPickerJson:
- Read the key name off the rejection. It is exactly the key your send omitted.
- Add the serialized payload under that key. The value is a JSON string, not a nested object.
- Confirm the agent holds the matching capability (see the next section). A correct key on an agent without the capability fails the next gate.
- Resend. The reject is deterministic; the corrected body passes on the first retry.
Capability-gated rejects
Rich interactions and Apple Pay are agent-specific. An agent withoutinteractive cannot carry a list picker; without form no form renders; without timePicker no timeslot sheet. Native Apple Pay needs both the applePay capability on the agent and a registered merchantIdentifier. Unsupported or malformed Apple payloads are rejected rather than rendered by another channel.
Two shapes show up in practice:
- Rich payload on an agent without the capability. The send is rejected or the payload is dropped. Read the agent record’s
capabilities, enable the one the payload needs, or fall back to plain text for that conversation. - Native Apple Pay without the merchant identifier. The checkout resolver degrades by design: with
applePayEnabledandmerchantIdentifierboth set it returnsmethod: "native"and the Apple Pay sheet payload; otherwise it returnsmethod: "hosted"withnativenull. If you expected a native sheet and received a hosted link, the merchant identifier is the gap. Register it with Apple and set it in the checkout config, or keep sendinghosted.urlinto the thread. Both paths reconcile against the samepaymentRequest, so your order logic does not fork. The commerce guide covers the decline-and-retry loop.
The HMAC secret at onboarding
The base64 HMACsecret_key you pass at agent creation authenticates the events Apple delivers to your AMB webhook. Orbit encrypts the key at rest and only exposes whether a secret is stored; it never returns the value.
- Stored indicator set, events verifying. Nothing to do. This is the healthy state.
- Secret lost on your side. You cannot read it back out of Orbit. Issue a new key in Apple Business Register and update the agent with the onboarding guide’s rotation steps. Until the stored secret matches Apple’s current one, inbound events fail verification.
- Secret changed at Apple. Update the agent before the old key stops working. Rotating or deleting an agent changes webhook verification and routing for that Apple business.
Decision checklist
- Onboarding or send?
pending/suspendedand secret problems are onboarding;422and capability rejects are send-side. - Onboarding: read the agent
status.pendingmeans wait on Apple and check the register;suspendedmeans repair or re-register, with no sends in between. - Send-side
422: read the key the rejection names, fix the template, resend once. Never retry the same body. - Capability reject: compare the payload against the agent’s
capabilities; for native pay, confirm themerchantIdentifieris registered and set. - Webhook-side: check the stored-secret indicator; rotate when the secret changed at Apple.
What not to try
- Do not send live traffic to a
pendingagent. Apple has not cleared it; the status will not move from your side. - Do not retry a
422that names a*Jsonkey. The reject is deterministic and nothing queues; the same body fails identically. - Do not move an Apple payload to another channel to dodge a capability reject. Apple payloads are not interchangeable with WhatsApp, RCS, or web-chat payloads; they are rejected rather than rendered elsewhere.
- Do not expect Orbit to return your HMAC secret. Only the stored indicator is exposed; rotate instead.
- Do not treat
suspendedas transient. It does not clear by itself; repair or re-register.
When to escalate
Open a support ticket when the register shows the business approved but the agent still readspending after several days, when a corrected template still returns the same 422 naming the same key, or when native Apple Pay is configured with a registered merchant identifier but the resolver still returns hosted. Include:
- The agent ID (
data.idfrom the create response), not just the Applebusiness_id. - One
meta.request_idfrom the rejection, for send-side failures. - The agent’s
capabilitiesarray and, for pay failures, themerchantIdentifieryou configured.
See also
- Apple Messages for Business — the channel page this runbook triages.
- Apple Messages for Business onboarding — the wizard, request bodies, status polling, and secret rotation.
- AMB commerce: interactive flows and Apple Pay checkout — payloads, cart merge, token capture, and reconciliation.
- KakaoTalk template gates — the comparable deterministic-422 runbook for another approval-gated channel.