Skip to content

TikTok Marketing API — Overview

The TikTok Marketing API gives programmatic access to the advertising accounts of Nova Play, a mobile game studio that runs user-acquisition campaigns for 10 games. Each game has its own advertiser account (one account per game and OS), and every account contains campaigns, ad groups and ads whose daily performance you can download through the Reporting endpoint.

This documentation covers everything you need to pull daily ad performance:

Section What it covers
Authentication How to send your access token
Advertiser List the advertiser accounts your token can access
Campaign Campaign metadata, naming convention, statuses
Ad Group Targeting (locations, OS, audience), optimization goal, app id
Ad Creatives (video / image / playable)
Reporting /report/integrated/get/ — daily metrics at advertiser, campaign, ad group or ad level
Tools Resolve numeric location_ids to countries and app_id to store packages
Errors & rate limits Error codes, the 60 requests/minute limit, retry rules

Base URL

https://business-api.huydata.com/open_api/v1.3

All endpoints are GET requests. Every path ends with a trailing slash (/campaign/get/, not /campaign/get). A request without the trailing slash receives an HTTP 307 redirect to the slashed path; most clients follow it, but curl does not unless you pass -L, so always write the slash.

Request format

  • Parameters are sent as query string parameters, even for the Reporting endpoint.
  • Parameters whose value is a list or an object (advertiser_ids, fields, dimensions, metrics, filtering) are sent as JSON-encoded strings. For example dimensions=["ad_id","stat_time_day","country_code"]. Because the value contains quotes, brackets and commas, it must be URL-encoded. With curl, use -G together with --data-urlencode and let curl do the encoding for you.
  • The access token is sent in the Access-Token HTTP header (see Authentication).
  • Dates use the YYYY-MM-DD format and the account time zone, which is UTC for every Nova Play account.

Response envelope

Every endpoint returns an HTTP 200 with the same JSON envelope:

{
  "code": 0,
  "message": "OK",
  "request_id": "6e596d719a0141599ce7",
  "data": { ... }
}
Field Type Description
code integer 0 means success. Any other value is an error; see Errors & rate limits.
message string "OK" on success, otherwise a human-readable error description.
request_id string Unique id of the request. Also returned in the x-request-id response header. Quote it when you report a problem.
data object The payload. Empty object {} on error.

Important: errors are returned with HTTP status 200 and code != 0. Checking the HTTP status is not enough; your client must read code from the JSON body on every call. The only cases with a different HTTP status are an unknown route (HTTP 404) and a non-GET method (HTTP 405); both still return the envelope with code 40000.

List endpoints return their rows in data.list together with a data.page_info object:

"page_info": {"page": 1, "page_size": 10, "total_number": 48, "total_page": 5}

page starts at 1, page_size defaults to 10 and may be at most 1000. Keep requesting page + 1 until page >= total_page.

Data freshness

  • Report dates are daily, in UTC. A report date D becomes available at 00:10 UTC on D + 1. Requests that include today's date return no rows for it (no error).
  • Spend, impressions and clicks are final when a date becomes available.
  • Conversions and purchases keep growing for 3 days after the report date (the attribution window). The values for the last three available report dates will still change on the next day; re-pull them. See Reporting → Data freshness.
  • The earliest report date in this account is 2026-06-30.

Quickstart

The three calls below are enough to get yesterday's spend per ad for one game. Export your token first:

export TIKTOK_ACCESS_TOKEN="<your personal token>"
export BASE="https://business-api.huydata.com/open_api/v1.3"

1. Find your advertiser accounts

curl -s "$BASE/oauth2/advertiser/get/" -H "Access-Token: $TIKTOK_ACCESS_TOKEN"
{
  "code": 0,
  "message": "OK",
  "request_id": "6e596d719a0141599ce7",
  "data": {
    "list": [
      {"advertiser_id": "7643153585721644371", "advertiser_name": "Dragon Merge Saga (Android)"},
      {"advertiser_id": "7548458757843580535", "advertiser_name": "Idle Mining Empire (Android)"},
      {"advertiser_id": "7990946724050865085", "advertiser_name": "Zombie Siege Defense (Android)"},
      ...
    ]
  }
}

2. Pull ad-level performance for one day, split by country

curl -s -G "$BASE/report/integrated/get/" \
  -H "Access-Token: $TIKTOK_ACCESS_TOKEN" \
  --data-urlencode "advertiser_id=7643153585721644371" \
  --data-urlencode "report_type=BASIC" \
  --data-urlencode "data_level=AUCTION_AD" \
  --data-urlencode 'dimensions=["ad_id","stat_time_day","country_code"]' \
  --data-urlencode 'metrics=["campaign_id","campaign_name","adgroup_id","adgroup_name","ad_name","spend","impressions","clicks","conversion","purchase","total_purchase_value"]' \
  --data-urlencode "start_date=2026-10-29" \
  --data-urlencode "end_date=2026-10-29" \
  --data-urlencode "page_size=1000"
{
  "code": 0,
  "message": "OK",
  "request_id": "713e0b341c244abc9d7c",
  "data": {
    "list": [
      {
        "dimensions": {"ad_id": "1808121195245644392", "stat_time_day": "2026-10-29 00:00:00", "country_code": "JP"},
        "metrics": {
          "campaign_id": "1871286220402645533",
          "campaign_name": "DMS_TT_AND_EA_INSTALL_202602",
          "adgroup_id": "1836683088316451285",
          "adgroup_name": "EA_Interest_Gaming_JP-KR",
          "ad_name": "PLAY_Meme_v2",
          "spend": "20.42",
          "impressions": "2646",
          "clicks": "19",
          "conversion": "2",
          "purchase": "0",
          "total_purchase_value": "0.00"
        }
      },
      ...
    ],
    "page_info": {"page": 1, "page_size": 1000, "total_number": 64, "total_page": 1}
  }
}

Note that every metric value is a string, including the numeric ones, and stat_time_day is returned as "YYYY-MM-DD 00:00:00".

3. Check code, then page

If code is not 0, stop and read message. If page_info.total_page is greater than page, repeat the call with page=2, page=3, ... See Reporting for a paging example.

Entity hierarchy

Advertiser (one per game, e.g. "Dragon Merge Saga (Android)")
└── Campaign   DMS_TT_AND_EA_INSTALL_202602      objective, daily budget, status
    └── Ad group   EA_Broad_JP-KR-TW             targeting: location_ids, OS, audience, optimization goal
        └── Ad     VID_Tutorial_v1               the creative: video, image or playable

All ids (advertiser_id, campaign_id, adgroup_id, ad_id, app_id, location_id) are numeric but are returned as strings. Keep them as strings; several of them exceed the 53-bit range that is safe for floating-point numbers.