Phone numbers
Salvy and BYON WhatsApp number lifecycle.
Available regions
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] |
Provision (Salvy)
Request body
| Field | Type | Notes |
|---|---|---|
dddrequired | string | pattern: ^\d{2}$ |
display_name | string | len 1..255 |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |
Connect (BYON)
Request body
| Field | Type | Notes |
|---|---|---|
phonerequired | string | pattern: ^\+\d{8,15}$ |
meta_phone_number_idrequired | string | len 1..∞ |
display_name | string | len 1..255 |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |
List
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |
Retrieve
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |
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
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
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |
Release
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
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |
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
| Field | Type | Notes |
|---|---|---|
source_project_idrequired | string | len 1..∞ |
source_environment_idrequired | string | len 1..∞ |
target_project_idrequired | string | len 1..∞ |
target_environment_idrequired | string | len 1..∞ |
confirm_phone_number_idrequired | string | len 1..∞ |
reason | string | len 1..500 |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "phone_number" | |
sourcerequired | "salvy" | "byon" | |
statusrequired | "requested" | "provisioning" | "provisioned" | "verifying" | "active" | "failed" | "release_requested" | "released" | "disconnected" | |
environmentrequired | "sandbox" | "production" | |
display_namerequired | string | null | |
dddrequired | string | null | |
phonerequired | string | null | |
provider_number_idrequired | string | null | |
meta_phone_number_idrequired | string | null | |
waba_idrequired | string | 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_tierrequired | string | null | |
meta_throughput_tierrequired | "1" | "2" | "3" | "4" | "unlimited" | null | |
meta_quality_ratingrequired | string | null | |
verified_namerequired | string | 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_reviewrequired | object | 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_reviewrequired | object | 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_atrequired | string<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_recipientsrequired | integer | range 0..9007199254740991 |
remaining_messaging_allowance_estimaterequired | integer | 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_coderequired | string | null | |
verification_code_received_atrequired | string<ISO-8601> | null | |
monthly_fee_brlrequired | string | null | |
error_coderequired | string | null | |
error_messagerequired | string | null | |
created_atrequired | string<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_atrequired | string<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_atrequired | string<ISO-8601> | null | |
released_atrequired | string<ISO-8601> | null | |
recent_messagesrequired | object[] |