API reference

Phone numbers

Salvy and BYON WhatsApp number lifecycle.

Available regions

GET/v1/phone-numbers/available-regions

Response

FieldTypeNotes
objectrequired"list"
datarequiredobject[]

Provision (Salvy)

POST/v1/phone-numbers/provision202 Accepted

Request body

FieldTypeNotes
dddrequiredstring
pattern: ^\d{2}$
display_namestring
len 1..255

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]

Connect (BYON)

POST/v1/phone-numbers/connect201 Created

Request body

FieldTypeNotes
phonerequiredstring
pattern: ^\+\d{8,15}$
meta_phone_number_idrequiredstring
len 1..∞
display_namestring
len 1..255

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]

List

GET/v1/phone-numbers

Response

FieldTypeNotes
objectrequired"list"
datarequiredobject[]
has_morerequiredboolean
next_cursorrequiredstring | null

Retrieve

GET/v1/phone-numbers/{id}

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]

verified_nameis Meta's current verified display name; in production it is observed by the scheduled health sweep and is null before that observation. Sandbox supplies a deterministic simulated value. display_name remains the customer-entered row label. pending_name_review is null or { requested_name: string | null; status: string | null; observed_at: ISO timestamp }: the pending Graph observation from a successful complete health sweep. Its nullable status is open Meta vocabulary and observed_at is the same freshness fact as meta_health_synced_at. A successful complete sweep is authoritative and writes or clears it. A completed callback can clear it immediately only when its requested name matches and its effective time is not older than observed_at; all other callbacks wait for the next sweep. Failed or partial refreshes leave prior values and freshness intact. Sandbox deterministically returns pending_name_review: null, which means no pending observation, not approval.name_review is separately null until a durable completed callback decision arrives; then its nullable requested_name and reason accompany reviewed_at and an open, forward-compatible Meta decision string. These read responses never call Meta.

remaining_messaging_allowance_estimateis how many more unique recipients this number can contact outside their customer-service windows before Tyxter begins holding sends. It is not a remaining-message count. A recipient already holding a slot in the moving 24-hour period costs nothing more, and any message from that recipient opens a separate 24-hour customer-service window whose sends also cost no allowance. It counts against a cap that already keeps a safety slice back, so it reaches zero slightly before WhatsApp’s own limit does. Treat it as a planning estimate, not a quota to spend exactly: concurrent sends move it, slots expire one by one with no reset moment, and a paused number can report a number above zero before any send has observed that allowance freed up. While a number’s limit tier has not been read from Meta yet (messaging_tier: "unknown") the estimate counts down from a deliberately low default rather than from the number’s real allowance. null means Tyxter cannot estimate it at all, and never means zero.

Disconnect

DELETE/v1/phone-numbers/{id}

Disconnects a number from the current environment and returns its terminal record. This operation is an idempotent no-op for an already disconnected, released, or failed number.

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]

Release

POST/v1/phone-numbers/{id}/release202 Accepted

Releases the upstream resource. Salvy numbers first enter release_requested while a worker cancels the rental; BYON numbers move directly to released. The request has no JSON body and supports Idempotency-Key.

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]

Transfer

POST/v1/phone-numbers/{id}/transfer

Moves a non-terminal number between projects or environments in the same organization. The body confirms both scopes and the route identifier; cross-organization targets return 404. This write supports Idempotency-Key.

Request body

FieldTypeNotes
source_project_idrequiredstring
len 1..∞
source_environment_idrequiredstring
len 1..∞
target_project_idrequiredstring
len 1..∞
target_environment_idrequiredstring
len 1..∞
confirm_phone_number_idrequiredstring
len 1..∞
reasonstring
len 1..500

Response

FieldTypeNotes
idrequiredstring
objectrequired"phone_number"
sourcerequired"salvy" | "byon"
statusrequired"requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected"
environmentrequired"sandbox" | "production"
display_namerequiredstring | null
dddrequiredstring | null
phonerequiredstring | null
provider_number_idrequiredstring | null
meta_phone_number_idrequiredstring | null
waba_idrequiredstring | null
quality_ratingrequired"green" | "yellow" | "red" | "unknown"
messaging_tierrequired"tier_50" | "tier_250" | "tier_1k" | "tier_2k" | "tier_10k" | "tier_100k" | "unlimited" | "unknown"
messaging_limit_tierrequiredstring | null
meta_throughput_tierrequired"1" | "2" | "3" | "4" | "unlimited" | null
meta_quality_ratingrequiredstring | null
verified_namerequiredstring | null
The current display name Meta has verified for this number. Production values come from the scheduled Meta health sweep; sandbox uses its deterministic simulated health snapshot. Null means Tyxter has not observed a verified name on a completed sweep yet.
pending_name_reviewrequiredobject | null
The latest pending Meta display-name review observed on a completed health sweep. Null when Meta reported no pending review. This is distinct from name_review, which records a completed callback decision; display_name remains the customer-entered name for this row.
name_reviewrequiredobject | null
The latest durable Meta display-name review. Null until Tyxter has received a review decision. The decision is an open Meta value; display_name remains the customer-entered name for this row.
meta_health_synced_atrequiredstring<ISO-8601> | null
When this number's Meta-reported health (quality_rating, messaging_tier, messaging_limit_tier) was last read from Meta. Null means it has never been read yet. A failed refresh leaves both the values and this marker untouched, so an older timestamp means those fields are as of that moment rather than now. Active numbers are refreshed by a background sweep roughly every 6 hours; a large fleet of numbers can take several cycles to come around.
current_24h_unique_recipientsrequiredinteger
range 0..9007199254740991
remaining_messaging_allowance_estimaterequiredinteger | null
Estimated number of NEW recipients this number can still start a conversation with before Tyxter starts holding sends. Measured against a rolling 24-hour window whose slots expire one by one — there is no reset moment — and against a cap that already has a safety slice held back, so it runs out slightly before WhatsApp’s own limit does. For a Meta number linked to a business portfolio, this is the shared portfolio estimate repeated on each linked phone; the phone’s raw health tier is descriptive, not a second quota. An unlinked Meta number uses a conservative per-phone fallback; sandbox follows its deterministic simulated phone tier. It is an ESTIMATE, not a quota you can spend exactly: concurrent sends move it, recipients already inside an open conversation window cost nothing against it, and a paused number can report a number above zero before any send has observed that allowance freed up. While Tyxter has no authoritative linked portfolio capability, or an unlinked number’s limit tier has not been read from Meta yet, this counts down from a deliberately low default rather than an assumed unlimited allowance, so a fresh number can look tighter than it is — messaging_tier reports "unknown" in that case. Null means Tyxter cannot estimate it at all — for example, Meta explicitly reports no finite linked portfolio cap — and never means zero.
verification_coderequiredstring | null
verification_code_received_atrequiredstring<ISO-8601> | null
monthly_fee_brlrequiredstring | null
error_coderequiredstring | null
error_messagerequiredstring | null
created_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
updated_atrequiredstring<ISO-8601>
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
activated_atrequiredstring<ISO-8601> | null
released_atrequiredstring<ISO-8601> | null
recent_messagesrequiredobject[]