> ## Documentation Index
> Fetch the complete documentation index at: https://docs.narrative.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing Your Trade Desk Taxonomy via the API

> Build, price, and maintain the taxonomy that third-party audiences are sold from at The Trade Desk, over the API

This guide shows you how to build, price, and maintain your taxonomy at The Trade Desk (TTD) over the API, with nobody signed in. The taxonomy is where third-party audiences are listed: each audience is an element in it, and the element sets who can buy the audience and at what price.

To attach data to an element and deliver it, see [Third-party delivery via the API](/guides/connector-apis/the-trade-desk/third-party-delivery-api). First-party delivery uses no taxonomy; see [First-party delivery via the API](/guides/connector-apis/the-trade-desk/first-party-delivery-api).

Before you start, complete the [prerequisites](/guides/connector-apis/the-trade-desk#prerequisites) and [set up API access](/guides/connector-apis/the-trade-desk#set-up-api-access).

## 1. Plan the tree

A taxonomy is a tree of [taxonomy elements](/reference/glossary#taxonomy-element). A folder (`buyable: false`) organizes. An audience (`buyable: true`) is what buyers purchase, and it carries the dataset and the [rate cards](/reference/glossary#rate-card).

```text theme={null}
SmartAudiences                      ← root folder, named for your brand
├── Auto Intenders                  ← audience, open to every buyer
├── Frequent Travelers              ← audience, open to every buyer
└── Custom Audiences                ← folder for one-to-one deals
    ├── Acme Q3 Retargeting         ← audience, priced for one advertiser
    └── Zenith Store Visitors       ← audience, priced for one partner
```

**Name the root for your audience product.** Create it even if you never plan to sell openly. It is the level everything else hangs from, and reshaping the top of the tree after audiences are live cannot be cleanly undone.

**Keep one-to-one deals under their own folder.** TTD suggests a folder such as `Custom Audiences` for audiences priced for a single advertiser or partner. It is a naming convention, not a special element type.

**Price every audience on the audience itself.** TTD stopped passing rates down from parent folders to new segments in March 2024, so each buyable element needs its own rate card.

## 2. Create the folders

One endpoint creates every element. `buyable` is what separates a folder from an audience.

```bash theme={null}
curl -X POST https://thetradedesk.narrativeconnectors.com/taxonomies/elements \
  -H "Authorization: Bearer $NIO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "SmartAudiences",
    "description": "Location intelligence audiences",
    "buyable": false,
    "parent_element_id": null,
    "datasets": [],
    "data_rates": []
  }'
```

Record the `element_id` that comes back. Child elements name it as `parent_element_id`. Then create `Custom Audiences` the same way, with `parent_element_id` set to the root's `element_id`.

| Field | Description |
| - | - |
| `display_name` | Required. Keep it under 50 characters so it reads well in TTD's interface, and avoid tabs and the characters `'`, `"`, and `^`. |
| `description` | Optional. Shown with the segment in TTD. |
| `buyable` | `false` for a folder, `true` for an audience. |
| `parent_element_id` | The parent folder's `element_id`. Omit it or send `null` for the root. |
| `datasets` | Narrative dataset IDs that feed the element. Empty for a folder. |
| `data_rates` | Rate cards. Empty for a folder. |

## 3. Create an audience

An audience is the same call with `buyable: true`, a parent, a dataset, and the rate cards that decide who can buy it and at what price.

```bash theme={null}
curl -X POST https://thetradedesk.narrativeconnectors.com/taxonomies/elements \
  -H "Authorization: Bearer $NIO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Acme Q3 Retargeting",
    "description": "Devices observed in target geofences, Q3",
    "parent_element_id": "<Custom Audiences element_id>",
    "buyable": true,
    "datasets": [12345],
    "data_rates": [
      {
        "type": "create_data_rate_advertiser",
        "advertiser_id": "<TTD advertiser id>",
        "rate_type": "hybrid",
        "cpm_rate": 2.50,
        "percent_of_media_cost_rate": 0.15
      }
    ]
  }'
```

The connector checks each dataset's schema against The Trade Desk when you attach it. To prepare a dataset, follow steps 1 through 5 of [Third-party delivery via the API](/guides/connector-apis/the-trade-desk/third-party-delivery-api).

### Who can buy it

Each entry in `data_rates` sets a price and who gets it:

| `type` | Who can buy | Also requires |
| - | - | - |
| `create_data_rate_system` | Every buyer in the marketplace | Nothing |
| `create_data_rate_partner` | One TTD partner and every advertiser beneath it | `partner_id` |
| `create_data_rate_advertiser` | One TTD advertiser | `advertiser_id` |

One element can carry several rates, and the most specific rate that applies to a buyer wins. To price one audience differently for different buyers, add one entry per advertiser or partner:

```json theme={null}
"data_rates": [
  { "type": "create_data_rate_advertiser", "advertiser_id": "<advertiser A>",
    "rate_type": "hybrid", "cpm_rate": 2.50, "percent_of_media_cost_rate": 0.15 },
  { "type": "create_data_rate_advertiser", "advertiser_id": "<advertiser B>",
    "rate_type": "hybrid", "cpm_rate": 4.00, "percent_of_media_cost_rate": 0.20 },
  { "type": "create_data_rate_partner", "partner_id": "<partner id>",
    "rate_type": "hybrid", "cpm_rate": 3.00, "percent_of_media_cost_rate": 0.18 }
]
```

Advertiser and partner IDs come from your TTD account representative, and they go straight onto the rate card. You do not register them with Narrative first.

### Setting the rate

Every rate carries both `cpm_rate` and `percent_of_media_cost_rate`, whatever its `rate_type`. `rate_type` is `cpm`, `percent_of_media_cost`, or `hybrid`, and TTD asks for `hybrid` on marketplace segments. A rate of `0.0` is valid if you provide the data at no cost.

A rate with a CPM below \$0.25 needs TTD's approval before it applies.

## 4. Revise before you synchronize

Elements you create are drafts, and nothing reaches The Trade Desk until you synchronize. Until then you can change anything with `PUT`. It replaces the whole element, so send every field:

```bash theme={null}
curl -X PUT https://thetradedesk.narrativeconnectors.com/taxonomies/elements/{element_id} \
  -H "Authorization: Bearer $NIO_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Acme Q3 Retargeting",
    "description": "Devices observed in target geofences, Q3",
    "parent_element_id": "<Custom Audiences element_id>",
    "buyable": true,
    "datasets": [12345],
    "data_rates": [
      { "type": "create_data_rate_advertiser", "advertiser_id": "<advertiser A>",
        "rate_type": "hybrid", "cpm_rate": 3.00, "percent_of_media_cost_rate": 0.18 },
      { "type": "create_data_rate_advertiser", "advertiser_id": "<advertiser B>",
        "rate_type": "hybrid", "cpm_rate": 4.00, "percent_of_media_cost_rate": 0.20 }
    ]
  }'
```

Once an element is `active`, its rates are fixed. A `PUT` that changes them is rejected with `data rates cannot be updated for active taxonomy element`, while one that sends the same rates again goes through. The display name, description, and datasets can still change, and a new name or description is sent on to TTD.

Put every buyer you expect on the element when you create it. Changing the price or the buyers of a live audience is not self-service: ask your Narrative relationship manager, who arranges it with The Trade Desk.

## 5. Synchronize

```bash theme={null}
curl -X POST https://thetradedesk.narrativeconnectors.com/taxonomies/synchronization-requests \
  -H "Authorization: Bearer $NIO_API_TOKEN"

# then poll
curl -s https://thetradedesk.narrativeconnectors.com/taxonomies/synchronization-requests \
  -H "Authorization: Bearer $NIO_API_TOKEN"
```

The request moves through `pending` and `in_progress` to `completed` or `failed`. Its `jobs` object counts the work in three parts: elements created in TTD (`create_taxonomy_elements`), rate batches (`create_data_rate_batches`), and delivery connections for attached datasets (`create_connections`). Failures carry per-element detail.

Two rules shape how you automate this:

* **Synchronization publishes every draft in your account**, not only the element you just changed. Create everything you want published, then synchronize once.
* **Only one synchronization runs at a time.** A second request while one is pending or in progress is rejected. A loop that creates one audience and synchronizes it breaks on its second pass, so batch your changes instead.

A request with no drafts to send is rejected with `Nothing to synchronize`, and one from a profile with no Brand ID is refused.

## 6. Wait for approval

```bash theme={null}
curl -s https://thetradedesk.narrativeconnectors.com/taxonomies \
  -H "Authorization: Bearer $NIO_API_TOKEN"
```

Each element reports two statuses, and an audience sells only once it is `active` and its `compliance_status` is `Approved`:

* `status` is the element's lifecycle in Narrative, from `draft` to `pending` to `active`.
* `compliance_status` is TTD's review, from `NotInQueue` to `Pending` to `Approved` or `Denied`.

See [Element status and approval](/reference/connectors/the-trade-desk#element-status-and-approval) for every value.

Narrative re-checks review status with TTD every 30 minutes, so a decision on their side can take up to half an hour to appear. Poll on that cadence, because anything faster tells you nothing new.

<Warning>
  Plan for lead time on your first taxonomy. Ask your Narrative relationship manager about turnaround for elements you add later, because that answer decides whether your integration must treat each new audience as pending for a while or only the first ones.
</Warning>

## 7. Maintain the taxonomy

**Add audiences** by repeating step 3, then synchronizing. Batch several new elements into one synchronization.

**Refresh who is in an audience** by writing to its dataset. The delivery connection keeps running, so you do not touch the element or its price. See [Keeping the audience current](/guides/connector-apis/the-trade-desk/third-party-delivery-api#keeping-the-audience-current).

**Watch the match rate.** Each element's `statistics` reports `received_ids_count`, the identifiers Narrative sent, and `active_ids_count`, the subset TTD matched. See [Confirm delivery](/guides/connector-apis/the-trade-desk/third-party-delivery-api#9-confirm-delivery).

**Create a new audience rather than reworking an old one** when the price changes, the schema changes, or it is a different audience for a different buyer. A live element's rates are fixed, so a new element is the only self-service way to price separately.

**Retiring a live audience is not self-service.** Contact your TTD Technical Account Manager and your Narrative relationship manager. Removing a custom segment from a named buyer requires 30 days' advance notice to that buyer.

<Warning>
  `DELETE /taxonomies/elements/{element_id}` archives the element and everything beneath it in Narrative only. Nothing is sent to The Trade Desk, and an element that is already live there stays buyable. Use it to clean up drafts, not to retire an audience.
</Warning>

## Taxonomy endpoints

All on `https://thetradedesk.narrativeconnectors.com`.

| Method | Path | Purpose |
| - | - | - |
| `GET` | `/whoami` | Confirm your key reaches the connector |
| `GET` | `/taxonomies` | The whole tree: elements, rate cards, statuses, and statistics |
| `POST` | `/taxonomies/elements` | Create a folder or an audience |
| `PUT` | `/taxonomies/elements/{element_id}` | Replace an element. Send the full object |
| `DELETE` | `/taxonomies/elements/{element_id}` | Archive an element and everything beneath it, in Narrative only |
| `POST` | `/taxonomies/synchronization-requests` | Publish every draft to TTD |
| `GET` | `/taxonomies/synchronization-requests` | Synchronization status |

## Troubleshooting

| Symptom | Cause | Fix |
| - | - | - |
| A second synchronization is rejected | Only one runs at a time | Wait for the running one to finish |
| `Nothing to synchronize` | No element, rate, or connection is in draft | Create or change something first |
| Synchronization refused for a missing brand ID | The connector profile has no Brand ID | Ask your Narrative relationship manager to add it |
| Elements went live that you were not ready to publish | Synchronization publishes every draft | Create only what you intend to publish, then synchronize |
| An audience has no price | It has no rate card of its own | Add a rate card to the element. Rates are not inherited from folders |
| `data rates cannot be updated for active taxonomy element` | The element is already live | Create a new element, or ask your Narrative relationship manager |
| An audience is active but not selling | `compliance_status` is not yet `Approved` | Poll `/taxonomies`. Review status refreshes every 30 minutes |
| A deleted element is still buyable in TTD | `DELETE` archives in Narrative only | Retire it through your TTD Technical Account Manager |

## Getting help

Contact your Narrative relationship manager with your company ID, the element ID, and the failing request and response. For review status, Brand ID, advertiser IDs, or partner IDs, your TTD account representative is the faster path.

***

## Related content

<CardGroup cols={2}>
  <Card title="Third-party delivery via the API" icon="store" href="/guides/connector-apis/the-trade-desk/third-party-delivery-api">
    Attach data to an element and deliver it
  </Card>

  <Card title="First-party delivery via the API" icon="user" href="/guides/connector-apis/the-trade-desk/first-party-delivery-api">
    Deliver into one advertiser's own seat, with no taxonomy
  </Card>

  <Card title="The Trade Desk Connector" icon="bullhorn" href="/reference/connectors/the-trade-desk">
    Full settings reference, identifiers, and status vocabularies
  </Card>

  <Card title="API Keys" icon="key" href="/account-settings/api-keys">
    Create and rotate keys for programmatic access
  </Card>
</CardGroup>
