Register 10DLC Campaigns via the API
This guide shows you how to register and track 10DLC campaigns programmatically with the /v3/profiles/{profileId}/campaigns endpoints. Use it when you manage US SMS registration for many brands at once, the typical setup for agencies and resellers, or when you want campaign submission wired into your own onboarding flow instead of the dashboard.
It assumes you already understand 10DLC and have a registered brand. If you are new to 10DLC, or you want the dashboard flow, start with the 10DLC Registration Guide. That guide also owns the content rules your campaign must satisfy: opt-in forms, autoresponses, and sample messages. This page covers only the API mechanics.
Prerequisites
- An organization with at least one Sender Profile. The
{profileId}in every campaign endpoint must be a profile that belongs to your organization. - A brand for the profile, either registered for the profile itself or inherited from the organization. Without one, campaign requests return
404 RESOURCE_009("Brand not found for this profile"). - Your organization API key, passed in the
x-api-keyheader.
Register a Campaign
Give the Profile Its Own Campaign
A profile whose TCR campaign is inherited from the organization (inherit_tcr_campaign: true) has read-only campaigns; create and update requests return 400 VALIDATION_001. To register a dedicated campaign for the profile, turn inheritance off first:
curl -X PATCH "https://api.sent.dm/v3/profiles/$PROFILE_ID" \
-H "x-api-key: $SENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inherit_tcr_campaign": false}'The brand can stay inherited: when inherit_tcr_brand is true, the campaign you create attaches to the organization's brand. This partial inheritance (shared brand, dedicated campaign) is a supported sender profile TCR pattern.
Create the Campaign
Send POST /v3/profiles/{profileId}/campaigns with at least one use case. Each use case carries 1 to 5 sample messages of up to 1,024 characters each.
curl -X POST "https://api.sent.dm/v3/profiles/$PROFILE_ID/campaigns" \
-H "x-api-key: $SENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 10dlc-reg-$PROFILE_ID" \
-d '{
"campaign": {
"name": "Customer Notifications",
"description": "Appointment reminders and account notifications",
"type": "App",
"useCases": [
{
"messagingUseCaseUs": "ACCOUNT_NOTIFICATION",
"sampleMessages": [
"Hi {name}, your appointment is confirmed for {date} at {time}.",
"Your order #{order_id} has been shipped. Track at {url}"
]
}
],
"messageFlow": "User signs up on website and opts in to receive SMS notifications",
"privacyPolicyLink": "https://acmecorp.com/privacy",
"termsAndConditionsLink": "https://acmecorp.com/terms",
"optinMessage": "You have opted in to Acme Corp notifications. Reply STOP to opt out.",
"optoutMessage": "You have been unsubscribed. Reply START to opt back in.",
"helpMessage": "Reply STOP to unsubscribe or contact support@acmecorp.com",
"optinKeywords": "YES, START, SUBSCRIBE",
"optoutKeywords": "STOP, UNSUBSCRIBE, END",
"helpKeywords": "HELP, INFO, SUPPORT"
}
}'name, description, type, and useCases are always required. When the brand is a TCR application, the compliance fields are required too: messageFlow, privacyPolicyLink, termsAndConditionsLink, all three autoresponse messages, and all three keyword lists. Requests missing any of them return 400 VALIDATION_001 naming the missing field. Write these values to pass carrier review, not just validation; the opt-in form requirements and autoresponse requirements list what reviewers reject.
The Idempotency-Key header makes retries safe: the API caches the response for 24 hours per key per customer, so a retried request cannot create a duplicate campaign. Refer to Idempotency for key rules.
To validate a payload without registering anything, add "sandbox": true next to "campaign" in the request body. The API runs authentication and validation, then returns a simulated 201 with no side effects. See Sandbox Mode.
Verify the Campaign Was Created
A successful create returns 201 with the campaign in data. Every new campaign starts in SENT_CREATED status with submittedToTCR: false:
{
"success": true,
"data": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Customer Notifications",
"brandId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "SENT_CREATED",
"submittedToTCR": false,
"tcrCampaignId": null,
"useCases": [
{
"messagingUseCaseUs": "ACCOUNT_NOTIFICATION",
"sampleMessages": ["..."]
}
]
}
}(Response abbreviated.) Store data.id; you need it to update or delete the campaign later.
To confirm the campaign from another process, list the profile's campaigns:
curl "https://api.sent.dm/v3/profiles/$PROFILE_ID/campaigns" \
-H "x-api-key: $SENT_API_KEY"For a profile with inherit_tcr_campaign: true, this returns the organization's inherited campaigns instead.
Campaign Status Lifecycle
Poll GET /v3/profiles/{profileId}/campaigns and read the status field to track each campaign:
| Status | Meaning | What to do |
|---|---|---|
SENT_CREATED | The campaign exists in Sent but TCR has not approved it. Every campaign starts here. | Wait for review and submission; see below. |
ACTIVE | TCR approved the campaign. Your US SMS traffic is registered. | Nothing; start sending. |
EXPIRED | TCR deactivated the campaign. Sent releases the campaign's dedicated number back to the pool. | Register a new campaign, or contact support@sent.dm to investigate. |
While the Campaign Is in SENT_CREATED
SENT_CREATED covers two waiting stages, distinguishable by submittedToTCR:
- Not yet submitted (
submittedToTCR: false): the Sent compliance team reviews your campaign content before submitting it to TCR on your behalf, the same review flow as dashboard submissions. - Submitted, awaiting TCR (
submittedToTCR: true,tcrCampaignIdset): TCR and the carriers are reviewing. Most submissions come back approved within 1 to 3 business days. When TCR reports a decision, Sent updatesstatusautomatically.
If a campaign sits in SENT_CREATED well past that window:
- Confirm every compliance field is filled in and meets the opt-in form requirements; incomplete content stalls review.
- Confirm the brand itself finished verification; campaigns cannot be approved under an unverified brand.
- Contact support@sent.dm with the campaign
id. If TCR rejected the campaign, the compliance team tells you exactly what to fix before resubmission.
US Messaging Use Case Values
messagingUseCaseUs accepts one of 13 values. Pick what matches your actual traffic; carriers flag mismatches between the registered use case and the messages you send. The campaign type guidance explains how to choose.
| Value | Typical traffic |
|---|---|
MARKETING | Promotional offers, discounts, announcements |
ACCOUNT_NOTIFICATION | Password resets, balance alerts, appointment reminders |
CUSTOMER_CARE | Support conversations, ticket updates |
FRAUD_ALERT | Suspicious-activity notices |
TWO_FA | One-time passcodes, login verification |
DELIVERY_NOTIFICATION | Order shipped, out for delivery |
SECURITY_ALERT | Security incident notifications |
M2M | Machine-to-machine traffic |
MIXED | Multiple use cases under one campaign |
HIGHER_EDUCATION | Messaging from colleges and universities |
POLLING_VOTING | Polling and voting notifications |
PUBLIC_SERVICE_ANNOUNCEMENT | Public service announcements |
LOW_VOLUME | Mixed use cases, capped at 2,000 messages per day |
Update or Delete a Campaign
To fix campaign content, for example after a rejection or to refresh sample messages, send the full campaign object to PUT /v3/profiles/{profileId}/campaigns/{campaignId}. The required fields match create: name, description, type, and useCases. The use cases you send replace the existing list; optional fields you omit keep their current values.
curl -X PUT "https://api.sent.dm/v3/profiles/$PROFILE_ID/campaigns/$CAMPAIGN_ID" \
-H "x-api-key: $SENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign": {
"name": "Customer Notifications",
"description": "Appointment reminders and account notifications",
"type": "App",
"useCases": [
{
"messagingUseCaseUs": "ACCOUNT_NOTIFICATION",
"sampleMessages": [
"Acme Corp: Your appointment is confirmed for {date} at {time}."
]
}
]
}
}'If the campaign was already submitted to TCR, Sent syncs the update to TCR. Check tcrSyncError in the response: null means the sync succeeded; otherwise it holds the TCR error message and the change is saved in Sent only.
To remove a campaign, send DELETE /v3/profiles/{profileId}/campaigns/{campaignId}. A successful delete returns 204 with no body.
Deleting a campaign is permanent. To change a campaign's content, update it instead of deleting and recreating it, so you keep its review progress.
Bulk Registration for Agencies and Resellers
TCR ties each campaign to the business responsible for the messages, so every client needs its own registration; you cannot bundle clients under one campaign. The API pattern:
- Map each client to a Sender Profile with a dedicated TCR campaign (and a dedicated or inherited brand, per client). The multi-tenant patterns page compares the options.
- Enumerate profiles with
GET /v3/profilesand create one campaign per profile, as shown earlier, collecting the client's compliance details in your own onboarding form. - Poll each profile's campaign list, or check it on demand, and surface
statusto the client until it readsACTIVE.
Two scoping notes for organization keys:
- The campaign endpoints take the profile ID in the URL path, so you do not need the
x-profile-idheader here. Your organization API key can address every profile in the organization directly. - Where you do use
x-profile-id(endpoints without a profile ID in the path, such as sending messages), only organization API keys may send it; profile-scoped keys receive403.
Use a distinct Idempotency-Key per profile (for example, derived from your client ID) so a retried batch never double-registers a client.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
400 VALIDATION_001: "Cannot create campaigns when inherit_tcr_campaign=true" (or "These campaigns are read-only") | The profile inherits the organization's campaign | PATCH /v3/profiles/{profileId} with {"inherit_tcr_campaign": false} |
400 VALIDATION_001: "MessageFlow is required for TCR applications" (or similar) | The brand is a TCR application and a compliance field is missing | Include messageFlow, both policy links, and all autoresponse messages and keywords |
404 RESOURCE_009: "Brand not found for this profile" | No brand is registered for the profile or its organization | Register the brand first; see the 10DLC Registration Guide |
404 RESOURCE_014: "Profile not found" | {profileId} is not a child profile of your organization (passing your organization's own ID also fails) | Use a profile ID returned by GET /v3/profiles |
404 RESOURCE_010: "Campaign not found for this profile" | {campaignId} does not belong to this profile's brand | List the profile's campaigns and reuse the returned id |
Campaign stays in SENT_CREATED | Review or TCR submission still pending | Work through the checks in Campaign Status Lifecycle |
Error codes and remediation for the whole API are in the Error Catalog.
Related Pages
- Endpoint reference: create campaign, list campaigns, update campaign, delete campaign
- 10DLC Registration Guide for the registration concepts, dashboard flow, and content requirements
- Sender Profiles for the inheritance model behind
inherit_tcr_brandandinherit_tcr_campaign - Idempotency and Sandbox Mode for safe retries and dry runs
10DLC Registration Guide
How to register your brand and messaging campaigns with TCR through the Sent dashboard, including the form inputs, opt-in rules, and autoresponses required
Compliance & Regulations
The compliance controls Sent enforces automatically at send time, what remains your responsibility, and per-region regulations with authoritative sources.