Status Tracking
Status Tracking
The SDK provides utilities to track registration progress and poll for status updates.
Registration State
The RegistrationState interface tracks the full registration lifecycle:
interface RegistrationState {
route: RegistrationRoute; // 'direct-standard', 'isv-sole-prop', etc.
// Customer Profile
customerProfileSid?: string;
customerProfileStatus?: ProfileStatus;
// Trust Product (A2P Bundle)
trustProductSid?: string;
trustProductStatus?: ProfileStatus;
// Brand
brandSid?: string;
brandStatus?: BrandStatus;
trustScore?: number;
// Campaigns
campaigns: CampaignState[];
}Refreshing Status
Use refreshRegistrationState() to fetch live status from Twilio:
import { refreshRegistrationState } from '@warp-message/a2p-sdk';
let state: RegistrationState = {
route: 'direct-standard',
customerProfileSid: 'BU...',
brandSid: 'BN...',
campaigns: [],
};
// Refresh all SIDs in the state
state = await refreshRegistrationState(client, state);
console.log('Profile status:', state.customerProfileStatus);
console.log('Brand status:', state.brandStatus);
console.log('Trust score:', state.trustScore);Behavior:
- Fetches live status for all SIDs in the state
- Silently preserves old status if a fetch fails (assumes resource may have been deleted)
- Returns updated
RegistrationState
Status Summary
Use getRegistrationSummary() to get a human-readable summary:
import { getRegistrationSummary } from '@warp-message/a2p-sdk';
const summary = getRegistrationSummary(state);
console.log('Is complete:', summary.isComplete);
console.log('Current step:', summary.currentStep);
console.log('Next action:', summary.nextAction);
console.log('Details:', summary.details);Example output:
{
isComplete: false,
currentStep: 'Brand Registration',
nextAction: 'Wait for TCR review (minutes to 7+ business days)',
details: {
customerProfile: 'twilio-approved',
trustProduct: 'twilio-approved',
brand: 'IN_REVIEW',
}
}Polling
Poll Brand Status
Use pollBrandUntil() to poll until a target status:
const brand = await client.pollBrandUntil(brandSid, 'APPROVED', {
intervalMs: 10_000, // Check every 10 seconds
timeoutMs: 600_000, // Stop after 10 minutes
});
if (brand.status === 'APPROVED') {
console.log('Brand approved! Trust score:', brand.trustScore);
} else {
console.log('Timeout - brand still:', brand.status);
}Behavior:
- Polls every
intervalMs(default 10s) - Stops when status matches target or timeout is reached
- Does NOT throw on timeout — returns last-fetched status
- Default timeout: 10 minutes
Important: Always check the returned status — timeouts don't throw.
Poll Campaign Status
Use pollCampaignUntil() to poll campaign status:
const campaign = await client.pollCampaignUntil(
messagingServiceSid,
campaignSid,
'VERIFIED',
{
intervalMs: 30_000, // Check every 30 seconds
timeoutMs: 1_800_000, // Stop after 30 minutes
}
);
if (campaign.status === 'VERIFIED') {
console.log('Campaign verified! Can start sending.');
} else {
console.log('Timeout - campaign still:', campaign.status);
}Behavior:
- Polls every
intervalMs(default 30s) - Stops when status matches target or timeout is reached
- Does NOT throw on timeout
- Default timeout: 30 minutes
Polling vs Webhooks
Polling:
- Simple to implement
- Good for initial status checks after submission
- Not recommended for long-running reviews (use webhooks instead)
Webhooks:
- Real-time updates
- No polling overhead
- Recommended for production
- Requires webhook endpoint and signature validation
Best practice: Use both — poll immediately after submission to catch fast approvals, then rely on webhooks for longer reviews.
Timelines
Expected review times:
| Step | Timeline |
|---|---|
| Customer Profile review | Up to 72 hours |
| Trust Product evaluation | Minutes to hours |
| Brand review (non-Sole Prop) | Minutes to 7+ business days |
| Sole Prop OTP verification | 24 hours (customer must verify) |
| Campaign vetting | 10-15 business days (realistically up to 2-3 weeks) |
Gotchas
Silent Error Swallowing
refreshRegistrationState() silently ignores fetch errors (assumes resource may have been deleted). If a Twilio API call fails, the old status is preserved. You won't know the refresh partially failed.
Solution: Wrap in try/catch if you need to detect failures.
Poll Timeouts Don't Throw
pollBrandUntil() and pollCampaignUntil() do NOT throw on timeout. They return the last-fetched status.
Solution: Always check the returned status:
const brand = await client.pollBrandUntil(brandSid, 'APPROVED');
if (brand.status !== 'APPROVED') {
console.warn('Brand not approved yet:', brand.status);
}Campaign Vetting Takes 10-15 Days
Despite the 30-minute default poll timeout, campaign vetting realistically takes 10-15 business days (up to 2-3 weeks). Use webhooks for campaign status updates.