A2P SDK
Guides

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:

StepTimeline
Customer Profile reviewUp to 72 hours
Trust Product evaluationMinutes to hours
Brand review (non-Sole Prop)Minutes to 7+ business days
Sole Prop OTP verification24 hours (customer must verify)
Campaign vetting10-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.

Next Steps

On this page