Med Data API (tidigare dokumenterat här som Server API) kan din backend läsa de identifieringsdata som TRACIO redan har samlat in för ditt workspace: en besökares historik, enskilda sessioner och velocity-räknare över korta fönster. Några routes skriver också — kontoposter, anpassade fält och listposter — så att din backend kan berika det TRACIO vet.
Det kompletterar webhooks i stället för att ersätta dem:
| Webhooks | Data API | |
|---|---|---|
| Riktning | TRACIO pushar till din endpoint | Din backend hämtar vid behov |
| Tidpunkt | Så snart en identifiering sker | När som helst, inom ditt lagringsfönster |
| Bäst för | Att reagera på en händelse | Att slå upp data under ett beslut, efterhämtningar, utredningar |
Båda gränssnitten är tillgängliga från prisplanen Pro och uppåt.
https://api.tracio.ai/v2Det här är en annan värd än browser-endpointen (edge.tracio.ai) och än dashboarden
(app.tracio.ai). Alla tre är separata: webbläsaren pratar med edge med din publika
nyckel, din backend pratar med Data API med din hemliga nyckel.
Routes under /v1 har tagits bort. Använd /v2: routes är desamma, och varje
JSON-nyckel och query-parameter skrivs i snake_case (visitor_id, risk_score,
min_risk_score). Nycklar i dina egna ordlistor fields och labels är dina data och
behåller sin ursprungliga stavning. JavaScript-SDK:t behåller sitt camelCase-gränssnitt.
Varje begäran bär din hemliga nyckel som en bearer-token:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"Data API är enbart server-till-server. CORS-headers returneras avsiktligt inte, så en webbläsare kan inte anropa det — det är just det som håller din hemliga nyckel utanför klientkoden. Leverera aldrig den hemliga nyckeln till webbläsaren.
Skapa den i dashboarden under API Keys och välj typen secret.
tracio_sk_ följt av 43 tecken, 53 totalt. Dashboarden
listar den utifrån dess första tecken så att du kan skilja nycklar åt.404, precis som för data som inte finns.Vid rotation utfärdas en ny nyckel medan den gamla fortsätter att fungera i 7 dagar, så att du kan rulla ut den utan avbrott. Rulla ut den nya nyckeln, bekräfta att trafiken har flyttat över, och låt den gamla löpa ut. Publika nycklar går inte att rotera — de är inga hemligheter och syns avsiktligt i sidans källkod.
| Metod | Sökväg | Returnerar |
|---|---|---|
GET | /v2/visitors/{visitor_id} | Aggregerad historik för en besökare, plus dennes senaste session |
GET | /v2/visitors/{visitor_id}/sessions | Paginerad lista över den besökarens sessioner |
GET | /v2/visitors/{visitor_id}/sessions/latest | Den enskilt senaste sessionen |
GET | /v2/visitors/{visitor_id}/velocity | Aktivitetsräknare över ett kort fönster |
GET | /v2/sessions/{request_id} | En session utifrån dess request-identifierare |
POST | /v2/accounts/metadata | Kopplar visningsnamn och e-postadresser till dina konto-id:n |
POST | /v2/events/fields | Kopplar anpassade fält till ett besök efter sidladdningen |
POST | /v2/events/fields/delete | Raderar anpassade fält från ett besök — själva besöket rörs inte |
GET | /v2/lists | Ditt workspace listor: id, namn, typ (åtgärden), läge, antal poster |
POST | /v2/lists/{list_id}/entries | Lägger till ett värde i en lista, valfritt med en TTL |
POST | /v2/lists/{list_id}/entries/delete | Tar bort ett värde från en lista |
GET | /.well-known/webhook-keys | Publika nycklar för webhookarnas plattformssignatur (ingen auth) |
Samma nyckel och värd betjänar också besluts-API:erna, helt i snake_case:
| Metod | Sökväg | Syfte |
|---|---|---|
POST | /v2/transactions | Ett synkront beslut APPROVE / REVIEW / DECLINE om en affärshändelse — från Business och uppåt, utom en affiliate-konvertering (account_register eller deposit med affiliate_id), som finns i varje prisplan med API-åtkomst |
GET | /v2/transactions/{transaction_id} | Läs om ett beslut med dess etikett och gällande tillstånd — från Business och uppåt, utom en transaktion som tillskrivs en affiliate |
PUT, DELETE | /v2/transaction-labels | Sätt eller ta bort utfallsetiketten för upp till 50 transaktioner — från Business och uppåt |
GET | /v2/transaction-labels/value-set | De godkända etikettvärdena med deras polaritet — från Business och uppåt |
POST | /v2/logins/assess | Bedöm en inloggning: allow / challenge / review / deny med skäl |
POST, GET | /v2/accounts/{user_id}/trusted-devices | Lita på enheten från ett besök för ett konto efter din step-up-verifiering, eller lista kontots betrodda enheter |
DELETE | /v2/accounts/{user_id}/trusted-devices/{device_ref} | Återkalla förtroendet för en enhet |
GET | /v2/affiliates/{affiliate_id} | Kvalitetsrapporten för en affiliate över 90 dagar, med en rekommendation hold / review |
POST, GET | /v2/self-exclusions | Sätt eller förläng en självavstängning för ett konto, eller lista dem |
DELETE | /v2/self-exclusions/{user_id} | Häv en självavstängning i förtid |
Deras utfall når dig också som webhook-händelser:
transaction_state_changed, login_risk, trusted_device_enrolled,
trusted_device_revoked och affiliate_threshold_crossed.
Ett avslutande snedstreck accepteras och ignoreras. En okänd sökväg eller fel metod returnerar samma JSON-felkuvert som allt annat, aldrig en HTML- eller klartextsida.
Varje läsning avgränsas av ett tidsfönster, styrt av två valfria query-parametrar:
| Parameter | Godtar |
|---|---|
from | YYYY-MM-DD eller en fullständig RFC 3339-tidsstämpel |
to | YYYY-MM-DD eller en fullständig RFC 3339-tidsstämpel |
to inkluderar hela det dygnet.400 invalid_request och meddelandet
time must be YYYY-MM-DD or RFC3339.meta, så kontrollera meta.from och meta.to i stället för att anta att din
begäran uppfylldes ordagrant.curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"Svaret bär den aggregerade historiken och bäddar in den senaste sessionen, så att det vanliga fallet kräver en begäran i stället för två:
{ "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "first_seen_at": "2026-05-02T10:11:12Z", "last_seen_at": "2026-07-25T08:00:00Z", "visits": 42, "incognito_visits": 3, "unique_ips": 5, "unique_countries": 2, "browsers": ["Chrome"], "os": ["macOS"], "devices": ["desktop"], "risk": { "max_risk_score": 63, "avg_bot_score": 12.5, "bot_sessions": 7, "last_decision": "real" }, "network": { "vpn_seen": false, "proxy_seen": false, "tor_seen": false, "datacenter_seen": true, "proxy_detected_seen": true, "last_isp": "Deutsche Telekom", "last_real_ip": { "address": "203.0.113.7", "country": "NL", "isp": "KPN" } }, "last_session": { "request_id": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "account_id": "user_8842", "account": { "id": "user_8842", "email": "ann@example.com", "display_name": "Ann Lee" }, "timestamp": "2026-07-25T08:00:00Z", "tag": "checkout", "fields": { "order_ref": "A-1029" }, "url": "https://shop.example.com/checkout", "ip": "203.0.113.42", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", "browser": { "name": "Chrome", "version": "126.0" }, "os": { "name": "macOS", "version": "14.5" }, "device": "desktop", "gpu": "Apple M2", "geo": { "country": "DE", "city": "Berlin", "timezone": "Europe/Berlin", "isp": "Deutsche Telekom" }, "network": { "vpn": false, "proxy": false, "tor": false, "datacenter": false, "connection_type": "residential", "proxy_detected": true, "real_ip": { "address": "203.0.113.7", "country": "NL", "isp": "KPN" }, "asn": 3320 }, "screen": { "width": 2560, "height": 1600, "color_depth": 30, "pixel_ratio": 2 }, "locale": { "languages": ["en-US", "de"], "timezone": "Europe/Berlin" }, "client_hints": { "architecture": "arm", "bitness": "64", "platform_version": "14.5.0" }, "extensions": [ { "slug": "ublock-origin", "name": "uBlock Origin", "category": "adblock", "risky": false, "store_url": "https://chromewebstore.google.com/detail/cjpalhdlnbpafiamejdnhcphjbkeiagm" } ], "bot": { "result": "human", "score": 4.5, "antidetect_score": 2.1 }, "identification": { "confidence": 0.97, "incognito": false, "match_type": "exact", "match_confidence": 0.99 }, "device_info": { "device_id": "d_4f9c2e", "cross_browser": true, "confidence": 0.88, "linked_browsers": 2 }, "decision": { "action": "real", "risk_score": 12, "suspect_score": 3 } }, "meta": { "plan": "business", "retention_days": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}| Fält | Betydelse |
|---|---|
visits, incognito_visits | Totalt antal besök i fönstret, och hur många av dem som skedde i ett privat fönster |
unique_ips, unique_countries | Distinkta adresser och länder som setts i fönstret |
browsers, os, devices | De distinkta miljöer den här besökaren har dykt upp i |
risk.max_risk_score | Den högsta riskpoäng som registrerats i fönstret, 0..100 |
risk.last_decision | Det beslut som registrerats för det senaste besöket |
risk.avg_bot_score, risk.bot_sessions | Genomsnittlig botpoäng och antalet bot-sessioner — från Business och uppåt |
network.*_seen | Om ett VPN, en proxy, en Tor-exitnod eller en datacenteradress någonsin setts för den här besökaren |
network.proxy_detected_seen | Om minst ett besök i fönstret gick ut genom en proxy eller ett VPN framför webbläsaren — se network.proxy_detected under Enhetsfakta |
network.last_isp | Den senaste ISP:n — från Business och uppåt |
network.last_real_ip | Den senaste adress som observerats bakom en proxy eller ett VPN (address, country, isp) — från Business och uppåt; saknas när inget besök har gett någon sådan adress |
last_session | Hela session-objektet för det senaste besöket |
meta | Prisplanen, dess lagring i dagar och det fönster som faktiskt tillämpades |
En besökare utan data inom lagringsfönstret ger 404 not_found med meddelandet
visitor not found in the retention window — det är inte ett fel i din integration,
det betyder att besökaren är ny eller har fallit ur lagringstiden.
Sessionen bär två verdikt, och de svarar på olika frågor — om klienten var automatiserad och vad riskmotorn kom fram till på det hela taget:
| Fält | Värden |
|---|---|
bot.result | human, bot, uncertain |
bot.type | Finns när bot.result är bot: antingen ett specifikt verktyg (playwright, puppeteer, selenium, jsdom, claude_computer_use…), en verifierad AI-agent (ai_agent:<vendor>) eller en familj när verktyget inte namnges — automation, headless, antidetect, extension, privacy_browser, impersonation, other |
decision.action | real, fake, suspicious |
bot.score och decision.risk_score löper båda 0..100. Från Business och uppåt gör
guidance om dem till råd per scenario på stegen
allow → challenge → review → deny — se
Guidance för vad varje steg betyder.
Värden och skalor stämmer med v3-webhookens body för samma besök, och guidance
beräknas enligt samma regler.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions?limit=100&min_risk_score=50"| Parameter | Standard | Anmärkningar |
|---|---|---|
limit | 50 | Taket är 500; ett större värde kapas, avvisas inte |
from, to | Prisplanens lagring | Det gemensamma tidsfönstret som beskrivs ovan |
cursor | — | Ogenomskinlig pagineringscursor från föregående sida |
bot_result | — | Behåll endast sessioner med detta bot-verdikt |
min_risk_score | — | Behåll endast sessioner på eller över denna riskpoäng, 0..100 |
Sessionerna kommer tillbaka med den nyaste först:
{ "items": [ { "request_id": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitor_id": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "timestamp": "2026-07-25T08:00:00Z" } ], "next_cursor": "MTcyMTg5NDQwMDAwMDphYmMxMjM", "has_more": true, "meta": { "plan": "business", "retention_days": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}Bläddringen är cursorbaserad. Det finns ingen parameter page eller offset: skicka
tillbaka den next_cursor du fick som cursor, och fortsätt så länge has_more är sant.
Den sista sidan behöver inte innehålla next_cursor alls, så gör inte det fältet
obligatoriskt.
async function allSessions(visitorId: string, secretKey: string) { const sessions = [] let cursor: string | undefined
do { const url = new URL(`https://api.tracio.ai/v2/visitors/${visitorId}/sessions`) url.searchParams.set("limit", "500") if (cursor) url.searchParams.set("cursor", cursor)
const res = await fetch(url, { headers: { Authorization: `Bearer ${secretKey}` } }) if (!res.ok) throw new Error(`Data API: ${res.status}`)
const page = await res.json() sessions.push(...page.items) cursor = page.has_more ? page.next_cursor : undefined } while (cursor)
return sessions}Behandla cursorn som ogenomskinlig — dess innehåll är en implementationsdetalj och kan
ändras. En cursor som har redigerats avvisas med 400 invalid_request och meddelandet
malformed cursor.
Vid sidan av webbläsaren och operativsystemet som hämtas från User-Agent bär en session det som besökarens webbläsare rapporterar om maskinen, sanerat på vår sida. Varje fält saknas när besöket inte bar med sig sådana data, så behandla vart och ett som valfritt.
| Fält | Innebörd |
|---|---|
gpu | Grafikkortets modell så som webbläsaren rapporterar den (WebGL), normaliserad till ett läsbart namn — Intel Iris Xe Graphics, Apple M1 Pro, Qualcomm Adreno 830; Software renderer betyder ingen riktig GPU (en virtuell maskin eller en headless-miljö); Safari rapporterar Apple GPU |
network.proxy_detected | Besökets HTTP-trafik och dess råa nätverksvägar går ut genom olika nätverk — en proxy eller ett VPN framför webbläsaren; två adresser hos samma leverantör (carrier-NAT, en andra utgång i samma VPN) räknas inte; flaggas inte när adresserna inte går att jämföra (iCloud Private Relay, IPv4 bredvid IPv6) |
network.real_ip.address, .country, .isp | Den publika adress som observerats på den råa nätverksvägen, det vill säga adressen bakom proxyn eller VPN:et, med dess land och ISP — från Business och uppåt; saknas när ingen sådan adress observerats (country och isp saknas när de inte gick att fastställa) |
device_info.device_id, .cross_browser, .confidence, .linked_browsers | Finns när en enhetsidentitet kunde fastställas: ett stabilt id för den fysiska enheten gemensamt för webbläsarna på den, om det här besöket kom via en annan webbläsare än tidigare, konfidensen för den matchningen och hur många distinkta besökare (webbläsare) som delar enheten — fler än en betyder en maskin under flera webbläsaridentiteter — från Business och uppåt |
os_environment | Skrivbordsmiljön som mätts på en Linux-maskin (Mint 22+, Ubuntu 25.04+, Ubuntu, GNOME, KDE) — från Business och uppåt; saknas när den inte har fastställts |
spoofing | Vad besöket påstod jämfört med vad oberoende kontroller mätte (claimed, real, spoofed_axes av os, gpu, screen, network, browser; anonymous_browser med produktnamn) — från Business och uppåt; finns endast när en förfalskning upptäckts |
screen.width, .height, .color_depth, .pixel_ratio | Skärmupplösning, färgdjup och device pixel ratio så som webbläsaren rapporterar dem — från Business och uppåt |
locale.languages, locale.timezone | Webbläsarens egna föredragna språk och tidszon — till skillnad från geo.timezone, som härleds från IP-adressen; en avvikelse mellan de två är ett vanligt tecken på en förfalskad plats — från Business och uppåt |
client_hints.architecture, .bitness, .model, .device_name, .platform_version | User-Agent Client Hints: CPU-arkitektur och bitness, enhetens modellkod (Android, t.ex. SM-A556B) med dess marknadsnamn från Google Plays enhetslista (device_name, t.ex. Samsung Galaxy A55 5G) och den exakta plattformsversionen; endast Chromium-baserade webbläsare — från Business och uppåt |
environment.virtual_machine, environment.hypervisor | Finns endast när grafikkortet angav sig självt som virtuellt; hypervisor är en sluten ordlista (vmware, virtualbox, parallels, qemu, hyperv, bochs, intel-gvt, vgpu). Ett block som saknas betyder att inget sådant belägg finns — från Business och uppåt |
extensions listar de webbläsartillägg som upptäckts under besöket — från Pro och uppåt.
Varje post är ett objekt:
| Fält | Betydelse |
|---|---|
slug | Stabil maskinidentifierare för tillägget, samma värde som webhooken levererar |
name | Läsbart namn för människor |
category | Grov klass — adblock, privacy, automation, wallet, vpn, devtools, other och så vidare |
risky | true för tillägg som förknippas med automatisering, förfalskning eller stöld av inloggningsuppgifter |
store_url | Länk till tilläggets sida i butiken, när den är känd |
Ett fynd rapporteras först när det har klarat våra tillförlitlighetskontroller — en miljö som svarar ”installerat” på varje sondering, eller en batch längre än tolv namn, förkastas som opålitlig. En tom eller saknad lista betyder därför ”inget vi kunde bekräfta”, inte ”inga tillägg installerade”. Läs den som ett indicium, inte som en inventering.
fields innehåller de anpassade nyckel-värde-par som din integration har kopplat till
besöket — en orderreferens, ett namn på en prisplan, utfallet av en betalning. Nycklar
och värden är alltid strängar: ett kopplat tal eller booleskt värde kommer tillbaka i
textform. Precis som resten av sessionen är fältet tillgängligt i varje prisplan med
API-åtkomst (Pro och uppåt) och saknas när besöket inte har några fält.
fields läses live vid varje anrop och kopieras inte vid besökstillfället. Fält som
kopplats efter besöket (se Koppla fält efter besöket)
syns också här, så för samma besök kan fields innehålla mer än webhooken levererade.
Lägg inte personuppgifter som namn, e-postadresser eller telefonnummer i anpassade fält — koppla i stället en referens som dina egna system kan slå upp, och skicka vem kontot är som en kontopost (se nedan).
account är din post för kontot bakom besöket — det du senast skickade för det
account_id via POST /v2/accounts/metadata:
{ "account": { "id": "user-42", "email": "ann@example.com", "display_name": "Ann Lee" }}| Fält | Beskrivning |
|---|---|
id | Ditt konto-id — samma värde som account_id |
email | E-postadressen du skickade för kontot; saknas när den är tom |
display_name | Visningsnamnet du skickade för kontot; saknas när det är tomt |
Posten läses live vid varje anrop, så ett namnbyte syns även på gamla besök: blocket beskriver kontot som det är nu, inte som det var vid besökstillfället. Det är tillgängligt i varje prisplan med API-åtkomst (Pro och uppåt). Etiketter som du skickade med posten returneras inte.
Blocket saknas när besöket inte har något kopplat konto, när det inte finns någon post för kontot (eller du har tömt den genom att skicka tomma värden), och — sällan — när posten inte gick att läsa: sessionen returneras ändå i sin helhet i stället för att begäran misslyckas, så behandla ett saknat block som ”okänt”, inte som ”det här kontot har ingen e-post”. Webhooks bär inte det här blocket.
Den senaste:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions/latest"Detta returnerar ett naket session-objekt — ingen array, och inte inslaget i ett kuvert.
En besökare utan sessioner i fönstret ger 404 not_found med
no sessions for this visitor in the retention window.
Eller via request_id, den identifierare som också dyker upp i webhook-payloaden:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/sessions/9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31?visitor_id=X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"visitor_id är valfri här, men att skicka med den när du känner till den gör
uppslagningen märkbart snabbare.
identification.drift_score — den utjämnade beteendepoäng som verdiktet om
kontokapning fattades på, från Business och uppåt — returneras endast av den här
läsningen av en enskild session. Beteendedrift mäts under besöket, efter den första
identifieringen, så routes för listan och den senaste sessionen utelämnar den. Ett
besök vars beteende aldrig bedömdes har ingen drift_score. Samma värde når dig via
webhooken account_takeover.
Ett besök kan levereras mer än en gång via webhook: först primary, sedan late eller
correction när långsammare signaler och beteendebelägg kommer in — och en senare fas
kan välta det tidigare verdiktet. Data API svarar utifrån posten primary. Senare
faser slås inte tillbaka in i den, så för ett korrigerat besök är den sista webhooken
det nyare svaret. Om du agerar minuter efter besöket, föredra den fas du fick sist
framför en ny läsning här.
En sak går åt andra hållet: när detektorn för kontokapning har slagit till för ett
besök återspeglar guidance här det, medan webhook-bodies av typen identification
för samma besök inte bär den axeln — den åker med den separata leveransen
account_takeover.
Velocity svarar på ”hur mycket har den här besökaren gjort på sistone” — formen på credential stuffing, card testing och massregistreringar.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/velocity?window=1h"window godtar 1h, 24h eller 7d och är som standard 24h. Varje annat värde
avvisas med 400 invalid_request och window must be one of: 1h, 24h, 7d.
{ "window": "1h", "events": 37, "unique_ips": 9, "unique_countries": 3, "unique_accounts": 12, "bot_events": 4, "meta": { "plan": "business", "retention_days": 90, "from": "2026-07-25T11:00:00Z", "to": "2026-07-25T12:00:00Z" }}unique_accounts räknar de distinkta linkedId-värden du skickat för den här enheten —
se Kontokoppling. bot_events finns från Business och uppåt;
nyckeln saknas på Pro.
TRACIO känner dina konton endast via det id som din webbplats skickar som linkedId —
en ogenomskinlig sträng som usr_8412. Skicka de läsbara etiketterna en gång, så visar
varje dashboardvy som visar det kontot namnet eller e-postadressen i stället för det
råa id:t, och session-objektet returnerar dem i sitt block
account. Inget här påverkar detektering eller poängsättning; det är
ett visningslager.
curl -s -X POST "https://api.tracio.ai/v2/accounts/metadata" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"accounts":[ {"account_id":"usr_8412","email":"ann@example.com","display_name":"Ann Lee","labels":{"tier":"vip"}}, {"account_id":"usr_9130","display_name":"Bob Ray"} ]}'{ "updated": 2 }fields. En
e-postadress eller ett namn som skickas hit finns bara i ditt workspace kontopost: den
lagras inte per besök, skrivs inte in i sidan, och ett enda anrop uppdaterar varje
besök för det kontot.400 invalid_request, och en felaktig post avvisar hela
batchen — felet anger dess position. Dubblerade konto-id:n i en batch går bra: det
sista vinner.Gränser: 1000 konton per begäran, 1 MiB body, account_id ≤ 256 tecken,
email ≤ 320, display_name ≤ 256, högst 16 etiketter med nycklar ≤ 64 och värden
≤ 256 tecken.
Webbläsaren kan bara skicka det som sidan vet vid renderingen — ett order-id, aldrig utfallet av en betalningskontroll eller något annat som avgörs senare. Den här routen fyller den luckan: hitta besöket via ett fält det redan bär och koppla fler fält till det på serversidan.
curl -s -X POST "https://api.tracio.ai/v2/events/fields" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"match":{"key":"order_ref","value":"A-1029"},"fields":{"amount":"120.00"}}'{ "updated": 1 }match hittar besöket via ett fält det redan har, inte via request_id, inom
nyckelns workspace och miljö.404 not_found — skriv fältet
snart efter att utfallet avgjorts.updated räknar distinkta besök. Det blir större än 1 bara när din match träffar
mer än ett besök — ett nyckel-värde-par som inte är unikt för en order eller
varukorg. En match som träffar mer än 100 händelser nekas med 400 invalid_request
i stället för att tillämpas på en godtycklig delmängd.server, och har företräde framför
ett värde med samma nyckel som skrivits av webbläsaren.404 not_found, inte ett tomt 200.Gränserna är desamma som i webbläsarkanalen: 50 fält per anrop, nycklar ≤ 40 byte,
värden ≤ 500 byte — byte, inte tecken — teckenuppsättning för nycklar
A-Za-z0-9_.:-, 1 MiB body.
Raderar anpassade fält — aldrig själva besöket. Använd det för värden som du inte längre behöver ha kopplade till ett besök, till exempel ett ordertotal. Webhooks som redan skickats och exporter som redan gjorts ändras inte.
# by request_id — clears every field on this one visitcurl -s -X POST "https://api.tracio.ai/v2/events/fields/delete" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"request_id":"9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31"}'
# by match — clears "order_ref" from every visit currently holding "A-1029"curl -s -X POST "https://api.tracio.ai/v2/events/fields/delete" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"match":{"key":"order_ref","value":"A-1029"}}'{ "deleted": 1 }request_id och match utesluter varandra — att skicka båda, eller ingen av dem,
ger 400 invalid_request. match använder samma 24-timmarsfönster och samma tak på
100 händelser som vid koppling.deleted räknar de fält som togs bort från besöket (via request_id) eller de
besök som fältet togs bort från (via match).404 not_found.Samma listor som dina operatörer hanterar i dashboarden, nåbara från din egen
back office. En listas typ är dess åtgärd på ett matchande besök — block,
manual_review, challenge, allow — och dess läge avgör om åtgärden
tillämpas: observe räknar bara träffar, enforce tillämpar den på guidance (axeln
list). Listor och deras läge skapas i dashboarden; Data API läser listor och lägger
till och tar bort poster.
curl -s "https://api.tracio.ai/v2/lists" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX"[ { "id": "7f3a9d2e-4c1b-4e8f-9a6d-1b2c3d4e5f60", "name": "Chargeback accounts", "type": "block", "mode": "enforce", "entries_count": 128 }]# ban an account for 30 dayscurl -s -X POST "https://api.tracio.ai/v2/lists/7f3a9d2e-4c1b-4e8f-9a6d-1b2c3d4e5f60/entries" \ -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ -H "Content-Type: application/json" \ -d '{"value":"usr_8412","value_type":"linked_id","ttl_minutes":43200}'{ "id": "02b4c8d1-6e7f-4a90-b1c2-d3e4f5a6b7c8", "value": "usr_8412", "value_type": "linked_id", "expires_at": "2026-10-19T12:00:00Z", "propagation": "immediate"}Ta bort en post med samma body via POST /v2/lists/{list_id}/entries/delete; svaret
är { "removed": true, "propagation": "immediate" }.
value_type är det som värdet matchas mot: linked_id, visitor_id,
device_id, ip, cidr eller country. Ett värde som inte går att tolka för sin typ
ger 400 invalid_request.linked_id →
visitor_id → device_id → ip → cidr → country — och inom den vinner den
strängaste åtgärden.ttl_minutes är valfri. Utelämnas den gäller listans standard-TTL; finns ingen
sådan löper posten aldrig ut (expires_at är null). Att lägga till en post igen
förnyar den.propagation anger när ändringen är i kraft: immediate, eller ttl — inom
ungefär fem minuter.200 med removed: false; 404 är
reserverat för en okänd lista.Ett fält som saknas betyder ”inga data”, aldrig noll. Fält utan värde utelämnas helt
i stället för att skickas som 0, "" eller null: en helt ny besökare har ingen
match_confidence, ett rent besök har ingen antidetect_score eller suspect_score. Det
enda avsiktliga undantaget är bot.score, som alltid finns med även när den är noll.
Läs fälten defensivt.
Payloaden beror på din prisplan. API-åtkomst börjar på Pro, och Pro får bassessionen
— identifierare, tidsstämpel, URL, IP, user agent, webbläsare, operativsystem, enhet,
geo, nätverk, bot, identifiering och beslut — tillsammans med
identification.match_type, identification.match_confidence, bot.score,
bot.type, bot.antidetect_score, gpu, network.proxy_detected, extensions,
fields och account. Business och Enterprise lägger till geo.isp, network.asn,
network.real_ip, decision.suspect_score, identification.drift_score, reasons,
behavior, guidance, device_info, spoofing, os_environment, screen, locale,
client_hints och environment. Fälten på personnivå (person_id, reputation,
linked_accounts_count, linked_visitors_count) är reserverade för Business och
Enterprise och dyker upp när personlagret slås på — i dag körs det i observationsläge
och dessa fält levereras inte. Att ett Business-fält saknas på en Pro-plan är inte ett
fel.
Interna detaljer på signalnivå returneras aldrig, i ingen prisplan: enskilda signalnamn, deras vikter, trösklarna bakom ett verdikt, råa signalvärden och uppdelningar av poäng stannar på vår sida. En poäng som kan bakåtkompileras till sina indata upphör att vara användbar som skydd.
Varje misslyckande använder ett och samma kuvert:
{ "error": { "code": "unauthorized", "message": "missing Authorization: Bearer <secret key>", "request_id": "8f14e45fceea167a5a36dedd" }}Den här request_id är inte besökets identifierare. Två olika värden delar namn:
inuti en session-payload är request_id besökets UUID, samma som webhooken levererar;
inuti ett felkuvert är det en trace-identifierare på 24 tecken som präglas per
HTTP-anrop. Trace-identifieraren kommer också tillbaka i headern X-Request-Id i varje
svar, lyckat eller inte. Ta med den när du kontaktar supporten — det är så vi hittar
just ditt anrop.
| HTTP | code | Betydelse |
|---|---|---|
| 400 | invalid_request | En parameter saknas eller är felformad |
| 401 | unauthorized | Nyckeln saknas, är ogiltig, återkallad eller utgången |
| 402 | upgrade_required | Din prisplan innehåller inte API-åtkomst |
| 404 | not_found | Inget matchade inom lagringsfönstret, eller det tillhör en annan miljö |
| 405 | method_not_allowed | Routen finns, men inte för den metoden |
| 429 | rate_limited | Antal begäranden per sekund, eller dygnskvoten, överskridet |
| 500 | internal | Något gick fel på vår sida |
| 503 | unavailable | En underliggande lagring är tillfälligt onåbar |
Kontrollerna körs i en fast ordning — nyckel, sedan prisplan, sedan gränser — så en
begäran med fel nyckel rapporterar alltid nyckeln först, aldrig ett kvotproblem. Data
från ett annat workspace går inte att skilja från data som inte finns: de ger 404,
inte 403.
Två 401-fall läses olika med flit: missing Authorization: Bearer <secret key> betyder
att headern aldrig kom fram, medan invalid or revoked API key betyder att den kom fram
och inte matchade. 402 bär Data API requires the Pro plan or higher.
Försök igen vid 429 och 503 med en växande paus; att försöka igen vid andra 4xx
är meningslöst — de betyder att själva begäran behöver rättas.
Svar där nyckeln har känts igen bär din aktuella ställning (svar med 401 och 402
gör det inte, och Enterprise, som saknar dygnskvot, får inga kvot-headers):
| Header | Betydelse |
|---|---|
X-RateLimit-Limit | Din dygnskvot; vid ett avslag per sekund, gränsen per sekund |
X-RateLimit-Remaining | Anrop kvar i dag |
X-RateLimit-Reset | Unix-tid för nollställningen — midnatt UTC |
Retry-After | Sekunder att vänta, skickas endast med ett 429 — gå efter den: den stämmer för båda gränserna |
| Prisplan | Begäranden per sekund | Begäranden per dygn | Historikdjup |
|---|---|---|---|
| Free | Ingen API-åtkomst | — | 7 dagar |
| Pro | 10 | 10 000 | 30 dagar |
| Business | 50 | 100 000 | 90 dagar |
| Enterprise | 200 | Utan kvot | 365 dagar |