Pending і опитування
Більшість перевірок відповідають у тій самій відповіді. Коли перевірка не може, API не змушує вас чекати на відкритому з'єднанні: воно приймає перевірку й відповідає status: "pending" із check_id. Тіло має точно ту саму форму, що й завершена перевірка, тож код, який читає відповідь, не змінюється; ви лише розгалужуєтеся за data.status.
Чому перевірка в стані pending
Перевірку передають у чергу й відповідають pending, коли їй справді потрібно більше часу, ніж має тримати запит:
- стороннє джерело даних зайняте, і запитам доводиться чекати своєї черги,
- холодний обхід блокчейну триває довше за бюджет запиту, або
- перевірка вичерпала час, відведений на відповідь у межах запиту.
Поки перевірка чекає на потрібні свідчення, вердикту, списання й вебхука про завершення немає. Усе врегульовується один раз, коли перевірка завершується.
Поля очікування
| Поле | Поки pending | Після завершення |
|---|---|---|
status | pending | completed або failed |
pending_reason | Чому перевірка чекає на свідчення, наприклад provider_pending (запити до стороннього джерела даних тривають) або provider_capacity (очікування ємності для запитів). Інформаційне: не розгалужуйтеся за значеннями, яких не знаєте. null, коли перевірка просто в черзі. | null |
deadline_at | Налаштований час, до якого перевірка буде завершена. Це межа, а не оцінка: більшість перевірок завершуються набагато раніше. Для нативних перевірок і перевірок пакета типово це 24 години після прийняття. | Зберігається як записано. null для перевірки, яка ніколи не чекала. |
next_attempt_at | Найраніший час наступного повтору чи перевірки готовності за розкладом. Це не обіцянка результату в цей час. | null |
Коли відомо, що джерело даних недоступне, перевірка не чекає свого крайнього терміну: вона завершується раніше частковим вердиктом, який каже чому (див. partial_reasons і degraded_sources у Перевірках адрес), і відповідає один раз.
Опитування перевірки
GET /v1/checks/{check_id} зі scope checks:read.
- Ідентифікатор у стані pending ніколи не відповідає
404. Він одразу повертаєstatus: "pending".404означає, що ідентифікатор не ваш, належить іншому середовищу або ніколи не існував. - Опитуйте не раніше
next_attempt_at. Між запланованими перевірками нічого не змінюється. Якщо воноnull, зачекайте кілька секунд. Опитування рахується до ліміту маршрутуGET, 30 запитів за хвилину з однієї IP-адреси джерела; див. Обмеження частоти запитів і ліміти. - Зупиняйтеся на
completedабоfailed. Обидва стани завершальні, і жодне поле потім не змінюється. Два читання завершеної перевірки повертають однакові тіла, тож її безпечно читати знову, коли потрібен вердикт. - Зупиняйтеся на
deadline_at. До цього часу перевірку буде завершено. Якщо невдовзі після нього остання відповідь усе щеpending, збережітьcheck_idі прочитайте перевірку пізніше замість циклу.
Віддавайте перевагу вебхуку, коли можете: ви реєструєте кінцеву точку один раз і отримуєте одну підписану доставку check.completed на кожну завершену перевірку, тож опитувати нічого. Залишайте опитування як запасний варіант на випадок доставки, що не надійшла.
- curl
- Node.js
- Python
curl -s https://api.leeri.ai/v1/checks/$CHECK_ID \
-H "Authorization: Bearer $LEERI_API_KEY"
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function waitForCheck(checkId) {
for (;;) {
const response = await fetch(`https://api.leeri.ai/v1/checks/${checkId}`, {
headers: { Authorization: `Bearer ${process.env.LEERI_API_KEY}` },
});
if (response.status === 429) {
await sleep(Number(response.headers.get('retry-after') ?? 5) * 1000);
continue;
}
if (!response.ok) throw new Error(`poll failed with ${response.status}`);
const { data } = await response.json();
if (data.status !== 'pending') return data;
if (data.deadline_at && Date.now() > Date.parse(data.deadline_at) + 60_000) {
throw new Error(`check ${checkId} is still pending after its deadline`);
}
const next = data.next_attempt_at ? Date.parse(data.next_attempt_at) - Date.now() : 5000;
await sleep(Math.min(Math.max(next, 2000), 60_000));
}
}
const check = await waitForCheck(checkId);
console.log(check.status, check.band, check.score);
import os
import time
from datetime import datetime, timezone
import requests
def parse(value):
return datetime.fromisoformat(value.replace("Z", "+00:00"))
def wait_for_check(check_id):
while True:
response = requests.get(
f"https://api.leeri.ai/v1/checks/{check_id}",
headers={"Authorization": f"Bearer {os.environ['LEERI_API_KEY']}"},
timeout=30,
)
if response.status_code == 429:
time.sleep(int(response.headers.get("Retry-After", "5")))
continue
response.raise_for_status()
data = response.json()["data"]
if data["status"] != "pending":
return data
now = datetime.now(timezone.utc)
if data["deadline_at"] and (now - parse(data["deadline_at"])).total_seconds() > 60:
raise RuntimeError(f"check {check_id} is still pending after its deadline")
wait = (parse(data["next_attempt_at"]) - now).total_seconds() if data["next_attempt_at"] else 5
time.sleep(min(max(wait, 2), 60))
check = wait_for_check(check_id)
print(check["status"], check["band"], check["score"])
Коли перевірка завершується невдачею
Перевірка, що завершилася без вердикту, має status: "failed", а score, band та інші поля вердикту дорівнюють null. За невдалу перевірку ніколи не списують. Якщо ви надсилаєте перевірку й вона завершується невдачею під час самого запиту, відповідь — 422 CHECK_FAILED; status: "failed" ви читаєте, коли отримуєте перевірку пізніше. Щоб спробувати знову, надішліть перевірку як новий запит із новим Idempotency-Key; див. Ідемпотентність.
Перевірка шляху pending
Ключ sandbox, що надсилає тестову адресу 1PENDNGCHECKADDRESSFRSANDBXTEST99 як перевірку адреси BTC, завжди отримує відповідь pending, тож ви можете будувати й тестувати опитування та обробку вебхуків, не чекаючи справжнього повільного запиту. Див. Sandbox і live.