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-key header.

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:

StatusMeaningWhat to do
SENT_CREATEDThe campaign exists in Sent but TCR has not approved it. Every campaign starts here.Wait for review and submission; see below.
ACTIVETCR approved the campaign. Your US SMS traffic is registered.Nothing; start sending.
EXPIREDTCR 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:

  1. 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.
  2. Submitted, awaiting TCR (submittedToTCR: true, tcrCampaignId set): TCR and the carriers are reviewing. Most submissions come back approved within 1 to 3 business days. When TCR reports a decision, Sent updates status automatically.

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.

ValueTypical traffic
MARKETINGPromotional offers, discounts, announcements
ACCOUNT_NOTIFICATIONPassword resets, balance alerts, appointment reminders
CUSTOMER_CARESupport conversations, ticket updates
FRAUD_ALERTSuspicious-activity notices
TWO_FAOne-time passcodes, login verification
DELIVERY_NOTIFICATIONOrder shipped, out for delivery
SECURITY_ALERTSecurity incident notifications
M2MMachine-to-machine traffic
MIXEDMultiple use cases under one campaign
HIGHER_EDUCATIONMessaging from colleges and universities
POLLING_VOTINGPolling and voting notifications
PUBLIC_SERVICE_ANNOUNCEMENTPublic service announcements
LOW_VOLUMEMixed 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:

  1. 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.
  2. Enumerate profiles with GET /v3/profiles and create one campaign per profile, as shown earlier, collecting the client's compliance details in your own onboarding form.
  3. Poll each profile's campaign list, or check it on demand, and surface status to the client until it reads ACTIVE.

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-id header 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 receive 403.

Use a distinct Idempotency-Key per profile (for example, derived from your client ID) so a retried batch never double-registers a client.

Troubleshooting

SymptomLikely causeFix
400 VALIDATION_001: "Cannot create campaigns when inherit_tcr_campaign=true" (or "These campaigns are read-only")The profile inherits the organization's campaignPATCH /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 missingInclude 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 organizationRegister 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 brandList the profile's campaigns and reuse the returned id
Campaign stays in SENT_CREATEDReview or TCR submission still pendingWork through the checks in Campaign Status Lifecycle

Error codes and remediation for the whole API are in the Error Catalog.

On this page