curl --request POST \
--url https://plainrouter.com/api/v1/events \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event_name": "<string>",
"consent_basis": "consent",
"event_id": "<string>",
"parent_event_id": "<string>",
"event_time": 123,
"event_source": "<string>",
"action_source": "<string>",
"visitor_id": "<string>",
"consent": {},
"consent_mode": {},
"tcf": {},
"user_data": {},
"click_ids": {},
"value_data": {
"value": "<string>",
"currency": "<string>",
"order_id": "<string>",
"contents": [
"<unknown>"
],
"num_items": 123
}
}
'import requests
url = "https://plainrouter.com/api/v1/events"
payload = {
"event_name": "<string>",
"consent_basis": "consent",
"event_id": "<string>",
"parent_event_id": "<string>",
"event_time": 123,
"event_source": "<string>",
"action_source": "<string>",
"visitor_id": "<string>",
"consent": {},
"consent_mode": {},
"tcf": {},
"user_data": {},
"click_ids": {},
"value_data": {
"value": "<string>",
"currency": "<string>",
"order_id": "<string>",
"contents": ["<unknown>"],
"num_items": 123
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
event_name: '<string>',
consent_basis: 'consent',
event_id: '<string>',
parent_event_id: '<string>',
event_time: 123,
event_source: '<string>',
action_source: '<string>',
visitor_id: '<string>',
consent: {},
consent_mode: {},
tcf: {},
user_data: {},
click_ids: {},
value_data: {
value: '<string>',
currency: '<string>',
order_id: '<string>',
contents: ['<unknown>'],
num_items: 123
}
})
};
fetch('https://plainrouter.com/api/v1/events', 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://plainrouter.com/api/v1/events",
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([
'event_name' => '<string>',
'consent_basis' => 'consent',
'event_id' => '<string>',
'parent_event_id' => '<string>',
'event_time' => 123,
'event_source' => '<string>',
'action_source' => '<string>',
'visitor_id' => '<string>',
'consent' => [
],
'consent_mode' => [
],
'tcf' => [
],
'user_data' => [
],
'click_ids' => [
],
'value_data' => [
'value' => '<string>',
'currency' => '<string>',
'order_id' => '<string>',
'contents' => [
'<unknown>'
],
'num_items' => 123
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://plainrouter.com/api/v1/events"
payload := strings.NewReader("{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://plainrouter.com/api/v1/events")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://plainrouter.com/api/v1/events")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}"
response = http.request(request)
puts response.read_body{
"event_id": "<string>",
"duplicate": true
}{
"event_id": "<string>",
"duplicate": true
}{
"message": "<string>"
}{
"message": "<string>",
"errors": {}
}Submit a conversion event
Accepts a consent-aware server-side conversion event. Supply either event_id in the JSON body or Idempotency-Key in the request headers to make retries idempotent.
curl --request POST \
--url https://plainrouter.com/api/v1/events \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event_name": "<string>",
"consent_basis": "consent",
"event_id": "<string>",
"parent_event_id": "<string>",
"event_time": 123,
"event_source": "<string>",
"action_source": "<string>",
"visitor_id": "<string>",
"consent": {},
"consent_mode": {},
"tcf": {},
"user_data": {},
"click_ids": {},
"value_data": {
"value": "<string>",
"currency": "<string>",
"order_id": "<string>",
"contents": [
"<unknown>"
],
"num_items": 123
}
}
'import requests
url = "https://plainrouter.com/api/v1/events"
payload = {
"event_name": "<string>",
"consent_basis": "consent",
"event_id": "<string>",
"parent_event_id": "<string>",
"event_time": 123,
"event_source": "<string>",
"action_source": "<string>",
"visitor_id": "<string>",
"consent": {},
"consent_mode": {},
"tcf": {},
"user_data": {},
"click_ids": {},
"value_data": {
"value": "<string>",
"currency": "<string>",
"order_id": "<string>",
"contents": ["<unknown>"],
"num_items": 123
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
event_name: '<string>',
consent_basis: 'consent',
event_id: '<string>',
parent_event_id: '<string>',
event_time: 123,
event_source: '<string>',
action_source: '<string>',
visitor_id: '<string>',
consent: {},
consent_mode: {},
tcf: {},
user_data: {},
click_ids: {},
value_data: {
value: '<string>',
currency: '<string>',
order_id: '<string>',
contents: ['<unknown>'],
num_items: 123
}
})
};
fetch('https://plainrouter.com/api/v1/events', 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://plainrouter.com/api/v1/events",
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([
'event_name' => '<string>',
'consent_basis' => 'consent',
'event_id' => '<string>',
'parent_event_id' => '<string>',
'event_time' => 123,
'event_source' => '<string>',
'action_source' => '<string>',
'visitor_id' => '<string>',
'consent' => [
],
'consent_mode' => [
],
'tcf' => [
],
'user_data' => [
],
'click_ids' => [
],
'value_data' => [
'value' => '<string>',
'currency' => '<string>',
'order_id' => '<string>',
'contents' => [
'<unknown>'
],
'num_items' => 123
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://plainrouter.com/api/v1/events"
payload := strings.NewReader("{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://plainrouter.com/api/v1/events")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://plainrouter.com/api/v1/events")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event_name\": \"<string>\",\n \"consent_basis\": \"consent\",\n \"event_id\": \"<string>\",\n \"parent_event_id\": \"<string>\",\n \"event_time\": 123,\n \"event_source\": \"<string>\",\n \"action_source\": \"<string>\",\n \"visitor_id\": \"<string>\",\n \"consent\": {},\n \"consent_mode\": {},\n \"tcf\": {},\n \"user_data\": {},\n \"click_ids\": {},\n \"value_data\": {\n \"value\": \"<string>\",\n \"currency\": \"<string>\",\n \"order_id\": \"<string>\",\n \"contents\": [\n \"<unknown>\"\n ],\n \"num_items\": 123\n }\n}"
response = http.request(request)
puts response.read_body{
"event_id": "<string>",
"duplicate": true
}{
"event_id": "<string>",
"duplicate": true
}{
"message": "<string>"
}{
"message": "<string>",
"errors": {}
}Authorizations
Per-tracker bearer secret. It authenticates only the Signal tracker represented by the credential.
Headers
Optional idempotency key. When event_id is omitted, PlainRouter uses this value as event_id. If both are supplied, they must match.
Body
- Option 1
- Option 2
Signal event name; maximum 100 characters.
Legal basis for processing. Legitimate-interest revenue lifecycle events are rejected; use an authenticated server adapter.
"consent"Caller-supplied idempotency key; maximum 128 characters.
Optional parent event id; maximum 128 characters.
Unix timestamp or ISO-8601 date-time. Defaults to receipt time.
Optional absolute source URL.
Optional action source; defaults to website and is limited to 50 characters.
Optional visitor identifier; maximum 255 characters.
Consent state supplied with the event.
Show child attributes
Show child attributes
Consent Mode v2 signal values supplied with the event.
Show child attributes
Show child attributes
TCF v2 data containing string and optional captured_at.
Show child attributes
Show child attributes
Identity fields accepted by the tracker.
Show child attributes
Show child attributes
Advertising click identifiers.
Show child attributes
Show child attributes
Optional commerce data. Contents accepts at most 50 items and 16 KB serialized.
Show child attributes
Show child attributes