List WhatsApp numbers
/v1/whatsapp/numbersfor await (const number of bird.whatsapp.numbers.list({ status: ["connected"] })) {
console.log(number.id, number.phone_number, number.status);
}for number in client.whatsapp.numbers.list(status=["connected"]):
print(number.id, number.phone_number, number.status)for number, err := range client.Whatsapp.Numbers.List(context.Background(), bird.WhatsappNumbersListParams{}) {
if err != nil {
log.Fatal(err)
}
fmt.Println(number.Id, number.PhoneNumber, number.Status)
}foreach ($bird->whatsapp->numbers->list(['status' => ['connected']]) as $number) {
echo $number->getId(), ' ', $number->getPhoneNumber(), ' ', $number->getStatus(), "\n";
}bird whatsapp numbers listcurl -X GET "https://us1.platform.bird.com/v1/whatsapp/numbers" \
-H "Authorization: Bearer $TOKEN" \
--url-query "sort=created_at" \
--url-query "order=desc" \
--url-query "limit=25"{
"data": [
{
"id": "wan_01krdgeqcxet5s7t44vh8rt9mg",
"waba": "102290129340398",
"phone_number": "+15550001234",
"number_id": "nda_01krdgeqcxet5s7t44vh8rt9mg",
"name": "Sales EU",
"scope": "workspace",
"data_localization_region": "DE",
"status": "connected",
"next": [
{
"kind": "operation"
}
],
"error": {
"code": "registration_pin_rejected",
"description": "Cannot Create Certificate: Please ensure two-factor authentication is disabled.",
"meta_error_code": "2388001"
},
"finish_setup_url": "https://bird.com/dashboard/w/ws_01krdgeqcxet5s7t44vh8rt9mg/whatsapp/numbers?finish_setup_number=wan_01krdgeqcxet5s7t44vh8rt9mg",
"quality_rating": "green",
"messaging_limit": "tier_250",
"throughput_level": "standard"
}
],
"next_cursor": "eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE0OjAzOjEwWlwiIiwiaSI6IjAxOTJmM2IxLTRjN2UtN2EyYi05ZDYxLThmM2E1YzJlN2I0MCJ9",
"prev_cursor": null,
"refresh_cursor": "eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE2OjQyOjAxWlwiIiwiaSI6IjAxOTJmM2IxLTllMDQtN2NkMy1iODE3LTJhNmY0ZDFjOGUwOSJ9"
}
Returns a paginated list of the WhatsApp numbers your workspace can send from. The list includes both platform-managed numbers and numbers on a WhatsApp Business Account you connected. Each item reports its WhatsApp status, quality rating, business portfolio messaging limit, allowed send rate, and Official Business Account status.
Page through the full set with the response cursors. A cursor naming a
platform-managed number is rejected once the active filters would exclude
it, including a scope=system cursor for a number that is not
platform-managed. Start again without starting_after or ending_before
whenever you change phone_number, waba, status, or scope.
Query Parameters
wabastringFilter to a single WhatsApp Business Account by its Meta-assigned ID. Use the waba of a connected WhatsApp Business Account, or the waba on a number this list returns. A platform-managed number belongs to no WhatsApp Business Account and is never returned when this is set, so pairing it with scope=system always returns an empty page. An account this workspace does not hold returns an empty page.
phone_numberstringFilter to a single number, given in E.164 format. The value is normalized before matching, so +31612340001 and +31 6 1234 0001 are the same filter. A value that cannot be normalized is matched exactly as given. A number this workspace cannot send from returns an empty page, rather than being rejected.
statusarrayFilter by the number's WhatsApp state: the status a number in this list carries. Every value matches that status exactly, so repeat the parameter for each state you want. pending covers both a number WhatsApp reports as not registered and one it has reported no state for at all, while the two states before that keep their own values: a number we are still verifying carries preparing, and one waiting for someone to finish signup carries awaiting_signup. Asking for all three reaches every connection that has not finished, plus any finished one WhatsApp has not reported on yet. failed matches a connection refused permanently. A value this vocabulary does not recognize matches nothing, rather than being rejected. Omit to return numbers in every state.
scopestringFilter by ownership tier: system for platform-managed numbers and workspace for numbers your workspace connected. Omit to return both. A system number belongs to no WhatsApp Business Account, so pairing this with waba always returns an empty page.
Possible values: system, workspace
sortstringField to sort by.
Possible values: created_at
orderstringSort direction. Defaults to desc, which sorts from newest to oldest or largest to smallest, depending on the selected sort field.
Possible values: asc, desc
limitintegerMaximum number of items to return per page.
starting_afterstringCursor from the next_cursor field of a previous list response. Returns items immediately after the cursor position in the current sort order.
ending_beforestringCursor from the prev_cursor or refresh_cursor field of a previous list response. Returns items immediately before the cursor position in the current sort order. prev_cursor returns the preceding page. refresh_cursor anchors at the first row of that response, which on a newest-first sort is how to fetch the items that have appeared since.
Response Payload
dataThe WhatsApp numbers your workspace can send from.
Show child attributes
data.idUnique identifier for the connected number.
data.wabaThe WhatsApp Business Account this number is connected under. Present only for a number your workspace connected itself.
data.phone_numberThe number in E.164 format. Null only while the number itself is not yet known: a number your workspace holds carries its E.164 from the moment setup starts, so a value here does not mean the number can send. status is what says that.
data.number_idThe number you hold with us that this WhatsApp number was connected from, as its id in GET /v1/numbers. Absent for a number you brought yourself.
data.nameYour workspace's own label for this number, given when it was connected and changeable afterwards. It has no bearing on what WhatsApp displays to people the number messages; GET /v1/whatsapp/numbers/{number_id}/profile returns that as display_name. For a number we operate on your behalf, this is our own label instead and cannot be changed.
data.scopeWhether the number sends under a WhatsApp Business Account we operate on your behalf (system) or one your workspace connected itself (workspace).
data.data_localization_regionThe country this number's message content is stored at rest in, as its two-letter ISO 3166 code. Absent when it uses WhatsApp's default storage. It can differ from the region requested at connection when WhatsApp requires a particular country for the number.
data.statusWhatsApp's own state for this number as of meta_synced_at, except for the three states we answer ourselves because WhatsApp holds nothing to report. A connection we are still verifying reads preparing, one waiting for someone to finish signup reads awaiting_signup, and a permanently refused one reads failed, with error saying why. pending is WhatsApp's own token for a number it does not hold as registered, and is also what a number with no stored WhatsApp status reads, including after setup completes, so it does not by itself establish whether setup is complete. A number we operate on your behalf reads connected as our own assertion rather than a reading from WhatsApp for every number we ship today; that tier carries no meta_synced_at.
data.nextWhat to do next about this number, given the state it is in. Each entry names one action and says why it is worth taking, so you can act on this response without working out the order yourself. Present on reads that compute it: an empty list means there is nothing to do, and the field is absent entirely on responses that do not report next actions.
While status is awaiting_signup this carries the browser step that finishes
the connection, because embedded signup sits behind an OAuth screen no API call
can stand in for.
Show child attributes
data.next.kindWhat you do about this step.
operation: call the operation named inoperation, then read again.external: act somewhere this API does not reach, then read again.wait: nothing is asked of you, so read again later.terminal: nothing you do resolves this, so stop retrying.
Tolerate a value you do not recognize: show the description and
offer no action.
Possible values (may grow over time): operation, external, wait, terminal
data.next.descriptionA short, human-readable label for the step, suitable for display.
data.next.operationThe operationId to call. Present only when kind is operation. The operation's own schema says how to call it; this says only which one, and what to address it with.
data.next.paramsThe parameters that address the operation, by name: {"sender_id": "…"} for an operation on /v1/sms/senders/{sender_id}/requirements. A parameter the operation takes in its query string is given the same way, so an operation addressed as ?subject_id= carries {"subject_id": "…"}. Every parameter the call needs is here, whether its value came from the thing you were acting on or is fixed for this step, so you can make the call from this object alone. Present only when kind is operation and the operation names a subject. A request body, when the operation takes one, is described by the operation's own schema and never appears here.
data.next.urlA URL to open. Present only when kind is external, and only when the step has one. An external step whose description says to go and do something with no URL to open is normal.
data.errorWhy this number's connection was refused for good. Present only while status is failed. A retryable step records its cause on a still-pending number without setting this field, because that cause is not a refusal yet, so a connection you are still waiting on reports no error here.
Show child attributes
data.error.codeStandardized failure reason.
data.error.descriptionWhy the connection failed: WhatsApp's own words, in the language of the account it refused, when WhatsApp answered; our own explanation when the number was refused before WhatsApp was asked; a generic sentence when WhatsApp refused without giving a reason. Absent when the attempt failed without ever reaching WhatsApp, which leaves code as the only account of the failure. Show it to the person who owns the number; never match on its text.
data.error.meta_error_codeWhatsApp's most specific code for the refusal: its error subcode where it sent one, otherwise its top-level code. Null when WhatsApp did not provide a code. Treat it as an opaque string.
data.finish_setup_urlWhere a person finishes connecting this number, present only while status is awaiting_signup. Finishing means completing WhatsApp's embedded signup, which is a browser flow behind an OAuth screen: it cannot be done over the API, so open this link and have someone with access to the workspace complete it. The number is offered to them already verified. Once they finish, status moves on and this link is no longer returned.
data.quality_ratingWhatsApp's quality rating for this number as of meta_synced_at. Absent until WhatsApp has reported one, and always absent for a number we operate on your behalf.
data.messaging_limitThe messaging limit WhatsApp applied to this number's business portfolio as of meta_synced_at. Absent until WhatsApp has reported one, and always absent for a number we operate on your behalf.
data.throughput_levelThe send rate WhatsApp allowed this number as of meta_synced_at. Absent until WhatsApp has reported one, and always absent for a number we operate on your behalf.
data.is_official_business_accountWhether WhatsApp grants this number Official Business Account status as of meta_synced_at. Absent until WhatsApp has reported it, and always absent for a number we operate on your behalf. WhatsApp grants the status per number, so two numbers on one WhatsApp Business Account can differ. The status also decides whether a rename is possible here: a number that has it cannot be renamed through PATCH /v1/whatsapp/numbers/{number_id}/profile at all, and has to be renamed through WhatsApp support instead.
data.meta_synced_atWhen this number's state was last read from WhatsApp. status, quality_rating, messaging_limit, throughput_level, and is_official_business_account all belong to that reading rather than representing live values. We re-read roughly hourly, so a change at WhatsApp can be up to an hour old here. Absent for a number we have never read back and for a number we operate on your behalf.
data.pre_verification_requested_atWhen we last asked WhatsApp to send this number a verification code, which we do only for a number your workspace connected itself from a number you hold with us. Absent for a number we operate on your behalf, and for one you connected through Embedded Signup with a code you read yourself. Wait a few hours after this before repairing a number whose verification failed: WhatsApp rotates the routes it verifies over during that period, and throttles a number asked repeatedly in a short window. Distinct from updated_at, which any change to the number moves.
data.created_atWhen this number was submitted for connection.
data.updated_atWhen this number was last changed.
next_cursorCursor for the next page. Pass back as starting_after to advance forward. null when no next page exists.
prev_cursorCursor for the previous page. Pass back as ending_before to step backward. null when no previous page exists.
refresh_cursorRefresh anchor, the first row of this response. Pass back as ending_before to fetch what precedes it in the current sort order. On a newest-first sort those are the items that have appeared since; on any other sort they are the items that sort earlier, so refreshing such a list means re-fetching it instead. Non-null whenever data is non-empty; null only on an empty page. Distinct from prev_cursor.
Related resources
Continue with the documentation, guides and examples for this topic.