ה-Data API (שתועד כאן בעבר בשם Server API) מאפשר לשרת שלכם לקרוא את נתוני הזיהוי ש-TRACIO כבר אספה עבור ה-workspace שלכם: ההיסטוריה של מבקר, סשנים בודדים ומוני velocity על חלון קצר.
הוא משלים את Webhooks ולא מחליף אותם:
| Webhooks | Data API | |
|---|---|---|
| כיוון | TRACIO דוחפת אל נקודת הקצה שלכם | השרת שלכם מושך לפי דרישה |
| תזמון | בכל פעם שמתרחש זיהוי | בכל עת, לאורך חלון השמירה שלכם |
| מתאים ל־ | תגובה לאירוע | חיפוש נתונים תוך כדי החלטה, מילוי לאחור וחקירות |
שני המשטחים זמינים החל מתוכנית Pro ומעלה.
https://api.tracio.ai/v1זהו מארח שונה מנקודת הקצה של הדפדפן (edge.tracio.ai) ומלוח הבקרה (app.tracio.ai).
שלושתם נפרדים: הדפדפן מדבר עם ה-edge באמצעות המפתח הציבורי שלכם, והשרת שלכם מדבר
עם ה-Data API באמצעות המפתח הסודי שלכם.
כל בקשה נושאת את המפתח הסודי שלכם כאסימון bearer:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v1/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"ה-Data API מיועד לתקשורת שרת-לשרת בלבד. כותרות CORS אינן מוחזרות במכוון, ולכן דפדפן אינו יכול לקרוא לו — וזה מה ששומר את המפתח הסודי שלכם מחוץ לקוד צד-הלקוח. לעולם אל תשלחו את המפתח הסודי לדפדפן.
צרו אותו בלוח הבקרה תחת API Keys, ובחרו בסוג secret.
tracio_sk_ ואחריו 43 תווים, 53 בסך הכול. לוח הבקרה מציג אותו לפי
מספר התווים הראשונים שלו כדי שתוכלו להבחין בין מפתחות.החלפה מנפיקה מפתח חדש ומשאירה את הישן פעיל למשך 7 ימים, כך שתוכלו להטמיע אותו בלי זמן השבתה. פרסו את המפתח החדש, ודאו שהתעבורה עברה אליו ותנו לישן לפוג. מפתחות ציבוריים אינם ניתנים להחלפה — הם אינם סודות והם גלויים בקוד המקור של העמוד שלכם במכוון.
כל נתיב הוא GET. אין פעולות כתיבה ב-Data API: הוא קורא נתונים, והתצורה שלכם חיה
בלוח הבקרה.
| מתודה | נתיב | מחזיר |
|---|---|---|
GET | /v1/visitors/{visitorId} | היסטוריה מצרפית של מבקר אחד, בתוספת הסשן האחרון שלו |
GET | /v1/visitors/{visitorId}/sessions | רשימה מעומדת של הסשנים של אותו מבקר |
GET | /v1/visitors/{visitorId}/sessions/latest | הסשן העדכני ביותר בלבד |
GET | /v1/visitors/{visitorId}/velocity | מוני פעילות על חלון קצר |
GET | /v1/sessions/{requestId} | סשן יחיד לפי מזהה הבקשה שלו |
GET | /.well-known/webhook-keys | מפתחות ציבוריים לחתימת פלטפורמת ה-webhook (ללא אימות) |
לוכסן בסוף הנתיב מתקבל ומתעלמים ממנו. נתיב לא מוכר או מתודה שגויה מחזירים את אותה מעטפת שגיאת 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/v1/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"התגובה נושאת את ההיסטוריה המצרפית ומשבצת בתוכה את הסשן האחרון, כך שהמקרה הנפוץ דורש בקשה אחת ולא שתיים:
{ "visitorId": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "firstSeenAt": "2026-05-02T10:11:12Z", "lastSeenAt": "2026-07-25T08:00:00Z", "visits": 42, "incognitoVisits": 3, "uniqueIps": 5, "uniqueCountries": 2, "browsers": ["Chrome"], "os": ["macOS"], "devices": ["desktop"], "risk": { "maxRiskScore": 63, "avgBotScore": 12.5, "botSessions": 7, "lastDecision": "real" }, "network": { "vpnSeen": false, "proxySeen": false, "torSeen": false, "datacenterSeen": true, "proxyDetectedSeen": true, "lastIsp": "Deutsche Telekom", "lastRealIp": "203.0.113.7" }, "lastSession": { "requestId": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitorId": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "accountId": "user_8842", "timestamp": "2026-07-25T08:00:00Z", "tag": "checkout", "url": "https://shop.example.com/checkout", "ip": "203.0.113.42", "userAgent": "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, "proxyDetected": true, "realIp": { "address": "203.0.113.7", "country": "NL", "isp": "KPN" }, "asn": 3320 }, "screen": { "width": 2560, "height": 1600, "colorDepth": 30, "pixelRatio": 2 }, "locale": { "languages": ["en-US", "de"], "timezone": "Europe/Berlin" }, "clientHints": { "architecture": "arm", "bitness": "64", "platformVersion": "14.5.0" }, "extensions": [ { "slug": "ublock-origin", "name": "uBlock Origin", "category": "adblock", "risky": false, "storeUrl": "https://chromewebstore.google.com/detail/cjpalhdlnbpafiamejdnhcphjbkeiagm" } ], "bot": { "result": "human", "score": 4.5, "antidetectScore": 2.1 }, "identification": { "confidence": 0.97, "incognito": false, "matchType": "exact", "matchConfidence": 0.99 }, "deviceInfo": { "deviceId": "d_4f9c2e", "crossBrowser": true, "confidence": 0.88, "linkedBrowsers": 2 }, "decision": { "action": "real", "riskScore": 12 } }, "meta": { "plan": "business", "retentionDays": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}| שדה | משמעות |
|---|---|
visits, incognitoVisits | סך הביקורים בחלון, וכמה מהם היו בחלון פרטי |
uniqueIps, uniqueCountries | כתובות ומדינות שונות שנצפו בחלון |
browsers, os, devices | הסביבות השונות שבהן הופיע המבקר הזה |
risk.maxRiskScore | ציון הסיכון הגבוה ביותר שנרשם בחלון, 0..100 |
risk.lastDecision | ההכרעה שנרשמה עבור הביקור האחרון |
risk.avgBotScore, risk.botSessions | ממוצע ציון הבוט ומספר סשני הבוטים — Business ומעלה |
network.*Seen | האם אי פעם נצפו עבור המבקר הזה VPN, פרוקסי, צומת יציאה של Tor או כתובת דאטה-סנטר |
network.proxyDetectedSeen | האם לפחות ביקור אחד בחלון יצא דרך פרוקסי או VPN שלפני הדפדפן — ראו network.proxyDetected בפרק „עובדות על המכשיר“ |
network.lastIsp | ספק האינטרנט האחרון — Business ומעלה |
network.lastRealIp | הכתובת האחרונה שנצפתה מאחורי פרוקסי או VPN — Business ומעלה; חסרה כשלא נצפתה אף כתובת כזו |
lastSession | אובייקט הסשן המלא של הביקור האחרון |
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…) או משפחה כשהכלי אינו מזוהה בשמו — automation, headless, antidetect, extension, privacy_browser, other |
decision.action | real, fake, suspicious |
גם bot.score וגם decision.riskScore נעים בטווח 0..100. ב-Business ומעלה,
guidance הופך אותם להמלצה לכל תרחיש על הסולם
allow ← challenge ← review ← deny — ראו
Guidance למשמעות של כל שלב.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v1/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions?limit=100&minRiskScore=50"| פרמטר | ברירת מחדל | הערות |
|---|---|---|
limit | 50 | חסום ב-500; ערך גדול יותר נחתך ולא נדחה |
from, to | שמירת התוכנית | החלון הזמני המשותף שתואר למעלה |
cursor | — | סמן עימוד אטום מהעמוד הקודם |
botResult | — | השאירו רק סשנים עם הכרעת הבוט הזו |
minRiskScore | — | השאירו רק סשנים בציון הסיכון הזה ומעלה, 0..100 |
הסשנים חוזרים מהחדש לישן:
{ "items": [ { "requestId": "9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31", "visitorId": "X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y", "timestamp": "2026-07-25T08:00:00Z" } ], "nextCursor": "MTcyMTg5NDQwMDAwMDphYmMxMjM", "hasMore": true, "meta": { "plan": "business", "retentionDays": 90, "from": "2026-04-26T00:00:00Z", "to": "2026-07-25T12:00:00Z" }}העימוד מבוסס סמן. אין פרמטר page ואין offset: העבירו את ה-nextCursor שקיבלתם
בחזרה כ-cursor, והמשיכו כל עוד hasMore הוא true.
async function allSessions(visitorId: string, secretKey: string) { const sessions = [] let cursor: string | undefined
do { const url = new URL(`https://api.tracio.ai/v1/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.nextCursor } 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 פירושו שאין GPU אמיתי (מכונה וירטואלית או סביבת headless); Safari מדווח Apple GPU |
network.proxyDetected | תעבורת ה-HTTP של הביקור והנתיבים הרשתיים הגולמיים שלו יוצאים דרך רשתות שונות — פרוקסי או VPN לפני הדפדפן; שתי כתובות של אותו ספק (NAT של המפעיל, מוצא שני של אותו VPN) אינן נחשבות |
network.realIp.address, .country, .isp | הכתובת הציבורית שנצפתה בנתיב הרשתי הגולמי, כלומר הכתובת שמאחורי הפרוקסי או ה-VPN, יחד עם המדינה וספק האינטרנט שלה — Business ומעלה; חסרה כשלא נצפתה כתובת כזו (country ו-isp חסרים כשלא ניתן היה לקבוע אותם) |
deviceInfo.deviceId, .crossBrowser, .confidence, .linkedBrowsers | קיים כאשר זוהתה זהות מכשיר: מזהה יציב של המכשיר הפיזי על פני הדפדפנים שעליו, האם הביקור הזה הגיע מדפדפן אחר מבעבר, מידת הביטחון בהתאמה הזו, וכמה מבקרים שונים (דפדפנים) חולקים את המכשיר — יותר מאחד פירושו מכונה אחת תחת כמה זהויות דפדפן — Business ומעלה |
osEnvironment | סביבת שולחן העבודה שנמדדה על מכונת Linux (Mint 22+, Ubuntu, GNOME, KDE) — Business ומעלה; חסרה כשלא נקבעה |
spoofing | מה שהביקור טען לעומת מה שבדיקות עצמאיות מדדו (claimed, real, spoofedAxes מתוך os, gpu, screen, network, browser; anonymousBrowser עם שמות מוצרים) — Business ומעלה; קיים רק כאשר זוהה זיוף |
screen.width, .height, .colorDepth, .pixelRatio | רזולוציית מסך, עומק צבע ו-device pixel ratio כפי שהדפדפן מדווח עליהם — Business ומעלה |
locale.languages, locale.timezone | שפות ההעדפה של הדפדפן עצמו ואזור הזמן שלו — בניגוד ל-geo.timezone, הנגזר מכתובת ה-IP; אי-התאמה בין השניים היא סימן שכיח למיקום מזויף — Business ומעלה |
clientHints.architecture, .bitness, .model, .deviceName, .platformVersion | User-Agent Client Hints: ארכיטקטורת המעבד ורוחב הסיביות, קוד דגם המכשיר (Android, למשל SM-A556B) עם השם השיווקי שלו מרשימת המכשירים של Google Play (deviceName, למשל Samsung Galaxy A55 5G) וגרסת הפלטפורמה המדויקת; דפדפנים מבוססי Chromium בלבד — Business ומעלה |
environment.virtualMachine, environment.hypervisor | קיים רק כאשר מתאם הווידאו הציג את עצמו כווירטואלי; hypervisor הוא מילון סגור (vmware, virtualbox, parallels, qemu, hyperv, bochs, intel-gvt, vgpu). היעדר הבלוק פירושו שאין ראיה כזו — Business ומעלה |
השדה extensions מפרט את הרחבות הדפדפן שזוהו במהלך הביקור — Business ומעלה. כל רשומה היא אובייקט:
| שדה | משמעות |
|---|---|
slug | מזהה מכונה יציב של ההרחבה, אותו ערך שה-webhook מוסר |
name | שם קריא לבני אדם |
category | סיווג גס — adblock, privacy, automation, wallet, vpn, devtools, other וכן הלאה |
risky | הערך true להרחבות המשויכות לאוטומציה, לזיוף או לגניבת אישורים |
storeUrl | קישור לדף ההרחבה בחנות, כשהוא ידוע |
ממצא מדווח רק לאחר שעבר את בדיקות האמון שלנו — סביבה שמשיבה „מותקנת“ לכל בדיקה, או אצווה ארוכה מיותר משנים עשר שמות, נפסלת כבלתי אמינה. לכן רשימה ריקה או חסרה פירושה „לא הצלחנו לאשר דבר“, ולא „לא מותקנות הרחבות“. קראו אותה כראיה, לא כמצאי.
העדכני ביותר:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v1/visitors/X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y/sessions/latest"זה מחזיר אובייקט סשן חשוף — לא מערך, ולא עטוף במעטפת. מבקר שאין לו סשנים בחלון מחזיר
404 not_found עם no sessions for this visitor in the retention window.
או לפי requestId, המזהה שמופיע גם במטען ה-webhook:
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v1/sessions/9c1f6a2e-3b7d-4c58-a1e2-6f0d8b4a7c31?visitorId=X7fh2Hg9LkMn3pQr5tBvQw3xZa9mK2pL4nR8dT6y"visitorId הוא אופציונלי כאן, אבל העברתו כשאתם יודעים אותו מזרזת את החיפוש במידה
ניכרת.
ה-velocity עונה על השאלה „כמה המבקר הזה עשה לאחרונה“ — זו הצורה של credential stuffing, בדיקת כרטיסים והרשמות בכמות.
curl -H "Authorization: Bearer tracio_sk_XXXX...XXXX" \ "https://api.tracio.ai/v1/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, "uniqueIps": 9, "uniqueCountries": 3, "uniqueAccounts": 12, "botEvents": 4, "meta": { "plan": "business", "retentionDays": 90, "from": "2026-07-25T11:00:00Z", "to": "2026-07-25T12:00:00Z" }}uniqueAccounts סופר את ערכי ה-linkedId השונים ששלחתם עבור המכשיר הזה — ראו
קישור חשבונות. botEvents הוא Business ומעלה.
שדה חסר פירושו „אין נתונים“, לעולם לא אפס. שדות ללא ערך מושמטים לחלוטין במקום
להישלח כ-0, "" או null: למבקר חדש לגמרי אין matchConfidence, ולביקור נקי אין
antidetectScore או suspectScore. החריג המכוון היחיד הוא bot.score, שנוכח תמיד גם
כשהוא אפס. קראו שדות בזהירות.
המטען תלוי בתוכנית שלכם. כל תוכנית עם גישת API מקבלת את הסשן הבסיסי — מזהים, חותמת זמן, URL, IP, user agent, דפדפן, מערכת הפעלה, מכשיר, מיקום, רשת, בוט, זיהוי והכרעה. Pro מוסיפה את identification.matchType, identification.matchConfidence, bot.type, bot.antidetectScore, gpu ו-network.proxyDetected. Business ו-Enterprise מוסיפות את extensions, geo.isp, network.asn, network.realIp, decision.suspectScore, identification.driftScore, reasons, behavior, guidance, deviceInfo, spoofing, osEnvironment, screen, locale, clientHints ו-environment. שדות רמת האדם (personId, reputation, linkedAccountsCount, linkedVisitorsCount) שמורים ל-Business ול-Enterprise ויופיעו ברגע ששכבת האדם תופעל — היום היא פועלת במצב תצפית והשדות האלה אינם נמסרים. היעדרו של שדה Business בתוכנית Pro אינו שגיאה.
פרטים פנימיים ברמת הסיגנל לעולם אינם מוחזרים, בשום תוכנית: שמות סיגנלים בודדים, המשקלים שלהם, הספים שמאחורי הכרעה, ערכי סיגנל גולמיים ופירוקי ציונים נשארים אצלנו. ציון שניתן להנדס לאחור לכדי הקלטים שלו חדל להיות שימושי כהגנה.
כל כישלון משתמש במעטפת אחת:
{ "error": { "code": "unauthorized", "message": "missing Authorization: Bearer <secret key>", "requestId": "8f14e45fceea167a5a36dedd" }}ה-requestId הזה אינו מזהה הביקור. שני ערכים שונים חולקים את אותו שם: בתוך מטען
סשן requestId הוא ה-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 | מאגר נתונים תומך אינו נגיש זמנית |
הבדיקות רצות בסדר קבוע — מפתח, אחר כך תוכנית, אחר כך מגבלות — כך שבקשה עם מפתח שגוי תמיד מדווחת קודם על המפתח, לעולם לא על בעיית מכסה.
שני מקרי 401 נקראים אחרת במכוון: missing Authorization: Bearer <secret key> פירושו
שהכותרת מעולם לא הגיעה, ואילו invalid or revoked API key פירושו שהיא הגיעה ולא
התאימה. 402 נושא את Data API requires the Pro plan or higher.
כל תגובה מאומתת נושאת את המצב הנוכחי שלכם:
| כותרת | משמעות |
|---|---|
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 ימים |