Skip to content
Browse documentation

API reference

Every REST API v1 endpoint — offers, events, creatives, partner access, affiliates, advertisers, reports, clicks, conversions, postbacks, tracking links, deals, product feeds and the Google Ads linter — with parameters, fields and examples.

Last updated 16 min read

On this page

Base URL https://app.trackcrown.com/api/v1. Every request needs Authorization: Bearer atk_… (Authentication & API keys). Conventions for money, times, IDs and date ranges are in the API overview; paging in Pagination; error codes in Rate limits & errors. The machine-readable description is https://app.trackcrown.com/api/v1/openapi.json (OpenAPI).

In the examples $ATK holds your key.

Account#

GET /me#

Who is calling: the key, its workspace, the partner/advertiser it belongs to, its permissions and the rate-limit state.

Shell
curl https://app.trackcrown.com/api/v1/me -H "Authorization: Bearer $ATK"
JSON
{
  "data": {
    "key": { "id": 7, "name": "BI export", "role": "analyst" },
    "workspace": { "id": 1, "slug": "demo", "name": "Demo Network", "timezone": "Asia/Kolkata", "currency": "USD" },
    "affiliate": null,
    "advertiser": null,
    "permissions": ["dashboard.read", "reports.read", "offers.read", "…"],
    "rate_limit": { "limit": 600, "remaining": 598, "reset_sec": 41 }
  }
}

Offers#

GET /offers#

ParameterDescription
statusComma-separated: active, paused, pending, archived.
visibilityComma-separated: public, approval, private.
advertiser_idStaff keys: offers of one advertiser.
accessPartner keys: approved, pending, rejected or none (never requested).
idsComma-separated offer ids.
qName contains / exact code.
limit, cursorPage size (default 50, max 200) and cursor.
Shell
curl "https://app.trackcrown.com/api/v1/offers?status=active&limit=2" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    {
      "id": 12,
      "code": "Kx7Lm2Q",
      "name": "Summer Sale — US",
      "status": "active",
      "visibility": "approval",
      "advertiser_id": 3,
      "category": "Retail",
      "description": "",
      "restrictions": "No incent traffic.",
      "preview_url": "https://shop.example.com/summer",
      "destination_url": "https://shop.example.com/summer?cid={click_id}&s1={sub1}",
      "fallback_url": "",
      "allowed_domains": [],
      "currency": "USD",
      "revenue_type": "rpa",
      "revenue": "7.0000",
      "payout_type": "cpa",
      "payout": "5.0000",
      "caps": { "conversions": { "daily": 100 } },
      "targeting": { "countries_allow": ["US"] },
      "conversion_method": "any",
      "unique_per_click": true,
      "attribution_days": 30,
      "default_status": "approved",
      "thumbnail_url": "",
      "tags": ["retail"],
      "is_featured": false,
      "events": [
        { "id": 40, "code": "default", "name": "Conversion", "revenue_type": "rpa", "revenue": "7.0000",
          "payout_type": "cpa", "payout": "5.0000", "is_default": true, "is_private": false, "allow_multiple": false }
      ],
      "created_at": "2026-10-01T09:30:00.000Z",
      "updated_at": "2026-10-08T14:02:11.000Z"
    }
  ],
  "next_cursor": null
}

What each role sees:

  • Partner keys get offers they can run or request — public and approval-required offers, plus private offers they are approved for — with payout_type/payout after their custom payout (CPC offers always show the offer's own per-click rate: custom payouts do not apply to click-priced offers), non-private events with their payouts, and three extra fields: access_status (approved, pending, rejected or null), can_run and tracking_link (their ready-to-use link while can_run is true). Revenue, advertiser, destination URL, fallback, caps and allowed domains are never included.
  • Advertiser keys get their own offers with revenue fields (their cost) and every event, but no payout.

GET /offers/{id}#

{id} is the numeric id or the offer code. Returns {"data": {…offer…}} in the same shape as the list.

POST /offers#

Admin keys. Creates the offer and its default event (with the offer's revenue and payout); events adds more events (goals). Omitted fields take the defaults shown.

FieldDefaultNotes
name—Required, max 200 characters.
destination_url—Required. Absolute http(s) URL; may contain macros like {click_id}.
codegenerated6-10 letters/digits used in tracking links; 409 conflict when taken.
advertiser_idnullAn advertiser of your workspace.
statusactiveactive, paused, pending, archived.
visibilityapprovalpublic (any active partner may run it), approval, private.
revenue_type, revenuerpa, "0"rpa per action, rps percent of sale amount (0-100), rpc per unique click, dynamic (from the postback).
payout_type, payoutcpa, "0"cpa per action, cps percent of sale amount (0-100), cpc per unique click.
currencyworkspace currencyISO-4217.
caps{}{"clicks":{"daily":5000},"conversions":{"daily":100,"total":1000},"payout":{"monthly":"2500.00"}} — calendar periods in the workspace time zone.
targeting{}{"countries_allow":["US"],"countries_deny":[],"devices":["mobile"],"os":["android"]}.
conversion_methodanyany, s2s, pixel.
unique_per_clicktrueOne conversion per click per event.
attribution_days301-365.
default_statusapprovedStatus of new conversions: approved or pending.
fallback_url, preview_url, thumbnail_url""Absolute URLs or empty.
allowed_domains[]Extra hosts allowed as transparent url= targets (example.com, *.example.com).
category, description, restrictions, tags, is_featuredempty
events[][{code, name, revenue_type, revenue, payout_type, payout, is_private, allow_multiple}]
Shell
curl -X POST https://app.trackcrown.com/api/v1/offers \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{
        "name": "Summer Sale — US",
        "destination_url": "https://shop.example.com/summer?cid={click_id}&s1={sub1}",
        "advertiser_id": 3,
        "revenue": "7.00",
        "payout": "5.00",
        "targeting": { "countries_allow": ["US"] },
        "events": [{ "code": "sale", "name": "Sale", "payout_type": "cps", "payout": "10", "revenue_type": "rps", "revenue": "15" }]
      }'

Returns 201 with {"data": {…offer…}}.

PATCH /offers/{id}#

Admin keys. Send only the fields to change (same fields as create, except code and events). Changing revenue_type, revenue, payout_type or payout also updates the default event so every conversion path uses the new terms.

Click-priced offers (payout_type: "cpc", revenue_type: "rpc") are credited per unique click at the offer's own rate in reports and billing, so they do not support per-partner overrides on that side: switching an offer to cpc (or rpc) while it has partner payout (or revenue) overrides returns 400 validation_failed with the field in details.fields — remove the overrides in the panel first.

Shell
curl -X PATCH https://app.trackcrown.com/api/v1/offers/Kx7Lm2Q \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"status": "paused"}'

Events#

Method & pathDescription
GET /offers/{id}/eventsEvents as the key may see them (partner keys: non-private events with payout only).
POST /offers/{id}/eventsAdmin keys. Body {code, name, revenue_type, revenue, payout_type, payout, is_private, allow_multiple}. code is 1–64 characters: letters, digits, _, . or - (the panel form is stricter: 1–40 lower-case letters, digits, _, -); default is reserved and codes are unique per offer regardless of case.
PATCH /offers/{id}/events/{event}Admin keys. {event} is the event id or code. The default event's code cannot change.
DELETE /offers/{id}/events/{event}Admin keys. Only events without conversions (409 in_use otherwise — mark them private instead). The default event cannot be deleted. Returns 204.
Shell
curl -X POST https://app.trackcrown.com/api/v1/offers/12/events \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"code": "deposit", "name": "First deposit", "revenue": "40", "payout": "30"}'
JSON
{ "data": { "id": 41, "code": "deposit", "name": "First deposit", "revenue_type": "rpa", "revenue": "40.0000",
            "payout_type": "cpa", "payout": "30.0000", "is_default": false, "is_private": false, "allow_multiple": false } }

Private events are hidden from partners and never fire their postbacks.

Partner access#

Method & pathDescription
GET /offers/{id}/affiliates?status=pendingStaff keys. Access requests and decisions for the offer.
PUT /offers/{id}/affiliates/{affiliate}Admin keys. {affiliate} is an affiliate id or code. Body {"status": "approved" | "pending" | "rejected" | "blocked", "note": "…"}. Creates the access row when the partner never asked. The partner is notified of approvals and rejections.
Shell
curl -X PUT https://app.trackcrown.com/api/v1/offers/12/affiliates/Pq3Rt8z \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"status": "approved", "note": "Welcome aboard"}'
JSON
{ "data": { "affiliate_id": 7, "affiliate_code": "Pq3Rt8z", "affiliate_name": "Acme Media", "status": "approved",
            "note": "Welcome aboard", "requested_at": "2026-10-09T10:00:00.000Z", "decided_at": "2026-10-10T08:15:30.123Z" } }

GET /offers/{id}/creatives#

The offer's creatives (banners, HTML, text, links, e-mail), read-only.

ParameterDescription
kindComma-separated: image, html, text, link, email.
statusStaff and advertiser keys: active, paused.

Staff keys see every creative; advertiser keys those of their own offers; partner keys the active creatives of offers they can run, with {tracking_link} replaced by their own tracking link and two extra fields: tracking_link and html (ready-to-paste markup for image creatives).

Shell
curl "https://app.trackcrown.com/api/v1/offers/Kx7Lm2Q/creatives?kind=image" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    { "id": 5, "offer_id": 12, "name": "Summer 300x250", "kind": "image", "url": "https://app.trackcrown.com/creative-files/…/summer-300x250.png",
      "body": "", "width": 300, "height": 250, "status": "active",
      "created_at": "2026-10-01T09:30:00.000Z", "updated_at": "2026-10-01T09:30:00.000Z" }
  ],
  "next_cursor": null
}

Affiliates#

Staff keys only (admin: read/write, analyst: read).

GET /affiliates#

Filters: status (active, pending, blocked, rejected), manager_id, tag, ids, q (name, company or e-mail contains / exact code), limit (default 50, max 200), cursor.

Shell
curl "https://app.trackcrown.com/api/v1/affiliates?status=active&q=acme" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    {
      "id": 7,
      "code": "Pq3Rt8z",
      "name": "Acme Media",
      "status": "active",
      "company": "Acme Media Ltd",
      "contact_name": "Jane Doe",
      "email": "ops@acme.example",
      "phone": "",
      "website": "https://acme.example",
      "country": "US",
      "messenger": "",
      "traffic_sources": "Search, native",
      "tier": "A",
      "manager_id": 4,
      "payment_method": "paypal",
      "payment_details": { "paypal": "billing@acme.example" },
      "payment_terms": "net30",
      "min_payout": "50.0000",
      "currency": "USD",
      "notes": "",
      "tags": ["search"],
      "approved_at": "2026-09-30T12:00:00.000Z",
      "created_at": "2026-09-29T08:00:00.000Z",
      "updated_at": "2026-10-02T16:45:00.000Z"
    }
  ],
  "next_cursor": null
}

payment_details is only included for admin keys.

GET /affiliates/{id}#

{id} is the numeric id or the affiliate code.

POST /affiliates#

Admin keys. name is required; every other field is optional: code (6-10 letters/digits, generated when omitted), status (default active), company, contact_name, email, phone, website, country (ISO-2), messenger, traffic_sources, tier, manager_id (a staff user of the workspace), payment_method (paypal, wire, payoneer, crypto, other), payment_details (object of strings), payment_terms (default net30), min_payout, currency (default: workspace currency), notes, tags.

Shell
curl -X POST https://app.trackcrown.com/api/v1/affiliates \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"name": "Acme Media", "email": "ops@acme.example", "country": "US", "payment_method": "paypal", "payment_details": {"paypal": "billing@acme.example"}}'

Returns 201 with the affiliate. To let the partner sign in, invite a user for them from the panel.

PATCH /affiliates/{id}#

Admin keys. Send only the fields to change, e.g. {"status": "blocked"}. Setting status to active for the first time records approved_at.

Advertisers#

Staff keys only.

Method & pathDescription
GET /advertisersFilters status (active, paused, inactive), ids, q; limit (default 50, max 200), cursor.
GET /advertisers/{id}One advertiser.
POST /advertisersAdmin keys. name required; optional status, company, contact_name, email, phone, website, country, currency, account_manager_id, billing_terms, notes, tags.
PATCH /advertisers/{id}Admin keys. Partial update.
Shell
curl -X POST https://app.trackcrown.com/api/v1/advertisers \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"name": "Shop Inc.", "website": "https://shop.example.com", "currency": "USD"}'
JSON
{
  "data": {
    "id": 3,
    "name": "Shop Inc.",
    "status": "active",
    "company": "",
    "contact_name": "",
    "email": "",
    "phone": "",
    "website": "https://shop.example.com",
    "country": "",
    "currency": "USD",
    "account_manager_id": null,
    "billing_terms": "net30",
    "notes": "",
    "tags": [],
    "postback_token": "9f0c…",
    "created_at": "2026-10-10T08:15:30.123Z",
    "updated_at": "2026-10-10T08:15:30.123Z"
  }
}

postback_token (the advertiser's S2S token, see Server-to-server postback reference) is only included for admin keys.

Reports#

GET /reports#

Runs the same engine as the panel's report builder: one aggregate over clicks, impressions and conversions, grouped by up to three dimensions, with totals computed by the database (never by adding up rows).

ParameterDescription
from, to, tz, presetDate range (default preset=last7). Max 400 days.
group_byUp to 3 comma-separated dimensions, outermost first (none = totals only).
metricsComma-separated metrics (default: the role's default set).
filtersComma-separated dimension:in:v1|v2 / dimension:not_in:v1|v2 (repeat filter= instead when a value contains a comma).
offer_id, affiliate_id, advertiser_idShortcuts for id filters (comma-separated ids).
date_basisconversion (default: conversions counted at conversion time) or click (at the time of their click).
currencyISO 4217 code of the money columns (default: the workspace currency).
sort-clicks (descending), clicks (ascending) or clicks:desc; any grouped dimension or requested metric.
limit, offsetRows per page (default 1000, max 10000) and offset; the response has next_offset (null on the last page).
formatjson (default) or csv — streams every row (max 200,000) plus a totals line as a download.

Dimensions:

GroupDimensions
Time (bucketed in tz)date, hour, week (weeks start Monday), month
Network (numeric ids; rows include <dim>_label)offer, affiliate, advertiser, smart_link, event, offer_url (landing page), referrer_offer, coupon
Sub IDssub1 … sub5, source_id; sub6 … sub10 (clicks and conversions; impressions are not split by them)
Traffictraffic_source, domain, link_type, country, region, city, device_type, os, browser
Ad platformext_campaign_id, ext_adgroup_id, ext_ad_id, ext_keyword, ext_placement
Google Ads (clicks only)click_mode, ext_network, ext_matchtype, ext_device, ext_loc, ext_keyword_id, ext_audience_id, ext_dsa_id, ext_partition_id, ext_feeditem_id, ext_extension_id, ext_asset_group_id, ext_loc_interest, ext_device_model, ext_target_category, ext_product_id, ext_merchant_id, ext_ad_type
Filter onlyclick_status (redirect, fallback, blocked, error), conversion_status (approved, pending, rejected)

"Clicks only" dimensions are click attributes: impressions and conversions are not split by them. What each Google Ads dimension holds: ValueTrack reference.

Metrics: impressions, clicks, unique_clicks, bot_clicks, ctr, conversions (approved), pending_conversions, rejected_conversions, cvr (approved ÷ unique clicks), revenue, payout, profit, margin, epc, rpc, cpc, avg_sale_amount, sale_amount; staff keys also ad_cost, roas and net_profit (below). Counts are numbers, money is a 4-decimal string, ratios are fractions (0.0315 = 3.15 %) or null when the denominator is 0.

Ad costs (ad_cost, roas = revenue ÷ ad cost, net_profit = revenue − payout − ad cost; staff keys only): media spend imported under Ad costs & ROAS, converted to the report currency at the ECB rate of the cost date. A cost row splits only by date, hour, week, month, offer, affiliate, advertiser, traffic_source, ext_campaign_id and ext_adgroup_id; with any other group_by the cost is reported under the empty value. An in filter on another dimension excludes the cost, not_in keeps it, and event and status filters leave it alone. Cost currencies without a usable rate are listed in other_currencies.

Partner keys only see their own traffic and never revenue, profit, margin, rpc, cpc, bot_clicks or the advertiser dimension; payout is their earnings and epc is earnings per click. Advertiser keys only see their own offers and never payout, profit, margin, rpc, cpc, bot_clicks or partner names; revenue is their cost. Requesting a metric or dimension the role cannot see is a 400 invalid_parameter.

Currencies: every offer has its own currency and money is never added across currencies. Money columns (revenue, payout, profit, epc, …) count only amounts in the report's currency (the currency parameter, else the workspace currency); counts (clicks, conversions) cover every currency. The response's other_currencies lists the other currencies that have money in the same range and scope — run the report again with currency=EUR (for example) to see those amounts. The CSV export names the currency in every money header and adds a note line when other currencies were left out.

Shell
curl "https://app.trackcrown.com/api/v1/reports?preset=last7&group_by=offer,date&metrics=clicks,conversions,revenue,payout,profit&sort=-clicks&filters=country:in:US|CA" \
  -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    { "offer": "12", "offer_label": "Summer Sale — US", "offer_sub": "Kx7Lm2Q", "date": "2026-10-09", "date_label": "Oct 9, 2026",
      "clicks": 1520, "conversions": 41, "revenue": "287.0000", "payout": "205.0000", "profit": "82.0000" }
  ],
  "totals": { "clicks": 1520, "conversions": 41, "revenue": "287.0000", "payout": "205.0000", "profit": "82.0000" },
  "columns": [
    { "key": "offer", "label": "Offer", "kind": "dimension", "format": "entity" },
    { "key": "date", "label": "Date", "kind": "dimension", "format": "date" },
    { "key": "clicks", "label": "Clicks", "kind": "metric", "format": "number" },
    { "key": "conversions", "label": "Conversions", "kind": "metric", "format": "number" },
    { "key": "revenue", "label": "Revenue", "kind": "metric", "format": "money" },
    { "key": "payout", "label": "Payout", "kind": "metric", "format": "money" },
    { "key": "profit", "label": "Profit", "kind": "metric", "format": "money" }
  ],
  "total_rows": 1,
  "next_offset": null,
  "currency": "USD",
  "other_currencies": ["EUR"],
  "range": { "from": "2026-10-03T18:30:00.000Z", "to": "2026-10-10T18:30:00.000Z", "tz": "Asia/Kolkata" },
  "group_by": ["offer", "date"],
  "metrics": ["clicks", "conversions", "revenue", "payout", "profit"],
  "date_basis": "conversion"
}

CSV export of the same report:

Shell
curl -o report.csv "https://app.trackcrown.com/api/v1/reports?preset=last_month&group_by=affiliate&format=csv" \
  -H "Authorization: Bearer $ATK"

GET /reports/timeseries#

A gap-filled series — one point per day (interval=day, default) or hour (interval=hour, ranges up to 31 days) in tz — for charts. Accepts from, to, tz, preset (default last30, or today for hours), metrics, filters, offer_id, affiliate_id.

Shell
curl "https://app.trackcrown.com/api/v1/reports/timeseries?preset=last7&metrics=clicks,payout" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    { "bucket": "2026-10-04", "clicks": 1288, "payout": "160.0000" },
    { "bucket": "2026-10-05", "clicks": 0, "payout": "0.0000" }
  ],
  "interval": "day",
  "metrics": ["clicks", "payout"],
  "range": { "from": "2026-10-03T18:30:00.000Z", "to": "2026-10-10T18:30:00.000Z", "tz": "Asia/Kolkata" }
}

Clicks#

GET /clicks#

The raw click log, newest first. Default range: today in tz; at most 93 days per request (use reports for longer periods).

ParameterDescription
from, to, tz, presetDate range.
limit, cursorPage size (default 100, max 1000) and cursor.
filters, offer_id, affiliate_idSame filter syntax as reports.
botyes = only bot clicks, no = exclude bots.
qExact match on click id, gclid/gbraid/wbraid, fbclid, msclkid, sub1 or source id.
Shell
curl "https://app.trackcrown.com/api/v1/clicks?preset=today&limit=1000&offer_id=12" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    {
      "click_id": "0192a6c3f1e04b7e9c2d8a1f3b5c7d9e",
      "ts": "2026-10-10T08:15:30.123Z",
      "link_type": "transparent",
      "status": "redirect",
      "status_reason": "",
      "offer_id": 12,
      "offer_label": "Summer Sale — US",
      "affiliate_id": 7,
      "affiliate_label": "Acme Media",
      "smart_link_id": 0,
      "is_unique": true,
      "is_bot": false,
      "is_datacenter": false,
      "country": "US",
      "city": "San Jose",
      "device_type": "mobile",
      "os": "Android",
      "browser": "Chrome",
      "traffic_source": "google",
      "sub1": "campaign-a",
      "sub2": "",
      "source_id": "",
      "gclid": "Cj0KCQjw…",
      "ext_campaign_id": "123456789",
      "ext_keyword": "running shoes",
      "domain": "trk.example.com",
      "destination": "https://shop.example.com/summer?cid=0192a6c3f1e04b7e9c2d8a1f3b5c7d9e"
    }
  ],
  "next_cursor": "MTc5MTYyNDUzMDEyMzowMTkyYTZjM2YxZTA0YjdlOWMyZDhhMWYzYjVjN2Q5ZQ",
  "range": { "from": "2026-10-09T18:30:00.000Z", "to": "2026-10-10T18:30:00.000Z", "tz": "Asia/Kolkata" }
}

Partner keys never receive destination (the offer's landing page). Advertiser keys never receive partner sub IDs, source_id, smart_link_id or partner names.

GET /clicks?gclid=…#

Find the clicks that carried a Google click identifier — for offline-conversion reconciliation or to join a parallel-tracking click. Pass one of gclid, gbraid or wbraid (1–512 URL-safe characters) and an explicit from (and optionally to); the range may span at most 90 days. limit: default 100, max 1,000. No cursor.

Shell
curl "https://app.trackcrown.com/api/v1/clicks?gclid=Cj0KCQjw8eOLBhC1ARIsAOzx5cG&from=2026-09-15" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    { "click_id": "0192a6c3f1e04b7e9c2d8a1f3b5c7d9e", "ts": "2026-10-10T08:15:30.123Z", "offer_id": 12, "affiliate_id": 7,
      "gclid": "Cj0KCQjw8eOLBhC1ARIsAOzx5cG", "gbraid": "", "wbraid": "", "traffic_source": "google",
      "link_type": "transparent", "domain": "trackcrown.com" }
  ],
  "next_cursor": null,
  "click_ids": ["0192a6c3f1e04b7e9c2d8a1f3b5c7d9e"],
  "range": { "from": "2026-09-14T18:30:00.000Z", "to": "2026-10-12T18:30:00.000Z", "tz": "Asia/Kolkata" }
}

Without from the request fails with 400 invalid_parameter. Partner and advertiser keys only find their own clicks.

GET /clicks/{click_id}#

Every stored column of one click (IP address and fraud flags for staff keys only), the extra parameters that were not mapped to a column, and the click's conversions.

Shell
curl https://app.trackcrown.com/api/v1/clicks/0192a6c3f1e04b7e9c2d8a1f3b5c7d9e -H "Authorization: Bearer $ATK"
JSON
{
  "data": {
    "click": { "click_id": "0192a6c3f1e04b7e9c2d8a1f3b5c7d9e", "ts": "2026-10-10T08:15:30.123Z", "offer_id": 12, "affiliate_id": 7,
               "country": "US", "device_type": "mobile", "gclid": "Cj0KCQjw…", "…": "…" },
    "extra": { "utm_source": "google" },
    "offer": { "id": 12, "label": "Summer Sale — US", "sub": "Kx7Lm2Q" },
    "affiliate": { "id": 7, "label": "Acme Media", "sub": "Pq3Rt8z" },
    "conversions": [
      { "id": "8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11", "conv_ts": "2026-10-10T08:31:02.000Z", "event_code": "default",
        "status": "approved", "status_reason": "", "payout": "5.0000", "revenue": "7.0000", "sale_amount": "0.0000",
        "currency": "USD", "adv_txid": "ORDER-1001", "method": "s2s", "is_duplicate": false }
    ]
  }
}

Conversions#

Conversions are read from the system of record, so status changes are visible immediately (reports catch up within a few seconds).

GET /conversions#

By conversion time, newest first. Default range: last 7 days in tz.

ParameterDescription
from, to, tz, presetDate range on the conversion time.
statusComma-separated: approved, pending, rejected.
offer_id, affiliate_idComma-separated ids (affiliate_id: staff and advertiser keys).
eventComma-separated event codes.
methodComma-separated: s2s, pixel, js, manual, api, import.
click_idConversions of one click.
adv_txidAdvertiser order id (staff and advertiser keys).
duplicatesinclude (default), exclude or only.
limit, cursorPage size (default 100, max 500) and cursor.
Shell
curl "https://app.trackcrown.com/api/v1/conversions?preset=yesterday&status=pending" -H "Authorization: Bearer $ATK"
JSON
{
  "data": [
    {
      "id": "8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11",
      "click_id": "0192a6c3f1e04b7e9c2d8a1f3b5c7d9e",
      "offer_id": 12,
      "offer_name": "Summer Sale — US",
      "affiliate_id": 7,
      "affiliate_code": "Pq3Rt8z",
      "affiliate_name": "Acme Media",
      "advertiser_id": 3,
      "smart_link_id": null,
      "event_id": 40,
      "event_code": "default",
      "status": "pending",
      "status_reason": "",
      "is_duplicate": false,
      "revenue": "7.0000",
      "payout": "5.0000",
      "sale_amount": "0.0000",
      "currency": "USD",
      "adv_txid": "ORDER-1001",
      "method": "s2s",
      "click_ts": "2026-10-09T08:15:30.123Z",
      "conv_ts": "2026-10-09T08:31:02.000Z",
      "domain": "trk.example.com",
      "link_type": "transparent",
      "sub1": "campaign-a", "sub2": "", "sub3": "", "sub4": "", "sub5": "",
      "source_id": "",
      "traffic_source": "google",
      "gclid": "Cj0KCQjw…", "gbraid": "", "wbraid": "", "fbclid": "",
      "ext_campaign_id": "123456789", "ext_adgroup_id": "", "ext_ad_id": "", "ext_keyword": "running shoes", "ext_placement": "",
      "country": "US", "region": "CA", "city": "San Jose",
      "device_type": "mobile", "os": "Android", "browser": "Chrome",
      "conv_ip": "198.51.100.20",
      "params": { "adv1": "blue" },
      "notes": "",
      "created_at": "2026-10-09T08:31:02.000Z",
      "updated_at": "2026-10-09T08:31:02.000Z"
    }
  ],
  "next_cursor": null,
  "range": { "from": "2026-10-08T18:30:00.000Z", "to": "2026-10-09T18:30:00.000Z", "tz": "Asia/Kolkata" }
}

Partner keys only see their own conversions of non-private events, without revenue, advertiser_id, adv_txid, params, notes or conv_ip. Advertiser keys only see conversions of their offers, without payout, partner names, sub IDs, source_id, conv_ip or notes.

GET /conversions/{id}#

One conversion by UUID, same shape and visibility rules.

POST /conversions#

Admin keys. Records a conversion by hand (method api). Payout and revenue are resolved exactly like an S2S postback (custom payouts, event terms, percentages of sale_amount) unless you override them; an approved conversion enqueues the partner's postbacks.

FieldDescription
offer_idRequired.
affiliate_idThe partner (taken from the click when click_id is given).
eventEvent code, default default.
click_idAttribute to a click (32 hex). The click must belong to the offer.
statusapproved, pending or rejected; default: the offer's default_status.
payout, revenueOverride the resolved amounts.
sale_amountSale amount for percentage payouts/revenue.
adv_txidAdvertiser order id; 409 conflict when the offer already has a conversion with it.
conv_tsConversion time (ISO-8601, default now, never in the future).
notesInternal note.
Shell
curl -X POST https://app.trackcrown.com/api/v1/conversions \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"offer_id": 12, "affiliate_id": 7, "event": "sale", "sale_amount": "200", "adv_txid": "ORDER-1001", "notes": "Phone order"}'

Returns 201 with the conversion.

PATCH /conversions/{id}#

Admin keys. Approve, reject or pend one conversion: {"status": "rejected", "reason": "fraud"}. Approving enqueues the partner postbacks that have not fired for this conversion yet; rejecting an approved conversion enqueues the fire_on: reversal postbacks (once per conversion, with {old_status}, {old_payout}, … and {payout_delta}) and the postbacks whose statuses include rejected. Duplicates can only be rejected. See Reversals.

Shell
curl -X PATCH https://app.trackcrown.com/api/v1/conversions/8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11 \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"status": "approved"}'

PATCH /conversions#

Admin keys. The same for up to 500 conversions at once:

Shell
curl -X PATCH https://app.trackcrown.com/api/v1/conversions \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"ids": ["8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11", "1f0e…"], "status": "rejected", "reason": "fraud"}'
JSON
{
  "data": {
    "updated": [ { "id": "8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11", "status": "rejected", "status_reason": "fraud" } ],
    "not_found": ["1f0e…"],
    "skipped_duplicates": 0
  }
}

Postbacks#

Outgoing partner postbacks and pixels (see Postback macros for {payout}, {sub1}, …).

  • Partner keys manage their own postbacks: affiliate_id is always their account (omit it), offers must be ones they can run, and private events are not available.
  • Admin keys manage every postback of the workspace; affiliate_id: null fires for every partner's conversions. Analyst keys can read them. Advertiser keys have no access.
  • Conversion-API destinations (Meta, TikTok, Microsoft UET) are not part of these endpoints; manage them in the panel (Meta Conversions API). fire_on accepts approved, any and reversal.
Method & pathDescription
GET /postbacksFilters affiliate_id (staff: an id or global), offer_id, status, kind; limit (default 50, max 200), cursor.
GET /postbacks/{id}One postback.
POST /postbacksCreate.
PATCH /postbacks/{id}Partial update.
DELETE /postbacks/{id}Delete (204). Already-sent postbacks stay in the log.
FieldDefaultDescription
affiliate_idnullStaff keys only.
offer_idnullnull = all offers.
event_codenullnull = every non-private event.
kinds2ss2s (server-to-server request), image (pixel URL), html (snippet in body).
methodGETPOST sends body (s2s only).
url—Required for s2s and image.
body""POST body or HTML snippet; macros expanded (JSON-escaped when it starts with {).
fire_onapprovedapproved: approved conversions (also when a pending one is approved later). any: approved + pending conversions (never rejected ones or duplicates). reversal: once when an approved conversion is rejected — by the advertiser's reversal postback, in the panel or advertiser portal, by API or by CSV import — with the extra macros {old_status}, {old_payout}, {old_revenue}, {old_sale_amount}, {payout_delta}. Every postback fires at most once per conversion.
statusactiveactive or paused.
Shell
curl -X POST https://app.trackcrown.com/api/v1/postbacks \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"offer_id": 12, "url": "https://tracker.example.net/postback?cid={sub1}&payout={payout}&status={status}"}'
JSON
{
  "data": {
    "id": 31,
    "affiliate_id": 7,
    "offer_id": 12,
    "event_code": null,
    "kind": "s2s",
    "method": "GET",
    "url": "https://tracker.example.net/postback?cid={sub1}&payout={payout}&status={status}",
    "body": "",
    "fire_on": "approved",
    "status": "active",
    "created_by_affiliate": true,
    "created_at": "2026-10-10T08:15:30.123Z",
    "updated_at": "2026-10-10T08:15:30.123Z"
  }
}

Builds a link for an offer. Nothing is stored. The host is the tracking domain assigned to the partner and offer (Tracking domains → Assignments: partner + offer, then partner, then offer), else the workspace default, unless you pass host.

ParameterDescription
offerRequired. Offer id or code (offer_id also accepted).
affiliateAffiliate id or code (affiliate_id also accepted). Staff keys: required for type=affiliate, optional for transparent. Partner keys: always their own account.
typeaffiliate (default): /r/{offer}/{affiliate}?…. transparent: a Google Ads tracking template /c/{offer}[-{affiliate}]?…&url={lpurl}.
sub1 … sub5, source_idValues to embed (each at most 500 characters).
urltransparent: the url= value — {lpurl} (default) or an absolute http(s) URL up to 4,096 characters.
googletransparent: add the Google Ads ValueTrack parameters. Default true.
hostOne of the workspace's active tracking domains; anything else is 400 invalid_parameter.

When the network forces a traffic-source template on the partner (Partner program → Traffic sources), its sub-ID and source_id values replace the requested ones.

Shell
curl "https://app.trackcrown.com/api/v1/tracking-link?offer=Kx7Lm2Q&affiliate=Pq3Rt8z&sub1=campaign-a" -H "Authorization: Bearer $ATK"
JSON
{
  "data": {
    "type": "affiliate",
    "url": "https://trackcrown.com/r/Kx7Lm2Q/Pq3Rt8z?sub1=campaign-a",
    "host": "trackcrown.com",
    "offer": { "id": 12, "code": "Kx7Lm2Q", "name": "Summer Sale — US" },
    "affiliate": { "id": 7, "code": "Pq3Rt8z" },
    "warnings": []
  }
}

A transparent tracking template for Google Ads:

Shell
curl "https://app.trackcrown.com/api/v1/tracking-link?offer=Kx7Lm2Q&affiliate=Pq3Rt8z&type=transparent" -H "Authorization: Bearer $ATK"
JSON
{
  "data": {
    "type": "transparent",
    "url": "https://trackcrown.com/c/Kx7Lm2Q-Pq3Rt8z?gclid={gclid}&campaignid={campaignid}&adgroupid={adgroupid}&creative={creative}&keyword={keyword}&matchtype={matchtype}&network={network}&device={device}&placement={placement}&loc_physical_ms={loc_physical_ms}&targetid={targetid}&feeditemid={feeditemid}&extensionid={extensionid}&assetgroupid={assetgroupid}&loc_interest_ms={loc_interest_ms}&devicemodel={devicemodel}&target={target}&adtype={adtype}&merchant_id={merchant_id}&product_id={product_id}&url={lpurl}",
    "host": "trackcrown.com",
    "offer": { "id": 12, "code": "Kx7Lm2Q", "name": "Summer Sale — US" },
    "affiliate": { "id": 7, "code": "Pq3Rt8z" },
    "link_key": "Kx7Lm2Q-Pq3Rt8z",
    "google_ads": {
      "tracking_template": "https://trackcrown.com/c/Kx7Lm2Q-Pq3Rt8z?gclid={gclid}&…&url={lpurl}",
      "certified": false,
      "cert_status": "applied",
      "final_url_suffix": "gclid={gclid}&campaignid={campaignid}&…&product_id={product_id}"
    },
    "warnings": ["Not yet certified by Google: new Google Ads accounts may only use certified trackers. Use Final URL suffix + SDK mode."]
  }
}

google_ads is present only when url is {lpurl}. The template contains no force_transparent parameter and every core ValueTrack tag; trim it to the tags your campaign type fills, or build it in the panel's template builder. The certification warning appears whenever google is on and the domain is not certified.

For staff keys warnings also explains why clicks would currently go to the fallback (offer not active, partner not active or not approved for a non-public offer). Partner keys get 403 not_approved until they may run the offer, and 404 for offers they cannot see. Advertiser keys cannot build links (403 forbidden). Without an active tracking domain the answer is 409 no_tracking_domain.

Deals & product feeds#

GET /deals#

Coupons and promotions of advertisers. Partner keys: active deals inside their start/end dates, of offers the partner can run, plus advertiser-wide deals. Advertiser keys: their own deals. Staff keys (advertisers.read): every deal. Fields: id, advertiser_id, advertiser, offer_id, offer_name, title, description, coupon_code, landing_url, starts_at, ends_at, status, updated_at. Partner keys get the same fields without advertiser_id, status and updated_at.

Shell
curl "https://app.trackcrown.com/api/v1/deals" -H "Authorization: Bearer $ATK"

GET /product-feeds#

Product catalogues (csv, tsv, xml, json) for product-level links, scoped like /deals. Fields: id, advertiser_id, advertiser, offer_id, offer_name, name, feed_url, format, status, description, updated_at (partner keys: without advertiser_id, status and updated_at).

Both return the whole list in one response (next_cursor is null).

POST /google-ads/lint#

Static check of a Google Ads or Microsoft Advertising tracking template, final URL and Final URL suffix — the same linter as the panel's template builder. Staff keys (admin or analyst). Body: template, final_url, suffix, platform (google | microsoft), allow_uncertified. At least one of template and suffix is required.

Shell
curl -X POST https://app.trackcrown.com/api/v1/google-ads/lint \
  -H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
  -d '{"template":"https://trackcrown.com/c/demo?gclid={gclid}&force_transparent=true&url={lpurl}","final_url":"https://shop.example.com/"}'

The response {"data": {"ok": …, "template": {"ok", "host", "length", "tags", "issues"}, "suffix": [issues]}} lists issues as {code, severity, message, hint?}. Every code is explained in Template linter, simulator and tester.

Something unclear or missing in this article?Tell us