UK

Тема

Колір акценту

Тема й колір збережуться на satelit.md і в застосунку.

Панель Обрати тариф

Кредити та ліміти

Два окремі ліміти: кредити на місяць, це ваша квота, і виклики на хвилину, які захищають сервіс.

Кредити

  • Невелика відповідь з бази даних коштує 1 кредит. Вартість кожного маршруту в таблиці цін.
  • Кредити списуються лише за відповідь 2xx. Помилка нічого не коштує.
  • Вони оновлюються в перший день вашого періоду, раз на місяць. Невикористане не переноситься.
  • Понад квоту ви отримуєте 429 quota_exceeded. API зупиняється, а рахунок не виставляється.

Ліміт на хвилину

Кожен план має ліміт на хвилину. Понад нього ви отримуєте 429 rate_limited із заголовком Retry-After.

Ліміти за планами

Кредитів на місяцьВикликів на хвилинуІсторія
Start5 0003030 дн.
Creator30 00012090 дн.
Pro300 000600365 дн.
Business3 000 0001 800усе
Enterpriseза договоромза договоромусе

Заголовки кожної відповіді

ЗаголовокЩо означає
X-RateLimit-LimitДозволено викликів на хвилину
X-RateLimit-RemainingЗалишилося викликів у поточній хвилині
X-RateLimit-ResetСекунд до скидання хвилини
X-Credits-CostСкільки кредитів коштував цей виклик
X-Credits-LimitКредити періоду
X-Credits-RemainingЗалишок кредитів
X-Credits-ResetКоли оновлюються кредити (ISO 8601)
Retry-AfterСкільки секунд чекати, лише для 429 і 503

Історія

Якщо ви просите більше днів, ніж дозволяє план, відповідь обрізається до ліміту плану, а meta.history_cut: true повідомляє про це.

Як повторити виклик

Прочитайте Retry-After, зачекайте вказаний час і спробуйте знову. Для quota_exceeded не повторюйте: дочекайтеся скидання з X-Credits-Reset.

async function call(url, key) {
  for (let attempt = 0; attempt < 3; attempt++) {
    const res = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
    const body = await res.json();
    if (res.ok) return body;
    if (body.error.code === "quota_exceeded") throw new Error(body.error.message);
    const wait = Number(res.headers.get("retry-after"));
    if (![429, 503].includes(res.status) || !wait) throw new Error(body.error.message);
    await new Promise((ok) => setTimeout(ok, wait * 1000));
  }
  throw new Error("still busy");
}
import json, time, urllib.error, urllib.request

def call(url, key):
    req = urllib.request.Request(url, headers={"Authorization": f"Bearer {key}"})
    for attempt in range(3):
        try:
            with urllib.request.urlopen(req) as res:
                return json.load(res)
        except urllib.error.HTTPError as err:
            body = json.load(err)
            wait = err.headers.get("Retry-After")
            if err.code not in (429, 503) or not wait or body["error"]["code"] == "quota_exceeded":
                raise
            time.sleep(int(wait))
    raise RuntimeError("still busy")
<?php
function call(string $url, string $key): array {
    for ($attempt = 0; $attempt < 3; $attempt++) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"]]);
        $raw = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        $size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        curl_close($ch);
        $body = json_decode(substr($raw, $size), true);
        if ($status < 400) {
            return $body;
        }
        preg_match("/retry-after: (\\d+)/i", substr($raw, 0, $size), $m);
        if (!in_array($status, [429, 503]) || empty($m[1]) || $body["error"]["code"] === "quota_exceeded") {
            throw new RuntimeException($body["error"]["message"]);
        }
        sleep((int) $m[1]);
    }
    throw new RuntimeException("still busy");
}