An agent on WhatsApp answers everyone who writes to your business number. Each person gets their own smith, with their own memory and history, and Ingram Cloud handles the WhatsApp side: Meta's webhook, signatures, duplicate deliveries, read receipts, the typing indicator and the replies.
Your numbers run on Ingram Cloud's WhatsApp Business Platform app. You don't create a Meta app, configure a webhook or hold a Meta token.
Before you start
You need:
- A phone number that isn't on WhatsApp. A number already registered with the WhatsApp or WhatsApp Business app can't be moved onto the platform until that account is deleted. A new mobile or landline number works; it only has to receive one SMS or voice call for verification.
- A display name for the number. Meta reviews it, and approves a name that matches your business and appears on your website (in the footer, say). Meta declines generic words and names with no visible link to you.
1. Get your number onboarded
Onboarding is done together with Ingram: contact us with the number and the display name you want. We register the number with Meta, verify it with the SMS or call it receives, and add it to your project.
Your project can hold several numbers. List them:
# Authorization: tenant-admin token (server-side only)
curl https://api.cloud.ingram.tech/v1/tenant/whatsapp \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# → { "data": [ { "phone_number_id": "106540352242922",
# "display_phone_number": "+32 460 00 00 00", … } ], … }
phone_number_id is Meta's id for the number. It's what the rest of this page
uses. DELETE /v1/tenant/whatsapp/{phone_number_id} removes a number from the
project, with the agent deployment pinned to it and every smith binding made
through it. A reply still queued for a removed number is recorded as a
whatsapp.send_failed event.
2. Answer as an agent
An agent deployment mints a smith for each person who writes in. Set address to
a number's phone_number_id to answer on that number only:
# Authorization: tenant-admin token (server-side only)
curl -X POST https://api.cloud.ingram.tech/v1/deployments \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "target": { "type": "agent", "id": "agt_…" },
"kind": "whatsapp", "address": "106540352242922" }'
A number answers as one agent at a time; a second deployment on it is a 409.
Leave address out and the agent answers on every number of the project that no
other agent holds.
Share the number as a https://wa.me/<number> link or a QR code; the first
message starts the conversation.
Or bind one smith
To connect a person to a smith you already have (an app user who links their
WhatsApp, say), create a smith deployment with a connect link. WhatsApp has no
/start, so the link's prefilled text carries a connect token. With several
numbers, name the one the link points at:
# Authorization: tenant-admin token (server-side only)
curl -X POST https://api.cloud.ingram.tech/v1/deployments \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01" \
-H "Content-Type: application/json" \
-d '{ "target": { "type": "smith", "id": "smt_…" },
"kind": "whatsapp",
"setup": { "mode": "start_token", "phone_number_id": "106540352242922" } }'
# → { "deep_link": "https://wa.me/32460000000?text=Connect%20my%20account%20…", … }
The person's first message, carrying the token, binds their WhatsApp account to the
smith on that number and fires deployment.bound. The deployment's address
becomes <phone_number_id>:<wa_id>: a person holds one smith binding per number,
and can be bound to a different smith on each of your numbers. A smith bound this
way also gets a whatsapp_send_message tool to write to them unprompted, from the
number it was bound through first.
A WhatsApp smith deployment is always created this way: an address without
setup is a 422 invalid_setup.
3. Read the conversations
Every WhatsApp conversation is a conversation with
metadata.channel set to whatsapp. List an agent's conversations, most recent
activity first, and read one's transcript:
# Authorization: tenant-admin token (server-side only)
curl "https://api.cloud.ingram.tech/v1/conversations?agent_id=agt_…" \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
# Authorization: tenant-admin token (server-side only)
curl https://api.cloud.ingram.tech/v1/conversations/thr_wa_…/items \
-H "Authorization: Bearer $IC_TOKEN" \
-H "IC-Api-Version: 2026-05-01"
Each deployment.inbound event also tells you a message arrived.
What the agent sees
- Text, and the title of a tapped button or list row. Any other interactive
reply, such as a WhatsApp Flow response, arrives as a line naming its type:
[nfm_reply reply, which you cannot read]. - Media as a description. An image, voice note, video, document or sticker
arrives as a line such as
[voice message attached, which you cannot open], with its caption. A location arrives with its name and coordinates, a shared contact with its name and number. A reaction, or a template button tap without text, runs no turn. - Who is writing. The sender's WhatsApp name and number, as a verified sender (see Verified sender identity).
Up to three quick-reply chips become
WhatsApp reply buttons; more become a list in the text. An
approval pause arrives as Approve / Reject buttons, and a tap
resumes the run through /submit.
Limits
- Replies only, inside 24 hours. WhatsApp lets a business write freely within 24 hours of the person's last message. Outside that window Meta requires a pre-approved template, and templates aren't supported yet, so the send fails.
- No outgoing media. Replies are text and buttons.
- No human takeover on WhatsApp. A person on your team can't yet reply on the number in the agent's place.
- Failures are recorded. A reply Meta refuses is recorded as a
whatsapp.send_failedevent with Meta's reason; thewhatsapp_send_messagetool returns that reason to the agent.
In the console
The console has no WhatsApp screen yet: use the API calls above.