Step 1: Connect your number
- In YCloud’s WhatsApp accounts, find which WABA owns the number, then confirm its owner in Meta Business Settings. If YCloud or an agency owns it, only they can release the number.
- In WhatsApp Manager, check the WABA for other numbers, templates, or assets you still need.
- Confirm you are an admin of the owning Business Portfolio, which Meta requires for removal.
- Under Account tools → Insights, confirm the number has not sent a paid message in the last 30 days.
- Turn off two-step verification on the number, or re-registration will ask for a PIN.
- Remove the phone number from the WABA.
- Wait about five minutes.
- In Kapso, start embedded signup. Share your existing WABA, or create one when the flow asks.
- Recreate your templates if you created a new WABA (see Step 5). Wait for Meta review.
Testing first? Build against a sandbox number while YCloud still carries production traffic. Create a session for your test phone, then send the 6-character code from WhatsApp.
Step 2: Get your phone number IDs
+E164 to phone_number_id. It replaces every "from": "+1555..." in your send code.
YCloud takes
wabaId in the request body for templates and flows. Kapso takes it in the path, as in POST /{waba_id}/message_templates. Templates belong to the WABA in both, so every number on that WABA can send them.
Step 3: Update message sending
YCloud has two send endpoints.POST /v2/whatsapp/messages queues the message and returns accepted, and POST /v2/whatsapp/messages/sendDirectly submits to Meta and waits.
Kapso has one: POST /{phone_number_id}/messages. It submits to Meta synchronously and returns the wamid, so it behaves like sendDirectly. If your code branches between the two YCloud endpoints, both branches collapse into this one.
Three things change in every call:
frommoves out of the body and into the path, asphone_number_id.messaging_product: "whatsapp"is required.tois written as bare digits by convention, but your existing E.164 values work unchanged. Kapso forwards the request body to Meta byte for byte, and Meta accepts the leading+.
- Template
- Text
- Media
- Interactive
- Read and typing
Business-initiated sends, outside the 24-hour window.YCloud:Kapso:The
template object is identical. externalId becomes biz_opaque_callback_data, capped at 512 characters and echoed back on status webhooks. See Simple text templates.wamid only later, on the sent status webhook. Kapso returns the wamid immediately:
id, switch that column to the wamid. Everything that took a wamid on YCloud (context.message_id, mark-as-read, reactions) keeps taking one.
The TypeScript SDK wraps all of this, so you do not have to write the envelopes by hand.
Step 4: Update webhooks
YCloud webhooks are account-wide: one endpoint receives every event for every number, and you route in your own handler. Which field carries your number depends on the event:
Kapso registers webhooks per phone number, so that routing disappears: the endpoint you register only ever receives that number’s events.
Event mapping
YCloud dispatches one event for delivery and asks you to switch on
whatsappMessage.status. Kapso dispatches one per status, named in the X-Webhook-Event header. The switch moves from the body to the header.
Account and number events
whatsapp.business_account.updated carries seven updateEvent values, on project webhooks:
Since 2026-06-10 YCloud sends partner removal as
business_account.deleted instead, so handle both. Its removedReason, removedInitiatedBy, and removedTime are optional, so their absence does not prove a real deletion.
Raw Meta webhooks
Kapso can also forward every Meta webhook for a number, unreshaped. Register a second webhook with"kind": "meta":
Field mapping
Inbound, fromwhatsappInboundMessage to Kapso’s whatsapp.message.received:
Outbound, from
whatsappMessage to the status events:
from is not always present. WhatsApp can identify a contact with business_scoped_user_id instead. See business-scoped user IDs.
Signature verification
YCloud signs the timestamp and the body together, and sends both in one header. Kapso signs only the body. YCloud:rawBody still applies. The freshness check does not carry over: Kapso signs no timestamp, so the tolerance you tuned against YCloud’s t has nothing to bind to. See Security for Python and Ruby.
Delivery behavior
See Advanced for buffering and ordering, and Security for verification in Python and Ruby.
Step 5: Templates
Same components, different addressing. YCloud takeswabaId in the body, Kapso takes it in the path.
YCloud:
Create and edit are one endpoint in Kapso.
hsm_id is a query parameter, not a body field: add ?hsm_id=... to update instead of create. Delete also identifies the template by query string, taking either ?name=... or ?hsm_id=....
Templates belong to the WABA. If the number stayed on a WABA you already owned, they are still there. If it landed on a new one, recreate them and wait for review.
Rebuilt them in WhatsApp Manager? Pull them in from WhatsApp → Templates → Sync from WhatsApp. See Template lifecycle.
Contacts and opt-outs
YCloud stores contacts in its own CRM, with tags, custom attributes, owners, and source attribution. Kapso stores a smaller contact record and a free-formmetadata object:
Export your YCloud unsubscriber list before you close the account and keep suppressing those contacts on your side. See Marketing opt-outs.
Multi-tenant setups
If you message on behalf of your own customers, each one becomes a Kapso customer that connects its own number through a setup link, instead of you onboarding WABAs on their behalf:url. They log in with Facebook and connect in about five minutes. You then get whatsapp.phone_number.created on your project webhook, with the customer.id and phone_number_id. See Onboard customers and Connection detection.
One API key covers every customer. Migrate one customer at a time.
Bulk sends
YCloud’s queueing endpoint absorbs bursts, so bulk sends there are often just a fast loop overPOST /v2/whatsapp/messages, whatever the message type. Kapso’s send endpoint is synchronous, and what replaces the loop depends on what you were sending.
Approved-template campaigns become broadcasts. whatsapp_template_id is required on create, so a broadcast always sends one approved template, of any category. The one restriction is that authentication templates cannot go to BSUID recipients:
suppressed and skipped, which covers what filterUnsubscribed did per send. The guard checks the template category first, so utility and authentication broadcasts are not subject to marketing opt-outs at all. They can still fail per recipient for other reasons, including the BSUID restriction above.
Bulk text, media, and interactive sends have no broadcast equivalent, because those are session messages rather than templates. Keep your own durable queue in front of POST /{phone_number_id}/messages for them, and pace it yourself against your rate limit.
POST /{id}/schedule sends later. Stopping depends on what state the broadcast is in: POST /{id}/cancel returns a scheduled broadcast to draft, and it does nothing for one that is already sending. To stop a send in flight, patch the status:
Billing
YCloud runs on a prepaid balance: you top up, YCloud pays Meta, andBALANCE_INSUFFICIENT stops sends. Kapso offers the same shape, or direct Meta billing:
Choose the mode when the WABA is connected. See Meta message billing and pricing.
Feature map
Things Kapso adds:
- Automatic voice-note transcription on inbound audio
- Functions on Cloudflare Workers, as workflow steps, agent tools, or plain endpoints
- Findings, which reads ended conversations with AI and groups the recurring problems
- Conversation lifecycle webhooks, so you can act when a conversation goes quiet or ends
What does not map
- SMS, email, voice, and Verify. YCloud’s
/v2/sms,/v2/emails,/v2/voices, and/v2/verify/verificationshave no Kapso equivalent. Kapso is WhatsApp only. Keep a YCloud account or another provider for those channels. - Contact attribute definitions, tags, and owners. Contact
metadatais schemaless. - Balance API. No
GET /v2/balance. Credits live in project settings.

