Migrating from Meta
If you already have an integration running against the Graph, migrating is a two-string change. The rest of this guide is about everything around it.
From the Meta Cloud API directly
1. Connect the number
The number has to leave your Business Manager and join ours. In the dashboard, under Connect number, Embedded Signup handles that — the customer authorizes through the Facebook window.
While the number hasn't moved, your old integration keeps working normally.
2. Swap domain and token
- https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages
+ https://api.joinotify.com/v1/{PHONE_NUMBER_ID}/messages
- Authorization: Bearer EAAG...
+ Authorization: Bearer sk_live_xxx
The phone_number_id changes during migration. Get the new one from GET /me or the
dashboard.
If your code passes the token as ?access_token=, that has to change: on Joinotify the
token always goes in the header. See
Meta compatibility.
3. Point the webhooks at us
You no longer configure a callback on Meta. Register your endpoint here:
curl -X POST https://api.joinotify.com/webhook-endpoints \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{ "name": "production", "url": "https://your-server.com/webhooks", "events": [] }'
The delivered body is the same Meta envelope, so your handler doesn't change. What does change is signature validation:
- X-Hub-Signature-256: sha256=<hmac of the body with the App Secret>
+ X-Joinotify-Signature-256: sha256=<hmac of "{timestamp}.{body}" with the whsec_>
The walkthrough is in Verify the signature.
4. Recreate the templates
Templates from your old WABA don't come along. Recreate them and wait for approval before flipping the switch — this is what delays migrations the most.
curl https://api.joinotify.com/templates \
-H 'Authorization: Bearer sk_live_xxx'
5. Flip the switch
With the number migrated, the templates approved and the webhook registered, change the
base URL in production. The new phone_number_id goes in at the same time.
From another provider (BSP)
The path is the same, with one extra detail: the number has to be released by your current provider before it can join our Business Manager. Some charge for that or impose a notice period — check the contract before picking a date.
If your current provider exposes a proprietary API rather than Meta's contract, your
sending code has to be rewritten. Joinotify's /v1 mirror follows Meta, not the provider.
What doesn't migrate
| Item | Situation |
|---|---|
| Conversation history | Doesn't migrate. In coexistence, it can be synced from the phone. |
| Templates | Have to be recreated and re-approved. |
| Number quality | Starts over. |
| 24-hour messaging limit | Starts at the initial tier and grows with usage. |
phone_number_id and waba_id | Change. Update wherever they're stored. |
Checklist
- Number connected in the Joinotify dashboard
- New
phone_number_idandwaba_idwritten down - API key created and stored in a secrets manager
- Token moved to the
Authorizationheader (no?access_token=) - Base URL changed to
https://api.joinotify.com/v1/ - Templates recreated and approved
- Webhook endpoint registered and tested with
POST /webhook-endpoints/{id}/test - Signature validation switched to
X-Joinotify-Signature-256 -
429handling withRetry-Afterimplemented - Old integration switched off only after the first message goes out through the new one