This article is the API reference for the Trackdesk endpoints your integration uses to register a new player, to record changes to that player's metrics over time, and to inspect the history of those changes. For the conceptual background (what a player is, what a movement records, what the dashboard shows), see Players in Trackdesk and Player movements.
Throughout the API, dashboard terms map to client_* field names: a Player is a client, a Brand is a revenue_origin, and a Player movement is a client_metric_movement. See the iGaming glossary for the full mapping.
Authentication and base URL
Every request authenticates with a personal access token sent in the X-Api-Key header.
To generate a token, navigate to Settings → Integrations → Personal access tokens, click Generate new token, and copy the value somewhere safe; you will not be able to see it again after closing the dialog.
All endpoints are served from your workspace's tenant subdomain. For example, if your dashboard is at https://acme.trackdesk.com, your tenant ID is acme and requests go to https://acme.trackdesk.com/.... The path prefix depends on the endpoint and is shown in each endpoint's heading below.
All requests use Content-Type: application/json. A successful response returns HTTP 200 with an empty JSON body for the write endpoints, or with the listed data for the read endpoints.
Register a player
Endpoint: POST /tracking/client/v1
Creates a new player record, linked to a previously tracked click. Call this whenever your platform creates a new account that should be attributed to an affiliate. Once the player exists, your integration can record movements against them.
The request body has three required fields:
externalId: your platform's identifier for the player (the user ID, account number, or player ID from your database). 1–255 characters. Must be unique per brand: trying to register the same external ID a second time under the same brand returns an error.revenueOriginId: the UUID of the brand the player belongs to. Find it on the brand record in your dashboard; see Where Can I Find My Revenue Origin ID? for the exact location.cid: the UUID of the original tracking click that referred the player, captured by your tracking integration when the visitor first lands on your site.
Example request body:
{
"externalId": "player-42",
"revenueOriginId": "0d7a8b6e-1f43-4f8d-9e2c-2b1f3a4e7c11",
"cid": "b1f3c5a7-9d2e-4a8b-bc11-7c2e0a9f4d6e"
}A successful call returns 200 OK with an empty body. The most common errors are:
conversion source not exists: theciddoes not match any tracked click. Verify that the click was actually recorded by your tracking integration.revenue origin not exists: therevenueOriginIddoes not match any brand in your workspace.duplicate client: a player with thatexternalIdalready exists under this brand.
Record a player movement
Endpoint: POST /tracking/clients/v1/metrics/movements
Records one or more metric updates against an existing player. Each request can update up to 20 metrics in one atomic call. The player must already be registered; this endpoint does not auto-create players.
The request body fields are:
externalClientId: the sameexternalIdyou used when registering the player. 1–255 characters. Required.revenueOriginId: the same brand UUID the player was registered under. Required.metrics: a list of 1–20 metric updates. Each metriccodemust be unique within the list. Each entry has three fields, described below.requestId: an optional idempotency key (1–100 characters). If your integration retries the same call with the samerequestIdfor the same player, the second attempt is rejected so the balance is not updated twice. Use a stable value from your platform's transaction or event ID. See Player movements for the full idempotency model.
Each entry in the metrics list contains:
code: the metric code exactly as defined on your workspace's player metrics page. Lowercase alphanumeric with hyphens (kebab-case), 1–100 characters. To discover the codes defined in your workspace, callGET /api/node/clients/v1/metrics(see below).valueType: eitherCLIENT_METRIC_VALUE_TYPE_ABSOLUTE(the value replaces the current balance) orCLIENT_METRIC_VALUE_TYPE_RELATIVE(the value is added to the current balance; can be negative). See Player movements for guidance on choosing the right type.value: the numeric value as a string. For example"100","19.99", or"-5". Must be a whole number if the metric is defined as an integer metric.
Example request body:
{
"externalClientId": "player-42",
"revenueOriginId": "0d7a8b6e-1f43-4f8d-9e2c-2b1f3a4e7c11",
"requestId": "deposit-2026-05-28-001",
"metrics": [
{
"code": "deposits-total",
"valueType": "CLIENT_METRIC_VALUE_TYPE_RELATIVE",
"value": "250.00"
},
{
"code": "ngr",
"valueType": "CLIENT_METRIC_VALUE_TYPE_ABSOLUTE",
"value": "1875.50"
}
]
}A successful call returns 200 OK with an empty body. The most common errors are:
client not found: no player matches theexternalClientIdandrevenueOriginIdpair. Register the player first.metric not found: one of the metric codes is not defined on your workspace. Check the spelling against the codes returned by the metric-listing endpoint.invalid integer metric value: a decimal value was sent for a metric defined as integer-typed. Send a whole number.duplicate metric movement request: a movement with the samerequestIdalready exists for this player. The original call was processed; the retry was correctly rejected.
List available metric codes
Endpoint: GET /api/node/clients/v1/metrics
Returns every player metric defined on your workspace, so your integration can validate metric codes at startup or build a configuration UI. The endpoint takes no parameters and uses the same X-Api-Key authentication as the tracking endpoints.
The response contains two arrays, integerMetrics and decimalMetrics, listing the metrics of each type separately. Each entry has:
id: the internal UUID of the metric.name: the display name shown on the dashboard.code: the metric code your integration sends in themetricslist of a movement.monetary: whether the metric represents an amount of money (alwaysfalsefor integer metrics).visible: whether the metric is currently shown as a column on the Player list and Player movements pages in the dashboard.
Example response body:
{
"integerMetrics": [
{
"id": "7e2c1a4b-9f3d-4b2e-8a11-b6c2e0a9f4d6",
"name": "Total bets",
"code": "bets",
"monetary": false,
"visible": true
}
],
"decimalMetrics": [
{
"id": "1a7c5e2f-3b4d-49a8-bcd1-72e0a9f4d6c8",
"name": "Lifetime deposits",
"code": "deposits-total",
"monetary": true,
"visible": true
}
]
}
List recorded movements
Endpoint: POST /api/node/clients/v1/metrics/movements/list
Returns the recorded movement history with paging and filtering. Each row carries the player it belongs to, every metric value the movement updated, the original request payload, the revshare contribution this movement made, and a reference to the settlement that paid it out (if any). This is the same data the dashboard's Players → Player movements log uses.
The endpoint is a POST because the filter object is structured. The request body has two required top-level fields:
pagination: an object withlimit(1–500) andoffset(starting at0).filters: an object with one required time range and four optional list filters, described below.
Inside filters:
timeRange: required. An object withfromandtotimestamps in RFC 3339 format (for example"2026-05-01T00:00:00Z").frommust be earlier thanto.clientIds: optional. A list of internal player UUIDs to filter by. Values must be unique.clientExternalIds: optional. A list of your platform's player identifiers (the same values you sent asexternalClientIdwhen recording movements). Each 1–255 characters, unique.revenueOriginIds: optional. A list of brand UUIDs. Useful when you operate multiple brands and want movements for a subset.requestIds: optional. A list of idempotency keys to look up specific movements your integration recorded. Each 1–100 characters, unique.
Example request body:
{
"pagination": { "limit": 50, "offset": 0 },
"filters": {
"timeRange": {
"from": "2026-05-01T00:00:00Z",
"to": "2026-05-28T23:59:59Z"
},
"clientExternalIds": ["player-42"]
}
}The response has two top-level fields:
rows: the movements that matched, one row per movement.pagination: an object withhasMore(whether more results exist beyond the current page) andtotalCount(the total number of matching movements, when available).
Each row contains:
client: an object identifying the player:id(internal UUID),externalId, andrevenueOriginId.integerMetrics: the integer metrics this movement updated, as a list of{ code, value }entries.decimalMetrics: the decimal metrics this movement updated, as a list of{ code, value }entries. Decimal values are returned as strings to preserve precision.requestData: the exact JSON payload your integration sent, stored verbatim for auditing.requestId: the idempotency key sent with the original call, if any.totalRevshare: the revshare contribution this movement generated, as a decimal string. Always present;"0"when no Player RevShare applies.accountSettlementId: the UUID of the settlement that paid this movement's revshare out, if it has already been settled. Absent on movements still contributing to an open balance.createdAt: the timestamp when the movement was recorded, in RFC 3339 format.
Example response body:
{
"rows": [
{
"client": {
"id": "c9e4f7d1-2a8b-4c3d-9e5f-1a2b3c4d5e6f",
"externalId": "player-42",
"revenueOriginId": "0d7a8b6e-1f43-4f8d-9e2c-2b1f3a4e7c11"
},
"integerMetrics": [],
"decimalMetrics": [
{ "code": "deposits-total", "value": "250.00" }
],
"requestData": "{\"externalClientId\":\"player-42\",\"metrics\":[...]}",
"requestId": "deposit-2026-05-28-001",
"totalRevshare": "12.50",
"createdAt": "2026-05-28T10:34:12Z"
}
],
"pagination": {
"totalCount": 1,
"hasMore": false
}
}
End-to-end flow
A typical integration runs these steps in order for every new player on your platform:
Capture the click: when a referred visitor lands on your site, your tracking integration receives the click UUID. Store this value alongside the visitor's session so it survives until signup.
Register the player: when the visitor creates an account on your platform, call
POST /tracking/client/v1with the new account'sexternalId, the brand'srevenueOriginId, and the savedcid.Record movements: on every event that updates a tracked metric (a deposit, a wager settlement, an NGR update), call
POST /tracking/clients/v1/metrics/movementswith the player'sexternalClientId, the metric code, the value type, and the value. Include arequestIdso retries are safe.
Once movements start flowing, the player's balance updates in real time, the movements appear in the Players → Player movements log, and any offer with Player RevShare configured starts paying the referring affiliate on each movement. To reconcile from your own systems, call POST /api/node/clients/v1/metrics/movements/list with the player's externalClientId or your stored requestId.

