REST API
Authentication, pagination and endpoints of the REST API v1.
23 min read
Browse documentation
The ArcTrack REST API gives programmatic access to one workspace: offers and their events, partners (affiliates), advertisers, reports, the raw click log, conversions, outgoing postbacks and tracking links. It speaks JSON over HTTPS and is described by an OpenAPI 3.1 document you can load into Postman, Insomnia or a code generator:
https://app.168-144-125-119.sslip.io/api/v1/openapi.jsonBase URL of every endpoint below:
https://app.168-144-125-119.sslip.io/api/v1Authentication#
Every request carries an API key in the Authorization header:
curl https://app.168-144-125-119.sslip.io/api/v1/me \
-H "Authorization: Bearer atk_AbCd1234_…"Keys look like atk_<8-character prefix>_<40-character secret>. Network staff create keys under
Settings → API keys; partners create their own key in the partner portal (API key) and advertisers in the
advertiser portal (Profile → API key). The full key is shown once — we
only store a SHA-256 hash of it, so a lost key cannot be recovered: revoke it and create a new one. The prefix is
shown in the panel so you can tell keys apart. X-Api-Key: atk_… is accepted as an alternative header.
Roles#
The role of a key decides what it can see and do. The workspace (and, for partner/advertiser keys, the partner or advertiser) always comes from the key — never from the request.
Requests for a disabled workspace, a partner that is not active, or an inactive advertiser are refused with
403.
Conventions#
- JSON in, JSON out. Send bodies with
Content-Type: application/json(max 512 KB). Unknown fields in a body are rejected, so typos never pass silently. - Money is always a decimal string with 4 decimals (
"12.5000"), in the currency of the row. On input you may send a string ("12.50") or a number; at most 4 decimals are accepted, and thousands separators like"1,234.50"are fine but ambiguous input like"1,5"is refused. - Times are ISO-8601 UTC instants (
"2026-10-10T08:15:30.123Z"). - IDs are integers, except conversions (UUID) and clicks (32 hex characters). Offers and affiliates can also
be addressed by their public code in paths:
/offers/Kx7Lm2Q=/offers/12. - Date ranges (
from,to,tz,preset) work the same everywhere:from/toas dates (2026-10-01) are calendar days in the time zonetz(default: the workspace time zone); a date intoincludes that whole day.from/toas timestamps with a zone (2026-10-01T00:00:00Z,2026-10-01T05:30:00+05:30) are exact instants;tois exclusive.- Instead of
from/to:preset=today|yesterday|last7|last30|this_month|last_month, always resolved against "today" intz. - Responses echo the absolute range that was used:
"range": {"from": …, "to": …, "tz": …}.
Pagination#
Lists return a page of results and an opaque cursor:
{
"data": [ { "id": 12, "…": "…" } ],
"next_cursor": "eyJrIjoib2ZmZXJzIiwidCI6IjIwMjYtMTAtMDFUMDk6MzA6MDAuMDAwMDAwWiIsImkiOiIxMiJ9"
}Pass next_cursor back as ? with the same filters to get the next page; next_cursor is null on the
last page. Results are ordered newest first (by creation time, or by conversion/click time for conversions and
clicks), and the cursor is a keyset position, so rows created while you page never shift or repeat results. Use
limit to choose the page size (defaults and maximums are listed per endpoint). A cursor from one list is refused by
another with 400 invalid_cursor.
Reports use limit + offset instead (see Reports).
Errors#
Errors use a stable shape and a meaningful HTTP status:
{
"error": {
"code": "validation_failed",
"message": "The request body failed validation.",
"details": { "fields": { "payout": "Enter a decimal amount with at most 4 decimals, e.g. \"12.50\".", "bogus": "Unknown field." } }
}
}Every response carries an X-Request-Id header — include it when you contact support.
Rate limits#
Each key may make 600 requests per minute (fixed one-minute windows). Every response reports the budget:
Over the limit you get 429 rate_limited with a Retry-After header (seconds). Back off until then. For bulk
reads prefer one report over many small requests, and the CSV export over paging through very large reports.
Account#
GET /me#
Who is calling: the key, its workspace, the partner/advertiser it belongs to, its permissions and the rate-limit state.
curl https://app.168-144-125-119.sslip.io/api/v1/me -H "Authorization: Bearer $ATK"{
"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#
curl "https://app.168-144-125-119.sslip.io/api/v1/offers?status=active&limit=2" -H "Authorization: Bearer $ATK"{
"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/payoutafter 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,rejectedornull),can_runandtracking_link(their ready-to-use link whilecan_runis 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.
curl -X POST https://app.168-144-125-119.sslip.io/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.
curl -X PATCH https://app.168-144-125-119.sslip.io/api/v1/offers/Kx7Lm2Q \
-H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
-d '{"status": "paused"}'Events#
curl -X POST https://app.168-144-125-119.sslip.io/api/v1/offers/12/events \
-H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
-d '{"code": "deposit", "name": "First deposit", "revenue": "40", "payout": "30"}'{ "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#
curl -X PUT https://app.168-144-125-119.sslip.io/api/v1/offers/12/affiliates/Pq3Rt8z \
-H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
-d '{"status": "approved", "note": "Welcome aboard"}'{ "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" } }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.
curl "https://app.168-144-125-119.sslip.io/api/v1/affiliates?status=active&q=acme" -H "Authorization: Bearer $ATK"{
"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.
curl -X POST https://app.168-144-125-119.sslip.io/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.
curl -X POST https://app.168-144-125-119.sslip.io/api/v1/advertisers \
-H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
-d '{"name": "Shop Inc.", "website": "https://shop.example.com", "currency": "USD"}'{
"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 postbacks) 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).
Dimensions: date, hour, week (weeks start Monday), month — bucketed in tz; offer, affiliate,
advertiser, smart_link, event (numeric ids; rows include <dim>_label); sub1 … sub5, source_id,
traffic_source, ext_campaign_id, ext_adgroup_id, ext_ad_id, ext_keyword, ext_placement, country,
region, city, device_type, os, browser, domain, link_type. Filter-only: click_status
(redirect, fallback, blocked, error) and conversion_status (approved, pending, rejected).
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. Counts are numbers, money is a 4-decimal string,
ratios are fractions (0.0315 = 3.15 %) or null when the denominator is 0.
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.
curl "https://app.168-144-125-119.sslip.io/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"{
"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:
curl -o report.csv "https://app.168-144-125-119.sslip.io/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.
curl "https://app.168-144-125-119.sslip.io/api/v1/reports/timeseries?preset=last7&metrics=clicks,payout" -H "Authorization: Bearer $ATK"{
"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).
curl "https://app.168-144-125-119.sslip.io/api/v1/clicks?preset=today&limit=1000&offer_id=12" -H "Authorization: Bearer $ATK"{
"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/{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.
curl https://app.168-144-125-119.sslip.io/api/v1/clicks/0192a6c3f1e04b7e9c2d8a1f3b5c7d9e -H "Authorization: Bearer $ATK"{
"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.
curl "https://app.168-144-125-119.sslip.io/api/v1/conversions?preset=yesterday&status=pending" -H "Authorization: Bearer $ATK"{
"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.
curl -X POST https://app.168-144-125-119.sslip.io/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; duplicates can only be rejected.
curl -X PATCH https://app.168-144-125-119.sslip.io/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:
curl -X PATCH https://app.168-144-125-119.sslip.io/api/v1/conversions \
-H "Authorization: Bearer $ATK" -H "Content-Type: application/json" \
-d '{"ids": ["8a6a2d0e-3c55-4c7e-9a43-0c1c2d8f0b11", "1f0e…"], "status": "rejected", "reason": "fraud"}'{
"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 macros for {payout}, {sub1}, …).
- Partner keys manage their own postbacks:
affiliate_idis 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: nullfires for every partner's conversions. Analyst keys can read them. Advertiser keys have no access.
curl -X POST https://app.168-144-125-119.sslip.io/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}"}'{
"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"
}
}Tracking links#
GET /tracking-link#
Builds a link on the workspace's default tracking domain (or host, which must be one of its active tracking
domains).
curl "https://app.168-144-125-119.sslip.io/api/v1/tracking-link?offer=Kx7Lm2Q&affiliate=Pq3Rt8z&sub1=campaign-a" -H "Authorization: Bearer $ATK"{
"data": {
"type": "affiliate",
"url": "https://track.example.com/r/Kx7Lm2Q/Pq3Rt8z?sub1=campaign-a",
"host": "track.example.com",
"offer": { "id": 12, "code": "Kx7Lm2Q", "name": "Summer Sale — US" },
"affiliate": { "id": 7, "code": "Pq3Rt8z" },
"warnings": []
}
}A transparent tracking template for Google Ads:
curl "https://app.168-144-125-119.sslip.io/api/v1/tracking-link?offer=Kx7Lm2Q&affiliate=Pq3Rt8z&type=transparent" -H "Authorization: Bearer $ATK"{
"data": {
"type": "transparent",
"url": "https://track.example.com/c/Kx7Lm2Q-Pq3Rt8z?gclid={gclid}&gbraid={gbraid}&wbraid={wbraid}&campaignid={campaignid}&adgroupid={adgroupid}&creative={creative}&keyword={keyword}&matchtype={matchtype}&network={network}&device={device}&placement={placement}&loc_physical_ms={loc_physical_ms}&targetid={targetid}&url={lpurl}",
"host": "track.example.com",
"offer": { "id": 12, "code": "Kx7Lm2Q", "name": "Summer Sale — US" },
"affiliate": { "id": 7, "code": "Pq3Rt8z" },
"link_key": "Kx7Lm2Q-Pq3Rt8z",
"google_ads": { "tracking_template": "https://track.example.com/c/Kx7Lm2Q-Pq3Rt8z?gclid={gclid}&…&url={lpurl}" },
"warnings": []
}
}For staff keys warnings explains why clicks would currently go to the fallback (offer paused, partner not active
or not approved). Partner keys get 403 not_approved until they may run the offer. Advertiser keys cannot build
links.
Example: nightly sync#
#!/usr/bin/env bash
# Pull yesterday's approved conversions page by page.
ATK="atk_…"
URL="https://app.168-144-125-119.sslip.io/api/v1/conversions?preset=yesterday&status=approved&limit=500"
CURSOR=""
while :; do
PAGE=$(curl -sf "$URL${CURSOR:+&cursor=$CURSOR}" -H "Authorization: Bearer $ATK") || exit 1
echo "$PAGE" | jq -c '.data[]'
CURSOR=$(echo "$PAGE" | jq -r '.next_cursor // empty')
[ -z "$CURSOR" ] && break
done