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.modebyo(ви приносите власний apex-домен) абоhosted(mintbot надає субдомен*.mintbot.ai). Колиhosted, поля DNS-провайдера навмисно порожні, незалежно від того, що партнер вводив раніше.domain.subdomain_label_preview- Відрендерений лейбл, який отримав би перший клієнтський агент (
agent1,1,001, …) за поточнихsubdomain_prefix,subdomain_numberingіsubdomain_pad_width. Використовуйте його для прев'ю «ось що побачать ваші клієнти» без повторної реалізації правил нумерації. bot.modeown(Telegram-бот, наданий партнером),borrow(використання бота mintbot під час тестування) абоweb(лише панель, без Telegram).template.modedefault(немає репозиторію кастомізації агента — агент працює на простій небрендованій базі) або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 — він передасть відгук, і ми оновимо сторінку.