Перейти до змісту

Brand Partner API

Невеликий і передбачуваний REST API для створення замовлень mintbot, перевірки їхнього статусу та отримання подій життєвого циклу. JSON на вході, JSON на виході. Автентифікація bearer-токеном. Ідемпотентні записи. Підписані webhooks.

Панель доступу до API Перейти до webhooks


Коротко

Base URL https://mint.mintbot.ai/api/v1
Auth `Authorization: Bearer ***
Idempotency Idempotency-Key: <uuid> для кожного POST
Content type application/json
Rate limit 120 req / 60 s на партнера
Webhooks Підписуються HMAC-SHA256, повторюються до 7 разів

Автентифікація

Кожен запит надсилає API-ключ партнера в заголовку Authorization. Створіть або ротуйте ключ у панелі керування.

Authorization: Bearer mo_liv...xxxx
Content-Type: application/json

Ротація не має пільгового вікна

Ротація ключа атомарно відкликає попередній. Заплануйте заміну значення у своїй конфігурації до натискання Rotate.

Ідемпотентність

Кожен POST потребує заголовка Idempotency-Key. Підійде будь-який UUID для кожного окремого запиту.

  • Ми кешуємо відповідь протягом 24 годин. Повторна спроба з тим самим ключем відтворює початкову відповідь із Idempotent-Replay: true.
  • Повторне використання того самого ключа з іншим тілом повертає 409 idempotency_key_mismatch.

Замовлення

Створити замовлення

POST /orders

Створює замовлення та повертає URL Stripe Checkout. Коли платіж підтверджено, mintbot розгортає агента, а подія доходу з часткою партнера записується автоматично.

Запит

{
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "language": "en",
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/cart",
  "webhook_url": "https://your.app/mintbot-webhook"
}
tier
Одне з trial, s1, s2, s4.
duration_months
Строк життя сервера в календарних місяцях. Має бути 1, 3 або 12.
credit_usd
Необов’язково. Попередньо поповнений кредит для чату, включений у замовлення.
language
Необов’язково. Впливає на локаль Stripe Checkout і мову вітального email.
external_id
Необов’язково. Повертається в кожному webhook і відповіді замовлення — використовуйте його, щоб пов’язувати замовлення mintbot із рядками у власній системі.
success_url · cancel_url
URL повернення Stripe Checkout. {ORDER_ID} підставляється на боці сервера.
webhook_url
Необов’язково. Перевизначення URL webhook рівня партнера для конкретного замовлення.

Відповідь — 201 Created

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "awaiting_payment",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…",
  "panel_url": null,
  "expires_at": null,
  "language": "en",
  "external_id": "your-side-id",
  "created_at": "2026-05-16 09:58:00",
  "paid_at": null
}

Приклад

curl -X POST https://mint.mintbot.ai/api/v1/orders \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "tier": "s1",
    "duration_months": 1,
    "credit_usd": 10,
    "success_url": "https://your.app/thanks?id={ORDER_ID}",
    "cancel_url":  "https://your.app/cart"
  }'
import os, uuid, requests

r = requests.post(
    "https://mint.mintbot.ai/api/v1/orders",
    headers={
        "Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "tier": "s1",
        "duration_months": 1,
        "credit_usd": 10,
        "success_url": "https://your.app/thanks?id={ORDER_ID}",
        "cancel_url":  "https://your.app/cart",
    },
    timeout=10,
)
r.raise_for_status()
order = r.json()
redirect_to = order["checkout_url"]

Отримати замовлення

GET /orders/{id}

Отримує одне замовлення за його mintbot id. Повертає ту саму форму, що й POST /orders.

curl https://mint.mintbot.ai/api/v1/orders/42 \
  -H "Authorization: Bearer ***

Список замовлень

GET /orders

Список із курсорною пагінацією, найновіші спочатку.

Параметри запиту

status
Необов’язково. Фільтр за awaiting_payment, completed, deployed, deploy_failed або expired.
cursor
Необов’язково. Передайте next_cursor з попередньої сторінки, щоб продовжити.

Відповідь

{
  "items": [ /* OrderResponse … */ ],
  "next_cursor": "37"
}

next_cursor дорівнює null, коли сторінок більше немає.


Продовжити замовлення

POST /orders/{id}/renew

Подовжує чинного агента ще на duration_months. Лише інфраструктура — новий кредит для чату не додається. Повертає новий id замовлення та новий URL Stripe Checkout.

Запит

{
  "duration_months": 1,
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/account"
}

Дохід

Прочитати дохід

GET /revenue

Підсумки плюс останні 200 подій реєстру.

Параметри запиту

include_paid
Необов’язково, за замовчуванням true. Установіть false, щоб бачити лише події, які ще не були виплачені.

Відповідь

{
  "currency": "usd",
  "gross_cents": 12000,
  "partner_cut_cents": 2000,
  "mintbot_cut_cents": 10000,
  "unpaid_cents": 800,
  "events": [
    {
      "id": 7,
      "order_id": 42,
      "kind": "order_paid",
      "gross_cents": 1200,
      "partner_cut_cents": 200,
      "mintbot_cut_cents": 1000,
      "currency": "usd",
      "created_at": "2026-05-16 09:58:00",
      "payout_id": null,
      "payout_at": null
    }
  ]
}

Профіль партнера

Отримати профіль

GET /partner

Повертає ваш профіль партнера плюс невиплачений баланс — зручно, щоб показувати заробіток у власній адмін-панелі без самостійного зберігання цих даних.

Відповідь

{
  "id": 12,
  "email": "you@kliendifirma.com",
  "pricing_currency": "usd",
  "balance_unpaid_cents": 800,
  "webhook_url": "https://your.app/mintbot-webhook",
  "api_key_prefix": "mo_live_a12b"
}

Налаштування

Отримати налаштування

GET /settings

Повертає вашу повну несекретну конфігурацію партнера в одному payload — обрані режими, apex-домен, DNS-провайдера, bot-провайдера, репозиторій кастомізації, шаблон субдомену (з відрендереним прев'ю-лейблом), ціноутворення для кожного тарифу, метадані API-ключа, метадані webhook і той самий статус готовності / статус кожної секції, який керує банером панелі MintOffice.

Розроблено для інтеграційних агентів, яким потрібно з'ясувати, як налаштований партнер, без скрейпінгу панелі чи опитування оператора. Типовий виклик — це кодувальний агент, що встановлює ваш white-label-набір на свіжому сервері — він може прочитати цей endpoint, розгалужити логіку за readiness.status і точно сказати оператору, які секції ще потребують уваги.

Жоден секрет ніколи не повертається

Усе, що партнер надав як обліковий дані — токен Telegram-бота, API-ключ Zone.ee, секрет підпису webhook, сам відкритий текст API-ключа — з'являється лише як булеве *_set. Секрет webhook додатково показує той самий 8-символьний прев'ю-префікс, що вже показано в панелі, тож виклик може підтвердити, який секрет налаштовано, жодного разу не побачивши значення.

Відповідь

{
  "id": 12,
  "email": "you@kliendifirma.com",
  "status": "live",
  "created_at": "2026-05-12 14:22:01",
  "onboarded_at": "2026-05-12 14:48:33",
  "activated_at": "2026-05-13 09:10:05",
  "last_login_at": "2026-05-20 00:51:18",
  "preferred_language": "en",
  "pricing_currency": "usd",
  "balance_unpaid_cents": 800,

  "domain": {
    "mode": "byo",
    "client_apex_domain": "agent99.cc",
    "dns_provider": "zone.ee",
    "zone_ee_username": "you@kliendifirma.com",
    "zone_ee_api_key_set": true,
    "subdomain_prefix": "agent",
    "subdomain_numbering": "natural",
    "subdomain_pad_width": 3,
    "subdomain_label_preview": "agent1"
  },

  "bot": {
    "mode": "own",
    "provider": "telegram",
    "telegram_bot_username": "agent99cc_bot",
    "telegram_bot_token_set": true
  },

  "template": {
    "mode": "default",
    "repo_url": null
  },

  "api": {
    "key_prefix": "mo_live_a12b",
    "key_created_at": "2026-05-13 09:11:42",
    "webhook_url": "https://your.app/mintbot-webhook",
    "webhook_secret_set": true,
    "webhook_secret_prefix": "ab12cd34"
  },

  "pricing": {
    "mode": "default",
    "currency": "usd",
    "tiers": {
      "trial": { "price_cents": 0,    "partner_cut_cents": 0,   "updated_at": null },
      "s1":    { "price_cents": 1200, "partner_cut_cents": 200, "updated_at": "2026-05-13 09:05:00" },
      "s2":    { "price_cents": 2400, "partner_cut_cents": 400, "updated_at": "2026-05-13 09:05:00" },
      "s4":    { "price_cents": 4800, "partner_cut_cents": 800, "updated_at": "2026-05-13 09:05:00" }
    }
  },

  "readiness": {
    "ready": true,
    "missing_fields": [],
    "dns_blocker": null,
    "status": "live"
  },

  "section_status": {
    "domain":   { "status": "ready", "mode": "byo",     "issue": null, "dns_blocker": null },
    "bot":      { "status": "ready", "mode": "own",     "issue": null, "dns_blocker": null },
    "template": { "status": "ready", "mode": "default", "issue": null, "dns_blocker": null },
    "api":      { "status": "ready", "mode": "live",    "issue": null, "dns_blocker": null },
    "all_ready": true
  }
}

Довідник полів

status
Життєвий цикл партнера. Одне з onboarding, live, paused. Brand Partner API відхиляє записи під час onboarding.
domain.mode
byo (ви приносите власний apex-домен) або hosted (mintbot надає субдомен *.mintbot.ai). Коли hosted, поля DNS-провайдера навмисно порожні, незалежно від того, що партнер вводив раніше.
domain.subdomain_label_preview
Відрендерений лейбл, який отримав би перший клієнтський агент (agent1, 1, 001, …) за поточних subdomain_prefix, subdomain_numbering і subdomain_pad_width. Використовуйте його для прев'ю «ось що побачать ваші клієнти» без повторної реалізації правил нумерації.
bot.mode
own (Telegram-бот, наданий партнером), borrow (використання бота mintbot під час тестування) або web (лише панель, без Telegram).
template.mode
default (немає репозиторію кастомізації агента — агент працює на простій небрендованій базі) або custom (партнерський agent customization repo за repo_url). Коли custom, власний VPS агента клонує цей репозиторій після стандартного деплою і запускає його install.sh / update.sh, щоб застосувати вашу персону, тему панелі та будь-яке додаткове оснащення поверх бази — центр ніколи не виконує сам репозиторій. Спрямуйте repo_url на свій GitHub HTTPS agent customization repo, коли хочете кастомний брендинг.
api.webhook_secret_prefix
Перші 8 символів секрету підпису webhook, присутні лише коли секрет налаштовано. Дозволяє виклику розрізнити, який секрет на місці, не бачачи повного значення. Панель показує той самий префікс.
readiness.missing_fields
Список назв полів панелі, які ще потрібні перед Go Live. Порожній, коли ready дорівнює true. Достатньо стабільний, щоб керувати UI «що ще відсутнє» у вашій власній адмінці.
readiness.dns_blocker
Установлюється в короткий рядок-причину, коли верифікація DNS не вдається (наприклад, nameservers_not_pointing, glue_record_missing). Інакше null.
section_status.*.issue
Зрозуміла людині підказка для кожної секції, коли ця секція блокує Go Live. Дзеркалить статусні плашки кожної секції в панелі.

Приклад

bash curl https://mint.mintbot.ai/api/v1/settings \ -H "Authorization: Bearer ***

import os, requests

r = requests.get(
    "https://mint.mintbot.ai/api/v1/settings",
    headers={"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"},
    timeout=10,
)
r.raise_for_status()
settings = r.json()

if not settings["readiness"]["ready"]:
    print("Still missing:", settings["readiness"]["missing_fields"])

Каталог

Список пакетів для продажу для вашої вітрини — публічні пакети (trial / starter / pro), поєднані з вашими розрахованими цінами, у вашій валюті ціноутворення. Формуйте картки тарифів із цього, а не жорстко прописуйте слаги тарифів і ціни: знятті з продажу пакети зникають самі по собі, а зміна ціни чи валюти, яку ви робите в панелі керування, доходить до вашої вітрини в межах її вікна кешування — без передеплою.

Це endpoint, який не дає вітрині рекламувати вчорашні пакети. Референсний портал викликає його під час кожного рендеру лендингу / /buy / /extend (з кешуванням і липким запасним варіантом).

Текст оформлення залишається вашим

display_name / description / featured — це канонічні метадані пакетів mintbot. Якщо ви хочете перейменувати пакет або переписати його опис для свого бренду, перевизначте це у власній вітрині (референсний портал постачає мапу PLAN_OVERRIDES саме для цього) — каталог є джерелом правди про те, які пакети існують і скільки вони коштують, а не про ваш маркетинговий текст.

Отримати каталог

GET /api/v1/catalog

Без параметрів. Лише Bearer-автентифікація — тут немає шлюзу активації, тож вітрина може відрендерити каталог ще до того, як ваш партнерський акаунт переведено в режим live.

Відповідь

{
  "currency": "usd",
  "packages": [
    {
      "tier": "trial",
      "display_name": "Trial",
      "description": "One day to kick the tires.",
      "featured": false,
      "default_credit_usd": 5,
      "durations": [
        { "months": 1, "label": "24 hours", "price_cents": 0 }
      ],
      "subscription": { "available": false, "price_cents": null }
    },
    {
      "tier": "starter",
      "display_name": "Starter",
      "description": "A month of assistant time.",
      "featured": true,
      "default_credit_usd": 10,
      "durations": [
        { "months": 1,  "label": "1 month",   "price_cents": 1500 },
        { "months": 3,  "label": "3 months",  "price_cents": 4500 },
        { "months": 12, "label": "12 months", "price_cents": 18000 }
      ],
      "subscription": { "available": true, "price_cents": 1500 }
    }
  ]
}
Поле Значення
currency Ваша валюта ціноутворення. Кожен price_cents нижче виражений у ній.
packages[] По одному запису на кожен публічний пакет, у порядку пропозиції/показу.
tier Слаг, який ви передаєте до POST /orders / POST /subscriptions.
display_name / description / featured Канонічний текст показу (перевизначте у своїй вітрині, якщо хочете).
default_credit_usd Підказка про вбудований LLM-кредит пакета (інформаційно).
durations[] Строки налаштування, на які можна купити цей пакет. months — це значення, яке ви надсилаєте як duration_months; price_cents — це те, що замовлення нарахує. Місячні пакети рекламують 1 / 3 / 12 місяців; trial рекламує єдиний 24-годинний строк.
subscription available дорівнює true для пакетів, які можна купити як щомісячне автопродовження через POST /subscriptions; price_cents — це щомісячна сума. trial ніколи не підтримує підписку.

Ціни відповідають тому, що вам нарахують

Кожен price_cents обчислюється тим самим резолвером цін, який використовує endpoint замовлень, тож ціна картки завжди дорівнює підсумковій сумі Stripe Checkout для цього (tier, duration_months).

Приклад

curl -s https://mint.mintbot.ai/api/v1/catalog \
  -H "Authorization: Bearer *** | jq
import os, requests

r = requests.get(
    "https://mint.mintbot.ai/api/v1/catalog",
    headers={"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"},
    timeout=10,
)
r.raise_for_status()
catalog = r.json()

for pkg in catalog["packages"]:
    month1 = next(d for d in pkg["durations"] if d["months"] == 1)
    print(pkg["display_name"], month1["price_cents"], catalog["currency"])

DNS-записи

Інтеграції brand-партнерів часто потребують створення DNS-записів на apex-домені партнера — спрямовуючи @, www або субдомени окремих клієнтів на потрібний сервер. MintOffice надає vendor-blind проксі, тож ви можете робити це, жодного разу не маючи справи з API-ключем вищестоящого провайдера у власній інфраструктурі. Облікові дані, які ви зберегли під час онбордингу (сьогодні: zone.ee; cloudflare і route53 заплановані за тією самою формою), залишаються зашифрованими в MintOffice; ваш виклик надходить із Bearer mo_live_…, а ми робимо вищестоящий виклик від вашого імені.

Областю дії є власний налаштований apex партнера (domain.client_apex_domain з GET /settings). Ви не можете чіпати запис у зоні, якою не володієте.

Сьогодні проксі підтримує операції, які використовує сам pipeline розгортання — A-записи (upsert / список / видалення за id). Підтримка CNAME / TXT / MX з'явиться за тією самою формою, коли абстракція вищестоящого провайдера їх отримає.

Idempotency-Key тут не потрібен

На відміну від endpoint'ів створення замовлень, DNS-апсерти природно ідемпотентні на рівні провайдера (повторний запуск із тими самими (subdomain, ip) нічого не змінює, а застарілі дублікати вичищаються під час кожного виклику). Вам не потрібно надсилати заголовок Idempotency-Key — повторні спроби завжди сходяться до єдиного A-запису на FQDN.

Зробити upsert A-запису

POST /dns/records

Ідемпотентно спрямуйте <subdomain>.<your-apex> на адресу IPv4. Передайте "" (або "@") для самого apex.

Запит

{
  "subdomain": "www",
  "ip": "203.0.113.10"
}

subdomain приймає:

  • "" або "@" — сам apex (example.com).
  • Один DNS-лейбл — "www", "api" — для <label>.<apex>.
  • Лейбли з крапками — "api.eu" — для вкладених субдоменів (api.eu.example.com).

ip має бути адресою IPv4 у крапковій нотації. Кожен лейбл — [a-z0-9_-], 1–63 символи, без - на початку чи в кінці.

Відповідь — 200

{
  "apex": "example.com",
  "provider": "zone_ee",
  "fqdn": "www.example.com",
  "records": [
    { "id": "9182734", "name": "www.example.com", "destination": "203.0.113.10" }
  ]
}

Список records після запису завжди відображає поточне уявлення вищестоящого провайдера про FQDN після вичищення дублікатів — тож успішна відповідь рівно з одним записом є сигналом щасливого шляху, що нічого застарілого не залишилось.

Список записів

GET /dns/records

Повертає кожен A-запис на налаштованому apex. Додайте ?name=<label-or-fqdn>, щоб відфільтрувати до одного FQDN — значенням може бути голий лейбл ("www"), субдомен із крапками ("api.eu") або повний FQDN ("www.example.com").

Відповідь — 200

{
  "apex": "example.com",
  "provider": "zone_ee",
  "items": [
    { "id": "9182734", "name": "example.com",     "destination": "203.0.113.10" },
    { "id": "9182735", "name": "www.example.com", "destination": "203.0.113.10" }
  ]
}

Видалити запис

DELETE /dns/records/{record_id}

record_id — це ідентифікатор постачальника, який повертає GET /dns/records (zone.ee видає цілочислові id, перетворені на рядки на межі API). Видалення запису, який уже не існує, вважається успіхом — endpoint ідемпотентний з боку клієнта.

Відповідь — 200

{ "deleted": true, "id": "9182734" }

Помилки

HTTP error.code Причина
401 unauthenticated / invalid_api_key Відсутній / некоректний Bearer-токен.
422 validation_error Некоректний субдомен або призначення не-IPv4.
422 dns_not_configured У партнера немає client_apex_domain або відсутні облікові дані налаштованого провайдера. Виправте в Settings → Domain.
422 dns_provider_unsupported DNS-провайдер партнера ще не підключено до проксі MintOffice (наприклад, заглушка cloudflare). Поки що перемкніться на zone_ee.
502 dns_provider_error Вищестоящий провайдер повернув 4xx/5xx, або транспорт не вдався. Поле message помилки містить вищестоящий статус і короткий уривок вищестоящого тіла з відредагованими секретами. Можна безпечно повторити.

Приклад

# Point apex + www at your server's IP.
curl https://mint.mintbot.ai/api/v1/dns/records \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -d '{"subdomain": "",    "ip": "203.0.113.10"}'

curl https://mint.mintbot.ai/api/v1/dns/records \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -d '{"subdomain": "www", "ip": "203.0.113.10"}'

# Verify.
curl "https://mint.mintbot.ai/api/v1/dns/records" \
  -H "Authorization: Bearer ***
import os, requests

URL = "https://mint.mintbot.ai/api/v1/dns/records"
H = {"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"}

for sub in ("", "www"):
    r = requests.post(URL, headers=H, json={"subdomain": sub, "ip": "203.0.113.10"})
    r.raise_for_status()
    print(sub or "@", r.json()["records"])

Webhooks

Коли із замовленням щось відбувається, ми надсилаємо POST із підписаною JSON-подією на налаштований вами URL webhook.

Типи подій

Event Коли спрацьовує
order.created Створено сесію Stripe Checkout, очікується оплата.
order.paid Stripe підтвердив оплату. Подію доходу записано.
order.cancelled Замовлення вичерпало час очікування або було явно скасоване.
agent.provisioning_started Для цього замовлення запущено pipeline розгортання.
agent.ready Розгортання успішне. Payload містить panel_url і expires_at.
agent.failed Pipeline розгортання завершився помилкою. Перевірте поле error, щоб знайти крок, який зламався.
agent.expired TTL агента минув. Партнер може продовжити через POST /orders/{id}/renew.

Доставка та повторні спроби

  • До 7 спроб за експоненційним розкладом: 0s, 30s, 2m, 10m, 1h, 6h, 24h.
  • Після останньої спроби доставка позначається як exhausted і повтори зупиняються.
  • Відповідайте статусом 2xx протягом 10 секунд, щоб підтвердити отримання.

Заголовки запиту

Content-Type: application/json
User-Agent: mintbot-webhook/1.0
X-Mintbot-Signature: t=<unix_ts>,v1=<hex_hmac_sha256>
X-Mintbot-Event-Id: evt_42_order.paid_1747371234567
X-Mintbot-Event-Type: order.paid

Приклад payload — order.paid

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "completed",
  "external_id": "your-side-id",
  "paid_at": "2026-05-16 10:02:14"
}

Перевірка підпису

Підпис — це HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Завжди перевіряйте сире тіло запиту — повторна серіалізація розібраного JSON зламає порівняння.

import hmac, hashlib, time

def verify(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
    try:
        ts_part, v1_part = header.split(",", 1)
        ts  = int(ts_part.split("=", 1)[1])
        sig = v1_part.split("=", 1)[1]
    except Exception:
        return False
    if abs(int(time.time()) - ts) > tolerance:
        return False
    expected = hmac.new(
        secret.encode(),
        f"{ts}.".encode() + body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, sig)
const crypto = require("crypto");

function verify(secret, rawBody, header, toleranceSec = 300) {
  const [tsPart, v1Part] = header.split(",");
  const ts  = Number(tsPart.split("=")[1]);
  const sig = v1Part.split("=")[1];
  if (Math.abs(Date.now() / 1000 - ts) > toleranceSec) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.`)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(sig, "hex"),
  );
}

Ідемпотентні отримувачі

Використовуйте X-Mintbot-Event-Id як ключ дедуплікації — повторні спроби використовують той самий id, тому рядковий INSERT … ON CONFLICT DO NOTHING для цієї колонки захищає ваш обробник.


Помилки

Кожна відповідь із помилкою містить стабільний code, за яким можна програмно розгалужувати логіку. Поле message — підказка для людини, і воно може змінюватися між релізами. request_id повторює заголовок відповіді X-Request-Id — додавайте його до звернень у підтримку.

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Code Значення
unauthenticated Відсутній або некоректно сформований заголовок Authorization.
invalid_api_key API-ключ невідомий або був виведений з обігу ротацією.
rate_limited Перевищено ліміт запитів на партнера або IP — див. Retry-After.
missing_idempotency_key Запит POST без Idempotency-Key.
idempotency_key_mismatch Той самий ключ повторно використано з іншим тілом запиту.
validation_error Тіло запиту не пройшло валідацію схеми.
not_found Ресурс не існує або не належить вашому партнеру.
payment_gateway_error Stripe відхилив створення сесії Checkout.

Ліміти запитів

  • 120 запитів / 60 s ковзного вікна, на партнера. Burst і steady-state використовують один кошик.
  • 60 запитів / 60 s в окремому кошику на IP для неавтентифікованих запитів і запитів із невдалою автентифікацією — це не дає brute-force bearer-токена витрачати квоту партнера.
  • Надлишкові запити повертають 429 rate_limited із заголовком Retry-After (секунди очікування перед повтором).

Потрібна допомога?

Ця документація написана для партнерів, які справді користуються API. Якщо щось відсутнє, незрозуміле або застаріле, згадайте це своєму агенту mintbot — він передасть відгук, і ми оновимо сторінку.