Brand vetting and carrier limits
#Vet a brand
External vetting raises your brand’s carrier score and daily throughput. Paid once, at your price for Standard, Enhanced, or the upgrade from Standard to Enhanced; the charge comes back as amount_cents. Needs the manage_brands permission.
Parameters
idinteger · pathRequired- The brand’s registration id.
vetting_typeenumDefaultSTANDARDSTANDARDorENHANCED, case-insensitive. A brand already vetted Standard can upgrade to Enhanced for the price difference (upgrade: true). If vetting can’t be submitted, the fee is refunded automatically.
Returns
charged, amount_cents, vetting_type, upgrade, card_last4, payment_intent_id- Card on file: charged now.
client_secret, has_card, payment_intent_id- Not charged yet (no card on file, or the saved card needs confirming): confirm with Stripe.js, then Confirm the vetting payment with this
payment_intent_id.
Errors
On these errors, error holds the code again. Show message to a person: it says what happened and what to do.
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_vetting_type | vetting_type isn’t STANDARD or ENHANCED. |
| 400 | not_a_brand_registration | Id is a campaign (error). |
| 400 | brand_not_linked_to_carrier | Brand not yet with the carriers (error). |
| 404 | reg_not_found | No registration has this id, or it isn’t your account’s or a sub-account’s. Both read the same (error). |
| 409 | already_vetted | The same tier or a lower one again (error). |
#Confirm the vetting payment
Applies the vetting after a client_secret payment. Safe to call twice. Needs the manage_brands permission.
Parameters
idinteger · pathRequired- The brand’s registration id.
payment_intent_idstringRequired- From Vet a brand.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | payment_intent_mismatch | The payment isn’t for this vetting. |
| 400 | payment_not_succeeded | Not paid yet (202 while processing; error). |
| 400 | could_not_retrieve_payment_intent | No such payment. |
| 409 | payment_refunded | That payment was refunded. |
| 503 | could_not_retrieve_payment_intent | We couldn’t check the payment. Don’t pay again; retry. |
#Get a brand’s carrier limits
Reads the carrier-assigned SMS limits for the campaigns belonging to a brand. No recipient validation is needed. These describe allowed capacity, not available daily headroom or measured sending speed: check approval and carrier status, use GET /v1/registration/throughput for account usage and warm-up restrictions, and allow for concurrent traffic and delivery time.
Parameters
idinteger · pathRequired- The Ready brand registration ID, such as
data.brand.idfrom GET /v1/registration, not a carrier ID or a campaign ID. The brand must be visible in the key’s account or selected sub-account. campaign_idinteger · query- Ready campaign registration ID. Return only that campaign under this brand.
after_idinteger · query- Pagination cursor. Return campaign registrations after this ID. Each page holds up to 10 campaigns.
Returns
data.brandobject- The brand’s
id,nameandstatus. data.campaigns[]array of objects- The brand’s campaigns.
Child attributes
id, name, statusinteger, string, string- The campaign’s registration id, name and status.
sourcestringcarrier_assignmentmeans Ready read the carrier’s assignment.not_registeredis a campaign not yet registered; thenchecked_atandcarriersarenull.checked_atstring | null- When Ready read the assignment. Results are cached for up to 60 seconds.
carriers.attobjectstatus,message_class,sms_per_minute,sms_per_second, andscope: "campaign". Fractional rates are preserved, such as 75 per minute = 1.25 per second.carriers.tmobileobjectstatus,tier,daily_messages, andscope: "brand". This is a shared daily allowance. Do not add the same brand allowance across campaigns.carriers.verizonobjectstatus,sms_per_second, andscope: "campaign". Anullrate means the carrier did not report one, not unlimited sending or instant arrival.
data.has_more, next_after_idboolean, integer | null- When
has_moreis true, call again withafter_id=data.next_after_id. data.cache_ttl_secondsinteger- How long results are cached, in seconds.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | no code | An invalid ID or cursor. |
| 404 | registration_not_found | The brand is not visible to this account, or the selected campaign does not belong to it. |
| 503 | throughput_unavailable | The database or carrier assignments could not be read. A failure does not return guessed limits. |
#Get throughput
Live sending capacity: 24-hour volume and rejections, T-Mobile daily cap and tier, warm-up state. You can cache the response for up to one minute. Warm-up rules: Sending caps.
Returns
data.total_24h, rejected_24h, reject_pctinteger, integer, number- Last 24 hours: messages, rejections (messages, not segments), percent rejected.
data.throttledbooleantrueat 50 or more rejections and 5% or more of the last 24 hours. Thendaily_loss_usdestimates what they cost, andbrandnames the brand to vet (cta:vet,upgradeormaxed) andprice_usd, what that vetting charges in dollars (the upgrade price is the difference;nullwhenmaxed).data.tmobileobject | nulldaily_cap,tier,next_cap,sent_today,pct,coverage,usage_reliable. Readsent_todayonly whenusage_reliableistrue. The ladder is 2,000, 10,000, 40,000, 100,000, 200,000;next_capisnullat the top. The whole object isnulluntil you have a T-Mobile tier.data.rampobject- Warm-up state:
in_warmup,sent,cap,remaining,capped,ends_at,registration_id,carrier_campaign_id,campaign_id. If more than one warm-up runs at once (a brand ramp and a newly approved campaign), this reports the one you’re most limited by.Child attributes
in_warmupboolean | null- While
true, pace withinremaining.falseonce you’re past it, andnullwithramp_unavailable: truewhen we couldn’t read it, so keep pacing. ends_atstring- An estimate.
registration_idinteger | null- The Ready registration ID of the campaign in warm-up: the value the limits endpoint takes as
campaign_id.nullfor the brand-wide ramp. carrier_campaign_idstring | null- The carrier’s campaign ID.
nullfor the brand-wide ramp. campaign_idstring | null- Deprecated: the same value as
carrier_campaign_id, not the Ready registration ID the limits endpoint takes ascampaign_id. Useregistration_idorcarrier_campaign_id.
cachedboolean- Cached for up to one minute; a cached answer has
"cached": true.
Errors
| HTTP | Code | When |
|---|---|---|
| 503 | throughput_unavailable | Couldn’t be read. Never a fake all-clear. |
Older paths
GET /v1/registration/denied is an older path, not an alias of Get registration status: it returns only the latest rejected registration, as { denied, reg_id, type, name, reasons, reason, ai_fix }, or { denied: false } when nothing is rejected, and 503 denied_status_unavailable when it cannot be read.
See also: the guide to doing this in the app.