> For the complete documentation index, see [llms.txt](https://docs.tnid.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tnid.com/10dlc/campaigns.md).

# 10DLC Campaigns

Create, submit, update and monitor 10DLC campaigns through TNID, including submitting a campaign automatically once its brand is verified.

A campaign registers a messaging use case (marketing, customer care, 2FA and so on) under an `ACTIVE` [brand](/10dlc/brands.md). Numbers are attached to campaigns; carriers use the campaign to decide throughput and filtering.

{% hint style="info" %}
All 10DLC operations are on the `/company` GraphQL server with a company token. Every operation is documented with request, variables and response in the [API Reference](https://docs.tnid.com/api-reference/002_company/002_ten_dlc).
{% endhint %}

## Campaign lifecycle

| Status                 | Meaning                                                                   |
| ---------------------- | ------------------------------------------------------------------------- |
| `DRAFT`                | Saved in TNID, not sent to TCR.                                           |
| `PENDING`              | Submitted to TCR (or waiting for the brand to become `ACTIVE`).           |
| `ACTIVE`               | Approved. Numbers can be assigned.                                        |
| `ERROR`                | Submission failed. Fix and resubmit with `updateAndSubmitTenDlcCampaign`. |
| `EXPIRED`, `SUSPENDED` | No longer usable for traffic.                                             |

These are campaign statuses. Brand statuses are a different set (`PENDING_REVIEW` belongs to brands).

## Three ways to submit

| Mutation                                                                         | When to use it                                                                                                                       |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `registerAndSubmitTenDlcCampaign(input)`                                         | The brand is already `ACTIVE`. Creates the campaign and submits it to TCR immediately.                                               |
| `registerTenDlcCampaignWhenReady(input)`                                         | The brand is still under review. TNID stores the campaign as `PENDING` and submits it automatically when the brand becomes `ACTIVE`. |
| `saveTenDlcCampaignAsDraft(input)` then `updateTenDlcCampaignAsDraft(id, input)` | You want to build the campaign up over time before submitting.                                                                       |

```graphql
mutation ($input: TenDlcRegisterCampaignInput!) {
  registerAndSubmitTenDlcCampaign(input: $input) {
    campaignId
    brandId
    usecase
    status
    description
    messageFlow
    autoRenewal
  }
}
```

```json
{
  "input": {
    "tenDlcApiKeyId": "<id returned by addTenDlcApiKey>",
    "internalBrandId": "<TNID id of the brand, from tenDlcBrands.records.id>",
    "usecase": "MARKETING",
    "description": "Promotions and product launches for opted-in customers",
    "messageFlow": "Customers opt in by texting JOIN to our number or ticking the box at checkout. They receive up to 4 messages a month.",
    "sample1": "Acme: Summer sale starts today. Show this text in store for 10% off. Reply STOP to opt out, HELP for help.",
    "subscriberOptin": true,
    "subscriberOptout": true,
    "subscriberHelp": true,
    "termsAndConditions": true,
    "nnid": "<your NNID, if you have one>",
    "resellerId": "<CSP reseller id, if applicable>"
  }
}
```

`campaignId` (for example `CZDFL35`) is the TCR identifier. `updateAndSubmitTenDlcCampaign(id, input)` changes a submitted campaign and re-syncs it with TCR, which is also the path after an `ERROR`. `deleteTenDlcCampaign(id)` removes it.

## Monitor campaigns and their numbers

```graphql
query ($brandId: String, $status: TenDlcCampaignStatus, $usecase: String, $page: Int, $pageSize: Int) {
  tenDlcCampaigns(brandId: $brandId, status: $status, usecase: $usecase, page: $page, pageSize: $pageSize) {
    page
    totalRecords
    records {
      id
      campaignId
      brandId
      usecase
      status
      workflowStatus
      autoRenewal
      ownershipType
    }
  }
}
```

`tenDlcCampaign(id)` returns the full record (message flow, opt-in/opt-out/help settings, expiration and billing dates). `tenDlcCampaignWithTelephoneNumbers(id)` adds the numbers attached to the campaign with their carrier workflow statuses (`osrWorkflowStatus`, `tmobileWorkflowStatus`), which is the quickest way to see whether a number is cleared to send.

## Sending traffic

TNID registers the campaign. Sending messages on the registered numbers happens through your messaging provider; on TSG Global, assign the campaign to a number with the `campaign_id` field of the [SMS enablement endpoint](https://docs.tsgglobal.com/api-reference/phone-numbers/manage-number-for-sms-and-10dlc/enable-sms-10dlc-on-a-number).

## What to read next

* [10DLC Brands](/10dlc/brands.md): the brand must be `ACTIVE` first.
* Webhooks: get notified instead of polling.
* API Reference: [all 23 10DLC operations](https://docs.tnid.com/api-reference/002_company/002_ten_dlc).
