REST → GraphQL migration guide

This guide provides a complete, field-level mapping between every REST endpoint in the Platform API and its GraphQL equivalent. Whether migrating an existing REST integration or building new functionality, this guide documents exactly how each REST operation, field, and pattern translates to GraphQL.

For general guidelines, see also GraphQL API Resource Hub.

Who this guide is for

Audience What this guide covers
Partner engineers Migrate existing REST integrations to GraphQL.
New integrators Choose between REST and GraphQL for a given operation.
AI agents and code-generation tools Get structured mappings to translate REST code to GraphQL automatically.

How to use this guide

Each domain has a domain page (a summary of all endpoints and shared types) and an endpoint detail page per REST endpoint (the full field mapping and code examples).

The following table provides a list of example tasks you might have to perform.

Task Step
Understand the systematic differences To see the patterns that apply across all endpoints (field naming, pagination, error handling, and so on), read Systematic differences between REST and GraphQL.
Find the relevant domain To find the REST endpoints in use, navigate to the corresponding domain page (for example, Advertiser, Ad Group, or Campaign).
Get the field-level mapping To get field-by-field input/output mappings, multi-step operation notes, and before/after code examples, follow the endpoint detail links from each domain page.

Systematic differences between REST and GraphQL

The following patterns apply uniformly across the entire API surface. Understanding them enables applying mechanical transformations to any endpoint without consulting the per-field mapping tables.

Field name cases

REST uses PascalCase. GraphQL uses camelCase.

REST GraphQL
AdvertiserName advertiserName
IsEnabled isEnabled
AttributionClickLookbackWindowInSeconds attributionClickLookbackWindowInSeconds

Most fields follow this rule exactly. Exceptions (where the GraphQL field was renamed, not just re-cased, or where a REST *Id becomes a nested object such as REST CampaignId → campaign.id) are documented in each endpoint's field mapping table.

Identifiers

REST endpoints use int, long, or string identifiers depending on the domain (for example, AdvertiserId is a string, CategoryId is a long). GraphQL uses the ID scalar for all entity identifiers—always transmitted as a string in JSON, regardless of the underlying storage type.

REST GraphQL
"AdvertiserId": "abc123" id: "abc123" (type ID!)
"CategoryId": 45 categoryId: 45 (type Long!)

Note that the GraphQL ID scalar is a string in transport. Numeric IDs that are typed as Long or Int in GraphQL remain numeric.

Single GraphQL endpoint

All GraphQL operations are sent to a single endpoint (POST https://GRAPHQL_ENDPOINT_URL_PLACEHOLDER/graphql). Include the same auth header used for REST:

POST /graphql HTTP/1.1
Content-Type: application/json
TTD-Auth: AUTH_TOKEN_PLACEHOLDER

Unlike REST, where each operation has its own URL path (/v3/advertiser, /v3/campaign, and so on), every GraphQL mutation and query is sent to the same URL. The operation is specified in the request body.

Pagination

See also GraphQL API response pagination in our GraphQL Hub.

REST uses offset-based pagination with PageStartIndex and PageSize. GraphQL uses cursor-based pagination.

Here's an example REST request:

{
  "PartnerId": "abc123",
  "PageStartIndex": 0,
  "PageSize": 25
}

Here's the equivalent GraphQL query:

POST /graphql HTTP/1.1
Content-Type: application/json
TTD-Auth: AUTH_TOKEN_PLACEHOLDER
query {
  advertisers(first: 25, after: null) {
    nodes {
      id
      name
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

To fetch the next page, pass the endCursor value from the previous response as the after argument:

POST /graphql HTTP/1.1
Content-Type: application/json
TTD-Auth: AUTH_TOKEN_PLACEHOLDER
query {
  advertisers(first: 25, after: "eyJpZCI6Mn0=") {
    nodes {
      id
      name
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Key differences:

Concept REST GraphQL
Page size PageSize first (forward) or last (backward)
Page position PageStartIndex (zero-based offset) after / before (opaque cursor)
Result count TotalFilteredCount in response totalCount on the connection
Items Result array nodes array (or edges with node and cursor)
Next page check Compare PageStartIndex + PageSize < TotalFilteredCount pageInfo.hasNextPage

Error handling

See also GraphQL API errors and complexity limits in our GraphQL Hub.

REST returns HTTP status codes (400, 401, 403, 404, 500) with a JSON error body. GraphQL always returns HTTP 200—errors are reported in the response payload.

Here's an example REST error response:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "Message": "Validation failed.",
  "ErrorDetails": [
    {
      "Property": "$.AdvertiserName",
      "Reasons": ["Advertiser name must not be empty."]
    }
  ]
}

In GraphQL, every mutation returns a payload with a data field and an errors field. When the mutation succeeds, data is populated and errors is empty. When it fails, data is null and errors contains one or more error objects with message and code:

POST /graphql HTTP/1.1
Content-Type: application/json
TTD-Auth: AUTH_TOKEN_PLACEHOLDER
mutation {
  advertiserCreate(input: { ... }) {
    data {
      id
      name
    }
    errors {
      message
      code
    }
  }
}

Here's an example success response:

{
  "data": {
    "advertiserCreate": {
      "data": { "id": "adv-123", "name": "Acme Corp" },
      "errors": []
    }
  }
}

Here's an example error response:

{
  "data": {
    "advertiserCreate": {
      "data": null,
      "errors": [
        {
          "message": "Advertiser name must not be empty.",
          "code": "VALIDATION_ERROR"
        }
      ]
    }
  }
}

Consult the GraphQL schema for the specific error types available on each mutation's errors field.

Timestamps

REST uses various DateTime string formats depending on the endpoint. GraphQL uses the DateTime scalar, which is always ISO 8601 format:

REST GraphQL
"2026-01-15T00:00:00" (varies) "2026-01-15T00:00:00Z" (ISO 8601, UTC)

Structural differences in response types

Some REST fields that are flat scalars or simple objects are represented differently in GraphQL responses. Here are the common patterns:

Pattern REST GraphQL
Country "Country": "US" (string) country { id shortName longName } (object)
Currency "CurrencyCode": "USD" (string) currency { id longName } (object)
Attribution windows "AttributionClickLookbackWindowInSeconds": 604800 (flat field) attribution { clickLookbackWindow clickInterval ... } (nested object)
Custom labels [{ "CustomLabelId": "lbl-1" }] (objects with IDs) customLabels: ["label-name"] (string names) on input; customLabels(first:) { nodes { ... } } (connection) on response

These per-field structural differences are documented in each endpoint's field mapping table. The patterns in this table are the most common ones encountered during migration.