curl --request POST \
--url https://e.trackplay.io/v1/conversion \
--header 'Content-Type: application/json' \
--data '
{
"workspace_code": "WS123",
"integration": "clickbank",
"order_id": "ORDER-9001",
"value": 97,
"currency": "USD",
"session_id": "3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22",
"customer_email": "buyer@example.com"
}
'import requests
url = "https://e.trackplay.io/v1/conversion"
payload = {
"workspace_code": "WS123",
"integration": "clickbank",
"order_id": "ORDER-9001",
"value": 97,
"currency": "USD",
"session_id": "3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22",
"customer_email": "buyer@example.com"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_code: 'WS123',
integration: 'clickbank',
order_id: 'ORDER-9001',
value: 97,
currency: 'USD',
session_id: '3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22',
customer_email: 'buyer@example.com'
})
};
fetch('https://e.trackplay.io/v1/conversion', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://e.trackplay.io/v1/conversion",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_code' => 'WS123',
'integration' => 'clickbank',
'order_id' => 'ORDER-9001',
'value' => 97,
'currency' => 'USD',
'session_id' => '3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22',
'customer_email' => 'buyer@example.com'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://e.trackplay.io/v1/conversion"
payload := strings.NewReader("{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://e.trackplay.io/v1/conversion")
.header("Content-Type", "application/json")
.body("{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://e.trackplay.io/v1/conversion")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"id": "<string>",
"conversion_source": "browser",
"verified": false,
"attributed": true
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "Too many requests"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}Record a browser-side conversion (fallback)
Reports a sale from the browser, for a cart integration that cannot post server-to-server. No token is required or checked; the endpoint is public, CORS-enabled, and rate-limited per IP instead.
This is a fallback, not a replacement for a real integration postback. Every row it writes is stamped unverified: it is excluded from revenue, EPC, RPV, ROAS, and every other aggregate that only counts server-confirmed sales, and it never fires ad-platform pixels or CRM webhooks. If the same order later arrives through the integration’s real postback, the two collapse into one row and the verified postback always wins, regardless of which arrived first.
The integration named in integration must have the browser conversion fallback turned on for this workspace, or the call is rejected. Turn it on in TrackPlay under that integration’s settings.
Server: https://e.trackplay.io
curl --request POST \
--url https://e.trackplay.io/v1/conversion \
--header 'Content-Type: application/json' \
--data '
{
"workspace_code": "WS123",
"integration": "clickbank",
"order_id": "ORDER-9001",
"value": 97,
"currency": "USD",
"session_id": "3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22",
"customer_email": "buyer@example.com"
}
'import requests
url = "https://e.trackplay.io/v1/conversion"
payload = {
"workspace_code": "WS123",
"integration": "clickbank",
"order_id": "ORDER-9001",
"value": 97,
"currency": "USD",
"session_id": "3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22",
"customer_email": "buyer@example.com"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_code: 'WS123',
integration: 'clickbank',
order_id: 'ORDER-9001',
value: 97,
currency: 'USD',
session_id: '3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22',
customer_email: 'buyer@example.com'
})
};
fetch('https://e.trackplay.io/v1/conversion', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://e.trackplay.io/v1/conversion",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_code' => 'WS123',
'integration' => 'clickbank',
'order_id' => 'ORDER-9001',
'value' => 97,
'currency' => 'USD',
'session_id' => '3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22',
'customer_email' => 'buyer@example.com'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://e.trackplay.io/v1/conversion"
payload := strings.NewReader("{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://e.trackplay.io/v1/conversion")
.header("Content-Type", "application/json")
.body("{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://e.trackplay.io/v1/conversion")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_code\": \"WS123\",\n \"integration\": \"clickbank\",\n \"order_id\": \"ORDER-9001\",\n \"value\": 97,\n \"currency\": \"USD\",\n \"session_id\": \"3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22\",\n \"customer_email\": \"buyer@example.com\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"id": "<string>",
"conversion_source": "browser",
"verified": false,
"attributed": true
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "Too many requests"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}Body
Every row this endpoint writes is stamped conversion_source: browser and verified: false. It never feeds the revenue, EPC, RPV, or ROAS numbers your dashboard treats as real: those only count verified rows. It also never fires ad-platform pixels or CRM webhooks, because an unverified sale must not reach a customer's ad account as a confirmed Purchase event. Use this only as a fallback for a cart that cannot post server-to-server; prefer the real integration postback or POST /conversions wherever you can reach either one.
Your workspace's public code. Required.
100Which cart integration this fallback backs, e.g. clickbank. Required. The integration must have the browser conversion fallback turned on for this workspace, or the call is rejected.
60Your order ID. Required. This is the dedup key: a server-to-server postback for the same integration and order collapses into the same row, and the server-confirmed row always wins.
190The sale amount. Required.
x >= 0340The player session that produced the sale, if you have it. Used to attribute the conversion and to pick up the session's video if video_code is omitted.
100100Wins over the session's last video when both are available.
10025564255255190Extra key/value pairs to keep with the conversion.