Pre-verified phone numbers
Why this matters?
Phone number addition and verification are the steps in Embedded Signup where most drop-offs and errors occur. Pre-verified numbers let you handle both steps in advance, so by the time your client goes through the ES flow the number is already ready to connect — no OTP wait, no failed verification attempts. This significantly improves the ES experience and is expected to increase onboarding success rates.
How pre-verification works
Pre-verification lets you verify phone numbers via API before your clients ever reach Embedded Signup. Instead of requiring clients to add a number and enter an OTP themselves during onboarding, you handle that step in advance — either by maintaining a pool of pre-verified numbers ready to be assigned, or by verifying a specific customer's number right before sending them to the ES flow.
Once a number is verified, you pass its ID to the onboarding flow. The client can then select and connect it without going through phone number verification at all. This works whether you are hosting your own Embedded Signup or using 360dialog's Integrated Onboarding.
Verification statuses
A number moves through the following statuses during its lifecycle:
NOT_VERIFIED
In the pool, ownership not yet proven.
VERIFIED
Ownership proven. Ready to be claimed during onboarding.
EXPIRED
The 90-day window closed. Must be re-verified before it can be used.
Verifying numbers
This section covers the API endpoints for managing your pre-verified pool: adding numbers, requesting and verifying OTPs, listing the pool, and deleting numbers.
Process overview
Add the number
Register it with Meta and get back a preverified_phone_number_id
Request an OTP
Trigger an SMS or voice code to be sent to the number
Verify the OTP
Submit the code to prove ownership. The number becomes VERIFIED and a 90-day window opens
Pass the ID to onboarding
Include the preverified_phone_number_id when sending the client to your ES flow or Integrated Onboarding link
Receive confirmation
A preverified_number_claimed webhook fires when the number is connected, telling you which channel it became
Base URLs
{partner_id} is your 360dialog partner ID (e.g. examplePA).
Authentication
Every request must include your Partner API key in the x-api-key request header.
Treat the API key as a secret. Never embed it in client-side code, URLs that get logged, or version control. Rotate it if it is exposed.
Error format
Errors share a common envelope:
360dialog_trace_id
Include this when contacting support — it identifies the request.
developer_message
Human-readable reason.
details
Present on validation errors; keyed by location (json, query, path) and then by field name.
A 401 is returned when the API key is missing or invalid.
Step 1 — Add a number to the pool
Please use this endpoint.
Registers a phone number with Meta and shares it with the partner's Meta business so it can later be claimed by a client.
Request body
phone_number
string
yes
Digits only, no leading +. 6–20 characters, pattern ^\d+$.
Response — 201 Created
preverified_phone_number_id
Meta's pre-verified phone number ID. Use it as {id} in subsequent calls.
country_code
ISO 3166-1 alpha-2 (lowercase), derived from the number. May be null if it can't be determined.
code_verification_status
Starts as NOT_VERIFIED.
Adding a number already in your pool returns the existing record (idempotent).
Error cases
400
phone_number fails validation, or the partner has no Meta business ID configured (Partner business id is not configured for this partner).
404
The partner does not exist.
409
The number is already registered in a different pool.
502
The request to Meta's API failed.
Step 2 — Request an OTP
Please use this endpoint.
Triggers a Meta OTP to be sent to the number.
Request body
code_method
string
yes
Delivery method. One of sms, voice.
language
string
yes
Locale for the OTP message, e.g. en_US.
Supported code_method values
sms
Code sent by SMS text message.
voice
Code delivered by an automated voice call.
language is a Meta locale code passed straight through to Meta — for example en_US, en_GB, de, es, fr, it, pt_BR, nl, id. Refer to Meta's list of supported languages for the full set. Choose a locale the recipient can read; voice calls read the code aloud in that language.
Response — 200 OK
Error cases
400
Invalid code_method, or Meta rejected the request (e.g. invalid number for OTP).
404
No pre-verified number with this ID in the pool.
Step 3 — Verify the OTP
Please use this endpoint.
Submits the code received on the number. On success the number becomes VERIFIED and the 90-day window starts.
Request body
code
string
yes
The OTP code received on the number, e.g. 123456.
Response — 200 OK
Error cases
400
Meta rejected the code (e.g. Invalid verification code).
404
No pre-verified number with this ID in the pool.
List numbers
Please use this endpoint.
Returns the numbers in the partner's pool.
Query parameters
code_verification_status
string
yes (exact)
One of NOT_VERIFIED, VERIFIED, EXPIRED.
phone_number
string
yes (exact)
Digits only, no leading +, pattern ^\d+$.
country_code
string
no
Ordering hint only — see below.
country_code (ISO 3166-1 alpha-2, lowercase) does not filter the result. Numbers whose country matches are returned first, all others follow. Use it to surface the most relevant numbers (e.g. de) at the top without hiding the rest of the pool.
Response — 200 OK
Error cases
400
An invalid query value, e.g. code_verification_status outside the allowed set.
Delete a number
Please use this endpoint.
Deletes the number from Meta and removes it from the partner's pool.
Response — 200 OK
Error cases
404
No pre-verified number with this ID in the pool.
502
The request to Meta's API failed.
Passing pre-verified numbers to onboarding
Once a number is VERIFIED, you need to make it available to your clients during their Embedded Signup session. How you do this depends on how you are delivering the onboarding flow.
Self-hosted Embedded Signup
If you host the ES flow yourself, you can surface pre-verified numbers in the signup form using pre-filled form data. Add a preVerifiedPhone object with an ids array to the setup object and assign the preverified_phone_number_id values of the numbers you want to make available:
Full example
If a VERIFIED number is not claimed within 90 days, its status becomes EXPIRED and the client will be required to verify the number themselves during signup. Track verification dates and re-verify numbers before the window closes to avoid this.
Completing the connection
After the client finishes the ES session, Meta returns a phone number ID. You must pass this to 360dialog to complete the channel setup:
Pass the Meta Phone Number ID received from the ES session in this request. See the self-hosted Embedded Signup documentation for the full details on this step.
360dialog Integrated Onboarding (direct link or Connect Button)
Pass the preverified_phone_number_id directly into your onboarding flow so the number is pre-selected when the client goes through the 360dialog-hosted signup.
Connect Button
Install the latest version of the Connect Button package:
Pass the ID via the preverified_phone_number_id query parameter:
Direct Link
If you're using a direct link instead of the Connect Button, append the query parameter to the onboarding URL ...?preverified_phone_number_id=<preverified_phone_number_id>
Webhook: preverified_number_claimed
When a client claims one of your pre-verified numbers during Embedded Signup, the number is removed from the pool and a channel is created for it. At that moment 360dialog sends a preverified_number_claimed event to your partner webhook so you can reconcile the claimed number with the channel it became.
When it fires
The number was in your partner pool (not the 360dialog-owned pool), and
a new channel was created for it during onboarding.
It fires once, on the onboarding that creates the channel — not on later re-syncs of an existing channel. Delivery only happens if you have a webhook URL configured for the partner.
Delivery
Method:
POSTto your configured partner webhook URL.Headers:
Content-Type: application/json.Expected response:
2xx. Delivery is a single attempt — not retried on failure, so your endpoint should acknowledge quickly and process asynchronously.
Payload
id
Unique event/delivery ID.
event
Always preverified_number_claimed.
data.preverified_phone_number_id
Matches the ID returned when you added the number to the pool.
data.id
The newly created channel ID.
data.setup_info.phone_number
The claimed phone number.
data.waba_account
The WABA the number was connected to (external_id is the Meta WABA ID).
data.client
The client that claimed the number.
Use data.preverified_phone_number_id to match the event back to the number you added to the pool, and data.id / data.waba_account to know which channel and WABA it became.
Last updated
Was this helpful?