forma · Merchant API
Документация интеграции
Что в API
Методы сгруппированы по трём блокам: мерчанты (профиль и счета), транзакции (публичные и защищённые маршруты), выплаты. Ниже — быстрые ссылки на карточки методов на этой странице; подробные описания, пути и примеры тел запросов — в соответствующих разделах ниже.
Базовый URL
База API: api.formapay.io. Все пути с префиксом /v1.
https://api.formapay.io/v1
Заголовки авторизации
Пример для защищённых маршрутов мерчанта.
X-API-Key: sp_your_public_key
Авторизация
Для методов мерчанта передавайте X-API-Key (публичный или приватный ключ). Ключ можно получить
и перевыпустить в кабинете мерчанта.
Публичные маршруты /v1/public/… не требуют ключа мерчанта; действует ограничение частоты
запросов по IP.
Webhook'и (исходящие события)
Forma шлёт POST с подписанным JSON на merchant.webhook_url (общий) или
transaction.callback_url (per-tx — если задан при POST /v1/transactions).
Доставка — с retry на 5xx/408/429 и таймауте; 4xx не повторяется.
Заголовки запроса
| Заголовок | Описание |
|---|---|
X-Forma-Event-Id | UUID конкретной попытки доставки — нужен для идемпотентности на стороне мерчанта. |
X-Forma-Event | Имя события (см. список ниже). |
X-Forma-Timestamp | Unix-секунды момента подписания. |
X-Forma-Signature | sha256=<hex> от HMAC-SHA256(webhook_secret, "<ts>.<raw_body>"). Проверяйте при |now − ts| ≤ tolerance, иначе ловите replay. |
User-Agent | forma-webhook/1. |
Content-Type | application/json. |
События
transaction.completed— оплата пришла полностью или с переплатой.transaction.expired— срок жизни инвойса истёк без оплаты.transaction.chargeback— диспут / возврат со шлюза.payout.broadcasted— заявка на вывод отправлена в сеть.payout.success— вывод подтверждён.payout.failed— окончательная ошибка по заявке.
Тело transaction.*
Поля payload'а
event- Имя события (то же, что в
X-Forma-Event). transaction.id- UUID транзакции.
transaction.external_id- Внешний ID заказа (если был сгенерирован).
transaction.merchant_id- UUID мерчанта.
transaction.status- Состояние tx на момент события (
completed/expired/chargebackи т.п.). transaction.currency- Валюта, в которой плательщик видел сумму (RUB для СБП/Card-RUB, USDT для крипто).
transaction.network- Сеть из метода (TRC20, SBP, Card и т.п.).
transaction.amount_expected,transaction.amount_received- Суммы в
currency(8 знаков).amount_received— пропорционально доле подтверждённой оплаты. transaction.amount_expected_usdt,transaction.amount_received_usdt- Те же суммы в USDT-нормировке ledger'а — для сверки с балансом forma.
transaction.tx_hash- Hash транзакции в сети (для крипто) или
null. transaction.address- Адрес кошелька (для address-flow) или
null. transaction.created_at,transaction.updated_at,transaction.target_action_at- Unix-секунды.
Тело payout.*
Поля payload'а
event- Имя события (то же, что в
X-Forma-Event). payout.id,payout.merchant_id,payout.status- Идентификаторы и текущий статус заявки.
payout.amount_requested,payout.amount_to_send,payout.network_fee,payout.service_fee- Суммы в USDT (8 знаков).
payout.tx_hash,payout.broadcasted_at,payout.processed_at- Hash транзакции и unix-секунды отправки/завершения.
payout.error_log,payout.attempts- Диагностика ошибок и счётчик попыток.
Проверка подписи (Python)
import hmac, hashlib, time
def verify_forma_webhook(secret: str, raw_body: bytes, headers: dict) -> bool:
ts = headers["X-Forma-Timestamp"]
sig = headers["X-Forma-Signature"] # "sha256=<hex>"
# 1) Reject if timestamp too old (e.g. ±5 min).
if abs(time.time() - int(ts)) > 300:
return False
# 2) Recompute HMAC over "<ts>.<raw_body>".
msg = f"{ts}.".encode() + raw_body
expected = "sha256=" + hmac.new(secret.encode(), msg, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
Мерчанты
Защищённые маршруты с ключом мерчанта: профиль и балансы, проверка возможности приёма платежей, список счетов для приёма.
Эндпоинты
-
Основная информация мерчанта
GET /v1/merchants/me — полный профиль мерчанта: email, балансы (
balance,hold_balance,available_balance,total_funds), статус, часовой пояс, публичный API-ключ, настройки уведомлений и URL, 2FA, Telegram, автовывод. -
Проверка создания платежей
GET /v1/merchants/me/accepting-payments — проверка, что аккаунт активен и может принимать платежи; при успехе тело
{"accepting": true}, иначе ошибка доступа (например 403). -
Счета мерчанта
GET /v1/merchants/me/accounts — список платёжных счетов с валютой, сетью, адресом, комиссиями и флагами активности. Тело ответа — JSON-массив счетов. Пагинация задаётся query-параметрами
limitиoffset.
Транзакции
Публичные методы без ключа мерчанта (данные для страницы оплаты, курс), а также защищённые маршруты: количество и список транзакций, создание платежа.
Эндпоинты
-
Создать транзакцию
POST /v1/transactions — создать платёж; в теле ответа 201 сервер возвращает
payment_url— готовую ссылку на страницу оплаты (при необходимости такжеpay_linkдля провайдера). Возможен сценарий с предвыбранным счётом или выбором способа на странице оплаты. -
Проверить транзакцию
GET /v1/public/transactions/{id} — публичные данные для страницы оплаты (статус, суммы, валюта, сеть, адрес, варианты способов при
awaiting_method);merchant_idне возвращается. Лимит запросов по IP. -
Список транзакций
GET /v1/transactions — постраничный список транзакций.
-
Количество транзакций
GET /v1/transactions/count — общее число транзакций мерчанта.
-
Курс RUB → USDT
GET /v1/public/rates/rub-per-usdt — текущий курс RUB за 1 USDT.
Выплаты
Защищённые маршруты: история заявок на вывод, создание заявки, список сохранённых кошельков для вывода.
Эндпоинты
-
Создать заявку на вывод
POST /v1/payouts — создание заявки на вывод на сохранённый кошелёк (суммы, комиссии, идемпотентность).
-
Список выплат
GET /v1/payouts — история заявок на вывод с суммами, комиссиями, статусом и хешем транзакции в сети (если есть).
-
Кошельки для вывода
GET /v1/payouts/wallets — сохранённые адреса для вывода (валюта, сеть, верификация).
Основная информация мерчанта
Возвращает полный профиль мерчанта по схеме MerchantResponse: все поля ниже присутствуют
в JSON при успешном ответе. Суммы — строки с 8 знаками после запятой, время — Unix-секунды.
URL запроса
https://api.formapay.io/v1/merchants/me
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Публичный или приватный ключ мерчанта. |
Accept |
нет | Рекомендуется application/json. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля MerchantResponse
id- UUID мерчанта.
email- Email учётной записи.
balance- Текущий баланс мерчанта (USDT).
hold_balance- Сумма, временно заблокированная до подтверждения.
available_balance- Сумма, доступная для вывода.
total_funds- Полная сумма средств мерчанта, включая заблокированные.
statusactive/inactive/blocked.timezone- IANA-имя часового пояса.
created_at,updated_at- Unix-секунды;
updated_atможет бытьnull. is_2fa_enable- Включена ли двухфакторная аутентификация.
withdrawal_frozen_until- До какого момента (Unix) заморожен вывод; иначе
null. security_profile_hold_until- Заморозка средств после смены пароля/ключей (Unix) или
null. public_api_key- Публичный ключ API (
sp_…). notification_email- Email для уведомлений или
null. notify_on_payment,notify_on_chargeback,notify_on_withdrawal- Флаги уведомлений.
email_verified- Подтверждён ли email.
telegram_linked,telegram_username,telegram_first_name- Связь с Telegram.
store_name,logo_url- Название и логотип магазина.
webhook_url,success_url,fail_url- URL для вебхуков и редиректов.
webhook_secret- HMAC-SHA256 ключ для проверки подписи исходящих вебхуков (заголовок
X-Forma-Signature). Ротация:POST /merchants/me/rotate-webhook-secret. auto_withdraw- Автовывод включён или нет.
min_withdrawal_amount- Порог авто-вывода в USDT (задаётся админом). При достижении этой суммы на доступном балансе создаётся заявка на вывод всего доступного баланса (USDT/TRC20).
0— авто-вывод отключён. payment_page_border_color- Hex-цвет акцента платёжной формы (
#RRGGBBили#RRGGBBAA);null— по умолчанию. payment_page_theme- Тема платёжной формы:
light,darkилиnull(авто). payment_page_gradient_enabled- Включён ли градиентный фон на платёжной форме.
payment_page_grid_enabled- Включена ли сетка на фоне платёжной формы.
payment_page_bg_image_url- URL фонового изображения платёжной формы или
null. payment_page_bg_image_opacity- Прозрачность фонового изображения (0–1).
payment_page_method_banner_url- URL баннера метода оплаты или
null. payment_page_method_banner_opacity- Прозрачность баннера метода (0–1).
payment_page_allow_theme_toggle- Может ли покупатель переключать тему на платёжной форме.
payment_page_allow_lang_toggle- Может ли покупатель переключать язык на платёжной форме.
payment_page_default_language- Язык платёжной страницы по умолчанию (
ru/en).null— автоопределение.
401 / 403 — поля ответа об ошибке
detail- Строка или массив объектов валидации.
message- Человекочитаемое сообщение (доменная ошибка).
code- Машинный код причины (доменная ошибка).
curl -sS -X GET "https://api.formapay.io/v1/merchants/me" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/merchants/me",
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
r.raise_for_status()
print(r.json())
<?php
$ch = curl_init('https://api.formapay.io/v1/merchants/me');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY',
'Accept: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const res = await fetch("https://api.formapay.io/v1/merchants/me", {
headers: {
"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY",
Accept: "application/json",
},
});
console.log(await res.json());
Ответы
200 OK — основная информация мерчанта
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "merchant@example.com",
"balance": "123.45000000",
"hold_balance": "10.00000000",
"available_balance": "113.45000000",
"total_funds": "133.45000000",
"status": "active",
"timezone": "Europe/Moscow",
"created_at": 1700000000,
"updated_at": 1700003600,
"is_2fa_enable": false,
"withdrawal_frozen_until": null,
"security_profile_hold_until": null,
"public_api_key": "sp_xxxxxxxxxxxxxxxxxxxxxxxx",
"notification_email": "notify@example.com",
"notify_on_payment": true,
"notify_on_chargeback": true,
"notify_on_withdrawal": true,
"email_verified": true,
"telegram_linked": false,
"telegram_username": null,
"telegram_first_name": null,
"store_name": "My store",
"logo_url": "https://example.com/logo.png",
"webhook_url": "https://example.com/webhook",
"success_url": "https://example.com/ok",
"fail_url": "https://example.com/fail",
"auto_withdraw": false,
"min_withdrawal_amount": "0.00000000"
}
401 Unauthorized — неверный или отсутствующий ключ
{
"detail": "Invalid or missing API key",
"message": "Invalid or missing API key",
"code": "invalid_api_key"
}
Проверка создания платежей
Проверка, что аккаунт активен и может принимать платежи. Успешный ответ — например
{"accepting": true}. Если приём выключен — ответ с ошибкой доступа (403).
URL запроса
https://api.formapay.io/v1/merchants/me/accepting-payments
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Accept |
нет | application/json. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля тела
acceptingtrue, если аккаунт может принимать платежи; иначе ошибка (часто 403).
403 — поля ответа об ошибке
detail- Текст причины.
message/code- Возможны в доменном формате — см. другие защищённые методы.
curl -sS -X GET "https://api.formapay.io/v1/merchants/me/accepting-payments" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/merchants/me/accepting-payments",
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$ch = curl_init('https://api.formapay.io/v1/merchants/me/accepting-payments');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const res = await fetch(
"https://api.formapay.io/v1/merchants/me/accepting-payments",
{ headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" } },
);
console.log(await res.json());
Ответы
200 OK — проверка создания платежей
{
"accepting": true
}
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden — приём выключен
{
"error": "forbidden",
"message": "Accepting payments is disabled"
}
Счета мерчанта
Список платёжных счетов: валюта, сеть, адрес, комиссии, активность. Пагинация query-параметрами
limit (1–100, по умолчанию 10) и offset (смещение, ≥ 0).
URL запроса
https://api.formapay.io/v1/merchants/me/accounts?limit=10&offset=0
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Accept |
нет | application/json. |
Параметры запроса (query)
| Параметр | Тип | Описание |
|---|---|---|
limit |
integer | Размер страницы, 1–100, по умолчанию 10. |
offset |
integer | Смещение, ≥ 0. |
for_new_transactions |
boolean | Если true — только счета, подходящие для создания новой транзакции. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля одного элемента MerchantAccountResponse
id- UUID счёта.
merchant_id- UUID мерчанта-владельца.
payment_method_id- ID платёжного метода.
currency,network,address- Для отображения: валюта, сеть, адрес из метода.
balance- Текущий баланс счёта (строка с точностью).
default_fee_percent- Комиссия метода (%), строка.
fee_percent- Доп. комиссия счёта (%); итоговая = default + fee_percent.
fee_payerbuyerилиmerchant— кто платит комиссию.is_active- Счёт принимает платежи.
payment_method_is_active- Метод включён;
false— новые транзакции по счёту недоступны. min_amount- Минимальная сумма транзакции или
null.
401 / 403 — поля ответа об ошибке
detail- Текст причины отказа.
message/code- Доменная ошибка при ограничении доступа.
curl -sS -G "https://api.formapay.io/v1/merchants/me/accounts" \
--data-urlencode "limit=10" \
--data-urlencode "offset=0" \
--data-urlencode "for_new_transactions=true" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/merchants/me/accounts",
params={"limit": 10, "offset": 0, "for_new_transactions": True},
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$q = http_build_query([
'limit' => 10,
'offset' => 0,
'for_new_transactions' => 'true',
]);
$ch = curl_init('https://api.formapay.io/v1/merchants/me/accounts?' . $q);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const u = new URL("https://api.formapay.io/v1/merchants/me/accounts");
u.searchParams.set("limit", "10");
u.searchParams.set("offset", "0");
u.searchParams.set("for_new_transactions", "true");
const res = await fetch(u, { headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" } });
console.log(await res.json());
Ответы
200 OK — список счетов
[
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"payment_method_id": 1,
"currency": "USDT",
"network": "TRC20",
"address": "TXyzExampleAddress123456789",
"balance": "0.00000000",
"default_fee_percent": "1.50",
"fee_percent": "0.50",
"fee_payer": "buyer",
"is_active": true,
"payment_method_is_active": true,
"min_amount": "10.00000000"
}
]
401 Unauthorized
{
"detail": "Invalid or missing API key",
"message": "Invalid or missing API key",
"code": "invalid_api_key"
}
403 Forbidden
{
"detail": "…",
"message": "…",
"code": "…"
}
Проверить транзакцию
Без API-ключа. Схема ответа — PublicTransactionResponse. Если счёт ещё не выбран
(awaiting_method), в теле — сумма в USDT, заглушки network/address, массив
payment_options, selected_merchant_account_id: null. После выбора счёта
в JSON заполнятся
amount_expected, currency, network, address, при необходимости
qr_code_url, selected_merchant_account_id = UUID счёта. Даты в формате ISO 8601.
merchant_id не возвращается. Лимит запросов по IP.
URL запроса
https://api.formapay.io/v1/public/transactions/{transaction_id}
{transaction_id} — UUID транзакции в пути.
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
Accept |
нет | Рекомендуется application/json. |
Ключ мерчанта не передаётся.
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля PublicTransactionResponse
id- UUID транзакции (для polling).
statusawaiting_method|created|pending|detecting|confirming|completed|expired|cancelled|failedи др.amount_expected- Сумма к оплате.
amount_received- Уже получено по транзакции.
currency- Тикер валюты отображения (например USDT или RUB при оригинале заказа).
network- Сеть (например TRC20) или заглушка «—» в
awaiting_method. address- Адрес для перевода; может быть пустой строкой до выбора способа.
qr_code_url- URL QR / hosted checkout (OxaPay) или
null. redirect_url- Внешняя страница оплаты для redirect-only шлюзов (SeverPay и т.п.); если задано — плательщика нужно редиректнуть туда. Для h2h-шлюзов
null. payment_flowaddress(h2h: адрес, QR, поллинг) илиredirect(редирект на страницу шлюза). Конкретный шлюз в превью методов — полеgateway_typeвнутриpayment_options[].expires_at,created_at- ISO 8601 или
null. payment_options- При
awaiting_method— массивPaymentOptionPreview(счёт, комиссии, суммы,gateway_type); иначеnull. selected_merchant_account_id- UUID выбранного счёта;
null, пока метод не зафиксирован. merchant_name- Название магазина мерчанта или
null. merchant_logo- URL логотипа мерчанта или
null. merchant_border_color- Hex-цвет акцента платёжной формы или
null. merchant_theme- Тема платёжной формы:
light,darkилиnull. payer_checkout_choicetrue— плательщик сам выбирает метод;false— метод зафиксирован при создании;null— неизвестно.merchant_gradient_enabled- Включён ли градиентный фон.
merchant_grid_enabled- Включена ли сетка на фоне.
merchant_bg_image_url- URL фонового изображения или
null. merchant_bg_image_opacity- Прозрачность фонового изображения (0–1).
merchant_method_banner_url- URL баннера метода оплаты или
null. merchant_method_banner_opacity- Прозрачность баннера метода (0–1).
merchant_allow_theme_toggle- Может ли покупатель переключать тему.
merchant_allow_lang_toggle- Может ли покупатель переключать язык.
merchant_default_language- Язык по умолчанию (
ru/en) илиnull.
404 / 429 — поля тела
detail- Строка: «not found», лимит и т.п..
curl -sS "https://api.formapay.io/v1/public/transactions/TRANSACTION_UUID" \
-H "Accept: application/json"
import requests
tid = "TRANSACTION_UUID"
r = requests.get(
f"https://api.formapay.io/v1/public/transactions/{tid}",
timeout=30,
)
print(r.json())
<?php
$tid = 'TRANSACTION_UUID';
$ch = curl_init("https://api.formapay.io/v1/public/transactions/{$tid}");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true]);
echo curl_exec($ch);
const tid = "TRANSACTION_UUID";
const res = await fetch(
`https://api.formapay.io/v1/public/transactions/${tid}`,
);
console.log(await res.json());
Ответы
200 OK — данные транзакции
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"status": "created",
"amount_expected": "103.01250000",
"amount_received": "0.00000000",
"currency": "USDT",
"network": "TRC20",
"address": "TXyzExampleAddress123456789",
"qr_code_url": null,
"redirect_url": null,
"payment_flow": "address",
"expires_at": "2026-03-17T14:30:00+00:00",
"created_at": "2026-03-17T14:00:00+00:00",
"payment_options": null,
"selected_merchant_account_id": "550e8400-e29b-41d4-a716-446655440001"
}
{
"id": "660e8400-e29b-41d4-a716-446655440002",
"status": "awaiting_method",
"amount_expected": "100.50000000",
"amount_received": "0.00000000",
"currency": "USDT",
"network": "—",
"address": "",
"qr_code_url": null,
"redirect_url": null,
"payment_flow": "address",
"expires_at": "2026-03-17T14:30:00+00:00",
"created_at": "2026-03-17T14:00:00+00:00",
"payment_options": [
{
"merchant_account_id": "550e8400-e29b-41d4-a716-446655440001",
"name": "",
"currency": "USDT",
"network": "TRC20",
"fee_percent_total": "3.00000000",
"fee_payer": "buyer",
"amount_base": "100.50000000",
"amount_expected": "103.51500000",
"gateway_type": "internal"
}
],
"selected_merchant_account_id": null
}
404 Not Found — транзакция недоступна
{
"detail": "Transaction not found"
}
429 Too Many Requests — лимит по IP
{
"detail": "Too many requests"
}
Курс RUB → USDT
Схема ответа — PublicRateResponse: в JSON ровно одно поле rub_per_usdt
(строка, без округления до двух знаков).
URL запроса
https://api.formapay.io/v1/public/rates/rub-per-usdt
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
Accept |
нет | application/json. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля PublicRateResponse
rub_per_usdt- Сколько рублей за 1 USDT (строка с фиксированной точностью).
429 — поля тела
detail- Обычно
Too many requests.
curl -sS "https://api.formapay.io/v1/public/rates/rub-per-usdt" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/public/rates/rub-per-usdt",
timeout=30,
)
print(r.json())
<?php
$ch = curl_init('https://api.formapay.io/v1/public/rates/rub-per-usdt');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true]);
echo curl_exec($ch);
const res = await fetch(
"https://api.formapay.io/v1/public/rates/rub-per-usdt",
);
console.log(await res.json());
Ответы
200 OK — курс RUB → USDT
{
"rub_per_usdt": "97.12345678"
}
429 Too Many Requests
{
"detail": "Too many requests"
}
Количество транзакций
Возвращает число транзакций текущего мерчанта. Требуется авторизация мерчанта.
URL запроса
https://api.formapay.io/v1/transactions/count
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — формат тела
- Значение
- Не объект: в JSON приходит число, например
42— число транзакций текущего мерчанта.
401 / 403 — поля ответа об ошибке
detail/message/code- Как у других защищённых методов.
curl -sS -X GET "https://api.formapay.io/v1/transactions/count" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/transactions/count",
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$ch = curl_init('https://api.formapay.io/v1/transactions/count');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const res = await fetch("https://api.formapay.io/v1/transactions/count", {
headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" },
});
console.log(await res.json());
Ответы
200 OK — количество транзакций
42
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}
Список транзакций
Список транзакций мерчанта, сортировка по дате создания (новые первые). Пагинация: limit,
offset. Тело ответа — JSON-массив объектов TransactionResponse (без
обёртки items/total); в списке дополнительно заполняются
target_action_kind и target_action_at для UI. Суммы — строки с 8 знаками.
URL запроса
https://api.formapay.io/v1/transactions?limit=20&offset=0
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Параметры запроса (query)
| Параметр | Тип | Описание |
|---|---|---|
limit |
integer | Число записей на страницу. |
offset |
integer | Смещение для пагинации. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля TransactionResponse (элемент массива)
id- UUID транзакции.
merchant_id- UUID мерчанта.
merchant_account_id- UUID счёта;
null, пока не выбран способ (awaiting_method). external_id- Внешний ID заказа или
null. recorded_fee_percent- Комиссия % на момент создания (строка, 8 знаков).
recorded_fee_payerbuyerилиmerchant.amount_base,amount_expected,amount_received- Суммы строками с 8 знаками после запятой.
base_amount,fee_percent,fee_payer- Алиасы (=
amount_base,recorded_fee_percent,recorded_fee_payer). currency- Для мерчанта — обычно
USDT. status- Статус транзакции (в т.ч.
awaiting_method,created,completed). payment_url- Ссылка на страницу оплаты для покупателя.
pay_link- URL инвойса OxaPay при соответствующем шлюзе; иначе
null. address- Адрес кошелька (white-label / внутренний метод) или
null. qr_code_url- URL QR или hosted checkout от шлюза или
null. is_sandbox- Признак песочницы OxaPay или
null. expires_at,created_at,updated_at,target_action_at- Даты UTC строкой
YYYY-MM-DD HH:MM:SS.mmm; необязательные поля могут бытьnull. target_action_kindpaid|cancelled|expired|chargeback|null— для UI списка.payment_options- Массив
PaymentOptionPreviewприawaiting_methodилиnull. original_currency- Оригинальная валюта запроса (RUB, BTC, …) если транзакция создавалась не в USDT; иначе
null. original_amount_base- Сумма без комиссии в оригинальной валюте или
null. original_amount_expected- Сумма к получению в оригинальной валюте или
null. callback_url- Per-transaction webhook URL или
null;null= webhook'и идут наmerchant.webhook_url.
401 / 403 — поля ответа об ошибке
detail/message/code- Стандартные и доменные форматы отказа.
curl -sS -G "https://api.formapay.io/v1/transactions" \
--data-urlencode "limit=20" \
--data-urlencode "offset=0" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/transactions",
params={"limit": 20, "offset": 0},
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$q = http_build_query(['limit' => 20, 'offset' => 0]);
$ch = curl_init('https://api.formapay.io/v1/transactions?' . $q);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const u = new URL("https://api.formapay.io/v1/transactions");
u.searchParams.set("limit", "20");
u.searchParams.set("offset", "0");
const res = await fetch(u, { headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" } });
console.log(await res.json());
Ответы
200 OK — список транзакций
[
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"merchant_account_id": "550e8400-e29b-41d4-a716-446655440001",
"external_id": null,
"recorded_fee_percent": "2.50000000",
"recorded_fee_payer": "buyer",
"amount_base": "10.00000000",
"amount_expected": "10.25000000",
"amount_received": "0.00000000",
"currency": "USDT",
"status": "created",
"payment_url": "https://formapay.io/pay/660e8400-e29b-41d4-a716-446655440001",
"pay_link": null,
"address": null,
"qr_code_url": null,
"is_sandbox": null,
"expires_at": "2026-03-17 14:30:00.000",
"created_at": "2026-03-17 14:00:00.000",
"updated_at": "2026-03-17 14:00:00.000",
"target_action_at": null,
"target_action_kind": "paid",
"payment_options": null,
"base_amount": "10.00000000",
"fee_percent": "2.50000000",
"fee_payer": "buyer"
},
{
"id": "660e8400-e29b-41d4-a716-446655440002",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"merchant_account_id": "550e8400-e29b-41d4-a716-446655440001",
"external_id": "ext-order-99",
"recorded_fee_percent": "1.00000000",
"recorded_fee_payer": "merchant",
"amount_base": "50.00000000",
"amount_expected": "50.00000000",
"amount_received": "50.00000000",
"currency": "USDT",
"status": "completed",
"payment_url": "https://formapay.io/pay/660e8400-e29b-41d4-a716-446655440002",
"pay_link": null,
"address": null,
"qr_code_url": null,
"is_sandbox": null,
"expires_at": "2026-03-16 10:00:00.000",
"created_at": "2026-03-16 09:30:00.000",
"updated_at": "2026-03-16 09:45:00.000",
"target_action_at": "2026-03-16 09:45:00.000",
"target_action_kind": "paid",
"payment_options": null,
"base_amount": "50.00000000",
"fee_percent": "1.00000000",
"fee_payer": "merchant"
}
]
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}
Создать транзакцию
Создаёт платёж. В ответе 201 — TransactionResponse с payment_url для покупателя.
Без account_id — сценарий «плательщик сам выберет способ» (статус awaiting_method, опции в payment_options).
URL запроса
https://api.formapay.io/v1/transactions
Этот маршрут не отдаёт «голый» URL в Location: ссылка на оплату приходит в JSON ответа в поле
payment_url (HTTP 201).
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Публичный или приватный API-ключ мерчанта. Получить и перевыпустить — в кабинете forma. |
Content-Type |
да | application/json. |
Idempotency-Key |
нет | Повтор запроса с тем же ключом (до ~24 ч) возвращает ту же транзакцию, 201. |
Поля тела запроса (JSON)
| Поле | Тип | Описание |
|---|---|---|
account_id |
string (UUID) | Счёт (опционально). Без него — выбор способа на странице оплаты; amount_base в USDT. |
amount_base |
string / number | Сумма без комиссии, > 0. |
fee_payer |
string | buyer или merchant (опционально). |
customer_id |
string | Внешний ID плательщика у мерчанта (опционально). |
callback_url |
string |
Per-transaction webhook URL (опционально, до 500 символов). Если задан — все
transaction.* webhook'и по этой транзакции пойдут сюда. Если не передан —
fallback на глобальный merchant.webhook_url из настроек кабинета.
Подпись (HMAC-SHA256 через webhook_secret) одинакова для обоих случаев.
|
Ответы API
201 Created — поля TransactionResponse (тот же набор, что в GET /v1/transactions)
id- UUID созданной транзакции.
merchant_id- UUID мерчанта.
merchant_account_id- UUID счёта или
nullприawaiting_method. external_id- Всегда задаётся на бэкенде при создании; в теле
POST /v1/transactionsне передаётся. recorded_fee_percent,recorded_fee_payer- Снимок комиссии и плательщика комиссии.
amount_base,amount_expected,amount_received- Суммы строками (8 знаков).
base_amount,fee_percent,fee_payer- Алиасы (=
amount_base,recorded_fee_percent,recorded_fee_payer). currency- Обычно
USDT. statuscreated(сaccount_id) илиawaiting_method(без счёта).payment_url- Ссылка на страницу оплаты для покупателя.
pay_link- Инвойс OxaPay при необходимости или
null. address,qr_code_url- Реквизиты white-label при ответе шлюза; чаще
nullсразу после создания. is_sandbox- Песочница OxaPay или
null. expires_at,created_at,updated_at- UTC строкой
YYYY-MM-DD HH:MM:SS.mmm. target_action_at,target_action_kind- Обычно
nullв ответе создания. payment_options- Массив вариантов оплаты при
awaiting_methodилиnull. original_currency- Оригинальная валюта запроса или
null. original_amount_base- Сумма без комиссии в оригинальной валюте или
null. original_amount_expected- Сумма к получению в оригинальной валюте или
null. callback_url- Per-transaction webhook URL или
null;null= webhook'и идут наmerchant.webhook_url.
400 / 401 / 403 — поля ответа об ошибке
detail- Описание ошибки или массив полей с ошибками.
message/code- Доменная бизнес-ошибка (например неактивный счёт).
curl -sS -X POST "https://api.formapay.io/v1/transactions" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Content-Type: application/json" \
-d '{"amount_base":"10.00","fee_payer":"buyer"}'
import requests
payload = {"amount_base": "10.00", "fee_payer": "buyer"}
r = requests.post(
"https://api.formapay.io/v1/transactions",
json=payload,
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.status_code, r.json())
<?php
$body = json_encode(['amount_base' => '10.00', 'fee_payer' => 'buyer']);
$ch = curl_init('https://api.formapay.io/v1/transactions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY',
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const res = await fetch("https://api.formapay.io/v1/transactions", {
method: "POST",
headers: {
"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ amount_base: "10.00", fee_payer: "buyer" }),
});
console.log(res.status, await res.json());
Ответы
201 Created — транзакция создана
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"merchant_account_id": null,
"external_id": "550e8400_pending_1710000000000_a1b2c3",
"recorded_fee_percent": "0.00000000",
"recorded_fee_payer": "buyer",
"amount_base": "10.00000000",
"amount_expected": "10.00000000",
"amount_received": "0.00000000",
"currency": "USDT",
"status": "awaiting_method",
"payment_url": "https://formapay.io/pay/660e8400-e29b-41d4-a716-446655440001",
"pay_link": null,
"address": null,
"qr_code_url": null,
"is_sandbox": null,
"expires_at": "2026-03-17 14:30:00.000",
"created_at": "2026-03-17 14:00:00.000",
"updated_at": "2026-03-17 14:00:00.000",
"target_action_at": null,
"target_action_kind": null,
"payment_options": [
{
"merchant_account_id": "550e8400-e29b-41d4-a716-446655440001",
"name": "USDT",
"currency": "USDT",
"network": "TRC20",
"fee_percent_total": "2.50000000",
"fee_payer": "buyer",
"amount_base": "10.00000000",
"amount_expected": "10.25000000",
"gateway_type": "internal"
}
],
"base_amount": "10.00000000",
"fee_percent": "0.00000000",
"fee_payer": "buyer"
}
400 Bad Request — неверное тело или бизнес-ошибка
{
"error": "validation_error",
"message": "amount_base must be greater than zero",
"details": {}
}
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}
Список выплат
История заявок на вывод для текущего мерчанта. Пагинация: limit, offset. Ответ —
JSON-массив PayoutResponse (без обёртки items).
URL запроса
https://api.formapay.io/v1/payouts?limit=20&offset=0
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Параметры запроса (query)
| Параметр | Тип | Описание |
|---|---|---|
limit |
integer | Размер страницы. |
offset |
integer | Смещение. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля PayoutResponse
id,merchant_id,payout_wallet_id- Идентификаторы выплаты, мерчанта и кошелька.
amount_requested- Запрошенная сумма (строка).
amount_to_send- Сумма к отправке на сеть после удержаний.
network_fee,service_fee- Комиссия сети и сервиса.
status- Например
pending,success,failed. tx_hash- Хэш транзакции в блокчейне или
null. error_log- Текст ошибки исполнения или
null. attempts- Число попыток обработки.
idempotency_key- Ключ идемпотентности или
null. created_at,updated_at- Unix-секунды.
401 / 403 — поля ответа об ошибке
detail/message/code- Отказ в доступе к выплатам.
curl -sS -G "https://api.formapay.io/v1/payouts" \
--data-urlencode "limit=20" --data-urlencode "offset=0" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/payouts",
params={"limit": 20, "offset": 0},
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$q = http_build_query(['limit' => 20, 'offset' => 0]);
$ch = curl_init('https://api.formapay.io/v1/payouts?' . $q);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const u = new URL("https://api.formapay.io/v1/payouts");
u.searchParams.set("limit", "20");
u.searchParams.set("offset", "0");
const res = await fetch(u, { headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" } });
console.log(await res.json());
Ответы
200 OK — список выплат
[
{
"id": "770e8400-e29b-41d4-a716-446655440001",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"payout_wallet_id": "aa0e8400-e29b-41d4-a716-446655440001",
"amount_requested": "100.00000000",
"amount_to_send": "97.50000000",
"network_fee": "1.50000000",
"service_fee": "1.00000000",
"status": "pending",
"tx_hash": null,
"error_log": null,
"attempts": 0,
"idempotency_key": "withdraw-20260317-001",
"created_at": 1700000000,
"updated_at": 1700000000
},
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"payout_wallet_id": "aa0e8400-e29b-41d4-a716-446655440001",
"amount_requested": "50.00000000",
"amount_to_send": "49.00000000",
"network_fee": "0.50000000",
"service_fee": "0.50000000",
"status": "success",
"tx_hash": "a1b2c3d4e5f6789...",
"error_log": null,
"attempts": 1,
"idempotency_key": null,
"created_at": 1699900000,
"updated_at": 1699900300
}
]
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}
Создать заявку на вывод
Создание заявки на вывод средств. Тело — JSON.
URL запроса
https://api.formapay.io/v1/payouts
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Content-Type |
да | application/json. |
Поля тела запроса (JSON)
| Поле | Тип | Описание |
|---|---|---|
payout_wallet_id |
string (UUID) | Кошелёк для вывода. |
amount_requested |
string / number | Запрошенная сумма (правила комиссий сервиса). |
service_fee |
string / number | Комиссия сервиса (опционально, по умолчанию 0). |
idempotency_key |
string | Идемпотентность (опционально). |
Ответы API
201 Created — поля PayoutResponse (как в «Список выплат»)
id,merchant_id,payout_wallet_id- Идентификаторы выплаты, мерчанта и кошелька.
amount_requested- Запрошенная сумма (строка).
amount_to_send- Сумма к отправке на сеть после удержаний.
network_fee,service_fee- Комиссия сети и сервиса.
status- Например
pending,success,failed. tx_hash- Хэш транзакции в блокчейне или
null. error_log- Текст ошибки исполнения или
null. attempts- Число попыток обработки.
idempotency_key- Ключ идемпотентности или
null. created_at,updated_at- Unix-секунды.
400 / 401 / 403 — поля ответа об ошибке
detail- Ошибки валидации полей запроса.
message/code- Отказ по бизнес-правилам или доступу.
curl -sS -X POST "https://api.formapay.io/v1/payouts" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Content-Type: application/json" \
-d '{"payout_wallet_id":"550e8400-e29b-41d4-a716-446655440000","amount_requested":"100.00"}'
import requests
payload = {
"payout_wallet_id": "550e8400-e29b-41d4-a716-446655440000",
"amount_requested": "100.00",
}
r = requests.post(
"https://api.formapay.io/v1/payouts",
json=payload,
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.status_code, r.json())
<?php
$body = json_encode([
'payout_wallet_id' => '550e8400-e29b-41d4-a716-446655440000',
'amount_requested' => '100.00',
]);
$ch = curl_init('https://api.formapay.io/v1/payouts');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY',
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const res = await fetch("https://api.formapay.io/v1/payouts", {
method: "POST",
headers: {
"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
payout_wallet_id: "550e8400-e29b-41d4-a716-446655440000",
amount_requested: "100.00",
}),
});
console.log(res.status, await res.json());
Ответы
201 Created — заявка на вывод создана
{
"id": "770e8400-e29b-41d4-a716-446655440003",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"payout_wallet_id": "aa0e8400-e29b-41d4-a716-446655440001",
"amount_requested": "100.00000000",
"amount_to_send": "97.50000000",
"network_fee": "1.50000000",
"service_fee": "1.00000000",
"status": "pending",
"tx_hash": null,
"error_log": null,
"attempts": 0,
"idempotency_key": "withdraw-20260317-002",
"created_at": 1700000100,
"updated_at": 1700000100
}
400 Bad Request — ошибка валидации
{
"error": "validation_error",
"message": "Invalid payout_wallet_id",
"details": {}
}
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}
Кошельки для вывода
Список сохранённых кошельков вывода (не удалённые). Пагинация: limit, offset. Ответ
— JSON-массив PayoutWalletResponse.
URL запроса
https://api.formapay.io/v1/payouts/wallets?limit=20&offset=0
Заголовки запроса
| Заголовок | Обязательно | Описание |
|---|---|---|
X-API-Key |
да | Ключ мерчанта. |
Параметры запроса (query)
| Параметр | Тип | Описание |
|---|---|---|
limit |
integer | Размер страницы. |
offset |
integer | Смещение. |
Тело запроса
Отсутствует (метод GET).
Ответы API
200 OK — поля PayoutWalletResponse
id- UUID сохранённого кошелька.
merchant_id- Владелец.
currency,network- Валюта и сеть вывода.
address- Адрес для выплаты.
is_verified- Прошёл ли проверку адреса.
is_deleted- Мягкое удаление; в выдаче обычно только не удалённые.
created_at,updated_at- Unix-секунды.
401 / 403 — поля ответа об ошибке
detail/message/code- Отказ в доступе к кошелькам.
curl -sS -G "https://api.formapay.io/v1/payouts/wallets" \
--data-urlencode "limit=20" --data-urlencode "offset=0" \
-H "X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY" \
-H "Accept: application/json"
import requests
r = requests.get(
"https://api.formapay.io/v1/payouts/wallets",
params={"limit": 20, "offset": 0},
headers={"X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY"},
timeout=30,
)
print(r.json())
<?php
$q = http_build_query(['limit' => 20, 'offset' => 0]);
$ch = curl_init('https://api.formapay.io/v1/payouts/wallets?' . $q);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_PUBLIC_OR_PRIVATE_KEY'],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
const u = new URL("https://api.formapay.io/v1/payouts/wallets");
u.searchParams.set("limit", "20");
u.searchParams.set("offset", "0");
const res = await fetch(u, { headers: { "X-API-Key": "YOUR_PUBLIC_OR_PRIVATE_KEY" } });
console.log(await res.json());
Ответы
200 OK — кошельки для вывода
[
{
"id": "aa0e8400-e29b-41d4-a716-446655440001",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"currency": "USDT",
"network": "TRC20",
"address": "TXyzExampleMainWallet123456789",
"is_verified": true,
"is_deleted": false,
"created_at": 1700000000,
"updated_at": 1700000000
},
{
"id": "aa0e8400-e29b-41d4-a716-446655440002",
"merchant_id": "550e8400-e29b-41d4-a716-446655440000",
"currency": "USDT",
"network": "TRC20",
"address": "TXyzExampleReserveWallet987654321",
"is_verified": false,
"is_deleted": false,
"created_at": 1699900000,
"updated_at": 1699900000
}
]
401 Unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}
403 Forbidden
{
"error": "forbidden",
"message": "Access denied"
}