๐ข Brand Status Check (A2P)
๐ Overviewโ
The Brand Status Check job monitors Twilio Application-to-Person (A2P) brand registrations and automatically provisions messaging infrastructure when brands are verified. It runs every minute, identifies accounts with pending or recently approved brands (both sole proprietor and low volume standard types), checks brand verification status with Twilio, and automatically creates messaging services and campaigns for verified brands. This ensures SMS sending compliance with 10DLC (10-Digit Long Code) regulations.
Complete Flow:
- Cron Initialization:
queue-manager/crons/communication/a2p/brand.js - Service Processing:
queue-manager/services/communication/a2p.js(brandStatusCheck) - Queue Definition:
queue-manager/queues/communication/a2p/brand.js
Execution Pattern: Frequent polling (every minute) with account-level queuing
Queue Name: comm_a2p_brandCheck
Environment Flag: QM_COMMUNICATION_A2P_BRAND=true (in index.js)
๐ Complete Processing Flowโ
sequenceDiagram
participant CRON as Cron Schedule<br/>(every 1 min)
participant SERVICE as Brand Status<br/>Service
participant ACCOUNT_DB as Accounts DB
participant QUEUE as Brand Check<br/>Queue
participant TWILIO as Twilio A2P API
CRON->>SERVICE: brandStatusCheck()
SERVICE->>ACCOUNT_DB: Aggregate accounts where:<br/>- Brand status = PENDING OR<br/>- Brand APPROVED + identity UNVERIFIED OR<br/>- Brand APPROVED + VERIFIED + no campaign
ACCOUNT_DB-->>SERVICE: List of accounts
loop Each account
SERVICE->>QUEUE: Add job: {account}
end
loop Each queued account
QUEUE->>QUEUE: Determine brand type:<br/>- sole_proprietor_brand<br/>- low_volume_standard_brand
QUEUE->>TWILIO: GET /BrandRegistrations/{sid}<br/>Fetch brand status
TWILIO-->>QUEUE: Brand details:<br/>status, identityStatus
QUEUE->>ACCOUNT_DB: Update account:<br/>twilio_account.a2p.{type} = brand
alt Brand APPROVED + VERIFIED
alt Messaging service not exists
QUEUE->>TWILIO: POST /Services<br/>Create messaging service
TWILIO-->>QUEUE: Service SID
QUEUE->>ACCOUNT_DB: Store service SID
end
QUEUE->>QUEUE: Build campaign payload:<br/>- Use case description<br/>- Message flow/consent<br/>- Sample messages<br/>- Opt-in/out keywords (standard only)
QUEUE->>TWILIO: POST /Services/{sid}/UsAppToPerson<br/>Create messaging campaign
TWILIO-->>QUEUE: Campaign SID + status
QUEUE->>ACCOUNT_DB: Store campaign data:<br/>- campaignSid<br/>- campaignStatus (IN_PROGRESS)
else Brand not verified
QUEUE->>QUEUE: Skip campaign creation<br/>(wait for next check)
end
end
๐ Source Filesโ
1. Cron Initializationโ
File: queue-manager/crons/communication/a2p/brand.js
Purpose: Schedule brand status check every minute
Cron Pattern: * * * * * (every minute)
Initialization:
const { brandStatusCheck } = require('../../../services/communication/a2p');
const cron = require('node-cron');
const logger = require('../../../utilities/logger');
let inProgress = false;
exports.start = async () => {
try {
cron.schedule('* * * * *', async () => {
if (!inProgress) {
inProgress = true;
await brandStatusCheck();
inProgress = false;
}
});
} catch (err) {
logger.error({ initiator: 'QM/communication/a2p/brand-status', error: err });
}
};
In-Progress Lock: Prevents overlapping executions.
2. Service Processingโ
File: queue-manager/services/communication/a2p.js (brandStatusCheck export)
Purpose: Find accounts with pending/approved brands and queue for verification
Key Features:
- Complex aggregation matching multiple brand states
- Supports both sole proprietor and low volume standard brands
- Batch job queuing with exponential backoff retry
- Promise.all for parallel queuing
Main Service Function:
const brandStatusCheck = require('../../queues/communication/a2p/brand');
const Account = require('../../models/account');
const logger = require('../../utilities/logger');
exports.brandStatusCheck = async () => {
try {
let accounts = await Account.aggregate([
{
$match: {
$or: [
{
$or: [
{ 'twilio_account.a2p.sole_proprietor_brand.status': 'PENDING' },
{
'twilio_account.a2p.sole_proprietor_brand.status': 'APPROVED',
'twilio_account.a2p.sole_proprietor_brand.identityStatus': 'UNVERIFIED',
},
{
'twilio_account.a2p.sole_proprietor_brand.status': 'APPROVED',
'twilio_account.a2p.sole_proprietor_brand.identityStatus': 'VERIFIED',
'twilio_account.a2p.messaging_service': { $exists: 0 },
'twilio_account.a2p.messaging_campaign': { $exists: 0 },
},
{
'twilio_account.a2p.sole_proprietor_brand.status': 'APPROVED',
'twilio_account.a2p.sole_proprietor_brand.identityStatus': 'VERIFIED',
'twilio_account.a2p.messaging_service': { $exists: 1 },
'twilio_account.a2p.messaging_campaign': { $exists: 0 },
},
],
},
{
$or: [
{ 'twilio_account.a2p.low_volume_standard_brand.status': 'PENDING' },
{
'twilio_account.a2p.low_volume_standard_brand.status': 'APPROVED',
'twilio_account.a2p.low_volume_standard_brand.identityStatus': 'UNVERIFIED',
},
{
'twilio_account.a2p.low_volume_standard_brand.status': 'APPROVED',
'twilio_account.a2p.low_volume_standard_brand.identityStatus': 'VERIFIED',
'twilio_account.a2p.messaging_service': { $exists: 0 },
'twilio_account.a2p.messaging_campaign': { $exists: 0 },
},
{
'twilio_account.a2p.low_volume_standard_brand.status': 'APPROVED',
'twilio_account.a2p.low_volume_standard_brand.identityStatus': 'VERIFIED',
'twilio_account.a2p.messaging_service': { $exists: 1 },
'twilio_account.a2p.messaging_campaign': { $exists: 0 },
},
],
},
],
},
},
{
$project: {
twilio_account: 1,
},
},
]);
if (accounts.length) {
let queue = await brandStatusCheck.start();
await Promise.all(
accounts.map(async a => {
try {
await queue.add(
{
account: a,
},
{
attempts: 5,
backoff: {
type: 'exponential',
delay: 60000,
},
removeOnComplete: true,
},
);
} catch (err) {
logger.error({ initiator: 'QM/communication/a2p/brand-status/add-queue', error: err });
}
}),
);
}
} catch (err) {
logger.error({ initiator: 'QM/communication/a2p/brand-status/service', error: err });
}
};
Query Breakdown:
Matches 4 scenarios per brand type:
- Pending: Brand registration submitted, awaiting Twilio review
- Approved but Unverified: Brand approved but identity not verified
- Verified, No Infrastructure: Brand verified but messaging service/campaign not created
- Service Created, No Campaign: Messaging service exists but campaign missing
3. Queue Processing (THE BRAND VERIFICATION LOGIC)โ
File: queue-manager/queues/communication/a2p/brand.js
Purpose: Check brand status and automatically create messaging infrastructure
Key Functions:
- Determine brand type (sole proprietor vs low volume standard)
- Fetch latest brand status from Twilio
- Create messaging service for verified brands
- Create messaging campaign with compliance metadata
- Handle different requirements for sole proprietor vs standard brands
Complete Processor:
const mongoose = require('mongoose');
const QueueWrapper = require('../../../common/queue-wrapper');
const logger = require('../../../utilities/logger');
const a2p = require('../twilio/services/a2p');
const processCb = async (job, done) => {
try {
const { account } = job.data;
const metadata = {
type: account.twilio_account.a2p.sole_proprietor_brand
? 'sole_proprietor_brand'
: 'low_volume_standard_brand',
twilio_creds: {
sid: account.twilio_account?.sid,
token: account.twilio_account?.authToken,
},
};
// Fetch latest brand status from Twilio
const brand = await a2p.getBrandStatus(
metadata,
account.twilio_account.a2p.sole_proprietor_brand?.sid ||
account.twilio_account.a2p.low_volume_standard_brand?.sid,
);
if (brand.status == 'APPROVED' && brand.identityStatus == 'VERIFIED') {
/**
* START: Create messaging service
*/
let service = account.twilio_account.a2p.messaging_service;
if (!service) {
service = await a2p.createMessagingService(metadata, {
friendlyName: `${account.twilio_account.a2p.submission_data.business.name} A2P Messaging Service`,
useInboundWebhookOnNumber: true,
});
}
/**
* END: Create messaging service
*/
/**
* START: Create messaging campaign
*/
const campaignBody = {
description: account.twilio_account.a2p.submission_data.campaign.use_case_description,
messageFlow: account.twilio_account.a2p.submission_data.campaign.end_user.consent,
messageSamples: account.twilio_account.a2p.submission_data.campaign.sample_messages,
usAppToPersonUsecase:
metadata.type == 'sole_proprietor_brand'
? 'SOLE_PROPRIETOR'
: account.twilio_account.a2p.submission_data.campaign.use_case,
hasEmbeddedLinks:
account.twilio_account.a2p.submission_data.campaign.messages_include_links,
hasEmbeddedPhone:
account.twilio_account.a2p.submission_data.campaign.messages_include_phone_numbers,
brandRegistrationSid: account.twilio_account.a2p[metadata.type].sid,
};
if (metadata.type == 'low_volume_standard_brand') {
campaignBody.optInKeywords =
account.twilio_account.a2p.submission_data.campaign.end_user.optin_keywords
.split(' ')
?.map(s => s.replace(/[^a-zA-Z0-9]/g, ''));
campaignBody.optInMessage =
account.twilio_account.a2p.submission_data.campaign.end_user.optin_message;
}
const campaign = await a2p.createMessagingCampaign(metadata, service.sid, campaignBody);
/**
* END: Create messaging campaign
*/
}
return done();
} catch (err) {
done(err);
}
};
const completedCb = async job => {};
let queue;
exports.start = async () => {
try {
if (!queue) queue = QueueWrapper(`comm_a2p_brandCheck`, 'global', { processCb, completedCb });
return Promise.resolve(queue);
} catch (err) {
logger.error({
initiator: 'QM/communication/a2p/brand-check/queue',
error: err,
message: `Error while starting queue`,
});
}
};
4. Twilio A2P Service Utilitiesโ
File: queue-manager/queues/communication/twilio/services/a2p.js
Purpose: Wrapper functions for Twilio A2P API calls with database updates
Key Functions:
- getBrandStatus: Fetch brand registration status
- createMessagingService: Create messaging service for sending SMS
- createMessagingCampaign: Create A2P campaign linked to brand
- deleteMessagingCampaign: Remove campaign and A2P data
Example Functions:
const getBrandStatus = async (metadata, id) => {
const client = Twilio(metadata.twilio_creds.sid, metadata.twilio_creds.token);
const brand = await client.messaging.v1.brandRegistrations(id).fetch();
await Account.findOneAndUpdate(
{
'twilio_account.sid': metadata.twilio_creds.sid,
},
{
$set: {
[`twilio_account.a2p.${metadata.type}`]: JSON.parse(JSON.stringify(brand)),
},
},
);
return brand;
};
const createMessagingService = async (metadata, data) => {
const client = Twilio(metadata.twilio_creds.sid, metadata.twilio_creds.token);
const service = await client.messaging.v1.services.create(data);
await Account.findOneAndUpdate(
{
'twilio_account.sid': metadata.twilio_creds.sid,
},
{
$set: {
'twilio_account.a2p.messaging_service': JSON.parse(JSON.stringify(service)),
},
},
);
return service;
};
const createMessagingCampaign = async (metadata, service, data) => {
const client = Twilio(metadata.twilio_creds.sid, metadata.twilio_creds.token);
const campaign = await client.messaging.v1.services(service).usAppToPerson.create(data);
await Account.findOneAndUpdate(
{
'twilio_account.sid': metadata.twilio_creds.sid,
},
{
$set: {
'twilio_account.a2p.messaging_campaign': JSON.parse(JSON.stringify(campaign)),
},
},
);
return campaign;
};
๐๏ธ Collections Usedโ
_accountsโ
- Operations: Aggregate, Update
- Model:
shared/models/account.js - Usage Context: Store A2P brand registration and campaign data
Key Fields (twilio_account.a2p object):
sole_proprietor_brand: Object - sole proprietor brand datasid: Brand registration SIDstatus: 'PENDING' | 'APPROVED' | 'REJECTED'identityStatus: 'UNVERIFIED' | 'VERIFIED'
low_volume_standard_brand: Object - standard brand datasid: Brand registration SIDstatus: 'PENDING' | 'APPROVED' | 'REJECTED'identityStatus: 'UNVERIFIED' | 'VERIFIED'
messaging_service: Object - Twilio messaging servicesid: Service SIDfriendlyName: Display nameuseInboundWebhookOnNumber: Boolean
messaging_campaign: Object - A2P campaignsid: Campaign SIDcampaignStatus: 'IN_PROGRESS' | 'VERIFIED' | 'REJECTED'usAppToPersonUsecase: Use case type
submission_data: Object - Original submission databusiness: Business informationname: Business name
campaign: Campaign detailsuse_case: Use case typeuse_case_description: Descriptionmessages_include_links: Booleanmessages_include_phone_numbers: Booleansample_messages: Array of sample messagesend_user: Opt-in/out configurationconsent: Message flow descriptionoptin_keywords: Keywords for opt-inoptin_message: Opt-in confirmation message
๐ง Job Configurationโ
Cron Scheduleโ
'* * * * *'; // Every minute
Frequency: 60 times per hour
Rationale: Frequent checks ensure quick campaign provisioning after brand approval.
Queue Settingsโ
QueueWrapper(`comm_a2p_brandCheck`, 'global', {
processCb,
completedCb,
});
Queue Name: comm_a2p_brandCheck
Concurrency: Default (1)
Job Options:
{
attempts: 5,
backoff: {
type: "exponential",
delay: 60000 // Start with 60-second delay
},
removeOnComplete: true
}
Exponential Backoff: 60s, 120s, 240s, 480s, 960s (up to 16 minutes total)
๐ Processing Logic - Detailed Flowโ
1. Brand Type Determinationโ
Logic:
const metadata = {
type: account.twilio_account.a2p.sole_proprietor_brand
? 'sole_proprietor_brand'
: 'low_volume_standard_brand',
twilio_creds: {
sid: account.twilio_account?.sid,
token: account.twilio_account?.authToken,
},
};
Brand Types:
- Sole Proprietor: Individual/freelancer business (simplified requirements)
- Low Volume Standard: Standard business (< 6,000 SMS/day, requires opt-in keywords)
2. Brand Status Checkโ
Twilio API Call:
GET https://messaging.twilio.com/v1/BrandRegistrations/{sid}
Response Fields:
status: Brand approval statusidentityStatus: Identity verification statussid: Brand registration SID- Other brand metadata
Database Update:
await Account.findOneAndUpdate(
{ 'twilio_account.sid': metadata.twilio_creds.sid },
{
$set: {
'twilio_account.a2p.sole_proprietor_brand': brand,
// OR
'twilio_account.a2p.low_volume_standard_brand': brand,
},
},
);
3. Messaging Service Creationโ
Condition: Brand status == 'APPROVED' AND identityStatus == 'VERIFIED'
Twilio API Call:
POST https://messaging.twilio.com/v1/Services
{
"friendlyName": "Acme Corp A2P Messaging Service",
"useInboundWebhookOnNumber": true
}
Response:
sid: Service SID (used for campaign creation)friendlyName: Display name- Other service metadata
Database Update:
await Account.findOneAndUpdate(
{ 'twilio_account.sid': metadata.twilio_creds.sid },
{
$set: {
'twilio_account.a2p.messaging_service': service,
},
},
);
4. Messaging Campaign Creationโ
Campaign Body Construction:
Common Fields (both brand types):
{
description: "Campaign description",
messageFlow: "Consent/opt-in process description",
messageSamples: ["Sample message 1", "Sample message 2"],
usAppToPersonUsecase: "SOLE_PROPRIETOR" | "MIXED",
hasEmbeddedLinks: true,
hasEmbeddedPhone: false,
brandRegistrationSid: "BNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Additional Fields (low volume standard only):
{
optInKeywords: ["START", "YES", "SUBSCRIBE"],
optInMessage: "Reply START to subscribe to our messages"
}
Opt-In Keywords Processing:
account.twilio_account.a2p.submission_data.campaign.end_user.optin_keywords
.split(' ')
?.map(s => s.replace(/[^a-zA-Z0-9]/g, ''));
Example: "START YES subscribe" โ ["START", "YES", "subscribe"]
Twilio API Call:
POST https://messaging.twilio.com/v1/Services/{serviceSid}/UsAppToPerson
{
// Campaign body
}
Response:
sid: Campaign SIDcampaignStatus: 'IN_PROGRESS' (initial status)- Other campaign metadata
Database Update:
await Account.findOneAndUpdate(
{ 'twilio_account.sid': metadata.twilio_creds.sid },
{
$set: {
'twilio_account.a2p.messaging_campaign': campaign,
},
},
);
5. Use Case Mappingโ
Sole Proprietor:
- Always uses
'SOLE_PROPRIETOR'use case - Simplified compliance requirements
- No opt-in keywords required
Low Volume Standard:
- Uses submitted use case from
submission_data.campaign.use_case - Common values: 'MIXED', 'MARKETING', 'ACCOUNT_NOTIFICATIONS', etc.
- Requires opt-in keywords and message
๐จ Error Handlingโ
Common Error Scenariosโ
Brand Not Approvedโ
Scenario: Brand status is 'PENDING' or 'REJECTED'
Handling: Job completes without creating messaging infrastructure, retry on next cron run
Impact: Account continues polling until approved
Identity Not Verifiedโ
Scenario: Brand approved but identityStatus == 'UNVERIFIED'
Handling: Job completes without creating messaging infrastructure
Impact: Account waits for Twilio to complete identity verification
Messaging Service Creation Failureโ
Scenario: Twilio API error (rate limit, invalid credentials, etc.)
Handling: Error thrown, job retries with exponential backoff (5 attempts)
Impact: Messaging service not created, campaign creation skipped
Campaign Creation Failureโ
Scenario: Invalid campaign data, missing required fields, API error
Handling: Error thrown, job retries
Impact: Messaging service created but campaign missing (resolved on retry)
Missing Submission Dataโ
Scenario: submission_data field missing or incomplete
Handling: Error thrown, job fails after retries
Impact: Cannot create campaign (manual intervention required)
Failed Job Callbackโ
Note: No explicit failedCb defined - relies on default Bull error handling.
Completed Job Callbackโ
const completedCb = async job => {};
Action: No-op (empty function)
๐ Monitoring & Loggingโ
Success Loggingโ
Service Level:
- No explicit success logging
Queue Level:
- No explicit success logging
Error Loggingโ
Cron Level:
- Error in cron initialization
Service Level:
- Error aggregating accounts
- Error queuing individual accounts
Queue Level:
- Error starting queue
Performance Metricsโ
- Brand Status Check: 1-2 seconds (Twilio API call)
- Service Creation: 1-2 seconds (Twilio API call)
- Campaign Creation: 2-5 seconds (Twilio API call)
- Total Job Time: 5-10 seconds per account
๐ Integration Pointsโ
Triggers This Jobโ
- Cron Schedule: Every minute (no external triggers)
- Brand Approval: Twilio approves brand via external process
External Dependenciesโ
- Twilio A2P API: Brand registration, messaging services, campaigns
- Twilio Credentials: Stored in
twilio_account.sidandtwilio_account.authToken
Jobs That Depend On Thisโ
- Campaign Status Check: Monitors campaign approval
- Number Assignment: Assigns phone numbers to verified campaigns
Related Featuresโ
- A2P Registration Form: Internal API creates initial brand registration
- SMS Sending: Requires verified campaign for 10DLC compliance
โ ๏ธ Important Notesโ
Side Effectsโ
- โ ๏ธ Messaging Service Creation: Creates billable Twilio service
- โ ๏ธ Campaign Creation: Submits campaign for review (may take hours/days)
- โ ๏ธ Database Updates: Modifies
twilio_account.a2pobject
Performance Considerationsโ
- Sequential Processing: One account at a time prevents Twilio rate limiting
- Exponential Backoff: 60-second initial delay prevents rapid retries
- Job Cleanup:
removeOnCompleteprevents queue bloat
Business Logicโ
Why Every Minute?
- Brand approvals can happen any time
- Quick provisioning improves customer experience
- Campaigns can take days for approval, but service should be ready
Why Two Brand Types?
- Twilio differentiates sole proprietors (simpler process)
- Standard brands have more compliance requirements
- Different opt-in/out rules apply
Why Automatic Provisioning?
- Reduces manual work for brand-to-campaign setup
- Ensures compliance requirements met immediately
- Customers can start sending SMS as soon as approved
Why Exponential Backoff?
- Twilio API rate limits apply
- Temporary errors (network, API downtime) resolve quickly
- Persistent errors (bad data) don't spam logs
Maintenance Notesโ
- Brand Types: Two types hardcoded (sole_proprietor, low_volume_standard)
- Use Cases: Mapped from submission data (varies by type)
- Opt-In Keywords: Sanitized with regex
/[^a-zA-Z0-9]/g(alphanumeric only) - Service Naming: Uses business name from submission data
- Job Cleanup:
removeOnComplete: trueprevents indefinite retention
Code Quality Issuesโ
Issue 1: Brand SID Retrieval
account.twilio_account.a2p.sole_proprietor_brand?.sid ||
account.twilio_account.a2p.low_volume_standard_brand?.sid;
Issue: Uses fallback instead of metadata.type-based lookup.
Suggestion: Use consistent lookup:
account.twilio_account.a2p[metadata.type]?.sid;
Issue 2: JSON.parse(JSON.stringify())
JSON.parse(JSON.stringify(brand));
Issue: Used to convert Twilio SDK object to plain object, but inefficient.
Suggestion: Use object destructuring or Object.assign({}, brand).
Issue 3: No Validation of Submission Data
account.twilio_account.a2p.submission_data.campaign.use_case_description;
Issue: No null checks, could throw error if submission_data incomplete.
Suggestion: Add validation before API calls.
๐งช Testingโ
Manual Triggerโ
# Via API (if QM_HOOKS=true)
POST http://localhost:6002/api/trigger/communication/a2p/brand
Simulate Brand Approvalโ
const Account = require('./models/account');
// Set brand to APPROVED + VERIFIED (but no campaign)
await Account.findByIdAndUpdate(accountId, {
'twilio_account.a2p.sole_proprietor_brand': {
sid: 'BNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
status: 'APPROVED',
identityStatus: 'VERIFIED',
},
'twilio_account.a2p.submission_data': {
business: {
name: 'Acme Corp',
},
campaign: {
use_case_description: 'Customer notifications',
end_user: {
consent: 'Users opt-in via website',
},
sample_messages: ['Your order has shipped'],
messages_include_links: false,
messages_include_phone_numbers: false,
},
},
});
console.log('Brand approved, waiting for messaging service/campaign creation');
Verify Campaign Creationโ
// Wait for next cron run (up to 1 minute)
await new Promise(resolve => setTimeout(resolve, 65000));
// Check account for messaging infrastructure
const account = await Account.findById(accountId);
console.log('Messaging service created:', !!account.twilio_account.a2p.messaging_service);
console.log('Campaign created:', !!account.twilio_account.a2p.messaging_campaign);
console.log('Campaign status:', account.twilio_account.a2p.messaging_campaign?.campaignStatus);
Test Low Volume Standard Brandโ
// Set standard brand (requires opt-in keywords)
await Account.findByIdAndUpdate(accountId, {
'twilio_account.a2p.low_volume_standard_brand': {
sid: 'BNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
status: 'APPROVED',
identityStatus: 'VERIFIED',
},
'twilio_account.a2p.submission_data': {
business: {
name: 'Acme Corp',
},
campaign: {
use_case: 'MIXED',
use_case_description: 'Marketing and notifications',
end_user: {
consent: 'Users opt-in via website',
optin_keywords: 'START YES subscribe',
optin_message: 'Reply START to subscribe',
},
sample_messages: ['Special offer today!'],
messages_include_links: true,
messages_include_phone_numbers: false,
},
},
});
// Verify opt-in keywords sanitized
await new Promise(resolve => setTimeout(resolve, 65000));
const account = await Account.findById(accountId);
console.log('Opt-in keywords:', account.twilio_account.a2p.messaging_campaign?.optInKeywords);
// Expected: ["START", "YES", "subscribe"]
Monitor Queue Processingโ
# Watch logs during brand checking
tail -f logs/queue-manager.log | grep "a2p"
# Expected outputs (in Twilio service functions):
# (No explicit logging in current implementation)
Job Type: Scheduled with Account-Level Queuing
Execution Frequency: Every minute
Average Duration: 5-10 seconds per account
Status: Active