يتيح Data API (الذي كان يُوثَّق هنا باسم Server API) لخادمك الخلفي أن يقرأ بيانات التعرّف التي جمعها TRACIO بالفعل لمساحة عملك: تاريخ الزائر، والجلسات المفردة، وعدّادات velocity على نافذة قصيرة. وبعض المسارات تكتب أيضًا — سجلات الحسابات والحقول المخصّصة ومُدخلات القوائم — ليتمكّن خادمك الخلفي من إثراء ما يعرفه TRACIO.
وهو مكمّل لـ Webhooks لا بديل عنها:
| Webhooks | Data API | |
|---|---|---|
| الاتجاه | يدفع TRACIO إلى نقطة النهاية لديك | يسحب خادمك الخلفي عند الطلب |
| التوقيت | مع وقوع كل عملية تعرّف | في أي وقت، ضمن نافذة الاحتفاظ لديك |
| الأنسب لـ | التفاعل مع حدث | البحث عن البيانات أثناء اتخاذ قرار، وإعادة التعبئة، والتحقيقات |
كلا السطحين متاح اعتبارًا من خطة Pro وما فوقها.
https://api.tracio.ai/v2هذا مضيف مختلف عن نقطة نهاية المتصفح (edge.tracio.ai) وعن لوحة التحكم
(app.tracio.ai). والثلاثة منفصلة: يتحدث المتصفح إلى الحافة بمفتاحك العام، ويتحدث
خادمك الخلفي إلى Data API بمفتاحك السرّي.
أُزيلت مسارات /v1. استخدم /v2: المسارات هي نفسها، وكل مفتاح JSON وكل معامِل استعلام
بصيغة snake_case (visitor_id، risk_score، min_risk_score). أما المفاتيح داخل
قاموسَي fields وlabels الخاصّين بك فهي بياناتك وتحتفظ بتهجئتها الأصلية. ويحتفظ
JavaScript SDK بواجهته بصيغة camelCase.
يحمل كل طلب مفتاحك السرّي بوصفه رمز bearer:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"Data API مخصّص للاتصال بين الخوادم فقط. فترويسات CORS لا تُعاد عن قصد، ولذلك لا يستطيع المتصفح استدعاءه — وهذا هو ما يُبقي مفتاحك السرّي خارج الكود الذي يعمل من جهة العميل. لا تشحن المفتاح السرّي إلى المتصفح أبدًا.
أنشئه في لوحة التحكم ضمن API Keys، واختر النوع secret.
tracio_sk_ متبوعًا بـ 43 حرفًا، أي 53 حرفًا في المجموع.
وتسرده لوحة التحكم بأحرفه الأولى القليلة لتتمكّن من التمييز بين المفاتيح.404،
تمامًا كما في حالة البيانات غير الموجودة.يُصدر التدوير مفتاحًا جديدًا ويُبقي القديم صالحًا لمدة 7 أيام، فيمكنك طرحه دون توقّف للخدمة. انشر المفتاح الجديد، وتأكّد من انتقال حركة الطلبات إليه، ثم دع القديم ينتهي. أما المفاتيح العامة فغير قابلة للتدوير — فهي ليست أسرارًا وهي ظاهرة في شفرة صفحتك عن قصد.
| الطريقة | المسار | ما يعيده |
|---|---|---|
GET | /v2/visitors/{visitor_id} | تاريخ مجمَّع لزائر واحد، إضافةً إلى أحدث جلسة له |
GET | /v2/visitors/{visitor_id}/sessions | قائمة مقسَّمة إلى صفحات بجلسات ذلك الزائر |
GET | /v2/visitors/{visitor_id}/sessions/latest | الجلسة الأحدث وحدها |
GET | /v2/visitors/{visitor_id}/velocity | عدّادات النشاط على نافذة قصيرة |
GET | /v2/sessions/{request_id} | جلسة واحدة بمعرّف طلبها |
POST | /v2/accounts/metadata | إرفاق أسماء العرض وعناوين البريد الإلكتروني بمعرّفات حساباتك |
POST | /v2/events/fields | إرفاق حقول مخصّصة بزيارة بعد تحميل الصفحة |
POST | /v2/events/fields/delete | محو الحقول المخصّصة من زيارة — دون المساس بالزيارة نفسها |
GET | /v2/lists | قوائم مساحة عملك: المعرّف، والاسم، والنوع (الإجراء)، والوضع، وعدد المُدخلات |
POST | /v2/lists/{list_id}/entries | إضافة قيمة إلى قائمة، مع TTL اختياريًا |
POST | /v2/lists/{list_id}/entries/delete | إزالة قيمة من قائمة |
GET | /.well-known/webhook-keys | المفاتيح العامة لتوقيع منصة الـ webhook (بلا مصادقة) |
ويخدم المفتاح نفسه والمضيف نفسه أيضًا واجهات القرار، وكلها بصيغة snake_case:
| الطريقة | المسار | الغرض |
|---|---|---|
POST | /v2/transactions | قرار متزامن APPROVE / REVIEW / DECLINE بشأن حدث تجاري — Business وما فوقها، باستثناء تحويل التسويق بالعمولة (account_register أو deposit مع affiliate_id)، المتاح في كل خطة تتيح الوصول إلى API |
GET | /v2/transactions/{transaction_id} | إعادة قراءة قرار مع وسمه وحالته الفعلية — Business وما فوقها، باستثناء المعاملة المنسوبة إلى شريك تسويق بالعمولة |
PUT, DELETE | /v2/transaction-labels | تعيين وسم النتيجة لما يصل إلى 50 معاملة أو إزالته — Business وما فوقها |
GET | /v2/transaction-labels/value-set | قيم الوسوم المقبولة مع قطبيتها — Business وما فوقها |
POST | /v2/logins/assess | تقييم تسجيل دخول: allow / challenge / review / deny مع الأسباب |
POST, GET | /v2/accounts/{user_id}/trusted-devices | منح الثقة لجهاز زيارة ما لحساب بعد التحقق الإضافي (step-up) لديك، أو سرد الأجهزة الموثوقة للحساب |
DELETE | /v2/accounts/{user_id}/trusted-devices/{device_ref} | إلغاء الثقة بجهاز |
GET | /v2/affiliates/{affiliate_id} | تقرير جودة شريك التسويق بالعمولة على مدى 90 يومًا، مع توصية hold / review |
POST, GET | /v2/self-exclusions | تعيين استبعاد ذاتي على حساب أو تمديده، أو سرد حالات الاستبعاد |
DELETE | /v2/self-exclusions/{user_id} | رفع الاستبعاد الذاتي مبكرًا |
وتصلك نتائجها أيضًا بوصفها أحداث webhook:
transaction_state_changed وlogin_risk وtrusted_device_enrolled
وtrusted_device_revoked وaffiliate_threshold_crossed.
تُقبل الشرطة المائلة في نهاية المسار ويجري تجاهلها. أما المسار غير المعروف أو الطريقة الخاطئة فيعيدان مغلّف أخطاء JSON نفسه الذي يعيده كل شيء آخر، لا صفحة HTML ولا نصًّا عاديًا أبدًا.
كل قراءة محدودة بنافذة زمنية يضبطها معامِلا استعلام اختياريان:
| المعامِل | يقبل |
|---|---|
from | YYYY-MM-DD أو طابع وقت كامل بصيغة RFC 3339 |
to | YYYY-MM-DD أو طابع وقت كامل بصيغة RFC 3339 |
to يشمل ذلك اليوم بأكمله.400 invalid_request وبالرسالة
time must be YYYY-MM-DD or RFC3339.meta، لذا راجع meta.from
وmeta.to بدل افتراض أن طلبك نُفِّذ حرفيًا.curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"تحمل الاستجابة التاريخ المجمَّع وتُضمّن أحدث جلسة، فتكفي الحالةَ الشائعة طلبٌ واحد بدل طلبين:
{ "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" }}| الحقل | المعنى |
|---|---|
visits، incognito_visits | إجمالي الزيارات في النافذة، وكم منها جرى في نافذة تصفّح خاصة |
unique_ips، unique_countries | العناوين والبلدان المختلفة التي رُصدت في النافذة |
browsers، os، devices | البيئات المختلفة التي ظهر فيها هذا الزائر |
risk.max_risk_score | أعلى درجة مخاطر سُجّلت في النافذة، 0..100 |
risk.last_decision | الحكم المسجَّل لأحدث زيارة |
risk.avg_bot_score، risk.bot_sessions | متوسط درجة البوت وعدد جلسات البوتات — Business وما فوقها |
network.*_seen | هل رُصد لهذا الزائر يومًا VPN أو بروكسي أو عقدة خروج Tor أو عنوان مركز بيانات |
network.proxy_detected_seen | هل خرجت زيارة واحدة على الأقل في النافذة عبر بروكسي أو VPN أمام المتصفح — راجع network.proxy_detected في حقائق الجهاز |
network.last_isp | أحدث مزوّد خدمة إنترنت — Business وما فوقها |
network.last_real_ip | أحدث عنوان رُصد خلف بروكسي أو VPN (address، country، isp) — Business وما فوقها؛ غائب عندما لا تأتي به زيارة |
last_session | كائن الجلسة الكامل لأحدث زيارة |
meta | الخطة، ومدّة احتفاظها بالأيام، والنافذة المطبَّقة فعليًا |
الزائر الذي لا توجد له بيانات داخل نافذة الاحتفاظ يعيد 404 not_found مع الرسالة
visitor not found in the retention window — وهذا ليس خطأً في تكاملك، بل يعني أن
الزائر جديد أو أن بياناته تجاوزت مدّة الاحتفاظ.
تحمل الجلسة حكمَين اثنين، وهما يجيبان عن سؤالين مختلفين — هل كان العميل مؤتمتًا، وإلامَ انتهى محرّك المخاطر إجمالًا:
| الحقل | القيم |
|---|---|
bot.result | human، bot، uncertain |
bot.type | موجود عندما تكون قيمة bot.result هي bot: إمّا أداة بعينها (playwright، puppeteer، selenium، jsdom، claude_computer_use…)، وإمّا وكيل ذكاء اصطناعي موثَّق (ai_agent:<vendor>)، وإمّا عائلة عندما لا تُسمّى الأداة — automation، headless، antidetect، extension، privacy_browser، impersonation، other |
decision.action | real، fake، suspicious |
يقع كل من bot.score وdecision.risk_score على المقياس 0..100. واعتبارًا من Business
وما فوقها، يحوّلهما guidance إلى توصية لكل سيناريو على السلّم
allow ← challenge ← review ← deny — راجع
Guidance لمعرفة معنى كل درجة.
وتطابق القيم والمقاييس جسم webhook بالإصدار v3 للزيارة نفسها، ويُحسب guidance وفق
القواعد نفسها.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions?limit=100&min_risk_score=50"| المعامِل | الافتراضي | ملاحظات |
|---|---|---|
limit | 50 | بحدّ أقصى 500؛ والقيمة الأكبر تُقلَّم ولا تُرفض |
from، to | احتفاظ الخطة | النافذة الزمنية المشتركة الموصوفة أعلاه |
cursor | — | مؤشّر تصفّح معتم من الصفحة السابقة |
bot_result | — | أبقِ الجلسات ذات هذا الحكم بشأن البوت فقط |
min_risk_score | — | أبقِ الجلسات عند درجة المخاطر هذه أو فوقها فقط، 0..100 |
تعود الجلسات بدءًا من الأحدث:
{ "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" }}التصفّح قائم على المؤشّر. ولا يوجد معامِل page ولا offset: مرِّر قيمة next_cursor
التي استلمتها بوصفها cursor، وواصِل ما دامت has_more صحيحة. وقد لا تتضمن الصفحة
الأخيرة next_cursor إطلاقًا، فلا تجعل هذا الحقل مطلوبًا.
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}تعامَل مع المؤشّر بوصفه معتمًا — فمحتواه تفصيل تنفيذي وقد يتغيّر. والمؤشّر الذي جرى
تعديله يُرفض بالرمز 400 invalid_request وبالرسالة malformed cursor.
إلى جانب المتصفح ونظام التشغيل المأخوذين من الـUser-Agent، تحمل الجلسة ما يبلّغه متصفح الزائر عن الآلة، بعد تنقيته لدينا. وكل حقل يغيب عندما لا تحمل الزيارة بيانات كهذه، فتعامل مع كلٍّ منها على أنه اختياري.
| الحقل | المعنى |
|---|---|
gpu | طراز مُهايئ الفيديو كما يبلّغ عنه المتصفح (WebGL)، مُطبَّع إلى اسم مقروء — Intel Iris Xe Graphics، Apple M1 Pro، Qualcomm Adreno 830؛ وSoftware renderer يعني غياب معالج رسوميات حقيقي (جهاز افتراضي أو بيئة headless)؛ وSafari يبلّغ Apple GPU |
network.proxy_detected | حركة HTTP الخاصة بالزيارة ومساراتها الشبكية الخام تخرج عبر شبكات مختلفة — أي وجود بروكسي أو VPN أمام المتصفح؛ وعنوانان لدى المزوّد نفسه (NAT المشغّل، أو مخرج ثانٍ لنفس الـVPN) لا يُحتسبان؛ ولا يُرفع عندما يتعذّر مقارنة العناوين (iCloud Private Relay، أو IPv4 إلى جانب IPv6) |
network.real_ip.address, .country, .isp | العنوان العام المرصود على المسار الشبكي الخام، أي العنوان خلف البروكسي أو الـVPN، مع بلده ومزوّد خدمة الإنترنت الخاص به — Business وما فوقها؛ غائب عندما لا يُرصد عنوان كهذا (ويغيب country وisp عندما يتعذّر تحديدهما) |
device_info.device_id, .cross_browser, .confidence, .linked_browsers | موجود عندما يُحدَّد تعريف الجهاز: معرّف ثابت للجهاز المادي عبر المتصفحات التي عليه، وهل جاءت هذه الزيارة عبر متصفح مختلف عن السابق، ودرجة الثقة في هذا التطابق، وكم زائرًا مختلفًا (متصفحًا) يتشارك الجهاز — وما زاد عن واحد يعني آلة واحدة تحت هويات متصفحات عدّة — Business وما فوقها |
os_environment | بيئة سطح المكتب المقيسة على جهاز Linux (Mint 22+، Ubuntu 25.04+، Ubuntu، GNOME، KDE) — Business وما فوقها؛ غائبة عندما لا تُحدَّد |
spoofing | ما ادّعته الزيارة مقابل ما قاسته فحوص مستقلة (claimed، real، وspoofed_axes من os وgpu وscreen وnetwork وbrowser؛ وanonymous_browser بأسماء المنتجات) — Business وما فوقها؛ موجود فقط عندما يُكتشف انتحال |
screen.width, .height, .color_depth, .pixel_ratio | دقة الشاشة وعمق الألوان وdevice pixel ratio كما يبلّغها المتصفح — Business وما فوقها |
locale.languages, locale.timezone | اللغات المفضّلة للمتصفح نفسه ومنطقته الزمنية — خلافًا لـgeo.timezone المشتقة من عنوان IP؛ والتباين بينهما علامة شائعة على موقع منتحَل — Business وما فوقها |
client_hints.architecture, .bitness, .model, .device_name, .platform_version | تلميحات العميل في User-Agent: معمارية المعالج وعرضه بالبتّات، ورمز طراز الجهاز (Android، مثل SM-A556B) مع اسمه التسويقي من قائمة أجهزة Google Play (device_name، مثل Samsung Galaxy A55 5G)، وإصدار المنصّة الدقيق؛ المتصفحات المبنية على Chromium فقط — Business وما فوقها |
environment.virtual_machine, environment.hypervisor | موجود فقط عندما يعرّف مُهايئ الفيديو نفسه بأنه افتراضي؛ وhypervisor قاموس مغلق (vmware، virtualbox، parallels، qemu، hyperv، bochs، intel-gvt، vgpu). وغياب الكتلة يعني أنه لا دليل من هذا القبيل — Business وما فوقها |
يسرد extensions إضافات المتصفح المكتشفة أثناء الزيارة — Pro وما فوقها. وكل مُدخل فيه كائن:
| الحقل | المعنى |
|---|---|
slug | معرّف آلي ثابت للإضافة، وهو القيمة نفسها التي يسلّمها webhook |
name | الاسم المقروء للبشر |
category | تصنيف عام — adblock، privacy، automation، wallet، vpn، devtools، other، وما إلى ذلك |
risky | القيمة true للإضافات المرتبطة بالأتمتة أو الانتحال أو سرقة بيانات الاعتماد |
store_url | رابط صفحة الإضافة في المتجر، عند معرفته |
لا يُبلَّغ عن أي نتيجة إلا بعد اجتيازها فحوص الثقة لدينا — فالبيئة التي تجيب «مثبَّتة» عن كل استقصاء، أو الدفعة التي تزيد على اثني عشر اسمًا، تُستبعد بوصفها غير موثوقة. ولذلك فالقائمة الفارغة أو الغائبة تعني «لا شيء استطعنا تأكيده»، لا «لا إضافات مثبَّتة». اقرأها بوصفها دليلًا لا جردًا.
يحمل fields أزواج المفتاح والقيمة المخصّصة التي أرفقها تكاملكم بالزيارة — مرجع طلب، أو اسم خطة، أو نتيجة دفع. المفاتيح والقيم سلاسل نصية دائمًا: الرقم أو القيمة المنطقية المُرفقة تعود بصيغتها النصية. ومثل بقية الجلسة، يتوفر في كل خطة تتيح الوصول إلى API (Pro وما فوقها)، ويغيب عندما لا تحمل الزيارة أي حقول.
يُقرأ fields مباشرةً عند كل طلب، ولا يُنسخ لحظة الزيارة. لذلك تظهر هنا أيضًا الحقول المُرفقة بعد الزيارة (راجع إرفاق الحقول بعد الزيارة)، وقد يحتوي fields للزيارة نفسها على أكثر مما سلّمه webhook.
لا تضعوا بيانات شخصية مثل الأسماء أو عناوين البريد الإلكتروني أو أرقام الهواتف في الحقول المخصّصة — أرفقوا بدلًا منها مرجعًا تستطيع أنظمتكم الخاصة الربط به، وأرسلوا هوية صاحب الحساب بوصفها سجلّ حساب (أدناه).
account هو سجلّك للحساب الذي يقف خلف الزيارة — آخر ما أرسلته لقيمة account_id تلك عبر POST /v2/accounts/metadata:
{ "account": { "id": "user-42", "email": "ann@example.com", "display_name": "Ann Lee" }}| الحقل | الوصف |
|---|---|
id | معرّف حسابك — القيمة نفسها الواردة في account_id |
email | عنوان البريد الإلكتروني الذي أرسلته للحساب؛ غائب عندما يكون فارغًا |
display_name | اسم العرض الذي أرسلته للحساب؛ غائب عندما يكون فارغًا |
يُقرأ السجلّ مباشرةً عند كل طلب، لذا تظهر إعادة التسمية على الزيارات القديمة أيضًا: فالكتلة تصف الحساب كما هو الآن، لا كما كان لحظة الزيارة. وهو متاح في كل خطة تتيح الوصول إلى API (Pro وما فوقها). ولا تُعاد الوسوم التي أرسلتها مع السجلّ.
تكون الكتلة غائبة عندما لا يكون للزيارة حساب مرتبط، وعندما لا يوجد سجلّ له (أو مسحته بإرسال قيم فارغة)، و— نادرًا — عندما يتعذّر قراءة السجلّ: إذ تُعاد الجلسة كاملةً بدل إفشال الطلب، فتعامَل مع الكتلة الغائبة على أنها «غير معروف»، لا على أنها «هذا الحساب بلا بريد إلكتروني». ولا تحمل الـ webhooks هذه الكتلة.
الجلسة الأحدث:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions/latest"يعيد هذا كائن جلسة مجرّدًا — لا مصفوفة ولا مغلَّفًا داخل غلاف. والزائر الذي لا جلسات له
في النافذة يعيد 404 not_found مع
no sessions for this visitor in the retention window.
أو عبر request_id، وهو المعرّف الذي يظهر أيضًا في حمولة الـ webhook:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/sessions/9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31?visitor_id=X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"visitor_id اختياري هنا، لكن تمريره حين تعرفه يجعل البحث أسرع بوضوح.
identification.drift_score — درجة السلوك المُنعَّمة التي صدر عليها حكم الاستيلاء على الحساب، Business وما فوقها — لا يعيدها إلا هذا المسار لقراءة جلسة مفردة. فانحراف السلوك يُقاس أثناء الزيارة، بعد التعرّف الأولي، ولذلك يحذفه مسارا القائمة وأحدث جلسة. والزيارة التي لم يُحكم على سلوكها قط لا drift_score لها. والقيمة نفسها تصلك عبر webhook الحدث account_takeover.
قد تُسلَّم الزيارة الواحدة أكثر من مرة عبر webhook: primary أولًا، ثم late أو correction مع وصول الإشارات الأبطأ والأدلة السلوكية — وقد تنقض المرحلة اللاحقة الحكم الأسبق. يجيب Data API من سجلّ primary. ولا تُدمج المراحل اللاحقة فيه، لذا فآخر webhook هو الإجابة الأحدث للزيارة المصحَّحة. وإذا كنت تتصرف بعد الزيارة بدقائق، فقدِّم المرحلة التي استلمتها أخيرًا على قراءة جديدة من هنا.
أمر واحد يسير في الاتجاه المعاكس: متى أُطلق كاشف الاستيلاء على الحساب لزيارة ما، يعكس guidance هنا ذلك، بينما لا تحمل أجسام webhook الحدث identification للزيارة نفسها هذا المحور — فهو يصل مع عملية التسليم المخصّصة account_takeover.
يجيب velocity عن سؤال «كم كان نشاط هذا الزائر مؤخرًا» — وهو شكل حشو بيانات الاعتماد واختبار البطاقات والتسجيلات بالجملة.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v2/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/velocity?window=1h"يقبل window القيم 1h أو 24h أو 7d وقيمته الافتراضية 24h. وأي قيمة أخرى تُرفض
بالرمز 400 invalid_request وبالرسالة 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 قيم linkedId المختلفة التي أرسلتها لهذا الجهاز — راجع
ربط الحسابات. وbot_events متاح في Business وما فوقها؛ ويغيب
المفتاح في Pro.
لا يعرف TRACIO حساباتك إلا بالمعرّف الذي يمرّره موقعك بوصفه linkedId — سلسلة معتمة مثل usr_8412. أرسل التسميات البشرية مرة واحدة، فتعرض كل شاشة في لوحة التحكم تُظهر ذلك الحساب الاسمَ أو البريد الإلكتروني بدل المعرّف الخام، ويعيدهما كائن الجلسة في كتلة account الخاصة به. ولا شيء هنا يؤثر في الكشف أو التقييم؛ إنها طبقة عرض.
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. فالبريد الإلكتروني أو الاسم
المرسَل هنا يعيش فقط في سجلّ الحساب لمساحة عملك: لا يُخزَّن لكل زيارة، ولا يُكتب في
الصفحة، وإرسال واحد يحدّث كل زيارة لذلك الحساب.400 invalid_request، ومُدخل واحد سيئ يرفض
الدفعة بأكملها — ويسمّي الخطأ موضعه. ولا بأس بتكرار معرّفات الحسابات في دفعة واحدة:
فالأخير هو الذي يفوز.الحدود: 1000 حساب لكل طلب، وجسم بحجم 1 MiB، وaccount_id ≤ 256 حرفًا، وemail ≤ 320،
وdisplay_name ≤ 256، و16 وسمًا على الأكثر بمفاتيح ≤ 64 وقيم ≤ 256 حرفًا.
لا يستطيع المتصفح أن يرسل إلا ما تعرفه الصفحة لحظة العرض — معرّف الطلب، لا نتيجة فحص الدفع أبدًا ولا أي شيء آخر يتحدّد لاحقًا. وهذا المسار يسدّ تلك الفجوة: اعثر على الزيارة بحقل تحمله بالفعل، وأرفق بها حقولًا إضافية من جانب الخادم.
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 على الزيارة بحقل تحمله بالفعل، لا عبر request_id، ضمن مساحة عمل
مفتاحك وبيئته.404 not_found — اكتب الحقل بعد
تحدّد النتيجة بوقت قصير.updated الزيارات المختلفة. ولا يتجاوز 1 إلا حين يصيب match أكثر من زيارة
— زوج مفتاح/قيمة غير فريد لطلب أو سلة واحدة. والـ match الذي يصيب أكثر من 100 حدث
يُرفض بالرمز 400 invalid_request بدل أن يُطبَّق على مجموعة جزئية اعتباطية.server، وتتقدّم على القيمة ذات
المفتاح نفسه التي كتبها المتصفح.404 not_found، لا 200 فارغة.تطابق الحدود قناة المتصفح: 50 حقلًا لكل استدعاء، والمفاتيح ≤ 40 بايت، والقيم ≤ 500
بايت — بالبايت لا بالأحرف — ومجموعة أحرف المفتاح A-Za-z0-9_.:-، وجسم بحجم 1 MiB.
يمحو الحقول المخصّصة — ولا يمحو الزيارة نفسها أبدًا. استخدمه للقيم التي لم تعد تحتاج إلى إرفاقها بزيارة، مثل إجمالي الطلب. ولا تتغيّر الـ webhooks المرسَلة بالفعل ولا عمليات التصدير المأخوذة بالفعل.
# 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 وmatch متنافيان — إرسالهما معًا، أو عدم إرسال أيّ منهما، هو
400 invalid_request. ويستخدم match نافذة الـ 24 ساعة نفسها وسقف الـ 100 حدث نفسه
المعتمدَين في الإرفاق.deleted الحقول المُزالة من الزيارة (عبر request_id) أو الزيارات التي أُزيل
منها الحقل (عبر match).404 not_found.القوائم نفسها التي يديرها مشغّلوك في لوحة التحكم، متاحة من مكتبك الخلفي. نوع القائمة هو إجراؤها على الزيارة المطابقة — block وmanual_review وchallenge وallow — ووضعها يقرّر ما إذا كان الإجراء يُطبَّق: observe يعدّ التطابقات فقط، وenforce يطبّقه على guidance (محور list). وتُنشأ القوائم وأوضاعها في لوحة التحكم؛ أما Data API فيقرأ القوائم ويضيف المُدخلات ويزيلها.
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"}أزِل مُدخلًا بالجسم نفسه عبر POST /v2/lists/{list_id}/entries/delete؛ والإجابة هي { "removed": true, "propagation": "immediate" }.
value_type هو ما تُطابَق القيمة معه: linked_id أو visitor_id أو
device_id أو ip أو cidr أو country. والقيمة التي لا تُحلَّل وفق نوعها هي
400 invalid_request.linked_id ←
visitor_id ← device_id ← ip ← cidr ← country — وداخله يفوز الإجراء الأشدّ.ttl_minutes اختياري. فإن حُذف، طُبِّق الـ TTL الافتراضي للقائمة؛ وإن لم يوجد،
فلا تنتهي صلاحية المُدخل أبدًا (expires_at هو null). وإعادة إضافة مُدخل تجدّده.propagation متى يسري التغيير: immediate، أو ttl — خلال خمس دقائق
تقريبًا.200 مع removed: false؛ و404 محجوز للقائمة غير
المعروفة.الحقل الغائب يعني «لا بيانات»، لا صفرًا أبدًا. فالحقول التي لا قيمة لها تُحذف
بالكامل بدل أن تُرسَل بالقيمة 0 أو "" أو null: فالزائر الجديد تمامًا لا
match_confidence له، والزيارة النظيفة لا antidetect_score لها ولا suspect_score.
والاستثناء الوحيد المقصود هو bot.score، فهو حاضر دائمًا حتى حين يساوي صفرًا. اقرأ
الحقول بحذر.
تعتمد الحمولة على خطتك. يبدأ الوصول إلى API من Pro، وتحصل Pro على الجلسة الأساسية — المعرّفات، والطابع الزمني، وعنوان URL، وعنوان IP، ووكيل المستخدم، والمتصفح، ونظام التشغيل، والجهاز، والموقع الجغرافي، والشبكة، والبوت، والتعرّف، والحكم — ومعها الحقول identification.match_type وidentification.match_confidence وbot.score وbot.type وbot.antidetect_score وgpu وnetwork.proxy_detected وextensions وfields وaccount. وتضيف Business وEnterprise الحقول 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 وenvironment. أما حقول مستوى الشخص (person_id وreputation وlinked_accounts_count وlinked_visitors_count) فمحجوزة لـ Business وEnterprise وستظهر حالما تُفعَّل طبقة الشخص — وهي تعمل اليوم في وضع المراقبة، ولا تُسلَّم هذه الحقول. وغياب حقل خاص بـ Business في خطة Pro ليس خطأً.
لا تُعاد أبدًا التفاصيل الداخلية على مستوى الإشارات، في أي خطة: فأسماء الإشارات المفردة وأوزانها والعتبات الكامنة خلف الحكم وقيم الإشارات الخام وتفصيل الدرجات تبقى لدينا. فالدرجة التي يمكن ردّها بالهندسة العكسية إلى مدخلاتها تكفّ عن كونها دفاعًا مفيدًا.
يستخدم كل إخفاق مغلَّفًا واحدًا:
{ "error": { "code": "unauthorized", "message": "missing Authorization: Bearer <secret key>", "request_id": "8f14e45fceea167a5a36dedd" }}request_id هذا ليس معرّف الزيارة. فقيمتان مختلفتان تتشاركان الاسم نفسه: داخل حمولة
الجلسة يكون request_id هو UUID الزيارة، وهو نفسه الذي يسلّمه الـ webhook؛ أما داخل
مغلَّف الخطأ فهو معرّف تتبّع من 24 حرفًا يُسكّ لكل استدعاء HTTP. ويعود معرّف التتبّع
أيضًا في ترويسة X-Request-Id مع كل استجابة، ناجحة كانت أم لا. أدرِجه حين تتواصل مع
الدعم — فهو الطريقة التي نعثر بها على استدعائك بالضبط.
| HTTP | code | المعنى |
|---|---|---|
| 400 | invalid_request | معامِل مفقود أو مشوَّه |
| 401 | unauthorized | المفتاح غائب أو غير صالح أو مُبطَل أو منتهي الصلاحية |
| 402 | upgrade_required | خطتك لا تشمل الوصول إلى API |
| 404 | not_found | لا شيء طابق داخل نافذة الاحتفاظ، أو أنه يعود إلى بيئة أخرى |
| 405 | method_not_allowed | المسار موجود، لكن ليس لتلك الطريقة |
| 429 | rate_limited | تجاوُز عدد الطلبات في الثانية أو تجاوُز الحصة اليومية |
| 500 | internal | أخفق شيء ما لدينا |
| 503 | unavailable | مخزن داعم غير قابل للوصول مؤقتًا |
تجري الفحوصات بترتيب ثابت — المفتاح، ثم الخطة، ثم الحدود — فالطلب بمفتاح خاطئ يُبلِّغ
عن المفتاح أولًا دائمًا، لا عن مشكلة في الحصة. والبيانات من مساحة عمل أخرى لا يمكن
تمييزها عن البيانات غير الموجودة: فهي تعطي 404، لا 403.
تُقرأ حالتا 401 بصيغتين مختلفتين عن قصد: missing Authorization: Bearer <secret key>
تعني أن الترويسة لم تصل إطلاقًا، بينما invalid or revoked API key تعني أنها وصلت ولم
تطابق. أما 402 فتحمل Data API requires the Pro plan or higher.
أعِد محاولة 429 و503 مع فترة انتظار متزايدة؛ أما إعادة محاولة رموز 4xx الأخرى فلا
جدوى منها — فهي تعني أن الطلب نفسه يحتاج إلى إصلاح.
تحمل الاستجابات التي جرى فيها التعرّف على المفتاح وضعك الحالي (لا تحمله استجابات 401
و402، ولا تحصل Enterprise، التي لا حصة يومية لها، على ترويسات الحصة):
| الترويسة | المعنى |
|---|---|
X-RateLimit-Limit | حصتك اليومية؛ وعند الرفض بسبب حدّ الثانية، حدّ الطلبات في الثانية |
X-RateLimit-Remaining | الاستدعاءات المتبقية اليوم |
X-RateLimit-Reset | وقت يونكس لإعادة الضبط — منتصف الليل بتوقيت UTC |
Retry-After | الثواني الواجب انتظارها، تُرسَل مع 429 فقط — اعتمد عليها: فهي صحيحة للحدّين معًا |
| الخطة | طلبات في الثانية | طلبات في اليوم | عمق التاريخ |
|---|---|---|---|
| Free | لا وصول إلى API | — | 7 أيام |
| Pro | 10 | 10,000 | 30 يومًا |
| Business | 50 | 100,000 | 90 يومًا |
| Enterprise | 200 | بلا عدّاد | 365 يومًا |