پرش به محتوا
مستندات
EN
ورود به پنل
شروع
  • نقشهٔ مستندات
  • راه‌اندازی سریع
  • مفهوم‌ها
جمع‌آوری داده
  • تعریف رویداد
  • فرهنگ‌نامهٔ رویدادها
  • گذاشتن رویداد
  • ادغام هویت
  • SDK وب
  • SDK اندروید
  • ثبت دستگاه
  • سرور به سرور
  • کاتالوگ محصولات
  • وب‌هوک
مخاطب و پیام‌رسانی
  • سگمنت
  • سناریو
  • پیام تراکنشی
  • رضایت و سقف
  • پیام درون‌برنامه‌ای
تحلیل و خروجی
  • گزارش و خروجی
مرجع توسعه‌دهنده
  • مرجع API
    • نقاط ورود داده
    • API مدیریتی
  • کدهای خطا
  • سقف‌ها
  • OpenAPI
ابزارهای توسعه
  • سرور MCP
  • کار با عامل
حریم خصوصی و تغییرات
  • داده‌های شخصی
  • نسخه و تغییرها

کدهای خطا و کاری که باید کرد

هر کدی که ممکن است برگردد، معنی‌اش، و اینکه باید دوباره تلاش کنید، چیزی را درست کنید یا صبر کنید.

خطا در سگمنتیک یک شکل ندارد. میزبان ورود داده یک شکل دارد، میزبان مدیریتی شکل دیگری، و شکل سومی روی یازده مسیر از میزبان مدیریتی بیرون می‌زند. کلاینتی که فقط یکی از این سه را می‌شناسد، روی دو تای دیگر undefined می‌خواند و شاخه‌ای را می‌رود که هیچ‌کس تستش نکرده است.

این صفحه هر کدی را که یک سطح مشتری‌رو می‌تواند برگرداند فهرست می‌کند، دسته‌بندی‌شده بر اساس کاری که باید بکنید.

#سه شکل خطا، نه یکی

محتاطانه پارس کنید. اگر error یک آبجکت است، error.code را بخوانید. اگر error یک رشته است، هیچ کدی وجود ندارد و تنها چیزی که دارید وضعیت HTTP است. اگر کلید error وجود ندارد، روی میزبان ورود داده هستید و فیلدی که می‌خواهید status است.

#میزبان ورود داده

نشانی https://in.segmentic.net یک آبجکت تخت برمی‌گرداند. هیچ فیلد code روی این میزبان وجود ندارد. مقدار ماشین‌خوان status است و همیشه یکی از دو رشته "ok" یا "error".

POST /v1/track, 400
{"status":"error","message":"malformed JSON"}

پاسخ موفق شمارش دارد. accepted و rejected وقتی صفرند فرستاده نمی‌شوند، نه اینکه 0 بیایند. پس دسته‌ای که کامل رد شده باشد در اصل کلید accepted ندارد.

POST /v1/track, 200
{
  "status": "ok",
  "accepted": 1,
  "warnings": [
    {
      "code": "generated_message_id",
      "field": "message_id",
      "note": "no message_id sent; retries of this event cannot be de-duplicated"
    }
  ]
}

در دسته، خرابی هر قلم با اندیس آرایه‌ای که فرستاده‌اید گزارش می‌شود، تا منطق تلاش دوباره شما بتواند آن قلم را بدون تطبیق محتوا پیدا کند. رویدادهایی که فرستاده‌اید ممکن است هنوز شناسه نداشته باشند، که خودش نیمی از دلیل رد شدنشان است.

POST /v1/batch, 200
{
  "status": "ok",
  "accepted": 2,
  "rejected": 1,
  "errors": [{"index": 1, "reason": "unknown_type: \"trak\""}]
}

رشته reason متن کامل خطاست و مقدار خودتان را هم در خود دارد. بخش پایدارش کلمه اول است، اینجا unknown_type. روی پیشوند تطبیق بدهید، نه روی کل رشته.

نوع محتوا روی هر پاسخ این میزبان application/json; charset=utf-8 است.

سه مسیر ورود داده از این شکل استفاده نمی‌کنند. POST /v1/bounce/{local} متن ساده برمی‌گرداند نه JSON. POST /v1/inbox و POST /v1/devices شکل خودشان را دارند که در دستگاه‌ها و پوش و درون‌سایتی و صندوق پیام آمده است. GET /s/{code} برای کد ناشناخته یک ۴۰۴ متن ساده و در حالت درست ۳۰۲ می‌دهد.

#میزبان مدیریتی

نشانی https://api.segmentic.net همه‌چیز را زیر error تودرتو می‌کند.

POST /v1/reports/funnel, 429
{"error":{"code":"budget_exhausted","message":"this key has spent its request budget for the minute"}}

فیلد details بخش ساختاریافته خطای اعتبارسنجی را می‌آورد، تا بتوانید انگشت بگذارید روی همان جای payload خودتان که مشکل دارد.

POST /v1/events, 413
{
  "error": {
    "code": "batch_too_large",
    "message": "a batch may carry at most 500 events",
    "details": {"limit": 500, "sent": 501}
  }
}

فیلد need روی ۴۰۳ می‌آید و درست نام همان مجوزی را می‌گوید که کلید ندارد. به‌عمد منتشر شده است: راه دیگر این بود که مشتری تیکت بزند تا بفهمد کدام مجوز را باید بدهد.

POST /v1/campaigns/41/send, 403
{
  "error": {
    "code": "forbidden",
    "message": "this key does not carry campaign.send, see GET /v1/whoami for what it does carry",
    "need": "campaign.send"
  }
}

روی POST /v1/events، مقدار details به‌جای آبجکت، آرایه قلم‌به‌قلم است.

POST /v1/events, 422
{
  "error": {
    "code": "all_events_rejected",
    "message": "no event in this batch could be accepted",
    "details": [
      {"index": 0, "reason": "missing_identity"},
      {"index": 1, "reason": "missing_identity"}
    ]
  }
}

#شکل تخت، روی یازده مسیر

یازده مسیر مدیریتی هندلرشان را با پنل به اشتراک می‌گذارند، و نویسنده خطای پنل یک رشته تخت بدون هیچ کدی می‌نویسد.

GET /v1/segments/7, 404
{"error":"segment not found"}

کلاینتی که فقط body.error.code را می‌خواند، روی تک‌تک این‌ها undefined می‌گیرد. مسیرها و خرابی‌هایی که این شکل را دارند:

مسیرخرابی‌های تخت
GET /v1/schema/events۵۰۳ با schema unavailable
GET /v1/schema/traits۵۰۳ با schema unavailable
POST /v1/audiences/validate۴۰۰ با malformed JSON
POST /v1/audiences/count۴۰۰ با malformed JSON، ۴۰۰ با متن خود کامپایلر، ۵۰۳ با count unavailable
GET /v1/segments۵۰۳ با segments unavailable
GET /v1/segments/{id}۴۰۰ با invalid segment id، ۴۰۴ با segment not found
GET /v1/campaigns۵۰۳ با campaigns unavailable
GET /v1/campaigns/{id}۴۰۰ با invalid campaign id، ۴۰۴ با campaign not found
POST /v1/reports/funnel۴۰۰ با invalid_report، ۵۰۳ با متن فارسی
POST /v1/reports/retention۴۰۰ با invalid_report، ۵۰۳ با متن فارسی
POST /v1/messages۴۰۰ و ۴۰۹ و ۴۲۹ و ۵۰۳، همه‌شان

کد invalid_report استثنای داخل استثناست: تخت است ولی کد دارد.

POST /v1/reports/funnel, 400
{"error":"قیف به دست‌کم دو مرحله نیاز دارد","code":"invalid_report"}

چهار رد شدن از نگهبان مشترک اعتبارنامه هم با همین شکل تخت به میزبان مدیریتی می‌رسند، با کد و متن فارسی: wrong_surface روی ۴۰۱، و impersonation_read_only و impersonation_forbidden و ip_not_allowed روی ۴۰۳. آخری با یک کلید API معمولی هم دیده می‌شود، چون فهرست نشانی‌های مجاز حساب روی هر اعتبارنامه‌ای اعمال می‌شود، نه فقط روی نشست مرورگر.

نه میزبان ورود داده و نه میزبان مدیریتی به Accept-Language توجه نمی‌کنند. میان‌افزار زبان فقط روی خود پنل سوار است. هر پیامی که از کاتالوگ ترجمه بیاید، هرچه بخواهید، فارسی به دست شما می‌رسد. این شامل هر چهار پیام quota_* و پیام account_locked است.

#روی کد شاخه بزنید، هرگز روی متن

کد قرارداد است. متن قرارداد نیست و هر وقت جمله بهتری پیدا شود عوض می‌شود.

دو پیام این را ملموس می‌کنند. متن write_key_rejected دو بار نویسه سه‌نقطه U+2026 دارد، داخل (wk_…) و (sk_seg_…)، نه سه نقطه جدا. متن قالب کلید تراکنشی بین ۸ و ۲۰۰ یک en dash با کد U+2013 دارد، نه خط تیره ساده. یکپارچه‌سازی‌ای که روی هرکدام از این دو رشته تطبیق بدهد، با نویسه‌ای می‌شکند که نویسنده‌اش هرگز تایپش نکرده است.

#درخواست را درست کنید

تلاش دوباره روی هرکدام از این‌ها یعنی فرستادن همان payload به همان رد شدن. شکل تودرتو، روی میزبان مدیریتی.

کدHTTPمسیرهایعنی چه
malformed_json۴۰۰هر مسیری که بدنه می‌گیردبدنه پارس نشد، یا بزرگ‌تر از 8 MiB بود
batch_empty۴۰۰POST /v1/eventsکلید events نبود یا خالی بود
bad_id۴۰۰PUT /v1/segments/{id}، DELETE /v1/segments/{id}، POST /v1/campaigns/{id}/send، POST /v1/campaigns/{id}/submitمسیر شناسه عددی مثبت نداشت
name_required۴۰۰POST /v1/segmentsفیلد name خالی یا فقط فاصله بود
invalid_channel۴۰۰POST /v1/campaignsاین کانال چیزی نیست که این حساب بتواند رویش بنویسد. مقدار details برابر {"field":"channel"} است
unknown_endpoint۴۰۴مسیر پیش‌فرضاین مسیر روی این میزبان ثبت نشده است. متن، متد و مسیر را می‌گوید و به GET /v1/capabilities ارجاع می‌دهد
not_found۴۰۴PUT /v1/segments/{id}، POST /v1/campaigns/{id}/send، POST /v1/campaigns/{id}/submitشناسه ناشناخته است، یا مال حساب دیگری است. این دو حالت به‌عمد از هم جدا نشده‌اند
batch_too_large۴۱۳POST /v1/eventsبیش از ۵۰۰ رویداد. مقدار details برابر {"limit":500,"sent":N} است. دسته را بشکنید
filter_invalid۴۲۲POST /v1/audiences/validate، POST /v1/segments، PUT /v1/segments/{id}تعریف مخاطب کامپایل نشد. متن، جمله خود کامپایلر است
campaign_invalid۴۲۲POST /v1/campaigns، POST /v1/campaigns/{id}/submitکمپین از اعتبارسنجی رد نشد
export_kind_invalid۴۲۲POST /v1/exportsمقدار kind یکی از events و messages و profiles و segment نبود
all_events_rejected۴۲۲POST /v1/eventsهیچ رویدادی از دسته نرمال‌سازی نشد. مقدار details آرایه قلم‌به‌قلم است

سه کد دیگر ۴۰۹ هستند و درست کردنشان کار آدم است، نه ویرایش payload.

کدHTTPمسیریعنی چه
approval_required۴۰۹POST /v1/campaigns/{id}/sendاین حساب تایید کمپین را قبل از ارسال لازم دارد. اول ثبتش کنید، بعد تایید بگیرید
approval_stale۴۰۹POST /v1/campaigns/{id}/sendکمپین بعد از تایید عوض شده است. دوباره ثبتش کنید
not_submittable۴۰۹POST /v1/campaigns/{id}/submitفقط کمپین پیش‌نویس یا متوقف‌شده را می‌شود برای تایید ثبت کرد

مسیر POST /v1/audiences/validate برای فیلتر نامعتبر ۴۲۲ می‌دهد، در حالی که نقطه معادلش در پنل ۲۰۰ با valid: false می‌دهد. پنل برای فرمی که کسی دارد در آن تایپ می‌کند درست است و برای یکپارچه‌سازی‌ای که خطایش روی وضعیت شاخه می‌زند غلط.

#اعتبارنامه را درست کنید

چهارتای این‌ها ۴۰۱ هستند و با هم فرق دارند. قبل از اینکه دنبال غلط تایپی بگردید کد را بخوانید.

کدHTTPیعنی چه
unauthenticated۴۰۱هیچ اعتبارنامه‌ای روی درخواست نبود، یا بود و شناخته نشد. متن: a valid API key is required
api_key_required۴۰۱نشست پنل فرستاده شده است. این میزبان فقط کلید sk_seg_ می‌گیرد
write_key_rejected۴۰۱توکن با wk_ شروع می‌شود. آن کلید عمومی است و داخل اپ شما منتشر می‌شود و چیزی نمی‌تواند بخواند. یک کلید API بسازید
key_expired۴۰۱کلید شناخته شد و تاریخ انقضایش گذشته است. بچرخانیدش
wrong_surface۴۰۱اعتبارنامه ستادی روی میزبان مشتری، یا برعکس. شکل تخت، متن فارسی
forbidden۴۰۳نقش کلید در اشتراک با دامنه‌اش این مجوز را ندارد. فیلد need نامش را می‌گوید. مسیر GET /v1/whoami مجموعه مؤثر را برمی‌گرداند
ip_not_allowed۴۰۳حساب فهرست نشانی مجاز دارد و این نشانی در آن نیست. شکل تخت، متن فارسی
impersonation_read_only۴۰۳نشست پشتیبانی فقط‌خواندنی خواسته چیزی را تغییر بدهد. شکل تخت
impersonation_forbidden۴۰۳نشست پشتیبانی کاری را خواسته که پشتیبانی هرگز در حساب شما نمی‌تواند بکند. شکل تخت

مسیر GET /v1/whoami یک واحد بودجه خرج می‌کند، مثل هر مسیر ساده دیگری، و مجموعه مؤثر مجوزها را برمی‌گرداند، پس یک کلاینت خوب می‌تواند موقع بالا آمدن شکست بخورد به‌جای اینکه روی همان یک فراخوانی ماهانه‌ای شکست بخورد که به مجوز نداشته‌اش نیاز دارد. تنها مسیر میزبان مدیریتی که سنجیده نمی‌شود GET /v1/status است.

Shell
curl -s https://api.segmentic.net/v1/whoami \
  -H "Authorization: Bearer sk_seg_..."
JSON
{
  "tenant_id": 42,
  "api_key_id": 7,
  "role": "analyst",
  "permissions": [
    "analytics.read", "audit.read", "campaign.read", "data.export",
    "event.read", "journey.read", "member.read", "profile.read",
    "segment.read", "settings.read", "template.read"
  ],
  "scoped": false
}

فهرست permissions مجموعه مؤثر است و الفبایی مرتب می‌شود. نقش یکی از این هفت‌تاست: owner و admin و marketer و analyst و viewer و approver و finance. کلید با نقش owner اصلا ساخته نمی‌شود، پس هیچ کلیدی tenant.transfer و tenant.delete ندارد.

مقدار scoped روی هر کلیدی که این محصول می‌تواند بسازد false است. ستون دامنه در پایگاه داده هست و خوانده هم می‌شود، ولی هیچ مسیری آن را نمی‌نویسد، پس هر کلید کل نقشش را دارد و کلید باریک‌تر از نقش هنوز ساختنی نیست.

روی میزبان ورود داده، هر دو پیام missing write key و invalid write key وضعیت ۴۰۱ دارند و هر دو دائمی‌اند. دومی برای کلید ناشناخته و کلید باطل‌شده و کلید معلق یک جواب می‌دهد، تا نشود با این نقطه فهمید چه کلیدهایی وجود دارند.

#صبر کنید

کدHTTPکجاچه کنید
budget_exhausted۴۲۹هر مسیر مدیریتی به‌جز GET /v1/statusهدر Retry-After: 60. سطل دقیقه با ساعت دیواری می‌چرخد. سقف‌ها را ببینید
بدون کد، error تخت۴۲۹POST /v1/messagesهدر Retry-After: 60. متن rate limit exceeded: N requests per minute است
HTTP
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json; charset=utf-8

{"error":{"code":"budget_exhausted","message":"this key has spent its request budget for the minute"}}

وضعیت ۴۲۹ تراکنشی شکل دیگری دارد:

HTTP
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 2
X-RateLimit-Remaining: 0
Content-Type: application/json; charset=utf-8

{"error":"rate limit exceeded: 2 requests per minute"}

میزبان ورود داده هرگز ۴۲۹ نمی‌دهد. هیچ محدودکننده نرخی ندارد.

#دوباره تلاش کنید

همه این‌ها ۵۰۳ هستند و همه یعنی ایراد از ماست. عقب بکشید و همان payload را دوباره بفرستید.

کدHTTPمسیرعلت
budget_unavailable۵۰۳هر مسیر مدیریتی به‌جز GET /v1/statusردیس در دسترس نبود و بررسی بودجه بسته شکست می‌خورد
ingest_unavailable۵۰۳POST /v1/eventsصف در دسترس نبود. به‌عمد ۵۰۳ است نه ۵۰۰: کسی که ۵۰۰ بگیرد فکر می‌کند payload خودش مشکل داشته و متوقف می‌شود
segment_unavailable۵۰۳POST /v1/segments، PUT /v1/segments/{id}، DELETE /v1/segments/{id}ذخیره‌گاه سگمنت خطا داد
campaign_unavailable۵۰۳POST /v1/campaigns، POST /v1/campaigns/{id}/sendذخیره‌گاه کمپین خطا داد
approval_unavailable۵۰۳ثبت و ارسالذخیره‌گاه تایید خطا داد. بسته شکست می‌خورد، پس ارسالی انجام نشده است
export_unavailable۵۰۳GET /v1/exports، POST /v1/exportsذخیره‌گاه خروجی خطا داد
بدون کد، error تخت۵۰۳POST /v1/messagesمتن message not sent. فقط وقتی هیچ شناسه پیامی برنگشته باشد. ارسال تراکنشی را ببینید
بدون کد، error تخت۵۰۳خواندن اسکیما و شمارش و سگمنت و کمپین، و دو مسیر گزارشانبار داده یا ذخیره‌گاه در دسترس نبود. روی گزارش‌ها متن یک جمله فارسی است

در کل محصول فقط یک ۵۰۳ هدر Retry-After دارد و آن هم روی میزبان ورود داده است: خرابی جست‌وجوی کلید نوشتن Retry-After: 5 می‌گذارد. بقیه ۵۰۳ها هیچ نمی‌گذارند. عقب‌نشینی خودتان را انتخاب کنید.

#پول بدهید، یا تیکت بزنید

تلاش دوباره هیچ‌کدام از این‌ها را باز نمی‌کند. کسی باید فاکتوری را پرداخت کند، پلنی را ارتقا بدهد یا مجوزی بدهد.

کدHTTPمسیریعنی چه
quota_cancelled۴۰۲POST /v1/events و هر مسیر ورود دادهاشتراک لغو شده است
quota_trial_over۴۰۲POST /v1/events و هر مسیر ورود دادهدوره آزمایشی تمام شده است
quota_event_cap۴۰۲POST /v1/events و هر مسیر ورود دادهحساب به سقف سخت رویداد پلنش در این ماه جلالی رسیده است
quota_message_cap۴۰۲هیچ‌جا به آن نمی‌رسدمسیر کد وجود دارد. هیچ فراخوانی‌ای سنجه پیام را به بررسی سهمیه نمی‌دهد، پس هرگز رخ نمی‌دهد
account_locked۴۰۳GET /v1/exports، POST /v1/exports، POST /v1/reports/funnel، POST /v1/reports/retentionمصرف به سه برابر سهمیه رسیده، یا فاکتوری ۷۵ روز از سررسیدش گذشته است. مقدار details یکی از {"reason":"usage_300"} یا {"reason":"overdue_75"} است

پیام‌های quota_* روی هر دو میزبان همیشه فارسی‌اند، هر چیزی که Accept-Language بگوید. این چهار جمله:

کدمتن
quota_cancelledاشتراک این حساب لغو شده است
quota_trial_overدورهٔ آزمایشی به پایان رسیده است
quota_event_capسقف رویدادهای این ماه پر شده است
quota_message_capسقف پیام‌های این ماه پر شده است

کد account_locked درست چهار مسیر مدیریتی را می‌بندد. ورود داده، ارسال تراکنشی، ساخت کمپین، ارسال کمپین و نوشتن سگمنت همگی موقع قفل بودن حساب باز می‌مانند، چون سوراخ در داده شما را بعدها نمی‌شود پر کرد و بدهی را بعدها می‌شود وصول کرد.

حکم سهمیه می‌داند حساب چقدر از سقف گذشته است. آن عدد به شما نمی‌رسد: پاسخ رد فقط جمله را دارد و بس. مصرف را از پنل بخوانید.

وضعیت ۴۰۲ باعث می‌شود هر SDK سگمنتیک دسته‌ای را که نگه داشته دور بریزد، نه اینکه بافرش کند. هر سه SDK هر ۴xx به‌جز ۴۲۹ را دائمی می‌شمارند. وقتی به سقف سخت رویداد بخورید، رویدادهایی که همان لحظه روی گوشی کاربران شما در صف بودند از دست می‌روند و بعدها هم برنمی‌گردند. هشدارهای مصرف را ببینید، نه پاسخ رد را.

#میزبان ورود داده وضعیت دارد، نه کد

روی https://in.segmentic.net فیلد code وجود ندارد. روی وضعیت HTTP شاخه بزنید.

HTTPمتنعلتکار
۴۰۰malformed JSONبدنه پارس نشددرست کنید
۴۰۰یکی از کلیدواژه‌های جدول پایینیک رویداد از اعتبارسنجی رد نشددرست کنید
۴۰۰batch_emptyصفر قلم در batchدرست کنید
۴۰۰batch_too_large: N items, limit 500بیش از ۵۰۰ قلمبشکنیدش
۴۰۱missing write keyنه Authorization: Bearer، نه X-Segmentic-Key، نه ?write_key=درست کنید. هرگز تلاش دوباره نکنید
۴۰۱invalid write keyکلید ناشناخته، باطل‌شده یا معلقدرست کنید. هرگز تلاش دوباره نکنید
۴۰۲متن فارسی سهمیهسقف سخت، اشتراک لغوشده، یا پایان دوره آزمایشیتلاش دوباره نکنید
۴۱۳request body too largeبزرگ‌تر از 5 MiBکمتر بفرستید
۵۰۳cannot verify the write key right now; retryجست‌وجوی کلید ما خطا داد. هدر Retry-After: 5 می‌گذاردتلاش دوباره، رویدادها را نگه دارید
۵۰۳temporarily unavailable, please retryهم گذرگاه پیام و هم بافر دیسک خطا دادندتلاش دوباره

دقت کنید که یک شرط روی دو میزبان دو وضعیت می‌گیرد: دسته بیشتر از ۵۰۰ قلم روی POST /v1/batch وضعیت ۴۰۰ می‌گیرد و روی POST /v1/events وضعیت ۴۱۳.

مسیرهای کانال و درون‌سایتی همین شکل را با متن‌های خودشان دارند.

مسیرHTTPمتن
POST /v1/devices۴۰۰malformed JSON، یا متن خود نرمال‌ساز به‌همراه warnings
POST /v1/devices۵۰۳temporarily unavailable, please retry
POST /v1/devices/unregister۴۰۰device_id is required
POST /v1/webpush/subscribe۴۰۰user_id and a complete subscription are required
POST /v1/webpush/unsubscribe۴۰۰endpoint is required
POST /v1/messenger/link۴۰۰user_id, chat_id and a known platform are required
POST /v1/messenger/unlink۴۰۰user_id and a known platform are required
POST /v1/inbox۴۰۰user_id is required
POST /v1/inbox۴۰۳user identity is not verified
POST /v1/onsite/event۴۰۰campaign_id and a visitor id are required، یا unknown action
POST /v1/onsite/response۴۰۰unknown campaign، یا متن خود اعتبارسنج
POST /v1/hooks/{source}/{token}۴۰۱signature mismatch، یا unauthorized
POST /v1/hooks/{source}/{token}۴۰۴unknown webhook
POST /v1/bounce/{local}۴۰۰ یا ۴۱۳متن ساده، نه JSON

دو مسیر به‌عمد هرگز خرابی گزارش نمی‌کنند. GET /v1/onsite وقتی ذخیره‌گاهش پایین است 200 {"campaigns":[]} می‌دهد، چون داخل بارگذاری صفحه شما اجرا می‌شود و کند شدن یا خطای گرفتن کمپین نباید به چشم بازدیدکننده شما بیاید. POST /v1/onsite/event همیشه ۲۰۰ است، حتی وقتی نوشتن نمایش خطا داده باشد. POST /v1/hooks/... برای payload ای که نمی‌تواند تبدیلش کند 200 {"status":"ok","accepted":0} می‌دهد، چون شاپیفای و ووکامرس پاسخ غیر ۲xx را روزها تکرار می‌کنند.

#چرا یک رویداد رد شد

این ده رشته بخش پایدار errors[].reason روی میزبان ورود داده و details[].reason روی POST /v1/events هستند. مجموعه بسته است. هرچه بیرون از آن باشد invalid شمرده می‌شود.

کلیدواژهمعنی
unknown_typeمقدار type یکی از track و identify و page و screen و alias نبود. با مقدار خودتان همراه است
missing_identityنه user_id بود و نه anonymous_id
missing_event_nameنوع track بدون event
event_name_too_longنام رویداد بیشتر از ۱۲۸ بایت
event_name_invalid_charsنام رویداد نویسه کنترلی یونیکد دارد
id_too_longیکی از user_id و anonymous_id و message_id بیشتر از ۲۵۶ بایت
missing_previous_idنوع alias بدون previous_id
batch_too_largeبیشتر از ۵۰۰ قلم. با متن batch_too_large: N items, limit 500
batch_emptyصفر قلم
timestamp_too_oldفقط در backfill. ورود داده زنده به‌جایش زمان را می‌چسباند و هشدار می‌دهد

#هشدارها، که روی ۲۰۰ می‌آیند

هشدار یعنی رویداد پذیرفته شد و چیزی اصلاح شد. خطا نیست و وضعیت را عوض نمی‌کند. هر هشدار {"code","field","note"} است و field و note وقتی خالی‌اند فرستاده نمی‌شوند.

کدفیلدچه شد
generated_message_idmessage_idنفرستادید، پس ساخته شد. تلاش دوباره این رویداد دیگر تکراری‌زدایی نمی‌شود
timestamp_in_futuretimestampساعت دستگاه از سرور جلوتر است. به زمان دریافت چسبانده شد
timestamp_too_oldtimestampقدیمی‌تر از پنجره ورود داده. به لبه پنجره چسبانده شد
too_many_propertiespropertiesبیشتر از ۲۵۶ ویژگی. ۲۵۶ تای اول نگه داشته شد
too_many_traitstraitsبیشتر از ۲۵۶ ویژگی پرونده. ۲۵۶ تای اول نگه داشته شد
unserialisable_propertyهمان کلیدمقدار قابل ذخیره نبود و حذف شد
invalid_phonephoneشماره موبایل ایرانی معتبر نیست. همان‌طور که فرستادید ذخیره شد
invalid_national_idnational_idرقم کنترلی نخواند. اصلا ذخیره نشد

پاسخ یک دسته وقتی پنجاه هشدار جمع کرد جمع کردن را بس می‌کند، هرچند همه‌شان در سنجه‌های کیفیت داده حساب شما شمرده می‌شوند. حواستان به generated_message_id باشد: تنها هشداری است که برایتان خرج دارد، چون یعنی رویدادی که دوباره فرستاده شود دو بار ذخیره می‌شود.

این جدول مال میزبان ورود داده است. مسیر POST /v1/events روی میزبان مدیریتی همین هشدارها را حساب می‌کند و بعد دورشان می‌ریزد، پس پاسخش هیچ‌وقت آرایه warnings ندارد و از روی آن نمی‌فهمید زمانی چسبانده شده یا شناسه پیامی ساخته شده. اگر این در را برای مهاجرت داده به کار می‌برید، حساب کنید که هیچ سیگنالی از اصلاح‌ها نمی‌گیرید.

#خطاهای ارسال تراکنشی

مسیر POST /v1/messages قدیمی‌ترین هندلر میزبان مدیریتی است و از اول تا آخر شکل تخت می‌دهد. هیچ‌کدام از خرابی‌هایش code ندارند.

همه این‌ها ۴۰۰ هستند و کل رشته error همان متن کلیدواژه است:

errorمعنی
transactional: user_id is requiredگیرنده‌ای نیست
transactional: template_id is requiredقالبی نیست
transactional: idempotency_key is requiredنه در بدنه و نه در هدر Idempotency-Key کلیدی نیست
transactional: idempotency_key must be 8-200 characters of letters, digits, dot, dash, underscore or colonکلید با ^[A-Za-z0-9._:-]{8,200}$ نخواند. متن روی سیم بین ۸ و ۲۰۰ نویسه U+2013 دارد
transactional: unknown channelکانالی نیست که این حساب رویش بفرستد
transactional: this endpoint does not send marketing; use a campaignمقدار category برابر marketing بود. این نقطه سقف تعداد و ساعت سکوت را دور می‌زند، پس قبول کردن پیام بازاریابی اینجا یعنی یک راه مستند برای دور زدن قواعد ارسال خودتان
transactional: too many variablesبیشتر از ۴۰ کلید در vars
malformed JSON: <detail>پارس نشد، یا فیلد ناشناخته داشت. فیلد ناشناخته رد می‌شود نه نادیده گرفته، تا idempotencyKey بدغلط ۴۰۰ بگیرد و روی هر تلاش یک کلید تازه نسازد

یک ۴۰۹ و یک ۵۰۳:

HTTPerrorمعنی
۴۰۹transactional: a message with this idempotency key is already in flightتلاش قبلی خودتان هنوز در جریان است. هدر Retry-After: 1
۵۰۳message not sentارسال خطا داد و هیچ شناسه پیامی برنگشت

وضعیت ۲۰۰ روی این نقطه یعنی تحویل داده شد نیست. فیلدهای reason و reason_fa را در بدنه بخوانید: وقتی پر می‌شوند که پیام به‌عمد فرستاده نشده باشد، برای انصراف کاربر، فهرست سیاه، یا نبود نشانی. و اگر ارسال انجام شد ولی ثبتش خطا داد، این نقطه به‌جای ۵۰۳ همان ۲۰۰ با نتیجه را می‌دهد، چون پیام به‌راستی رفته و کسی که خلافش را بشنود دوباره می‌فرستد و پیام دوم ارسال می‌شود.

#تلاش دوباره

قاعده‌ای که SDKها پیاده کرده‌اند، و همانی که باید خودتان پیاده کنید.

وضعیتتلاش دوبارهچرا
۴۰۰، ۴۰۲، ۴۰۳، ۴۰۴، ۴۰۹، ۴۱۳، ۴۲۲نههمان payload تا ابد همان جواب را می‌گیرد. استثنا ۴۰۹ روی POST /v1/messages است که تلاش خودتان است
۴۰۱نهاعتبارنامه هرگز کار نخواهد کرد. کلید را درست کنید
۴۲۹بله، بعد از Retry-Afterپنجره می‌چرخد
۵xxبله، با عقب‌نشینی نمایی و jitterایراد از ماست

هر سه SDK سگمنتیک این را در یک خط گفته‌اند: هرچه در بازه ۴۰۰ تا ۴۹۹ باشد به‌جز ۴۲۹ دائمی است و دور ریخته می‌شود؛ بقیه با عقب‌نشینی نمایی و jitter کامل تکرار می‌شوند، از پایه ۱ ثانیه تا سقف ۵ دقیقه.

تفاوت ۴۰۱ و ۵۰۳ کل دلیل جدا بودنشان روی میزبان ورود داده است. SDK وضعیت ۴۰۱ را «این کلید هرگز کار نمی‌کند» می‌خواند، متوقف می‌شود و رویدادهای بافرشده را دور می‌ریزد؛ ۵۰۳ را «بعدها دوباره امتحان کن» می‌خواند و نگهشان می‌دارد. این میزبان پیش‌تر وقتی خود جست‌وجوی کلید خطا می‌داد هم ۴۰۱ می‌داد، که ایراد ماست نه کلید شما: با پایگاه داده خاموش‌شده، هشت رویداد از هشت رویداد ۴۰۱ گرفتند و سمت مشتری نابود شدند، در حالی که لاگ خودشان می‌گفت کلید نوشتنشان نامعتبر است. حالا آن حالت ۵۰۳ با Retry-After: 5 است، و بافر دیسک پشت کالکتور درست برای همین هست که خرابی زیرساخت هیچ رویدادی را نبرد.

نتیجه برای شما: هر ۴۰۱ از ما را ایراد پیکربندی بدانید، نه گذرا. اگر روی کلیدی که دیروز کار می‌کرد ۴۰۱ انبوه دیدید، به‌راستی مشکل اعتبارنامه است، چون حالت خرابی دیگر این شکلی نیست.

#کجا تلاش دوباره محافظت‌شده است

مسیرساز و کارپنجره
هر مسیر روی میزبان ورود دادهتکراری‌زدایی با message_id در ردیس۴۸ ساعت، با DEDUPE_TTL
POST /v1/messagesکلید idempotency_key خودتان، رزرو در دفتر با یک رفت و برگشت۷ روز، با API_IDEMPOTENCY_RETENTION
وب‌هوک‌های ورودیشناسه پیام قطعی، تا تکرار پلتفرم بعد از timeout حالت عادی باشد۴۸ ساعت

روی هر رویداد message_id بفرستید. بدون آن ما می‌سازیمش، شما هشدار generated_message_id می‌گیرید، و تلاش دوباره بعد از timeout شبکه رویداد را دو بار ذخیره می‌کند. با آن، تلاش دوباره رایگان است.

این محافظت روی POST /v1/events نیست. آن مسیر رویدادها را بی‌آنکه ردیس را ببیند مستقیم منتشر می‌کند، پس message_id آنجا فقط شناسه رویداد است و هیچ‌چیز تکراری را نمی‌گیرد. تلاش دوباره روی این در، حتی با همان message_id، رویداد را دو بار ذخیره می‌کند. قبل از فرستادن دوباره یک خواندن بزنید.

رویداد تکراری‌زدایی‌شده به‌عنوان پذیرفته‌شده گزارش می‌شود، نه به‌عنوان تکراری. هیچ فیلد duplicate روی سیم نیست و شمارش‌ها این دو را از هم جدا نمی‌کنند. این عمدی است: منطق تلاش دوباره شما نباید مجبور باشد اهمیت بدهد، و تکراری در سهمیه شما شمرده نمی‌شود.

وقتی ردیس در دسترس نیست، بررسی تکراری‌زدایی رد می‌شود و تکراری احتمالی پذیرفته می‌شود، به‌جای اینکه رویداد از دست برود.

ارسال تراکنشی بازپخش‌شده علامت دارد. فیلد replayed را در نتیجه بخوانید تا «پیش‌تر این کار را کردیم» را از «همین حالا کردیم» جدا کنید، که وقتی تلاش اولتان timeout خورده و نمی‌دانید کدامش شده مهم است.

هیچ نوشتن مدیریتی دیگری به‌جز POST /v1/messages کلید idempotency نمی‌گیرد. مسیرهای POST /v1/segments و POST /v1/campaigns و POST /v1/campaigns/{id}/send و POST /v1/exports و POST /v1/events چنین فیلدی ندارند، پس تلاش دوباره روی POST /v1/campaigns کمپین دوم می‌سازد. این‌ها را فقط بعد از یک خواندن که مطمئن شوید تلاش اول ننشسته دوباره بفرستید.

#شناسه پیگیری برای تیکت

هر پاسخ از هر میزبان هدر X-Segmentic-Trace دارد، شانزده نویسه شانزده‌شانزدهی.

HTTP
HTTP/1.1 503 Service Unavailable
X-Segmentic-Trace: 4f2a9c81b0d3e756
Content-Type: application/json; charset=utf-8

{"error":{"code":"ingest_unavailable","message":"could not queue these events; retry"}}

در بدنه خطا نیست. از هدر لاگش کنید و در تیکت پشتیبانی بیاوریدش: همین است که به ما اجازه می‌دهد درست همان درخواست را در لاگ پیدا کنیم، نه دسته‌ای از درخواست‌های شبیه هم. اگر خودتان شناسه پیگیری دارید، آن را با همین هدر روی درخواست بفرستید: وقتی بین ۸ تا ۶۴ نویسه شانزده‌شانزدهی باشد، با حروف کوچک رعایتش می‌کنیم و در پاسخ برمی‌گردانیمش. هرچیز دیگری دور ریخته می‌شود و شناسه خودمان جایش می‌نشیند، چون این مقدار داخل خط‌های لاگ ما می‌رود.

نام هدر مال خودمان است و traceparent استاندارد کنسرسیوم وب نیست، چون پشتش نه تصمیم نمونه‌گیری هست و نه سلسله‌مراتب span، و هدری که شبیه traceparent باشد ولی نباشد اولین کسی را که ابزار ردیابی واقعی را به آن وصل کند گمراه می‌کند.

#آنچه در بدنه خطا نیست

این‌ها را نوشته‌ایم چون هرکدام چیزی است که خواننده دنبالش می‌گردد و پیدا نمی‌کند.

  • فیلد request_id وجود ندارد. شناسه پیگیری فقط در هدر است.
  • فیلد message_fa وجود ندارد. شکل مدیریتی code و message و details و need دارد و بس. هرجا متنی فارسی باشد، در همان message فارسی است.
  • کد جدا برای خطاهای گزارش وجود ندارد. سیزده خطای اعتبارسنجی موتور گزارش‌ها همه در یک کد invalid_report جمع می‌شوند. نه تای آن‌ها جمله فارسی کاتالوگ را در error می‌گذارند؛ چهار تای دیگر، یعنی نام رویداد بلند و فیلتر زیاد و کلید ویژگی بلند و مقدار ویژگی بلند، از شاخه پیش‌فرض رد می‌شوند و متن انگلیسی خود خطا را می‌آورند، مثل analytics: too many filters. پس زبان error روی این دو مسیر ثابت نیست. بدون خواندن آن رشته هم نمی‌توانید «مراحل قیف زیاد است» را از «بازه زمانی خیلی گسترده است» جدا کنید.
  • فیلدهای used و limit روی ۴۰۲ وجود ندارند. حکم سهمیه هر دو را حساب می‌کند و قبل از نوشتن پاسخ دور می‌ریزد.
  • بودجه باقی‌مانده در GET /v1/whoami وجود ندارد. پنج فیلد برمی‌گرداند و هیچ‌کدام بودجه نیست.
  • **هدرهای X-RateLimit-* روی بودجه مدیریتی وجود ندارند.** فقط روی POST /v1/messages هستند، آن هم فقط وقتی محدودیت نرخی تنظیم شده باشد که به‌طور پیش‌فرض نشده است. سقف‌ها را ببینید.

مرتبط: سقف‌ها و محدودیت نرخ، API ورود داده، API مدیریتی.

قبلیAPI مدیریتیبعدیسقف‌ها

در این صفحه

  • سه شکل خطا، نه یکی
  • روی کد شاخه بزنید، هرگز روی متن
  • درخواست را درست کنید
  • اعتبارنامه را درست کنید
  • صبر کنید
  • دوباره تلاش کنید
  • پول بدهید، یا تیکت بزنید
  • میزبان ورود داده وضعیت دارد، نه کد
  • چرا یک رویداد رد شد
  • هشدارها، که روی ۲۰۰ می‌آیند
  • خطاهای ارسال تراکنشی
  • تلاش دوباره
  • کجا تلاش دوباره محافظت‌شده است
  • شناسه پیگیری برای تیکت
  • آنچه در بدنه خطا نیست

سگمنتیک

این صفحه از روی کد نوشته شده است