Каскадна маршрутизація
Каскадна маршрутизація дозволяє визначити кілька upstream цілей для одного запиту. MirApi спробує їх послідовно (Priority) або паралельно (Race) і поверне першу успішну відповідь.
Каскадні маршрути налаштовуються у вашому дашборді та активуються заголовком X-Route-Key.
Налаштування маршруту у дашборді
Section titled “Налаштування маршруту у дашборді”- Відкрийте Routes → Створити маршрут
- Вкажіть ім’я (наприклад,
ai-providers) - Додайте цілі — список повних URL через кому:
https://api.openai.com/v1/chat/completions,https://api.anthropic.com/v1/messages,https://api.groq.com/openai/v1/chat/completions
- Оберіть стратегію: Priority або Race
- Задайте тайм-аут на ціль (мілісекунди)
- Опційно налаштуйте body mapping та витягнення відповіді

Активація маршруту
Section titled “Активація маршруту”curl -X POST https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: ai-providers" \ -H "X-Identity-Key: Bearer $OPENAI_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Привіт"}]}'Стратегії каскаду
Section titled “Стратегії каскаду”Priority (Послідовний failover)
Section titled “Priority (Послідовний failover)”Цілі пробуються по порядку. Наступна ціль пробується лише якщо попередня провалилась (5xx, тайм-аут або помилка з’єднання).
Ціль 1: https://api.openai.com/... → збій (503)Ціль 2: https://api.anthropic.com/... → збій (тайм-аут)Ціль 3: https://api.groq.com/... → успіх ✓
Відповідь: X-Rescued: cascade_fallbackНайкраще для:
- Економії коштів (лише один API-виклик у happy path)
- Платіжних API де потрібний детермінований порядок
- Будь-яких сценаріїв де важливий пріоритет
# AI провайдер — спочатку OpenAI, потім Anthropic, потім Groqcurl -X POST https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: ai-priority" \ -H "X-Identity-Key: Bearer $OPENAI_KEY" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Що таке Go?"}]}'Race (Паралельно)
Section titled “Race (Паралельно)”Всі цілі викликаються одночасно. Перша успішна відповідь перемагає; решта скасовуються через context cancellation.
Ціль 1: https://api.openai.com/... → відповів за 1200ms ✗ (програв)Ціль 2: https://api.anthropic.com/... → відповів за 890ms ✗ (програв)Ціль 3: https://api.groq.com/... → відповів за 89ms ✓ (переміг)Найкраще для:
- Ультранизьких затримок де час відповіді критичний
- Read-only запитів (курси валют, пошук, ембеддинги)
- Коли всі провайдери повертають еквівалентні відповіді
curl -X POST https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: ai-race" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Швидке питання"}]}'Комбінування з іншими функціями
Section titled “Комбінування з іншими функціями”Маршрут + Повтори
Section titled “Маршрут + Повтори”curl -X POST https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: payment-cascade" \ -H "X-Retry-Count: 2" \ -H "X-Retry-Delay: 300ms" \ -H "X-Proxy-Timeout: 10s" \ -d '{"amount": 9900, "currency": "usd"}'# Ціль 1 повторюється до 2 разів перед переходом до Цілі 2Маршрут + Async Webhook
Section titled “Маршрут + Async Webhook”curl -X POST https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: payment-cascade" \ -H "X-Webhook-Callback: https://your-app.com/payments/done" \ -H "X-Proxy-Idempotency-Key: order_789_pay_1" \ -d '{"amount": 9900, "currency": "usd"}'# Повертає 202 негайно# Воркер виконує повний каскад у фоні# POST з першою успішною відповіддю на callbackМаршрут + Smart Cache
Section titled “Маршрут + Smart Cache”curl https://proxy.mirapi.io/ \ -H "X-MirApi-Key: $MIRAPI_KEY" \ -H "X-Route-Key: exchange-rates-cascade" \ -H "X-Smart-Cache: 300s"# Пробує всі цілі маршруту# Всі провалились → кеш → X-Rescued: cacheМаппінг тіла запиту цілі
Section titled “Маппінг тіла запиту цілі”Маппінг тіла запиту розбирає JSON-тіло вхідного запиту, перейменовує ключі, обходить вкладені поля та масиви, і формує запит перед відправкою на upstream. Перейменовані ключі-джерела автоматично видаляються.
Формат правила маппінгу — розділений комами список правил: шлях_джерела=>шлях_цілі або шлях_джерела=>шлях_цілі(шаблон).
Підтримуваний синтаксис шляху
Section titled “Підтримуваний синтаксис шляху”| Можливість | Приклад | Опис |
|---|---|---|
| Плоске перейменування | amount=>sum | Перейменовує кореневий ключ |
| Вкладений об’єкт (dot-notation) | data.order=>data.order_id | Перейменовує order на order_id всередині об’єкта data |
Перебір масиву з [] | data.orders[].order=>data.orders[].order_id | Перейменовує order на order_id у кожному елементі масиву orders |
Перебір масиву без [] | data.orders.order=>data.orders.order_id | Те саме — дужки необов’язкові, визначаються автоматично |
Шаблон значення {value} | order=>order_text(Order ID: #{value}) | Форматує значення поля у рядковий шаблон |
Міжпольовий шаблон {field_name} | status=>status(Order {order} status is {value}) | Інтерполює значення інших полів з поточного JSON-контексту |
Як це працює:
Section titled “Як це працює:”- Ваш клієнт надсилає запит до проксі-шлюзу з оригінальною структурою JSON.
- Шлюз перехоплює тіло запиту і перед відправкою на upstream перейменовує та трансформує ключі згідно з
body_mapцієї цілі. - Вкладені шляхи та елементи масивів обходяться автоматично. Решта ключів залишаються без змін.
A. Плоске перейменування:
// body_map: "amount=>sum, currency=>cur"// Вхід: {"amount": 100, "currency": "USD"}// Вихід: {"sum": 100, "cur": "USD"}B. Вкладені об’єкти:
// body_map: "data.order=>data.order_id"// Вхід: {"action": "get_status", "data": {"order": 353454876}}// Вихід: {"action": "get_status", "data": {"order_id": 353454876}}C. Перебір масиву:
// body_map: "data.orders[].order=>data.orders[].order_id"// або "data.orders.order=>data.orders.order_id"// Вхід: {"data": {"orders": [{"order": 101}, {"order": 102}]}}// Вихід: {"data": {"orders": [{"order_id": 101}, {"order_id": 102}]}}D. Динамічний шаблон значення {value}:
Форматує значення поля у рядковий шаблон. {value} — пластина для значення джерельного поля:
// body_map: "order=>order_text(Order ID: #{value})"// Вхід: {"order": 101}// Вихід: {"order_text": "Order ID: #101"}E. Міжпольовий шаблон {field_name}:
Інтерполює значення інших полів з того ж JSON-контексту. Поле шукається спочатку в поточному об’єкті, а потім у глобальному корені:
// body_map: "status=>status(Order {order} status is {value})"// Вхід: {"order": 101, "status": "success"}// Вихід: {"order": 101, "status": "Order 101 status is success"}F. Посилання на сусідні поля у масивах:
Доступає до сусідніх ключів всередині кожного окремого елементу масиву під час ітерації:
// body_map: "data.orders.status=>data.orders.status_text(Order {order} is {value})"// Вхід: {"data": {"orders": [{"order": 101, "status": "success"}, {"order": 102, "status": "fail"}]}}// Вихід: {"data": {"orders": [{"order": 101, "status_text": "Order 101 is success"}, {"order": 102, "status_text": "Order 102 is fail"}]}}
---
## Власні умови відкату по тілу відповіді
За замовчуванням каскадна маршрутизація переходить до наступної цілі лише тоді, коли поточний ендпоінт повертає статус `5xx`, виникає тайм-аут або помилка з'єднання.
Однак багато API (особливо платіжні шлюзи) повертають статус `200 OK` навіть тоді, коли транзакцію відхилено або вона завершилася помилкою. Для підтримки маршрутизації на основі бізнес-логіки збоїв, кожна ціль маршруту може визначати власну умову відкату у дашборді чи базі даних за допомогою двох параметрів:- `fallback_field`: вираз JSONPath, що вказує на поле в JSON відповіді для перевірки. Префікс `$.` є **необов'язковим** — додається автоматично, якщо відсутній. Підтримуються вкладені об'єкти (dot-notation) та елементи масиву (нотація `[]`).- `fallback_value`: рядкове значення для співпадіння (регістронезалежна перевірка на входження підрядка).
### Підтримуваний синтаксис `fallback_field`
| Приклад | Еквівалентно | Опис ||---|---|---|| `status` | `$.status` | Поле на верхньому рівні || `error.code` | `$.error.code` | Поле вкладеного об'єкта || `errors[].code` | `$.errors[*].code` | Поле всередині будь-якого елемента масиву |
### Як це працює:1. Цільовий ендпоінт повертає успішний код статусу (менше `500`).2. Шлюз зчитує тіло відповіді та витягує значення поля за вказаним шляхом JSONPath у `fallback_field`.3. Якщо витягнуте значення містить `fallback_value` як підрядок, шлюз розглядає цю відповідь як **помилку**.4. Шлюз відкидає цю відповідь, логує спрацювання умови та негайно переходить до наступної цілі у ланцюжку каскаду.

### Приклад: Відкат при відхиленні платежуUpstream платіжного процесора повернув статус `200 OK`, але платіж відхилено:```json{ "transaction_id": "tx_abc123", "status": "declined", "failure_reason": "insufficient_funds"}Налаштувавши ціль параметрами:
- Fallback Field:
status(або$.status) - Fallback Value:
declined
Шлюз перехопить 200 OK, виявить, що $.status дорівнює "declined", трактуватиме це як збій і надішле запит на оплату до наступного резервного банку у вашому каскаді.
Приклад: Відкат за кодом помилки в масиві
Section titled “Приклад: Відкат за кодом помилки в масиві”Upstream повертає помилки як масив:
{ "errors": [{"code": "card_declined", "message": "Недостатньо коштів"}]}Налаштувавши ціль параметрами:
- Fallback Field:
errors[].code - Fallback Value:
card_declined
Шлюз перевіряє поле code кожного елемента масиву errors і тригерить відкат, якщо будь-яке з них співпадає.
Захист від петель
Section titled “Захист від петель”Шлюз валідує всі цільові URL щодо власних IP-адрес та хостнеймів. Будь-яка цільова URL що резолвиться до самого проксі блокується з 400 Bad Request.
Заголовок відповіді
Section titled “Заголовок відповіді”Коли використовується не первинна ціль:
HTTP/1.1 200 OKX-Rescued: cascade_fallbackЯкщо первинна ціль (перша у списку) успішна — X-Rescued не додається.