Migrating from v1 to v2
Move from per-number v1 keys and endpoints to v2 account keys, one REST surface and signed v2 webhooks — step by step.
v1 keeps working, so you can move one call at a time. The message model is the same: the body you send to v1 POST /whatsapp/public/messages works on v2 POST /v2/messages once you add numberId.
Authentication
| v1 | v2 | |
|---|---|---|
| Key | v1One x-api-key per number | v2Account keys: Authorization: Bearer wsl_live_… |
| Permissions | v1Fixed per number | v2Scopes, number restriction, IP allowlist, expiry, rotation |
| Choosing the number | v1Implied by the key | v2numberId in the body / path |
Your v1 number key also works on the v2 message endpoints of its own number, so you can switch URLs first and keys later.
Endpoints
v1 (/api/v1/whatsapp/public/…) | v2 (/api/v2/…) |
|---|---|
POST messages, message/send, media/send, interactive/send | v2 (/api/v2/…)POST /v2/messages |
POST media/upload | v2 (/api/v2/…)POST /v2/media |
POST messages/{id}/react · edit · delete | v2 (/api/v2/…)POST /v2/messages/{id}/reactions · PATCH /v2/messages/{id} · DELETE /v2/messages/{id} |
GET interactions/{id} | v2 (/api/v2/…)interactive.reply webhook · GET /v2/messages/{id} |
| Dashboard only | v2 (/api/v2/…)Numbers, campaigns, auto-replies, OTP, Number Shield, stats, groups, webhooks — all in v2 |
Errors
v1 answers { statusCode, code, message, … }; v2 answers { error: { code, message, details?, docsUrl, requestId } }. Codes keep their names where they exist in both. Read error.code.
Webhooks
| v1 field | v2 |
|---|---|
messageId | v2data.messageId |
from / senderPhoneNumber | v2data.from.phone (data.from.lid when WhatsApp hides the number) |
fromName | v2data.from.name |
messageType | v2data.type |
content / caption | v2data.text / data.caption |
mediaUrl | v2data.media.url (signed) / data.media.id |
latitude / longitude | v2data.location.lat / .lng |
isGroup / groupId | v2data.chat.type / data.chat.groupId |
rawMessage | v2removed |
Steps
- Create an account key with the scopes you need (Settings → API keys).
- Point your send calls to
POST /v2/messageswithnumberIdand anIdempotency-Key. - Update your webhook handler to read the v2 envelope (verify the signature the same way), switch the number to webhook version 2, send a test event and watch the log.
- Replace polling with webhooks (
message.status,campaign.status,number.status). - Revoke the old number keys you no longer use.
The v1 reference stays online.