Invitations
An invitation is how you start a conversation with a customer who hasn’t messaged you yet. It’s a branded card sent to their phone number, not a free-text message.
Send: POST /v1/invitations with to, template_id and a
reference_id (your order number, case id or similar, echoed on the
delivery webhooks). An Idempotency-Key header is required, so a retry
never sends a second card.
Send in bulk: POST /v1/invitation_batches takes up to 10,000
recipients on one template, and we check every recipient when you submit,
before anything goes out. A batch can be cancelled for anyone not yet
reached.
Setup, once: create an invitation template: the brand name printed on the card, and optionally your logo, uploaded in the same request:
POST /v1/invitation_templates
Content-Type: multipart/form-data
name = "Acme Rides"
logo = <PNG file, optional>
The response carries the template’s id (invt_…). A template with a logo
sends the logo card, which shows your image; one without sends the
plain card. The platform picks the card from the template. Creating a template never depends
on approval.
Approval, and your first send. A business must be approved for invitation messages, and for each card separately: approval for the logo card does not cover the plain card, or the other way round. That approval is checked when an invitation is sent, not when you create a template, so send one invitation before your first batch: if the business is not approved yet, that one send tells you, with the reason.
Then, per invitation:
POST /v1/invitations
Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
{"to": "+15551234567", "template_id": "invt_a4f2c718d0", "reference_id": "order-4417"}
One condition applies: template_id is one of your template ids
(GET /v1/invitation_templates lists them). The number’s thread must also be
open: a customer who left an earlier invitation closed it, and a send into a
closed thread is 409 chat_closed.
If the customer accepts, a chat is created and you message it normally. Each
invitation reports its whole lifecycle as invitation.* events: delivery as
invitation.sent or invitation.failed, then the customer’s answer as
invitation.accepted, invitation.declined, or invitation.opted_out.
When an invitation is not delivered, it arrives as invitation.failed
with a reason, and last_error explains it in plain words. It carries the
invitation_id and your reference_id, so you can match it to the
invitation you sent:
reason | What it means | What to do |
|---|---|---|
invitation_template_not_allowed | The business is not approved for this template’s card (last_error names it: the logo card or the plain card) | Request approval for that card, or send with a template for the other card if that one is approved |
invitation_business_not_eligible | The business is not enabled for invitation messages | Request invitation access for the business |
invitation_undeliverable | The number cannot receive it: no active Apple Account, a device below iOS 18, or the customer opted out of your invitations | Reach the customer on another channel; do not resubmit |
auth_error | A credentials problem on our side | Nothing on yours; we are alerted |
platform_error | A defect on our side | Do not resubmit; we are alerted |
undelivered | A temporary failure that outlasted our retries | Resubmit later |
None of these is retried automatically once final, and the first two do not change until the approval does.
The opt-in is yours. You collect it and you hold it; we do not ask for a copy and we refuse nothing for its absence. The rule you sign up to under the channel’s service terms: an invitation goes only to a customer who opted in at your point of sale (your website, app, customer service number or physical location), the opt-in covers the transaction it was given for and lasts at most two years, every invitation offers a way to opt out, and the following sentence appears at the point of sale, where your other legal notices are, before the customer opts in:
Separate from your opt-in to receive Business Updates from us, your use of Apple Messages for Business service is also governed by Apple’s terms, including those at https://www.apple.com/legal/privacy/data/en/messages-for-business/. Unless you have opted-out on your Apple device, Apple may process your personally identifiable information.
Every device on the customer’s Apple Account must be on iOS 18 or macOS 15 or later for the card to be delivered; that check is Apple’s, not something you can see in advance.
When a customer opts out. A customer who types STOP on an invitation
thread, or leaves it, is recorded as opted out: GET /v1/invitations/{inv}
reads opted_out: true. A later invitation to that number is still sent if
the thread is open (it is your assertion that the customer opted in again at
your point of sale), and that send is noted once in the chat’s events as
send_after_opt_out, after which the thread reads opted_out: false.
POST /v1/invitation_batches submits up to 10,000 invitations at once, all
from one template: its name and logo are resolved when you submit and
frozen into the run, so editing the template mid-run never changes what
queued recipients receive. We check every recipient when you submit, so you
learn which numbers are unusable before we send anything. Each recipient is
then sent as its own invitation. The run tells you how far it has got
(GET /v1/invitation_batches/{batch}); each invitation tells you its
result, as invitation.sent or invitation.failed carrying the reference_id
you gave that recipient, exactly as a single invitation does. A run that is
completed has sent everything it will send; it does not mean every
invitation was delivered. POST /v1/invitation_batches/{batch}/cancel stops
any recipient we haven’t tried yet.