Esențialul API-ului
Tratează neprevăzutul.
Coduri stabile în funcție de care decizi și când să reîncerci.
Fiecare eșec are un message tradus și, în afară de o simplă eroare de validare, un
code stabil. Decide în funcție de cod — mesajul este tradus pe server și se va schimba.
{
"message": "This API key is not entitled to this lottery.",
"code": "lottery_not_entitled"
}
O eroare de validare — un parametru pe care API-ul nu l-a putut accepta — nu are code. Este un
422 care are în schimb harta errors a Laravel, cu parametrul drept cheie:
{
"message": "This is not a date the API can read.",
"errors": { "filter.from": ["This is not a date the API can read."] }
}
Un filtru, o sortare sau o includere nedeclarată le are pe amândouă: unul dintre codurile
invalid_* de mai jos și o intrare în errors sub filter, sort sau include.
Codurile
| HTTP | code | Semnificație |
|---|---|---|
| 401 | api_key_missing | Nu a fost prezentată nicio credențială |
| 401 | invalid_api_key | Cheie necunoscută sau incorect formată |
| 401 | api_key_revoked | Cheia a fost revocată |
| 401 | api_key_expired | Cheia a depășit data de expirare |
| 402 | subscription_required | Contul nu are un plan activ sau perioada de probă s-a încheiat (trial_ended_at) |
| 403 | origin_not_allowed | Cheie legată de browser, apelată din altă origine |
| 403 | insufficient_scope | Cheia ta nu are permisiunea cerută de această rută |
| 403 | lottery_not_entitled | Jocul există, dar nu este în selecția ta |
| 403 | plan_upgrade_required | Planul nu include această rută; required_plan numește cel mai ieftin plan care o include |
| 403 | history_not_included | Rezultatul e mai vechi decât istoricul inclus în planul tău — sau, pe o cheie de sandbox, mai nou decât întârzierea ei de șapte zile ori mai vechi decât ultimele 50 de rezultate |
| 403 | export_not_permitted | Cheia cu care a fost cerut exportul a fost revocată, a expirat sau nu mai are exports:read, deci linkul nu mai merge |
| 404 | not_found | URL necunoscut sau înregistrare necunoscută — intenționat identice |
| 410 | export_expired | Fișierul exportului a fost șters; cere un export nou |
| 422 | invalid_filter | Cu filtrele permise în mesaj |
| 422 | invalid_sort | Cu câmpurile sortabile în mesaj |
| 422 | invalid_include | Cu relațiile care pot fi incluse în mesaj |
| 422 | invalid_query | Șirul de interogare nu a putut fi citit |
| 422 | ticket_check_unsupported | Biletele acestui joc nu pot fi verificate încă (ticket_check.kind e null pe joc) |
| 422 | distributions_unsupported | Distribuțiile extragerilor nu se potrivesc acestui joc: jocurile de tip bingo, unde numărul de bile extrase e chiar rezultatul, și jocurile cu mai multe urne (statistics.distributions e false pe joc) |
| 422 | generator_unsupported | Pentru acest joc nu se pot genera bilete: jocurile de tip bingo, jocurile cu mai multe urne și cursele (tools.generate e false pe joc) |
| 422 | generator_impossible | Niciun bilet nu poate respecta aceste filtre împreună; mesajul spune care nu poate fi îndeplinit |
| 422 | generator_space_too_small | Filtrele permit mai puține bilete diferite decât cere count; mesajul spune câte |
| 422 | generator_filters_too_narrow | Niciun bilet generat nu a trecut de filtre (sau toate cele care au trecut ieșiseră deja): relaxează-le |
| 422 | wheel_unsupported | Sistemele reduse se construiesc doar pentru jocurile în care un bilet e un set de numere diferite: nu pentru jocurile pe cifre, cele cu mai multe urne sau curse (tools.wheel e false pe joc) |
| 422 | wheel_too_large | Sistemul redus cerut e prea mare pentru a fi calculat: alege mai puține numere sau altă garanție |
| 422 | not_enough_draws | Filtrele din extragerile trecute cer cel puțin 100 de extrageri în window |
| 422 | ticket_check_too_large | Prea multe extrageri pentru atâtea bilete deodată: verifică mai puține bilete sau o fereastră mai scurtă |
| 422 | webhook_limit_reached | Cheia are deja numărul maxim permis de abonamente webhook |
| 422 | delivery_still_retrying | Livrarea e încă reîncercată și nu poate fi reluată deocamdată |
| 429 | rate_limit_exceeded | Vârf pe minut. retry_after este în secunde |
| 429 | quota_exceeded | Cota zilnică s-a epuizat. Reîncearcă după resetarea UTC, nu peste o secundă |
| 429 | stream_limit_reached | Contul are deja numărul maxim permis de fluxuri live |
| 429 | stream_capacity_reached | Fluxul a atins capacitatea maximă pentru toți clienții |
| 429 | export_limit_reached | Contul a cerut toate exporturile incluse în plan luna aceasta; resets_at spune când se reînnoiește plafonul |
| 429 | export_in_progress | Contul pregătește deja câte exporturi poate simultan; încearcă din nou când unul e gata |
Un widget răspunde cu un mesaj în cadrul lui, nu cu JSON; codurile lui (widget_*) sunt listate în
Widget-uri.
Reîncercări
Un 429 are retry_after în secunde și un header Retry-After. Cele două coduri pentru limita de
cereri înseamnă lucruri diferite și merită tratate diferit: rate_limit_exceeded se rezolvă în cursul minutului,
în timp ce quota_exceeded nu se rezolvă până la miezul nopții UTC — o reîncercare peste o
secundă irosește cererea și se contorizează oricum.
Înregistrările necunoscute și URL-urile necunoscute primesc intenționat același răspuns. Dacă le-am deosebi, un apelant ar putea enumera ce există.
ID-urile cererilor
Fiecare răspuns dat după autentificare are un header X-Request-Id, inclusiv cele reușite:
X-Request-Id: 01a115a8-4360-7128-8584-0bce749aabfa
Salvează-l în jurnal lângă propria eroare. Când scrii la suport despre un
apel eșuat, ID-ul cererii ne permite să găsim exact acel apel — butonul Întreabă suportul despre
acest apel din jurnalul cererilor îl completează pentru tine. Tot așa găsești și tu apelul:
Jurnalul cererilor din spațiul de lucru păstrează fiecare cerere timp
de 30 de zile, cu statusul, timpul de răspuns și code-ul și message-ul returnate, și îl poți
căuta după ID-ul cererii.
Un 401 sau un 403 origin_not_allowed răspunde înainte ca cheia să fie acceptată, așa că nu
are ID de cerere și nu apare în jurnal.
E problema noastră?
Pagina de stare arată, cu verificări în fiecare minut, dacă API-ul răspunde, dacă rezultatele noi sosesc la timp și dacă webhook-urile pleacă din coadă. Când raportează o perturbare, nu ai nimic de reparat de partea ta.