ДОКУМЕНТАЦІЯ ДЛЯ РОЗРОБНИКІВ
Документація API
Підключи рахунки, сторінку оплати й платіжні сповіщення.
Результати пошуку
Нічого не знайдено. Спробуй назву ендпоїнта, поля або посібника.
Швидкий старт
Створи перший рахунок.
- Підготуй магазин
Увімкни способи оплати, налаштуй провайдерів і зроби резервні копії гаманців проєкту.
- Створи облікові дані API
У панелі відкрий Налаштування → Доступ до API, вибери читання/запис і признач проєкт.
- Надішли запит
Використовуй свій хост API та скопіюй ID проєкту й магазину. Надсилай десяткові суми як рядки.
- Відкрий сторінку оплати
Перенаправ на
links.checkoutз відповіді. Перевір остаточну оплату, перш ніж виконувати замовлення.
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"exchange_rate_spread_percent": "0.5"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Приклади містять заповнювачі й не надсилають запити з цієї сторінки. Усі поля рахунку та формат відповіді →
ID проєкту й магазину
Де знайти YOUR_PROJECT_ID і YOUR_STORE_ID.
Використовуй UUID із панелі, а не назви проєкту чи магазину або їхні читабельні ідентифікатори.
| Заповнювач | Де знайти | Для чого потрібен |
|---|---|---|
| YOUR_PROJECT_ID | Проєкт → Налаштування → ID для API → ID проєкту для API → Копіювати. Також є на вкладці «Основне» магазину. | Запити рівня проєкту й магазину. |
| YOUR_STORE_ID | Проєкт → Магазини → вибери магазин → Основне → ID для API → ID магазину для API → Копіювати. | Створення рахунків і запити способів оплати магазину. |
- Для створення рахунку потрібні обидва ID, навіть для магазину за замовчуванням. Магазин має належати цьому проєкту, а облікові дані API мають давати доступ до нього.
- Створення, список, деталі рахунків і сторінка оплати повертають invoice_id: той самий UUID, що надходить в IPN/вебхуках. Використовуй його в шляхах рахунків, а не внутрішній id чи order_id. Починаючи з версії мерчанта 4.0.0, старе поле відповіді public_id прибране; онови інтеграції перед оновленням програми.
- REST API не має маршрутів списків проєктів/магазинів. Скопіюй ID в панелі або використай обмежені областю доступу інструменти MCP list_projects і list_stores у версії мерчанта 5.0.0+.
- Магазин → Основне → Домени магазину задає активні хости merchant, pay і API. Посилання оплати у відповідях і нових колбеках спочатку беруть домени цього магазину, потім магазину за замовчуванням, потім системні. Видалені або неактивовані імена не вибираються. Налаштуй SDK на бажаний хост API; зміна вибору не перенаправляє інші активні псевдоніми.
Автентифікація та область доступу
Зберігай облікові дані на сервері й надавай лише потрібний доступ.
| Хост за замовчуванням | Призначення |
|---|---|
| merchant.example.com | Панель мерчанта й налаштування |
| pay.example.com | Сторінка оплати покупця |
| api.example.com | Запити API мерчанта |
Заміни example.com на свій домен. Наявні інсталяції зберігають налаштовані імена; керуй псевдонімами в Налаштування → Система.
Authorization: Bearer YOUR_MERCHANT_API_TOKEN| Налаштування | Як це працює |
|---|---|
| Рівень доступу | Облікові дані лише для читання дозволяють отримувати списки й окремі записи. Читання/запис також дозволяє створювати рахунки й оновлювати задокументовані політики активів. |
| Проєкти | Признач проєкти, до яких ці дані дають доступ. ID магазину й рахунку мають належати призначеному проєкту. |
| IP-обмеження | За бажанням дозволь конкретні публічні вихідні IPv4 або IPv6 у Налаштування → Доступ до API. |
| Зберігання облікових даних | Тримай токени в конфігурації бекенду. Ніколи не додавай bearer-токен у браузер або посилання оплати. |
Публічні маршрути оплати використовують публічний ID рахунку й показують лише безпечні для оплати дані. Сеанси панелі та адміністративні засоби відокремлені від облікових даних API мерчанта.
Активи й гаманці
Вибирай способи оплати окремо для кожного магазину.
- Переглянь платіжні активи проєкту та їхню готовність.
- Увімкни нативну мережу та налаштуй її гаманець і провайдерів.
- Переглянь токени-кандидати і перевір контракт або mint перш ніж увімкнути токен.
- Вибери впорядковані способи оплатимагазину. Нові рахунки використовують готові вибрані способи.
Токени використовують гаманець своєї нативної мережі. Баланси гаманців повертають точні суми в найменших одиницях та орієнтовні фіатні значення. Поля готовності у відповіді показують, які способи можуть приймати платежі.
Перевірені ERC-20 токени використовують підтримувані EVM-мережі; перевірені SPL токени використовують Solana. Нативні способи оплати доступні в 30 інтегрованих мережах. Monero використовує прив'язане до проєкту зовнішнє підключення гаманця лише для перегляду.
API приймання та підтримка монет/токенів
| Платіжний канал | Підтримка | Докази | Вимоги |
|---|---|---|---|
| Нативні платіжні канали | підтримується | Сканування транзакцій | BTC, SOL, ETH (Ethereum/Base/Arbitrum/OP), BNB, HYPE, AVAX і POL; виходи Bitcoin, канонічні транзакції/квитанції EVM та розібрані перекази Solana дають докази оплати рахунку. |
| Канали токенів ERC-20 | підтримується | Сканування транзакцій | Ethereum, Base, BNB Chain, HyperEVM, Avalanche, Polygon, Arbitrum і Optimism потребують перевірки в блокчейні; індексовані логи Transfer прив'язують платіж до рахунку. |
| Канали токенів SPL | підтримується | Сканування транзакцій | Кандидати Solana потребують перевірки основної мережі та mint; точні зміни балансу токена в розібраних транзакціях прив'язують платіж до рахунку. |
| Додаткові нативні UTXO-канали | підтримується | Сканування транзакцій | BCH/LTC/DOGE використовують Esplora; BCH/DOGE також приймають Bitcore, LTC/DOGE/DASH приймають BlockCypher, Dash приймає Insight, а прозорий ZEC приймає zcash-explorer. Усі також приймають повністю збережені Core-сумісні блоки node-rpc. Режим сирих блоків потребує 1–48 підтверджень, а не виявлення в мемпулі. Захищений Zcash не підтримується. |
| Індексовані нативні канали облікових записів | підтримується | Сканування транзакцій | TRON використовує tron-indexer або остаточні дані node-rpc; XRP використовує xrpl-jsonrpc; Stellar використовує stellar-horizon або збережені реєстри Stellar node-rpc; Cosmos Hub використовує cometbft-jsonrpc; Algorand використовує algorand-indexer або algod node-rpc; Hedera потребує hedera-mirror, а не EVM-реле. |
| Нативні платіжні канали реєстрів | підтримується | Сканування транзакцій | Aptos використовує aptos-rest; Sui використовує sui-graphql; NEAR використовує near-jsonrpc; Kaspa використовує kaspa-rest. Polkadot Asset Hub приймає substrate-rest або фіналізовані node-rpc з урахуванням метаданих; Tezos приймає tezos-tzkt або повні операції Octez node-rpc. Лише нативні надходження; для старих рахунків потрібне збереження архівної історії. |
| Нативні канали Cardano й TON | підтримується | Сканування транзакцій | Cardano потребує cardano-koios, а TON потребує toncenter-v3. Теги XRP, числові memo Stellar та коментарі рахунків TON повертаються як destination_tag і мають надсилатися точно. |
| Цілісність остаточної оплати | підтримується | Незалежна перевірка | За замовчуванням остаточна оплата потребує згоди двох незалежних провайдерів щодо точної транзакції/події, суми, канонічного блока чи слота та фінальності. Сирі й спільні вікна EVM також перевіряють повне покриття. Адміністратор може явно вибрати для мережі одного довіреного провайдера; це прибирає незалежну перехресну перевірку, але не перевірки ідентичності, повноти чи фінальності. |
| Нативний канал Monero | підтримується | RPC гаманця лише для перегляду, прив'язаний до проєкту | Окремий зовнішній wallet-RPC лише для перегляду за HTTPS-шлюзом із дозволеним списком методів створює субадреси облікового запису 0. Налаштований поріг демонів основної мережі (за замовчуванням 2 незалежні джерела, опційно 1) дає докази остаточної оплати. Нативний --restricted-rpc несумісний із create_address; резервну копію гаманця й відсутність ключа витрачання явно засвідчує оператор, а ключі не надсилаються до Wholly Crypto. |
Баланси бірж і вибір sweep до гаманця або біржі для кожного активу доступні в панелі, а не в публічному API v1. Переглянути налаштування бірж.
Життєвий цикл рахунку
Докази платежу, остаточна оплата й виконання замовлення.
| Статус | Значення |
|---|---|
| new | Очікує оплату |
| processing | Платіж помічено; очікується прийнятна сума або фінальність |
| settled | Прийнято за політикою остаточної оплати рахунку або вручну |
| expired | Строк минув; відстеження запізнілих платежів може тривати |
| invalid | Платіж не можна прийняти автоматично |
| cancelled | Скасовано; повторне відкриття можливе лише через явне звіряння |
amount_status записує none, partial, paid або overpaid. timing_status відрізняє своєчасні й запізнілі платежі. Правила магазину задають потрібні підтвердження та допустиму недоплату.
Використовуй дані рахунку invoice_id разом із маршрутом деталей рахунку. Саме перенаправлення зі сторінки оплати не доводить остаточну оплату. Перевіряй винятки через звіряння.
Безпечні повторні запити
Створення рахунку потребує Idempotency-Key. Після таймауту повтори запит із тими самими обліковими даними, ключем і точним тілом. Новий ключ використовуй лише для нового рахунку.
Сканування EVM-платежів
Спільне виявлення нативних блоків і ERC-20 групує недавні рахунки окремо від надолужування старої історії. Кожен рахунок зберігає стійкий курсор історії. Запити токенів охоплюють щонайбільше 100 блоків і зменшуються за суворіших лімітів провайдера. За замовчуванням кожне вікно перевіряють два незалежні провайдери. Налаштування → Підключення мереж → Деталі дозволяє вибрати одне довірене джерело без незалежної перехресної перевірки; перевірки канонічної транзакції, суми й підтверджень залишаються. Деталі підключення відрізняють затримки сканера, обмеження історії та паузи через квоти від базового стану вузла. Пропускна здатність публічних RPC не гарантована.
IPN та вебхуки
Отримуй і перевіряй платіжні події.
IPN отримує кожну створену подію рахунку на його фактичний ipn_url. Вебхуки отримують лише події, вибрані для кожного ввімкненого ендпоїнта магазину. Обидва надсилають POST з однаковим знімком JSON; вони незалежні, тож увімкнення обох може сповістити застосунок двічі.
Задай ipn_url під час створення рахунку або успадкуй налаштування магазину. IPN використовує Магазин → IPN секрет; кожен Магазин → Вебхуки ендпоїнт має власний секрет. Жоден із них не є твоїм ключем API.
Коли виконувати замовлення?
Для обробки за подіями використовуй event_type = invoice.settled разом зі status = settled як сигнал перевірити замовлення. Перевір поточний рахунок і виконуй кожне замовлення лише раз.
status - це стан рахунку на час створення події. event_type показує, що сталося. payment.received може містити processing або settled; це не другий платіж і не окремий сигнал виконання замовлення.
Які події та статуси надсилаються?
| Подія в налаштуваннях/історії | Статус у тілі | Значення |
|---|---|---|
| invoice.created | new | Рахунок створено, він очікує оплату. Також використовується, коли контрольоване повторне відкриття повертає рахунок у new. |
| payment.received | Resulting invoice status | Платіж записано або отримана сума зросла. Зазвичай processing або settled; сама ця подія не доводить остаточну оплату. |
| invoice.processing | processing | Платіж виявлено, але прийнятної суми чи потрібної фінальності ще немає. Сюди входять часткові платежі. |
| invoice.settled | settled | Політику остаточної оплати виконано або платіж прийнято вручну. Перед виконанням перевір resolution і замовлення. |
| invoice.expired | expired | Строк оплати минув. Запізнілий платіж ще може змінити статус, поки триває відстеження. |
| invoice.invalid | invalid | Автоматичне прийняття неможливе, докази платежу втрачено або мерчант відхилив його. Перевір рахунок. |
| invoice.cancelled | cancelled | Рахунок скасовано. Не виконуй замовлення; скасування не повертає платіж у блокчейні. |
Чому потоки подій Ethereum і Solana можуть відрізнятися
Підтвердження надходять пізніше (приклад Ethereum)
| Послідовність | event_type | status |
|---|---|---|
| 1 | invoice.created | new |
| 2 | payment.received | processing |
| 2 | invoice.processing | processing |
| 3 | invoice.settled | settled |
Уже остаточний на момент виявлення (приклад Solana)
| Послідовність | event_type | status |
|---|---|---|
| 1 | invoice.created | new |
| 2 | payment.received | settled |
| 2 | invoice.settled | settled |
Тут показано створення подій, а не гарантований порядок доставлення. Обидва варіанти можливі й в інших мережах залежно від часу виявлення та політики остаточної оплати. Не вимагай подію processing перед settled.
Виконання один раз: приклад приймача й захист від дублікатів
| Підхід | Як обробляти |
|---|---|
| Приймач на основі подій | Зберігай окремі події за підписаним event_id, потім вибирай invoice.settled зі status = settled. Не відкидай цю подію лише тому, що payment.received із тим самим sequence надійшла першою. |
| Вхідна черга станів замовлення в SDK | Надані приклади приймачів PHP, Python і Node об'єднують project + invoice_id + sequence. Обробляй збережений стан незалежно від event_type, отримуй поточний рахунок і виконуй замовлення один раз, якщо він settled. Після такого об'єднання не додавай фільтр лише для invoice.settled. |
Повторне надсилання зберігає event_id і початкове тіло. Різні події можуть мати спільний sequence, але різні event_id. Для обробки за подіями усувай дублікати доставлення за підписаним event_id; окремо захищай виконання за налаштованою інсталяцією/проєктом + invoice_id і своїм замовленням. Повторна остаточна оплата пізніше не має зарахувати замовлення вдруге.
HTTP receiver:
Verify raw-body signature, timestamp and configured project/store scope.
Save to a durable inbox; deduplicate the signed event_id.
Return HTTP 2xx only after persistence succeeds.
Event-based background worker:
Other events go to status/reconciliation handling, not fulfilment.
Continue here only for event_type = invoice.settled and status = settled.
Fetch the current invoice from your configured API origin.
Check settled status, project/store, order, amount, currency and review policy.
In one database transaction:
Lock the order and check the scoped invoice has not been fulfilled.
Credit/complete once and save the fulfilment record.
Queue any external fulfilment with the same business idempotency key.
SDK order-state worker:
Use the same current-invoice checks and fulfil-once transaction.
Do not filter event_type after collapsing events by invoice revision.Псевдокод, а не готовий до встановлення приймач.
Усі стани рахунку й платіжні винятки
| Поле | Значення | Значення |
|---|---|---|
| status | new, processing, settled, expired, invalid, cancelled | Стан рахунку на час створення події; не обов'язково поточний стан на час доставлення. |
| amount_status | none, partial, paid, overpaid | Отримана сума з урахуванням допустимої недоплати. paid не означає остаточність підтверджень. |
| timing_status | on_time, late | Чи платіж надійшов до строку рахунку. |
| resolution | automatic, manually_settled, manually_invalidated | Чи результат визначили звичайні правила або ручне прийняття/відхилення. |
| requires_review | false, true | Ознака винятку, а не ще один статус рахунку чи автоматичний дозвіл виконати замовлення/повернути кошти. |
| Ситуація | Обробка |
|---|---|
| Недоплата / допуск | За автоматичними правилами partial не завершує оплату. paid може включати допустиму недоплату, але фінальність усе одно потрібна. Використовуй статус рахунку, а не лише порівняння сум. |
| Переплата | overpaid може поєднуватися з settled і requires_review = true. Застосуй свою політику переплат; ніколи не зараховуй замовлення двічі та не повертай кошти автоматично на неперевірену адресу. |
| Запізнілий платіж | expired може згодом змінитися, поки триває відстеження. timing_status = late вказує на потребу перевірки; не відкривай і не відправляй скасоване замовлення автоматично. |
| Прийняття вручну | invoice.settled може мати resolution = manually_settled без достатніх коштів у блокчейні. Виріши, чи твоя інтеграція приймає таке перевизначення; підсумкові платіжні поля можуть бути null. |
| Реорганізація / визнання недійсним | Новіша ревізія може зробити попередні докази платежу недійсними. Знову отримай поточний стан і оброби зміну через звіряння. Не ігноруй її лише тому, що замовлення колись було settled. |
| Нуль підтверджень / нульова сума | За нульових підтверджень оплата може завершитися при виявленні й має ризик реорганізації. Явно дозволений рахунок із нульовою сумою завершується без платежу. В обох випадках попередня подія payment.received не обов'язкова. |
Для виконання використовуй status = settled, а не amount_status = paid чи перенаправлення зі сторінки оплати. Якщо потрібні нуль підтверджень, оплата може завершитися при виявленні; це має ризик реорганізації.
Недоплата - це amount_status = partial; переплата - overpaid. paid означає, що прийнятний мінімум, включно з допуском недоплати рахунку, надійшов. Це стани суми, а не статуси рахунку. late - значення timing_status, а не окрема подія.
Типовий шлях - new → processing → settled, але проміжні стани можуть пропускатися. Явно дозволений рахунок із нульовою сумою завершується без платежу й зберігає amount_status = none. Ручне прийняття позначається manually_settled.
Колбеки - незмінні знімки, а не відповіді з поточним статусом. Вони можуть надходити із запізненням, не за порядком або кілька разів. Події платежу й статусу можуть мати спільний sequence рахунку та однакові поля його стану, але різні підписані event_id і event_type. Кількість підтверджень не гарантує колбек для кожного блока.
Що ти отримуєш
{
"invoice_id": "11111111-2222-4333-8444-555555555555",
"status": "settled",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 3,
"amount": "49.9",
"currency": "EUR",
"order_id": "order-1042",
"payload_version": 2,
"event_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
"event_type": "invoice.settled",
"occurred_at": "2026-09-14T12:05:00Z",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"description": "Annual plan",
"email": "ada@example.test",
"customer": {
"firstname": "Ada",
"lastname": "Lovelace",
"countryiso2": "GB"
},
"metadata": {
"firstname": "Ada",
"lastname": "Lovelace",
"countryiso2": "GB",
"cart_id": "cart-681"
},
"created_at": "2026-09-14T12:00:00Z",
"updated_at": "2026-09-14T12:05:00Z",
"expires_at": "2026-09-14T12:15:00Z",
"monitoring_expires_at": "2026-09-21T12:15:00Z",
"settled_at": "2026-09-14T12:05:00Z",
"paid_chain": "ethereum",
"paid_asset": "USDC",
"paid_asset_amount": "58.17342",
"paid_asset_amount_received": "58.17342",
"paid_payment_method_id": "33333333-3333-4333-8333-333333333333",
"settlement_exchange_rate": {
"rate": "1.17",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"observed_at": "2026-09-14T12:05:00Z",
"as_of": "2026-09-14T12:04:30Z",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T12:04:30Z",
"asset_fetched_at": "2026-09-14T12:04:30Z",
"stale": false,
"is_fixed": false,
"reference_currency": "USD",
"uses_reference_proxy": false
},
"cancelled_at": null,
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"reason_code": "payment_confirmed",
"requires_review": false,
"links": {
"checkout": "https://pay.example.com/invoice/11111111-2222-4333-8444-555555555555",
"invoice": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555",
"payments": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555/payments"
},
"payment_info": {
"active_payment_method_id": "33333333-3333-4333-8333-333333333333",
"method_count": 1,
"methods_truncated": false,
"methods": [
{
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"caip_network_id": "eip155:1",
"asset_id": "44444444-4444-4444-8444-444444444444",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"asset_name": "USD Coin",
"symbol": "USDC",
"asset_kind": "token",
"asset_decimals": 6,
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"token_standard": "erc20",
"destination_address": "0x1111111111111111111111111111111111111111",
"destination_tag": null,
"status": "paid",
"amounts": {
"expected_amount": "58.17342",
"expected_amount_atomic": "58173420",
"received_amount": "58.17342",
"received_amount_atomic": "58173420",
"confirmed_amount": "58.17342",
"confirmed_amount_atomic": "58173420",
"unconfirmed_amount": "0",
"unconfirmed_amount_atomic": "0",
"minimum_payment_amount": "57.591686",
"minimum_payment_amount_atomic": "57591686",
"remaining_amount": "0",
"remaining_amount_atomic": "0",
"remaining_to_full_amount": "0",
"remaining_to_full_amount_atomic": "0",
"overpaid_amount": "0",
"overpaid_amount_atomic": "0"
},
"acceptance": {
"finality_mode": "confirmations",
"required_confirmations": 2,
"observed_confirmations": 2,
"underpayment_tolerance_percent": "1"
},
"quote": {
"effective_rate": "1.1658",
"reference_rate": "1.16",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"exchange_rate_spread_percent": "0.5",
"quote_expires_at": "2026-09-14T12:15:00Z",
"provenance_available": true,
"rounding": "up",
"unrounded_payment_amount": "58.17342",
"rounding_adjustment": "0",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T11:59:30Z",
"asset_fetched_at": "2026-09-14T11:59:30Z"
},
"market_rate_at_event": {
"rate": "1.17",
"units": "asset_per_invoice_currency",
"currency": "EUR",
"symbol": "USDC",
"observed_at": "2026-09-14T12:05:00Z",
"pricing_provider": "kraken",
"asset_provider": "kraken",
"pricing_fetched_at": "2026-09-14T12:04:30Z",
"asset_fetched_at": "2026-09-14T12:04:30Z",
"as_of": "2026-09-14T12:04:30Z",
"stale": false,
"is_fixed": false,
"reference_currency": "USD",
"uses_reference_proxy": false
},
"payment_count": 1,
"payments_truncated": false,
"payments": [
{
"payment_id": "55555555-5555-4555-8555-555555555555",
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"transaction_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"payment_hash": null,
"event_index": 0,
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_id": "44444444-4444-4444-8444-444444444444",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"symbol": "USDC",
"asset_decimals": 6,
"amount": "58.17342",
"amount_atomic": "58173420",
"status": "final",
"counts_towards_received": true,
"confirmations": 2,
"block_height": 26000000,
"observed_at": "2026-09-14T12:04:30Z",
"chain_time": "2026-09-14T12:04:20Z",
"finalized_at": "2026-09-14T12:05:00Z",
"explorer_name": "Etherscan",
"explorer_url": "https://etherscan.io/tx/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
],
"links": {
"payments": "https://api.example.com/v1/projects/11111111-1111-4111-8111-111111111111/invoices/11111111-2222-4333-8444-555555555555/payments?payment_method_id=33333333-3333-4333-8333-333333333333"
}
}
]
}
}amount початкова сума рахунку. payment_info описує помічені криптоперекази, відсутні суми й зафіксовані курси. Версія 2 також підписує назву події, ID події та область проєкту/магазину.
Усі поля колбеку й додаткові дані рахунку
| Поле | Тип | Значення |
|---|---|---|
| invoice_id | UUID | Публічний UUID рахунку, що використовується автентифікованим маршрутом його деталей |
| status | string | Стан рахунку у знімку: new, processing, settled, expired, invalid, cancelled |
| amount_status | string | none, partial, paid або overpaid; paid включає допустиму недоплату, але не остаточність підтверджень |
| timing_status | string | on_time або late |
| resolution | string | automatic, manually_settled або manually_invalidated |
| sequence | integer | Зростаюча ревізія рахунку; різні події можуть мати спільну ревізію. Порівнюй без втрати точності цілих чисел |
| amount | decimal string | Початкова сума рахунку, а не отримана криптосума; зберігай десяткову точність |
| currency | string | Валюта amount, наприклад EUR для рахунку в EUR, оплаченого USDC |
| order_id | string | null | Посилання на замовлення мерчанта |
| payload_version | integer | 2 для нових подій версії 4.1.0+; відсутнє у збережених старих подіях |
| event_id | UUID | Підписаний ідентифікатор події, незмінний при повторних спробах і ручному доставленні |
| event_type | string | Одна із семи подій підписки |
| occurred_at | timestamp | Час створення цієї незмінної події, а не час доставлення |
| project_id | UUID | Область проєкту мерчанта; звір із налаштованим приймачем |
| store_id | UUID | Область магазину мерчанта; звір із налаштованим приймачем |
| description | string | null | Початковий опис рахунку |
| string | null | Необов'язковий email покупця на час створення події | |
| customer | object | Розпізнані необов'язкові поля метаданих покупця; без вгаданих чи доповнених персональних даних |
| metadata | object | Початкові метадані мерчанта в тому вигляді, який був на час створення події |
| created_at | timestamp | Час створення рахунку |
| updated_at | timestamp | Час оновлення стану рахунку |
| expires_at | timestamp | Кінцевий строк оплати рахунку |
| monitoring_expires_at | timestamp | Кінцевий строк відстеження запізнілих платежів |
| settled_at | timestamp | null | Час остаточної оплати |
| paid_chain | string | null | 4.1.2+: slug мережі доведеного способу остаточної оплати, наприклад ethereum; null без збереженої відповідної оплати |
| paid_asset | string | null | 4.1.2+: тикер нативної монети чи токена, наприклад BTC, ETH або USDC; підпис для показу, а не унікальний ідентифікатор активу |
| paid_asset_amount | decimal string | null | 5.0.1+: повна зафіксована сума до сплати в одиницях paid_asset, до віднімання допуску; збережена при остаточній оплаті |
| paid_asset_amount_received | decimal string | null | 5.0.1+: загальна дійсна отримана сума способу-переможця на час остаточної оплати, з допустимою недоплатою/переплатою; зафіксована, а не поточний баланс |
| paid_payment_method_id | UUID | null | 4.1.2+: ID платіжного наміру остаточної оплати; відповідає payment_info.methods[].payment_method_id і його точній мережі/контракту |
| settlement_exchange_rate | object | null | 4.1.2+: збережений при остаточній оплаті ринковий знімок до спреду, з явними одиницями, валютою, часом джерел і ознаками якості; не переоцінюється при доставленні |
| cancelled_at | timestamp | null | Час скасування |
| exchange_rate_spread_percent | decimal string | Зафіксований спред, а не поточне налаштування магазину |
| underpayment_tolerance_percent | decimal string | Зафіксований допуск рахунку; кожен спосіб також повідомляє свій фактичний допуск |
| reason_code | string | null | Машиночитана причина переходу стану |
| requires_review | boolean | Ознака платіжного винятку; не дозвіл автоматично виконати замовлення чи повернути кошти |
| links | object | URL сторінки оплати, автентифікованого рахунку й платежів на час створення події. Спочатку діють домени Магазин → Основне, потім магазин за замовчуванням, потім глобальний основний; використовуються лише активні домени відповідної ролі. Повторні спроби зберігають початкові підписані посилання; null, якщо немає запису активного хоста. |
| payment_info | object | Фактично помічені способи, точні суми, зафіксована котировка, орієнтовний ринковий знімок та обмежена кількість спостережень платежів; дивись групи полів нижче |
Підсумок остаточної оплати: settlement_exchange_rate
| Поле | Тип | Значення |
|---|---|---|
| rate / units / currency / symbol | strings | Одиниці активу до спреду за одну одиницю валюти рахунку. Десятковий рядок, а не сума платежу чи виконана угода. |
| observed_at / as_of | timestamps | Час фіксації остаточної оплати / старіша позначка часу джерела. Не сприймай кешовані дані як поточний тік. |
| pricing_provider / asset_provider / pricing_fetched_at / asset_fetched_at | strings / timestamps | Джерела фіатної ціни й ціни активу та час їх отримання, збережені при остаточній оплаті. |
| stale / is_fixed / uses_reference_proxy / reference_currency | booleans / string | Ті самі ознаки якості, що й у market_rate_at_event. Фіксовані ціни проєкту позначені; референсна валюта - USD. |
| Missing snapshot or price | null | Історичний курс не вгадується. До остаточної оплати всі підсумкові поля null; сама відсутність ціни не прибирає доведені ідентифікатори paid_*. |
Способи оплати: payment_info
| Поле | Тип | Значення |
|---|---|---|
| active_payment_method_id | UUID | null | Спосіб-переможець або вибраний помічений спосіб. Null до виявлення або після визнання недійсним; типовий спосіб не вгадується. |
| method_count / methods_truncated | integer / boolean | Загальна кількість помічених способів і чи вбудований список неповний. |
| methods[] | object[] | Щонайбільше вісім помічених способів, активний першим. Без підсумовування різних активів. |
| payment_method_id / payment_rail | UUID / string | Ідентичність платіжного наміру рахунку та транспорт onchain або lightning. |
| chain_slug / network / caip_network_id | string | Ідентичність мережі. Завжди поєднуй ідентичність токена з його мережею. |
| asset_id / asset_key / caip_asset_id | UUID / string / nullable string | Перевірена ідентичність у реєстрі; самі символи не унікальні. |
| asset_name / symbol / asset_kind | string | Відображувана назва активу, тикер і тип native або token. |
| contract_address / token_standard | string | null | Контракт або mint токена та стандарт; null для нативних активів. |
| asset_decimals | integer | Точність найменшої одиниці; Lightning BTC використовує 11. |
| destination_address / destination_tag | string | null | Публічна адреса приймання та потрібний memo/tag. Для Lightning адреса null; це ніколи не приватний ключ. |
| status | string | Стан способу: pending, partial, paid, overpaid, expired або invalid. Сам по собі paid не означає остаточну оплату рахунку. |
| payment_count / payments_truncated / payments[] | integer / boolean / object[] | Загальна кількість спостережень і останні п'ять або менше. Кожне спостереження описане нижче. |
| links.payments | HTTPS URL | null | Автентифікована історія з пагінацією для цього способу на налаштованому origin API. |
Точні суми: methods[].amounts
| Поле | Тип | Значення |
|---|---|---|
| expected_amount | decimal string | Повна зафіксована котировка після спреду й округлення вгору. |
| received_amount / confirmed_amount | decimal strings | Дійсні виявлені кошти / кошти, що відповідають політиці підтверджень або фінальності цього способу. |
| unconfirmed_amount | decimal string | max(received - confirmed, 0). Це не додаткова сума до надсилання. |
| minimum_payment_amount | decimal string | Прийнятний поріг після допуску. Може бути нижчим за повну котировку. |
| remaining_amount | decimal string | max(minimum accepted - received, 0). Додаткові кошти до прийнятного порога, а не прогрес підтверджень. |
| remaining_to_full_amount | decimal string | max(full quote - received, 0), без урахування допуску. |
| overpaid_amount | decimal string | max(received - full quote, 0). Не дозволяє автоматичне повернення. |
| Every amount's *_atomic companion | integer string | Точне представлення в найменших одиницях. Використовуй бібліотеки десяткових або цілих чисел; ніколи не float чи JavaScript Number для грошей. |
Політика підтверджень: methods[].acceptance
| Поле | Тип | Значення |
|---|---|---|
| finality_mode / required_confirmations | string / integer | Зафіксована кількість підтверджень або політика finalized. Нуль підтверджень явно дозволений політикою мерчанта, це не загальна фінальність мережі. |
| observed_confirmations | integer | null | Мінімум серед дійсних спостережень, а не лише найновіший переказ. Null для Lightning або за відсутності дійсних спостережень. |
| underpayment_tolerance_percent | decimal string | Фактичний допуск способу. Lightning використовує нуль, навіть якщо рахунок має ненульовий on-chain допуск. |
Курси: methods[].quote і market_rate_at_event
| Поле | Тип | Значення |
|---|---|---|
| quote.effective_rate / units / currency / symbol | strings | Зафіксований курс asset_per_invoice_currency зі спредом; currency і symbol явно задають напрямок. |
| quote.exchange_rate_spread_percent / quote_expires_at | decimal string / timestamp | Зафіксований спред і строк котировки. Ніколи не замінюються поточними налаштуваннями магазину. |
| quote.reference_rate / unrounded_payment_amount / rounding_adjustment | decimal string | null | Референсний курс до спреду, сума платежу до округлення та надбавка округлення вгору в одиницях активу. |
| quote.pricing_provider / asset_provider / pricing_fetched_at / asset_fetched_at | string or timestamp | null | Початкові джерела/час ціни валюти й активу. Без API-ключів чи облікових даних провайдерів. |
| quote.provenance_available / rounding | boolean / string | False для старих рахунків без збереженого знімка джерела; округлення - up. |
| market_rate_at_event | object | null | Орієнтовний кешований ринковий знімок на час створення події. Відсутні дані залишаються null; він не змінює суми рахунку й не затримує подію заради мережевого запиту. |
| market_rate_at_event.rate / units / currency / symbol | strings | Ринковий курс до спреду з тим самим явним напрямком, що й quote. |
| market_rate_at_event.observed_at / as_of / pricing_fetched_at / asset_fetched_at | timestamps | Час знімка події / старіший із двох часів джерел / час кожного джерела. |
| market_rate_at_event.pricing_provider / asset_provider | strings | Кешовані джерела валюти й активу, включно з налаштованими цінами власних токенів. |
| market_rate_at_event.stale / is_fixed / uses_reference_proxy / reference_currency | booleans / string | Чи кеш застарів, ціна токена фіксована або USD-референс використовує стейблкоїн як заміну. Референсна валюта - USD. Ознака застарілості довідкова; це не свіжа котировка. |
Записи переказів: methods[].payments[] і GET …/payments
| Поле | Тип | Значення |
|---|---|---|
| payment_id / payment_method_id | UUID | Ідентичність спостереження / батьківського платіжного наміру. Для усунення дублікатів історії використовуй payment_id. |
| transaction_id / payment_hash / event_index | string | null / integer | Хеш у блокчейні та індекс переказу/логу/виходу або хеш Lightning. Lightning не має транзакції чи посилання на оглядач. |
| payment_rail / chain_slug / network / asset_id / asset_key / caip_asset_id / symbol / asset_decimals | strings / UUID / integer | Ті самі ідентифікатори активу й мережі, що у способу, який містить запис. |
| amount / amount_atomic | decimal / integer strings | Точна сума цього переказу, ніколи не фіатна конвертація. |
| status / counts_towards_received | string / boolean | detected, confirming і final враховуються; reorged, replaced і invalid - ні. Зберігай недійсну історію для звіряння. |
| confirmations / block_height | integer | null | Дані блока спостереження; confirmations має null для Lightning. |
| observed_at / chain_time / finalized_at | timestamp | null | Перше локальне виявлення, довірений час мережі за наявності та час досягнення фінальності за політикою. |
| explorer_name / explorer_url | string | null | Перевірене посилання на публічний оглядач блоків, якщо підтримується. |
Версія мерчанта 5.13.3 виключає перевірені внутрішні перекази на газ із сум платежів покупців, payment_info, API платежів рахунку, лімітів повернення й подій payment.received. Їхні мережеві/казначейські записи залишаються для обліку гаманця. Звичайні перекази й справжні переплати далі враховуються. Наявні підписані тіла колбеків ніколи не переписуються. Якщо стара остаточна оплата залежала від внутрішнього фінансування замість коштів покупця, звіряння створює invoice.invalid із reason_code internal_gas_funding_excluded; перевір її, а не виконуй замовлення знову.
Версія мерчанта 4.1.0 додає payload_version 2 без переміщення чи зміни початкових дев'яти полів. Події, що вже були в черзі, зберігають початкове тіло й можуть не мати payload_version. event_id, event_type та ID проєкту/магазину тепер у підписаному тілі; транспортні заголовки події/доставлення залишаються непідписаними.
payment_info описує помічені платежі, а не всі доступні варіанти оплати. До виявлення active_payment_method_id має null, а methods порожній. Реорганізовані/недійсні спостереження можуть залишатися в methods навіть після того, як активний спосіб став null. Ніколи не додавай суми різних активів або мереж.
Усі суми, цілі числа найменших одиниць, курси й відсотки - рядки. received_amount включає дійсні кошти, що чекають підтвердження; confirmed_amount відповідає політиці фінальності способу. remaining_amount - max(minimum_payment_amount мінус received_amount, 0); remaining_to_full_amount - max(expected_amount мінус received_amount, 0). Приклад: очікується 100 USDC, отримано 99, допуск 1% означає remaining_amount 0 і remaining_to_full_amount 1. Фінальність усе одно потрібна.
quote - зафіксований розрахунок рахунку: одиниці активу за одну одиницю валюти рахунку. Спред застосовується перед округленням вгору. Для точного порівняння платежу використовуй expected_amount_atomic; сам відображений курс може не відтворити округлення вгору. Старі рахунки без збереженого походження джерела повертають null у полях джерела/референсу/округлення та provenance_available false, а не сьогоднішні дані під виглядом історичної котировки.
market_rate_at_event - довідкові кешовані дані до спреду, зафіксовані при створенні події. Містить час джерел, ознаки застарілості й референсної заміни; null, якщо немає придатної кешованої пари. Запит поточного курсу не блокує сповіщення, і це ринкове спостереження не змінює належну суму. Фіксовані власні токени позначені is_fixed; DEX-токени використовують джерело свого проєкту, а не токен із таким самим символом.
Поля верхнього рівня paid_chain, paid_asset, paid_payment_method_id і settlement_exchange_rate (4.1.2+) визначають доведений спосіб-переможець після остаточної оплати, а не вибраний варіант оплати чи суму різних способів. До остаточної оплати, після визнання недійсним, для старих оплат без знімка або ручного прийняття без відповідних фінальних коштів ці поля null. Символи - підписи для показу: використовуй ID способу для точної ідентичності мережі/активу/контракту.
Версія мерчанта 5.0.1 додає paid_asset_amount і paid_asset_amount_received як точні десяткові рядки в одиницях paid_asset; payload_version залишається 2. paid_asset_amount - повна зафіксована котировка зі спредом і округленням вгору, ніколи не поріг допуску чи залишок до сплати. paid_asset_amount_received - усі дійсні надходження способу-переможця на час остаточної оплати, включно з коштами, що чекають підтвердження, та допустимою недоплатою чи переплатою. Приклад: котировка 100 USDC, отримано й прийнято з допуском 99 - значення 100 і 99, а не 99 і 99. Обидва зафіксовані зі знімком остаточної оплати; для надходжень на час кожної події використовуй payment_info.methods[].amounts, а для поточних записів - API платежів. Без відповідного знімка та у знімках до 5.0.1 вони null; тіла старих подій у черзі не змінюються. Для обліку ніколи не перетворюй точні десяткові рядки на числа з рухомою комою.
settlement_exchange_rate - кешоване ринкове спостереження до спреду, збережене при остаточній оплаті, а не зафіксована котировка рахунку чи виконана біржова угода. Формат відповідає market_rate_at_event; 1.17 asset_per_invoice_currency з EUR/USDC означає 1 EUR = 1.17 USDC. Час джерел та ознаки stale/fixed/proxy описують якість. Якщо пари немає, курс null, але доведений спосіб зберігає поля paid_*. Він не змінює суму до сплати й не чекає поточного запиту провайдера. Пізніші платежі тим самим способом, повторні спроби та доставлення не замінюють знімок, навіть збережений null-курс. Справжня повторна остаточна оплата або зміна способу остаточної оплати створює новий знімок; observed_at визначає цей момент, а settled_at може зберігати час першої оплати. Старі тіла подій незмінні.
Включено щонайбільше вісім помічених способів і п'ять останніх спостережень платежів на спосіб, із кількостями та ознаками обрізання. Ліміт розміру даних може ще скоротити масиви. Спостереження платежу - один переказ/лог/UTXO-вихід, не обов'язково унікальний хеш транзакції. Для повної поточної історії використовуй GET /v1/projects/YOUR_PROJECT_ID/invoices/{invoice_id}/payments з payment_method_id, limit і offset. Деталі рахунку зберігають усі котировані способи та їхні quote_details. API-посилання потребують налаштованого хоста й облікових даних; ніколи не пересилай bearer-токен на довільний URL із колбеку.
Lightning використовує payment_hash замість transaction_id; адреса приймання, оглядач і помічені підтвердження мають null. Точна сума BTC має 11 десяткових знаків (мілісатоші), фактичний допуск - нуль. Не включаються preimage платежу BOLT11, ключ гаманця, секрет підпису чи облікові дані провайдера. Поля покупця/метаданих належать лише відповідям мерчанта й підписаним колбекам, ніколи публічній сторінці оплати; не клади облікові дані в метадані.
Безпечне приймання
- До розбору перевір точне сире тіло відповідним секретом. Магазин → IPN дає секрет IPN, включно з доставленням на власний ipn_url. Кожен ендпоїнт Магазин → Вебхуки має власний секрет. Жоден не є API-токеном; заміна одного не змінює інші.
- Перевір підписаний час (SDK за замовчуванням допускає п'ять хвилин у кожен бік) і звір підписані ID проєкту/магазину з конфігурацією приймача, якщо вони є. Надійно постав у чергу перед відповіддю HTTP 2xx. Для обробки окремих подій event_id у v2 підписаний; самі ID в заголовках не захищають від повторення, бо заголовки не підписані. Для черг стану замовлення усувай дублікати invoice_id і sequence та порівнюй початкові поля стану рахунку, а не все тіло v2: різні типи/ID подій можуть мати спільну ревізію.
- У воркері отримай поточний рахунок із налаштованого origin API, а не довільного посилання колбеку. Звір збережене замовлення, проєкт/магазин, суму й валюту, вимагай поточний статус settled і застосуй політику ручного прийняття та винятків. Заблокуй замовлення й виконай його один раз у транзакції бази даних, незалежно від усунення дублікатів подій.
- Ніколи не застосовуй старіший sequence поверх новішого. Різні події можуть мати спільну ревізію; не поєднуй дедуплікацію за ревізією з фільтром лише invoice.settled. Повторне відкриття/звіряння може змінити статус; порядок оновлень задає sequence, а не фіксований рейтинг статусів. Записуй скасування результатів для перевірки, а не виконуй замовлення знову.
Приклади приймачів: PHP · Python · Node.js / TypeScript.
Перевірка підпису й правила доставлення
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyWhollySignature(rawBody, header, signingSecret, toleranceSeconds = 300) {
const match = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
if (!match) return false;
const timestamp = Number(match[1]);
if (!Number.isSafeInteger(timestamp)) return false;
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > toleranceSeconds) return false;
// rawBody must be the exact request Buffer, before JSON parsing.
const expected = createHmac("sha256", signingSecret)
.update(String(timestamp))
.update(".")
.update(rawBody)
.digest();
const presented = Buffer.from(match[2], "hex");
return timingSafeEqual(expected, presented);
}| Правило доставлення | Деталі |
|---|---|
| Заголовки | Wholly-Signature, Wholly-Event-Id і Wholly-Delivery-Id; Content-Type - application/json. |
| Підпис | HMAC-SHA256 для <unix timestamp>.<exact raw body>; формат заголовка t=<timestamp>,v1=<64 lowercase hex>. |
| Успіх | Будь-яка відповідь HTTP 2xx. Перенаправлення не виконуються; відповіді не-2xx вважаються помилкою. |
| Таймаути | 5 секунд на підключення й 10 секунд на весь запит. |
| Розклад повторних спроб | До 8 спроб для помилок, які можна повторити: одразу, потім через 10 с, 1 хв, 5 хв, 15 хв, 1 год, 6 год і 24 год після завершення попередньої спроби. IPN повторюється автоматично; автоматичні повтори вебхуків можна вимкнути для кожного ендпоїнта. |
| Безпека адреси призначення | Лише публічний HTTPS. DNS повторно перевіряється й закріплюється для доставлення; локальні/приватні/зарезервовані адреси відхиляються. |
| Зберігання подій | Дані подій сповіщень та історія доставлення заплановані до зберігання 90 днів; деталі видаляються обмеженими пакетами. |
| Усунення дублікатів | Зберігай підписані invoice_id і sequence в межах налаштованого проєкту. Wholly-Event-Id визначає подію; Wholly-Delivery-Id - запис доставлення (повторні спроби використовують його знову; ручне повторне доставлення створює інший). Жоден ID-заголовок не підписаний. |
| Назви подій | Версія 2 підписує event_id і event_type в тілі. Старі події в черзі не мають жодного з них. Різні типи подій можуть мати спільний sequence рахунку; звіряй стан рахунку за ревізією або усувай дублікати окремих подій за підписаним event_id. |
| Заміна секрету | Заміна не має періоду перекриття чи заголовка версії та одразу змінює підписи для черги, повторних і ручних доставлень. |
| Призупинені доставлення | Недостатній баланс обробки призупиняє IPN/вебхуки, включно з повторними спробами. Вхідні платежі тривають; сповіщення в черзі відновлюються після поповнення в межах строку зберігання їхніх даних. |
ШІ-помічники · MCP
Підключи асистента до своєї інсталяції мерчанта.
Версія мерчанта 5.0.0 містить опційний MCP-сервер на налаштованому API-домені. Він працює всередині твоєї інсталяції, а не через спільний ретранслятор Wholly Crypto.
- Відкрий Налаштування → Доступ до API. Створи окремі облікові дані, признач лише потрібні асистенту проєкти й почни з читання. На акаунті, який хостить оператор, спочатку оператор вмикає MCP інсталяції; ти керуєш лише власними обліковими даними й дозволами.
- У «AI-підключення · MCP» увімкни MCP, вибери облікові дані та збережи їхній MCP-доступ. Наявні облікові дані не мають MCP-доступу, доки його явно не ввімкнено.
- Скопіюй URL MCP-сервера в налаштування віддаленого HTTP-сервера клієнта. З OAuth увійди в панель мерчанта, перевір назву клієнта й адресу повернення, вибери облікові дані та схвали. Наявні Basic Auth і TOTP залишаються чинними.
- Створення рахунків додатково потребує читання/запису, режиму «Читати + створювати рахунки» в MCP-політиці, OAuth-області mcp:invoice:create та явного схвалення. OAuth-підключення не отримує проєкти, додані до облікових даних після схвалення.
{
"mcpServers": {
"whollycrypto": {
"url": "https://api.example.com/mcp"
}
}
}| Інструмент | Доступ | Призначення |
|---|---|---|
| list_projects | Переглянь | Увімкнені проєкти, призначені підключенню; пагінація limit/offset. |
| list_stores | Переглянь | Магазини, ID та стан увімкнення в межах project_id; пагінація limit/offset. |
| list_payment_methods | Переглянь | Налаштовані способи мереж, токенів і Lightning для project_id + store_id. |
| get_wallet_balances | Переглянь | Адреси приймання й кешовані баланси з полями свіжості/доступності; ніколи не секрети гаманця. |
| list_invoices | Переглянь | Рахунки проєкту з фільтром за магазином, статусом або пошуком; пагінація limit/offset. |
| get_invoice | Переглянь | Повні деталі рахунку й посилання оплати за project_id + invoice_id. |
| get_delivery_history | Переглянь | Статуси IPN/вебхуків магазину, спроби та HTTP-результати. Необов'язкові фільтри invoice_id/kind; без секретів і тіл колбеків. |
| convert_amount | Переглянь | Кешована довідкова конвертація за from, to й десятковим рядком amount; не котировка рахунку. |
| create_invoice | Явний запис | project_id, store_id, idempotency_key та invoice (наявне тіло створення рахунку). invoice.payment_methods фільтрує ввімкнені способи магазину; 5.4.0+ ігнорує неактивні/неприйняті варіанти й повертається до налаштувань магазину, якщо нічого не збігається. Лише мережа вибирає всі активні прийняті активи. asset_tickers у межах мережі підтримуються з 5.3.0. Повертає звичайну відповідь рахунку. |
Протокол, OAuth і безпека
Використовуй Streamable HTTP через HTTPS. Узгодь оголошену версію протоколу й передавай MCP-Protocol-Version у наступних POST. Надсилай Content-Type: application/json і Accept: application/json, text/event-stream. Відповіді - скінченні JSON; повторне підключення не потребує ID сеансу MCP.
OAuth використовує короткочасні токени доступу (15 хвилин), одноразові S256 PKCE-коди (5 хвилин) та змінні refresh-токени (строк підключення 30 днів). Повторне використання вже використаного refresh-токена відкликає підключення. Підключись знову після завершення строку, заміни облікових даних, зміни політики чи канонічного API-домену.
OAuth discovery публічний лише коли MCP ввімкнено. Параметр resource має точно відповідати канонічному URL із discovery, включно з /mcp. Динамічна реєстрація підтримується; віддалені документи метаданих client-ID і клієнтські секрети - ні.
Клієнти з власними Authorization-заголовками натомість можуть використовувати API-токен мерчанта з увімкненим MCP як Bearer. Він зберігає окремі REST-права; для підключення, обмеженого MCP, краще OAuth. Ніколи не вставляй облікові дані в чат, URL, аргументи інструментів чи систему контролю версій.
MCP використовує спільну з REST похвилинну квоту облікових даних і точні IP-обмеження джерела, а також IP-обмеження API-хоста. OAuth не обходить білий список. Для віддалених AI-клієнтів дозволь їхні задокументовані вихідні IP або свідомо залиш це обмеження вимкненим. До MCP/OAuth-маршрутів не слід застосовувати вебперевірки безпеки чи кешування.
HTTP-помилки: 401 потребує автентифікації, 403 забороняє origin/IP/дозвіл, 404 означає вимкнений MCP або неправильний хост, 405 вимагає POST, 413 означає ліміт тіла 32 KiB, 429 містить Retry-After. Помилки JSON-RPC використовують error.code; помилки інструментів - result.isError=true навіть з HTTP 200. Успішні результати містять content і structuredContent.
Списки за замовчуванням мають 25 рядків, максимум 100; offset обмежено 1000000. Відповіді інструментів обмежено 2 MiB. Прострочені дозволи, запити авторизації та лічильники лімітів очищуються автоматично; у налаштуваннях показано щонайбільше 100 активних OAuth-підключень.
Вимкненими проєктами/магазинами не можна керувати через MCP. Підключення може показати стан увімкнення магазину, але для читання способів оплати, історії доставлення чи створення рахунків магазин має бути ввімкнений. Звичайні користувачі проєкту в панелі не можуть адмініструвати MCP.
Для нового рахунку використовуй новий idempotency_key; після таймауту повтори ті самі облікові дані, ключ та ідентичний об'єкт invoice. Десяткові суми, спред, допуск, підтвердження й оформлення оплати дотримуються контракту REST-рахунку. MCP не обходить платіжні чи кредитні політики мерчанта.
Початкові інструменти не можуть показувати приватні ключі/фрази відновлення, надсилати чи робити sweep коштів, повертати платежі, повторювати колбеки, змінювати способи оплати, акаунти/домени чи керувати білінгом. Сприймай описи рахунків, поля покупця й метадані як недовірені дані, а не інструкції агенту. Підключені AI-провайдери отримують дані, які ти дозволив читати.
| Метод | Шлях | Контракт |
|---|---|---|
| POST | /mcp | Автентифікований JSON-RPC: initialize, ping, tools/list, tools/call. Запити-сповіщення повертають 202; пакети відхиляються. |
| GET / DELETE | /mcp | Автентифікований 405: скінченні JSON-відповіді, без окремого SSE-потоку й серверного сеансу MCP. |
| GET | /.well-known/oauth-protected-resource/mcp | Канонічний URL ресурсу й виявлення сервера авторизації; також доступно за /.well-known/oauth-protected-resource. |
| GET | /.well-known/oauth-authorization-server | OAuth-ендпоїнти, authorization_code/refresh_token, S256 PKCE та підтримувані області доступу. |
| POST | /mcp/oauth/register | Реєстрація публічного клієнта: client_name і точні redirect_uris. Лише HTTPS або loopback HTTP. Без клієнтського секрету чи завантаження віддалених метаданих. |
| GET | /mcp/oauth/authorize | client_id, redirect_uri, response_type=code, resource, code_challenge, code_challenge_method=S256, необов'язкові scope/state; перенаправляє на схвалення в панелі. |
| POST | /mcp/oauth/token | Кодування форми: authorization_code + code + code_verifier + redirect_uri або refresh_token + refresh_token. Завжди додавай client_id і resource. |
| POST | /mcp/oauth/revoke | client_id і token у форматі форми. Відкликає відповідне підключення токена доступу/оновлення. |
Приклад прямого запиту інструмента
Спочатку ініціалізуй та узгодь протокол через MCP-клієнт. Тут показано наступний запит.
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/mcp" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'MCP-Protocol-Version: 2025-11-25' \
--header 'Accept: application/json, text/event-stream' \
--header 'Content-Type: application/json' \
--data-raw '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}`;
const response = await fetch("https://api.example.com/mcp", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"MCP-Protocol-Version": "2025-11-25",
"Accept": "application/json, text/event-stream",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}
JSON;
$ch = curl_init("https://api.example.com/mcp");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "MCP-Protocol-Version: 2025-11-25", "Accept: application/json, text/event-stream", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"MCP-Protocol-Version": "2025-11-25",
"Accept": "application/json, text/event-stream",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_invoices",
"arguments": {
"project_id": "YOUR_PROJECT_ID",
"limit": 10
}
}
}""".encode("utf-8")
request = Request("https://api.example.com/mcp",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))API оператора
Створюй хостованих мерчантів окремими серверними ключами з обмеженим доступом.
Хости кілька бізнесів і автоматизуй їхнє налаштування через api.example.com/v1/operator. Доступно з 7.4.0 лише в режимі оператора. Звичайний API мерчанта не змінюється.
- Відкрий Оператор → Налаштування → API оператора й увімкни його (типово вимкнений). Створи окремі облікові дані лише з потрібними дозволами й хостованими мерчантами.
- Тримай ключ wc_operator_ на сервері. Використовуй хост API, а не хост панелі оператора чи ключ мерчанта.
- Зберігай Idempotency-Key і точне тіло запиту перед кожним POST оператора. Після невизначеного результату прочитай акаунт; не замінюй ключ лише заради повторення.
- Створи мерчанта з onboarding: direct і паролем або onboarding: invitation без пароля. Потім створи проєкти/магазини й видай ключ мерчанта, обмежений проєктом, для інтеграції оплати.
| Область доступу | Доступ |
|---|---|
| merchants.read / merchants.write | Список/читання та створення/оновлення хостованих мерчантів. |
| users.read / users.write / users.security | Читання/створення/оновлення користувачів; зміна паролів або відкликання сеансів окремо. Ніколи не створює адміністратора оператора. |
| invitations.read / invitations.write | Список/читання, створення, заміна й відкликання одноразових посилань запрошення/скидання. Нові користувачі також потребують users.write; скидання - users.security. |
| credits.read / credits.write / fees.write | Читання балансів/облікової книги; надання чи коригування локального балансу; встановлення майбутніх тарифів. Ненульовий стартовий баланс потребує credits.write. |
| topups.read / topups.write | Читання чи створення запитів оплати поповнення хостованого мерчанта. Жодна API-дія не може позначити їх оплаченими. |
| projects.read / projects.write / reports.read | Створення проєктів, магазинів, оформлення й платіжних налаштувань мерчанта; читання рахунків, балансів гаманців та фінансових звітів. |
| merchant_credentials.read / merchant_credentials.write | Керування звичайними обмеженими ключами мерчанта. Потужний дозвіл: після видачі ці ключі діють незалежно. |
| events.read / webhooks.write / audit.read / health.read | Читання історії життєвого циклу; налаштування підписаних колбеків; читання аудиту/можливостей/стану вузлів. |
Початок роботи, баланс, дозволи й безпечні повтори
| Тема | Правило |
|---|---|
| Облікові дані | Необов'язковий строк дії й точний список дозволених IPv4/IPv6; за замовчуванням 60 запитів/хвилину, налаштовується 1–600. Кожен запит перевіряє адміністратора, який видав ключ, і поточні області доступу. HTTP 429 містить Retry-After. |
| Ізоляція | Ключі мають доступ лише до призначених хостованих мерчантів. Створення мерчантів і перегляд звітів усієї інсталяції потребують доступу до всіх мерчантів. Власний бізнес оператора виключено. |
| Перший вхід | Прямо створені акаунти підтверджують, що хост має доступ до ключів гаманців. require_password_change додає зміну пароля при першому вході. Прийняття запрошення потребує явного підтвердження доступу хоста до ключів, потім звичайного входу. Basic Auth і наявний TOTP залишаються чинними. |
| Запрошення | Посилання нового користувача діють 48 годин; скидання пароля - одну годину. Токени одноразові. Повторна видача відкликає старе посилання. Прийняття SMTP не гарантує потрапляння у вхідні; перевір email_delivery. |
| Безпечні повторні запити | Кожен POST оператора потребує ключа з 16–128 символів (літери, цифри, -, _ або .). Той самий ключ і точні URL/тіло повертають збережений результат. Інші байти повертають 409. Секрети/посилання при повторі пропускаються; за потреби заміни або перевидай їх новою явною операцією. |
| Невизначені результати | operator_request_in_progress означає, що операція виконується або була перервана до запису результату. Перевір ресурс і аудит; не надсилай навмання новий ключ. Завершені результати ущільнюються через 30 днів; старі ключі все одно не можна виконати знову. |
| Баланс і комісії | Десяткові рядки, щонайбільше шість знаків. starting_credit - одноразове локальне нарахування. Коригування потребують суми зі знаком, примітки й request_id, а також HTTP-ключа повторення. fee_bps=100 означає 1%; зміни впливають на майбутні рахунки. Нарахування не поповнюють власний передплачений баланс інсталяції. |
| Призупинення | enabled=false вимикає хостований акаунт і відкликає сеанси панелі. payments_paused=true зупиняє нові рахунки. Відстеження наявних платежів триває. Створення проєктів/магазинів та автоматизація зберігають кредитну політику інсталяції. |
| Не надається | Немає секретів гаманців, підписування, надсилання, повернень, остаточного видалення, скидання TOTP, змін доменів чи серверних налаштувань. Звичайні запити рахунків далі використовують ключ мерчанта й API мерчанта. |
Вебхуки життєвого циклу оператора
| Подія | Дані |
|---|---|
| merchant.created / merchant.updated | merchant_id, enabled, payments_paused, fee_bps. |
| user.created / user.updated | merchant_id, user_id, enabled. Подія оновлення охоплює зміни email, стану ввімкнення та ролі адміністратора. |
| invitation.accepted / password_reset.completed | merchant_id, user_id, invitation_id. |
| topup.settled / credit.balance_changed | merchant_id, ledger_id, kind, amount і balance. Для звіряння прочитай валюту балансу мерчанта або деталі облікової книги. |
Події життєвого циклу оператора відокремлені від IPN рахунків/вебхуків магазинів. Підписка належить обліковим даним оператора, які її створили; до 10 ендпоїнтів на ключ. У чергу потрапляють лише майбутні відповідні події; для збереженої історії використовуй GET /events.
Тіло містить event_id, event_type, merchant_id, occurred_at і data. Перевір Wholly-Signature над точним сирим тілом одноразовим signing_secret ендпоїнта: HMAC-SHA256(secret, timestamp + '.' + raw_body), заголовок t=...,v1=.... Застосовуй короткий часовий допуск.
Використовуй загальний перевірник підпису SDK, а не парсер сповіщень рахунку. Потім перевір merchant_id і event_type, транзакційно збережи/дедуплікуй event_id та повертай 2xx лише після надійного прийняття. Wholly-Event-Id має відповідати підписаному тілу. Не сприймай непідписані заголовки як бізнес-дані.
Доставлення відбувається щонайменше один раз, може йти не за порядком і має до 8 спроб. Читай поточні ресурси для звіряння; occurred_at не є монотонною послідовністю. Область доступу, увімкнення й строк дії повторно перевіряються перед доставленням. Вимкнені підписки ставлять на паузу наявну чергу, але не додають нові події, поки вимкнені.
Події та історія доставлення зберігаються 30 днів. Політика автоматизації інсталяції може призупинити доставлення. GET /webhooks/{id}/deliveries показує результат і незмінні дані; публічний API не примушує доставляти прострочений запис.
{
"event_id": "55555555-5555-4555-8555-555555555555",
"event_type": "merchant.created",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"occurred_at": "2026-10-01T12:00:00Z",
"data": {
"merchant_id": "11111111-1111-4111-8111-111111111111",
"enabled": true,
"payments_paused": false,
"fee_bps": 300
}
}API Marketplace
Одна оплата із захищеними частками продавців і контрольованими виплатами.
Один рахунок покупця, точні частки продавців і контрольовані виплати в тому самому активі. Вмикається для кожного проєкту. Версія 8.0.0 підтримує Bitcoin mainnet та налаштовані підтримувані нативні EVM-монети / стандартні ERC-20 токени, а не всі мережі приймання.
- Увімкни Marketplace в проєкті, вибери магазини-учасники й залиш виплати на паузі під час налаштування.
- Зареєструй продавців і незалежно перевір їхні адреси виплат. Створена адреса очікує схвалення; воно потребує destinations.approve.
- Створи окремі облікові дані Marketplace у Налаштування → Доступ до API. Звичайні облікові дані мерчанта, оператора й MCP не можуть витрачати кошти Marketplace.
- Створи рахунок із 1–100 додатними десятковими рядками часток, сума яких точно дорівнює сумі рахунку. Кожен продавець потребує схваленої адреси в спільній підтримуваній мережі магазину.
- Дочекайся доступності перевірених часток. Підготуй виплату, прочитай незмінних одержувачів і ліміти витрат, потім схвали її ревізію та точний plan_hash. Опитуй виплату або перевіряй підписані події.
| Тема | Правило |
|---|---|
| Зберігання коштів | Кошти покупця спочатку надходять у гаманці проєкту. Власник маркетплейсу/сервера контролює ключі до виплати продавцям. Це не прямий платіж покупець-продавець, ескроу чи система входу для продавців. |
| Три продавці | Рахунок 300 USD із трьома частками по 100 USD та комісією 4% виділяє кожному продавцю еквівалент 96 USD у котированій криптовалюті, залишаючи 12 USD-еквівалент валової комісії. План гарантує найменші одиниці криптоактиву, а не майбутню фіатну вартість. |
| Комісії | Наявна плата за обробку застосовується один раз до початкової суми/валюти остаточно оплаченого рахунку. За налаштованого 1% це 3 USD передплаченого балансу, залишаючи 9 USD-еквівалент комісії до мережевих витрат. Виплати продавцям не створюють додаткової комісії за продаж покупцю. |
| Розподіл | Метод найбільшого залишку зберігає кожну найменшу одиницю. Комісія округлюється вниз; чиста сума продавця - решта. Перевизначення частки, рахунку, продавця й типові значення магазину/проєкту зберігаються у знімку. При виплаті новий курс не застосовується. |
| Захищені кошти | Звичайні надсилання, sweep, біржові депозити й автопоповнення балансу виключають адреси приймання Marketplace. Мережеві комісії та газ токенів потребують окремих вільних нативних монет. Кешовані суми гаманців довідкові; перед підписом незалежно перевіряється поточне забезпечення. |
| Фінальність | Для доказу виплати Marketplace потрібні додатний мінімум підтверджень мережі та два незалежні сумісні провайдери, навіть якщо оплата приймає нуль підтверджень чи один сканер. Паузи провайдерів відкладають перевірку/виплату, а не створення інакше коректного рахунку. |
| Винятки | Недоплати, прийняті звичайним допуском оплати, утримуються, а не розподіляються понад наявні кошти. Привілейоване розблокування може схвалити точний менший повністю забезпечений розподіл. Сама переплата ніколи не блокує котировані частки продавців у BTC або підтримуваних EVM native/ERC-20 способах. Надлишок утримується окремо. Bitcoin повертає захищену решту на адресу рахунку; окремі кошти проєкту покривають комісії й доповнення до мінімуму dust. Змішані способи, запізнілі/неоднозначні/реорганізовані платежі та нестача забезпечення потребують перевірки. |
| Повернення | Підготуй повне повернення в тому самому активі одного однозначного підтвердженого способу, потім окремо схвали як виплату. Невиплачені частки й комісія сторнуються. Коли всі продавці вже отримали кошти, окремо поповни основну адресу гаманця; примусового повернення від продавців немає. Частково оплачені групи продавців і повернення змішаних активів спочатку потребують звіряння. Повернення частини суми й виведення комісії не надаються у 8.0.0. |
| Повторні спроби | Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату. |
| Ревізії | Змінювані записи потребують поточної revision. Схвалення/відновлення також потребує expected_plan_hash і confirm:true. Підготовка резервує кошти на 15 хвилин; схвалення дозволяє одну годину. Прострочена непідписана робота безпечно звільняється. Підписані/невизначені перекази зберігають ідентичності й резервування. |
| Автоматичні виплати | Типово вимкнені. Політики для кожного активу дозволяють схвалені адреси, додатний мінімум, ліміти основної суми на виплату/рухомі 24 години та нативних комісій/газу, інтервал і підтвердження. Зміна/відкликання дозволу зупиняє ненадіслану роботу; відстеження триває. Ліміти включають зарезервовані й невизначені плани. Призупинені білінгом політики справедливо переплановуються. Недійсний рахунок утримується для перевірки, не блокуючи інші придатні групи рахунків. |
| Пауза й відновлення | Низький баланс і захисні перемикачі переказів далі зупиняють витрачання. Відстеження та звіряння облікової книги тривають. Відновлення перевіряє той самий збережений план. Канонічний EVM revert, доведений двома незалежними провайдерами, можна замінити після явного схвалення в межах залишкового бюджету комісій; початкові хеші й витрати лишаються записаними. Невідомі результати або невідповідність доставлення токена залишаються утриманими. Резервуй усю базу й ключі; після відновлення звір надіслані хеші, перш ніж дозволяти виплати. |
| Ідентифікатори й пагінація | Використовуй UUID проєкту з його налаштувань і UUID магазину з Магазини → Основне → ID для API. ID продавця/виплати/активу повертає цей API. invoice_id - публічний UUID рахунку. Ресурси з пагінацією повертають data і pagination {page,per_page,total,pages}; типово 1/25, максимум 100 рядків. Точні грошові значення - рядки. |
| Область облікових даних | Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках. |
Дозволи Marketplace
marketplace.read · vendors.write · destinations.write · destinations.approve · invoices.write · policies.write · commissions.override · payouts.write · payouts.approve · webhooks.write · reconciliation.write
Стани розподілених часток
pending · held · available · reserved · paid · refunding · refunded · shortfall
Стани виплат
awaiting_approval · queued · funding_gas · sending · confirming · partially_paid · paid · needs_attention · cancelled · expired
Події Marketplace
Окремий секрет підпису Marketplace з тими самими заголовками Wholly та алгоритмом HMAC для сирого тіла, що в колбеках рахунків. Перевір час/підпис, усунь дублікати event_id й швидко поверни 2xx. Доставлення щонайменше одноразове, до восьми спроб; з історії можна знову доставити ту саму подію. Зміни ендпоїнта скасовують старі ненадіслані доставлення замість перенаправлення даних покупців. Остаточна оплата рахунку не означає завершення виплати продавцю. Ніколи не надсилай гроші лише тому, що зовнішній колбек так каже.
marketplace.invoice.createdmarketplace.allocations.availablemarketplace.allocations.heldmarketplace.payout.approvedmarketplace.payout.broadcastmarketplace.payout.confirmedmarketplace.payout.partialmarketplace.payout.failedmarketplace.payout.cancelledmarketplace.refund.preparedmarketplace.refund.confirmed
{
"event_id": "11111111-1111-4111-8111-111111111111",
"event_type": "marketplace.payout.confirmed",
"payload_version": 1,
"project_id": "YOUR_PROJECT_ID",
"occurred_at": "2026-10-06T12:00:00Z",
"data": {
"payout_id": "YOUR_PAYOUT_ID",
"asset_id": "YOUR_ASSET_ID",
"amount_atomic": "28800000",
"transactions": [
{
"transaction_id": "EXAMPLE_TRANSACTION_ID",
"explorer_url": "https://mempool.space/tx/EXAMPLE_TRANSACTION_ID"
}
]
}
}Налаштувати платежі для кількох продавців · Створити рахунок Marketplace
Помилки й ліміти
Передбачувано обробляй перевірки, квоти й повторні спроби.
Перевір HTTP-статус і Content-Type перш ніж розбирати відповідь. Для 429зачекай щонайменше Retry-After перед повторною спробою.
| Ліміт | Деталі |
|---|---|
| Частота запитів | Квота на облікові дані: типово 120 запитів за UTC-хвилину, налаштовується від 1 до 6000 у Налаштування → API. Усі автентифіковані читання й записи v1, включно з ідемпотентними повторами та помилками авторизації/валідації після автентифікації, ділять ліміт між доменами, проєктами й процесами. Недійсні облікові дані, маршрути панелі й публічна оплата його не витрачають. |
| Заголовки обмеження частоти | Автентифіковані відповіді v1 містять X-RateLimit-Limit, X-RateLimit-Remaining і X-RateLimit-Reset (Unix-секунди наступної межі UTC-хвилини). Зайві запити повертають JSON 429 rate_limit_exceeded та Retry-After у цілих секундах. Зачекай принаймні цей час і додай випадкову затримку. Фіксовані вікна допускають сплески на межі хвилин; це не гарантія запитів за секунду. |
| Тіло запиту мерчанта | Максимум 32 KiB у роутері застосунку. Проксі може відхилити завеликий запит ще до створення JSON-помилки. |
| Список рахунків | limit типово 50, допускає 1–100; offset допускає 0–1 000 000. Пошук до 100 символів. Результати від нових до старих, із метаданими total/has_more. |
| Способи магазину | Щонайбільше 64 вибрані активи на магазин: достатньо для всіх 30 нативних мереж і обмеженого каталогу перевірених токенів. Політика проєкту, можливості сканера й готовий гаманець мережі з резервною копією далі визначають можливість створення рахунку. |
| Пошук токенів | Ліміт кандидатів типово 50, допускає 1–100. Знайдені результати не стають платіжними активами до успішної перевірки в блокчейні. |
| Зареєстровані токени проєкту | Щонайбільше 20 постійних токен-активів на проєкт. Уже зареєстровані активи можна використовувати повторно без нового місця. |
| Ідемпотентність | Обов'язкова для створення рахунку. 1–128 видимих ASCII-символів без пробілів; ключі унікальні в межах магазину, повтор має використовувати початкові облікові дані й точне сире тіло. |
| Метадані | Лише JSON-об'єкт, максимум 4 096 закодованих байтів і п'ять рівнів вкладеності. |
| Колбеки | Публічний HTTPS URL до 2 048 байтів. Тіла запитів сповіщень обмежено 256 KiB; збережені дані подій рахунків - 64 KiB з обмеженою історією платежів. |
| Ресурси сторінки оплати | Відповіді QR SVG приватні й no-store, бо недоплата змінює точний залишок. PNG-логотипи з версією кешуються публічно на рік і незмінні. |
| Проксі API | Керовані запити до upstream API мають таймаут читання 30 секунд. Задавай викликачам явні таймаути, коротші за часовий бюджет їхнього завдання. |
| Помилки не у форматі JSON | Некоректний UUID/витяг параметрів, неправильні методи та захист довжини 32 KiB можуть повернути текст або порожню відповідь фреймворку. Невідомі шляхи /v1 наразі повертають 404 з HTML панелі; перевір статус і Content-Type перед розбором. |
Довідник помилок
| HTTP | Код помилки | Значення |
|---|---|---|
| 400 | invalid_reconciliation_action | Некоректний статус винятку, причина, пошук або фільтр сторінки історії. |
| 500 | reconciliation_unavailable | Не вдалося завантажити чергу винятків або докази. Повтори читання з наростаючою затримкою. |
| 402 | billing_required | Кожен новий рахунок потребує перевіреного прив'язаного кредитного акаунта й поточної авторизації. Недостатній передплачений баланс не блокує створення чи вхідні платежі: натомість IPN, вебхуки й Sweep призупиняються, а комісії далі нараховуються. Створення лишається заблокованим для призупинених акаунтів, простроченої/недійсної перевірки білінгу, недоступного кредитного сервісу чи недозволеної фіатної основи рахунку. Комісії беруться з початкової фіатної суми рахунку, не з отриманої крипто, спреду, переплати чи мережевих витрат. Ця сума й незалежна конвертація реєструються до створення оплати. Наявне відстеження й отримання рахунків тривають під час збоїв. Після поповнення сповіщення в черзі відновлюються в межах звичайного строку зберігання, а ввімкнені sweep-правила продовжуються. Перевір Налаштування → Комісії та повтори невдале створення з тим самим Idempotency-Key. |
| 400 | invalid_json | Некоректний JSON, невідоме поле або тіло, що не відповідає задокументованому запиту. |
| 400 | idempotency_key_required | У створенні рахунку пропущено Idempotency-Key. |
| 400 | invalid_idempotency_key | Ключ порожній, довший за 128 байтів, не-ASCII, має пробіли або керівний байт. |
| 400 | invalid_payment_request | Перевірюване поле чи вибраний активний спосіб спричинили помилку. Прочитай error.message і error.details.payment_methods (PaymentMethodIssue[]) для точної причини. SDK 2.4.0+ додає безпечні практичні описи винятків і допоміжні методи; старі PHP SDK мають getApiMessage(). |
| 400 | invalid_invoice_status | Статус списку не входить до шести задокументованих станів рахунку. |
| 400 | invalid_callback_url | Фактична IPN-адреса не пройшла перевірку HTTPS, публічної адреси, DNS або SSRF. |
| 400 | invalid_wallet_request | Некоректний параметр підготовки гаманця/адреси. |
| 400 | invalid_token_asset | Некоректна мережа токена, запит кандидатів, ідентичність CoinGecko, метадані каталогу або контракт/mint. |
| 401 | authentication_required | Bearer-токен відсутній, некоректний, вимкнений, замінений або невідомий. |
| 403 | source_ip_denied | IP-обмеження облікових даних не містить точну публічну адресу джерела запиту. |
| 403 | source_ip_not_allowed | IP-обмеження хостнейму виключає цього клієнта. Адміністратор керує списками дозволених адрес живих хостів у Налаштування → Система; вони діють додатково до IP-обмежень облікових даних. |
| 503 | source_access_unavailable | Перевірка доступу до хостнейму тимчасово недоступна. Спробуй пізніше; за неможливості перевірки доступ закритий. |
| 403 / 409 / 500 | merchant_api_access_denied | Авторизація не пройшла: права/область проєкту можуть дати 403, вимкнений проєкт/магазин - 409, збій бекенду авторизації - 500. Гаманці приймання оператора зарезервовані для панелі оператора, не для облікових даних API мерчанта чи MCP, навіть зі старим явним дозволом проєкту. |
| 403 | project_access_denied | Транзакційна повторна перевірка під час створення виявила, що облікові дані більше не мають доступу до проєкту. |
| 404 | invoice_not_found | В авторизованому проєкті немає рахунку з цим публічним ID або сторінка оплати не може його показати. |
| 404 | payment_resource_not_found | Потрібний при підготовці рахунку проєкт, магазин, актив або гаманець більше не існує. |
| 404 | token_candidate_not_found | Проєкт недоступний або токена більше немає в поточному зіставленому каталозі пошуку. |
| 409 | idempotency_conflict | Ключ у межах магазину вже існує, але відрізняються облікові дані або точні сирі байти запиту. |
| 409 | store_unavailable | Проєкт/магазин вимкнений або недоступний. |
| 409 | no_ready_payment_methods | Жоден спосіб магазину не готовий. Прочитай error.message і error.details.payment_methods для chain_slug, asset_ticker і reason_code. Резервна копія/активація гаманця, встановлений адаптер та ціна мають бути коректні. З 6.0.6 паузи сканерів, невдалі чи застарілі перевірки стану й відсутній кворум провайдерів не блокують створення. |
| 409 | payment_method_unavailable | Вибраний спосіб став недоступним під час атомарної повторної перевірки створення. |
| 409 | store_payment_method_not_selected | Перевизначення підтверджень магазину запитано для активу, який цей магазин зараз не вибрав. |
| 409 | wallet_unavailable | Платіжний гаманець став недоступним під час атомарної повторної перевірки створення. |
| 409 | ipn_secret_required | Фактичний IPN URL є, але магазин не має секрету підпису IPN. |
| 409 | payment_resource_not_ready | Потрібний платіжний актив чи гаманець вимкнений, без резервної копії, чекає доказу активації спільного акаунта, вичерпаний або інакше не готовий. |
| 409 | account_activation_unverified | Активацію акаунта XRP Ledger або Stellar не вдалося довести через налаштовану кількість справних ендпоїнтів основної мережі (типово 2, опційно 1); поповни точний акаунт і повтори перевірку. |
| 400 | invalid_monero_wallet_rpc | Некоректний HTTPS-ендпоїнт, точна основна адреса mainnet, назва або повні дані Digest/Basic/заголовкової автентифікації. |
| 404 | monero_wallet_rpc_not_found | Прив'язки wallet-RPC Monero в межах проєкту не існує. |
| 409 | monero_wallet_rpc_not_ready | Актив Monero, кворум двох демонів, незмінна прив'язка або явне засвідчення резервної копії/режиму лише перегляду не готові. |
| 409 | monero_wallet_rpc_unavailable | Створення рахунку потребує активної, перевіреної й засвідченої прив'язки Monero wallet-RPC проєкту з дійсними серверними обліковими даними. |
| 503 | lightning_unavailable | Єдиний готовий спосіб магазину - Lightning, але його гаманець чи котировку не вдалося перевірити. Повтори з тим самим ключем ідемпотентності. Якщо є інший готовий on-chain спосіб, недоступний Lightning просто пропускається. |
| 422 | monero_wallet_rpc_verification_failed | Перевірка точного гаманця, HTTPS-закріплення, синхронізації, кворуму демонів основної мережі або доказу заборони методів шлюзом не пройшла. |
| 503 | monero_wallet_rpc_failed | Зовнішній wallet-RPC лише для перегляду не зміг безпечно створити й повторно прочитати субадресу рахунку; запасна адреса не вигадується. |
| 409 | token_chain_not_ready | Нативний актив мережі вимкнений, зіставлення пошуку змінилося при перевірці або проєкт уже має поточний максимум 20 зареєстрованих токен-активів. |
| 503 | dex_price_unavailable | DEX-провайдер недоступний, зайнятий, обмежив частоту, повернув застарілі чи некоректні дані. Повтори через хвилину; фіксована ціна залишається доступною. |
| 422 | invalid_dex_price | Некоректне поєднання режимів ціни або вибраний пул не дає придатної ціни точного контракту. Вибери інший пул або фіксовану ціну USD. |
| 422 | token_verification_failed | Усі придатні вузли не пройшли перевірку ідентичності мережі, коду контракту, десяткової точності, запиту балансу або mint. |
| 422 | invalid_store_confirmation_policy | Перевизначення магазину недоступне для цього режиму фінальності, виходить за повернуті межі мережі або просить непідтримуване прийняття без підтверджень. |
| 409 | invoice_not_payable | Рахунок оплати в кінцевому стані або строк платежу минув. |
| 409 | invoice_payment_method_locked | Дійсний платіж уже вибрав інший актив; продовжуй з active_payment_method_id. |
| 409 | payment_method_not_payable | Вибраний спосіб завершений або більше не приймає додатковий платіж. |
| 422 | payment_qr_unavailable | Платіжний запит завеликий для кодування в SVG QR. |
| 503 | payment_rates_unavailable | Для жодного готового способу оплати немає свіжої надійної котировки. |
| 500 | authentication_unavailable | Bearer-автентифікація не змогла безпечно прочитати чи перевірити збережені облікові дані. |
| 429 | rate_limit_exceeded | Ці облікові дані вичерпали поточний ліміт UTC-хвилини. Зачекай принаймні Retry-After секунд; повтори створення рахунку з тим самим ключем ідемпотентності. |
| 500 | database_error / internal_error | Тимчасова серверна помилка; безпечно повтори з тим самим ключем ідемпотентності. |
Огляд API
Вибери ендпоїнт, щоб побачити поля, приклади й відповідь.
Рахунки
POSTСтворити рахунок/v1/projects/{project_id}/stores/{store_id}/invoicesGETСписок рахунків/v1/projects/{project_id}/invoicesGETОтримати рахунок/v1/projects/{project_id}/invoices/{invoice_id}GETСписок платежів рахунку/v1/projects/{project_id}/invoices/{invoice_id}/paymentsСпособи оплати
GETСписок платіжних активів проєкту/v1/projects/{project_id}/payment-assetsPUTОновити політику активів проєкту/v1/projects/{project_id}/payment-assets/{asset_id}GETПереглянути токени-кандидати для оплати/v1/projects/{project_id}/payment-token-candidatesPOSTПеревірити й зареєструвати токен/v1/projects/{project_id}/payment-token-assetsGETЗнайти DEX-пули власного токена/v1/projects/{project_id}/payment-token-dex-poolsPOSTДодати власний токен або змінити його ціну/v1/projects/{project_id}/payment-token-assets/customGETСписок способів оплати магазину/v1/projects/{project_id}/stores/{store_id}/payment-assetsPUTЗамінити способи оплати магазину/v1/projects/{project_id}/stores/{store_id}/payment-assetsPUTЗадати політику підтверджень магазину/v1/projects/{project_id}/stores/{store_id}/payment-assets/{asset_id}/confirmation-policyГаманці
GETСписок гаманців і балансів проєкту/v1/projects/{project_id}/walletsЗвіряння
GETСписок платіжних винятків/v1/projects/{project_id}/reconciliationGETПереглянути докази для звіряння/v1/projects/{project_id}/reconciliation/{invoice_id}API Marketplace
GETМожливості/v1/marketplace/capabilitiesGETЗвіт Marketplace/v1/marketplace/overviewGETНалаштування проєкту/v1/marketplace/settingsPOSTЗберегти налаштування проєкту/v1/marketplace/settingsGETСписок продавців/v1/marketplace/vendorsPOSTСтворити продавця/v1/marketplace/vendorsGETОтримати продавця/v1/marketplace/vendors/{vendor_id}POSTОновити продавця/v1/marketplace/vendors/{vendor_id}/updatePOSTАрхівувати продавця/v1/marketplace/vendors/{vendor_id}/archiveGETАдреси призначення продавця/v1/marketplace/vendors/{vendor_id}/destinationsPOSTДодати адресу для виплат/v1/marketplace/vendors/{vendor_id}/destinationsPOSTСхвалити адресу призначення/v1/marketplace/vendors/{vendor_id}/destinations/{destination_id}/approvePOSTВимкнути адресу призначення/v1/marketplace/vendors/{vendor_id}/destinations/{destination_id}/disableGETБаланси продавця/v1/marketplace/vendors/{vendor_id}/balancesGETРахунки Marketplace/v1/marketplace/invoicesPOSTСтворити рахунок для кількох продавців/v1/marketplace/invoicesGETРахунок і розподілені частки/v1/marketplace/invoices/{invoice_id}GETДокази оплати рахунку/v1/marketplace/invoices/{invoice_id}/paymentsGETРозподілені частки рахунку/v1/marketplace/invoices/{invoice_id}/allocationsPOSTСкасувати неоплачений рахунок/v1/marketplace/invoices/{invoice_id}/cancelPOSTЗаблокувати розподілені частки/v1/marketplace/invoices/{invoice_id}/allocations/holdPOSTПеревірити й розблокувати частки/v1/marketplace/invoices/{invoice_id}/allocations/releasePOSTЗмінити адресу для ще не виплачених коштів/v1/marketplace/invoices/{invoice_id}/allocations/{allocation_id}/destinationPOSTПідготувати повне повернення/v1/marketplace/invoices/{invoice_id}/refundGETЗнайти частки для виплати/v1/marketplace/allocationsGETБаланси облікової книги проєкту/v1/marketplace/balancesGETНезмінний журнал/v1/marketplace/ledgerGETІсторія виплат/v1/marketplace/payoutsPOSTПереглянути план розподілу/v1/marketplace/payouts/previewPOSTПідготувати виплату/v1/marketplace/payoutsGETДеталі виплати/v1/marketplace/payouts/{payout_id}POSTСхвалити й надіслати/v1/marketplace/payouts/{payout_id}/approvePOSTПеревірити й відновити виплату/v1/marketplace/payouts/{payout_id}/resumePOSTСкасувати непідписану роботу/v1/marketplace/payouts/{payout_id}/cancelGETПолітики автоматичних виплат/v1/marketplace/policiesPOSTДозволити політику виплат/v1/marketplace/policiesGETВебхуки Marketplace/v1/marketplace/webhooksPOSTСтворити вебхук Marketplace/v1/marketplace/webhooksPOSTОновити вебхук Marketplace/v1/marketplace/webhooks/{webhook_id}/updatePOSTВимкнути вебхук Marketplace/v1/marketplace/webhooks/{webhook_id}/disableGETПодії Marketplace/v1/marketplace/eventsGETПрочитати збережену подію/v1/marketplace/events/{event_id}GETІсторія доставлення Marketplace/v1/marketplace/webhook-deliveriesGETДеталі доставлення/v1/marketplace/webhook-deliveries/{delivery_id}POSTПовторно доставити ту саму подію/v1/marketplace/webhook-deliveries/{delivery_id}/resendAPI оператора
GETМожливості/v1/operator/capabilitiesGETСтан сервісу/v1/operator/healthGETСписок мерчантів/v1/operator/merchantsPOSTСтворити мерчанта/v1/operator/merchantsGETОтримати мерчанта/v1/operator/merchants/{merchant_id}POSTОновити мерчанта/v1/operator/merchants/{merchant_id}GETСписок користувачів/v1/operator/merchants/{merchant_id}/usersPOSTСтворити користувача/v1/operator/merchants/{merchant_id}/usersGETОтримати користувача/v1/operator/merchants/{merchant_id}/users/{user_id}POSTОновити користувача/v1/operator/merchants/{merchant_id}/users/{user_id}POSTЗадати пароль користувача/v1/operator/merchants/{merchant_id}/users/{user_id}/passwordPOSTВідкликати сеанси користувача/v1/operator/merchants/{merchant_id}/users/{user_id}/revoke-sessionsGETСписок запрошень/v1/operator/merchants/{merchant_id}/invitationsPOSTСтворити запрошення/v1/operator/merchants/{merchant_id}/invitationsGETОтримати запрошення/v1/operator/invitations/{invitation_id}POSTПовторно надіслати запрошення/v1/operator/invitations/{invitation_id}/resendPOSTВідкликати запрошення/v1/operator/invitations/{invitation_id}/revokeGETОтримати передплачений баланс/v1/operator/merchants/{merchant_id}/creditsGETСписок записів балансу/v1/operator/merchants/{merchant_id}/credits/ledgerPOSTСкоригувати передплачений баланс/v1/operator/merchants/{merchant_id}/credits/adjustmentsGETСписок поповнень/v1/operator/merchants/{merchant_id}/topupsPOSTСтворити поповнення/v1/operator/merchants/{merchant_id}/topupsGETОтримати поповнення/v1/operator/merchants/{merchant_id}/topups/{topup_id}GETЗвіти/v1/operator/reportsGETСписок записів аудиту/v1/operator/auditGETСписок подій/v1/operator/eventsGETСписок вебхуків/v1/operator/webhooksPOSTСтворити вебхук/v1/operator/webhooksPOSTОновити вебхук/v1/operator/webhooks/{webhook_id}POSTЗамінити секрет вебхука/v1/operator/webhooks/{webhook_id}/rotateGETСписок доставлень вебхуків/v1/operator/webhooks/{webhook_id}/deliveriesGETСписок проєктів/v1/operator/merchants/{merchant_id}/projectsPOSTСтворити проєкт/v1/operator/merchants/{merchant_id}/projectsGETОтримати проєкт/v1/operator/merchants/{merchant_id}/projects/{project_id}POSTОновити проєкт/v1/operator/merchants/{merchant_id}/projects/{project_id}GETСписок магазинів/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesPOSTСтворити магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesGETОтримати магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}POSTОновити магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}GETОтримати оформлення магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearancePOSTОновити оформлення магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearanceGETСписок платіжних активів магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsPOSTОновити платіжні активи магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsGETСписок вебхуків магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksPOSTСтворити вебхук магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksPOSTОновити вебхук магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks/{webhook_id}GETСписок рахунків/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoicesGETОтримати рахунок/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoices/{invoice_id}GETСписок гаманців/v1/operator/merchants/{merchant_id}/projects/{project_id}/walletsGETСписок адрес гаманця/v1/operator/merchants/{merchant_id}/projects/{project_id}/wallets/{wallet_id}/addressesGETСписок облікових даних мерчанта/v1/operator/merchants/{merchant_id}/api-credentialsPOSTСтворити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentialsPOSTОновити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}POSTЗамінити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/rotatePOSTВідкликати облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/revokePOSTПеревірити токен запрошення/v1/onboarding/invitations/checkPOSTПрийняти запрошення або скидання пароля/v1/onboarding/invitations/acceptОплата
GETОболонка сторінки оплати/GETРозміщена сторінка оплати/invoice/{invoice_id}GETБезпечні для сторінки оплати дані рахунку/checkout-api/invoices/{invoice_id}GETПерегляд сторінки оплати магазину/invoice/preview/{project_id}GETДані попереднього перегляду оплати/checkout-api/previews/{project_id}GETЗображення сторінки оплати магазину/checkout-api/invoices/{invoice_id}/appearance-images/{kind}/{revision}/image.pngGETЗображення попереднього перегляду магазину/checkout-api/previews/{project_id}/stores/{store_id}/appearance-images/{kind}/{revision}/image.pngGETЛоготип попереднього перегляду з версією/checkout-api/previews/{project_id}/logo/{revision}/image.pngGETЗображення QR-коду оплати/checkout-api/invoices/{invoice_id}/payment-methods/{intent_id}/qr.svgGETЛоготип сторінки оплати з версією/checkout-api/invoices/{invoice_id}/logo/{revision}/image.pngСервіс
GETВиявлення сервісу API/GETСтан сервісу/healthzGETМожливості/v1/operator/capabilitiesЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/capabilities" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/capabilities", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/capabilities");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/capabilities",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"api_version": "v1",
"operator_version": "7.4.0",
"scopes": [
"health.read"
],
"all_merchants": false,
"merchant_ids": [
"11111111-1111-4111-8111-111111111111"
],
"onboarding": [
"direct",
"invitation"
],
"write_methods": [
"POST"
],
"idempotency_required": true
}Поля відповіді
Примітки до використання
- Потребує health.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСтан сервісу/v1/operator/healthЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/health" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/health", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/health");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/health",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"version": "7.4.0",
"nodes": []
}Поля відповіді
Примітки до використання
- Потребує health.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок мерчантів/v1/operator/merchantsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує merchants.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити мерчанта/v1/operator/merchantsЧитання + запис
Атомарно створи хостованого мерчанта й першого адміністратора: прямо з паролем або через запрошення.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Example shop",
"email": "admin@example.test",
"onboarding": "direct",
"password": "REPLACE_WITH_A_UNIQUE_TEMPORARY_PASSWORD",
"require_password_change": true,
"currency": "EUR",
"starting_credit": "0",
"external_id": "customer-1042"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
onboardingdirect | invitationобов'язковоdirect потребує password, не надсилає email-запрошення. invitation пропускає password.
passwordstring · direct only12–128 символів (до 512 байтів UTF-8); ніколи не повертається й не надсилається поштою. Для тимчасових паролів використовуй require_password_change.
require_password_changebooleanнеобов'язковоПотребує нового пароля при першому вході. Кожен прямо створений акаунт має підтвердити доступ хоста до гаманця.
currencyfiat codeнеобов'язковоВалюта передплаченого акаунта; типово регіональна валюта, після створення не змінюється.
fee_bpsintegerнеобов'язково0–10000; 100 означає 1%. Якщо пропущено, бере типове значення оператора. Потребує fees.write.
starting_creditdecimal stringнеобов'язковоТочне одноразове локальне нарахування. Ненульове потребує credits.write. Не поповнює баланс інсталяції оператора.
send_invitation_emailbooleanнеобов'язковоЛише запрошення. Потребує налаштованого SMTP; відповідь відрізняє прийняття поштовим сервером від створення акаунта.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"merchant_id": "11111111-1111-4111-8111-111111111111",
"user_id": "22222222-2222-4222-8222-222222222222",
"merchant": {
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "0"
},
"onboarding": "direct",
"access_link": null,
"email_delivery": {
"status": "not_requested"
},
"custody_acceptance_required": true
}Поля відповіді
Примітки до використання
- Потребує merchants.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Потрібен доступ до всіх мерчантів. Явні перевизначення комісій також потребують fees.write; ненульовий starting_credit - credits.write. Початок через запрошення також потребує invitations.write. Без автоматичного входу, обходу Basic Auth чи повторного нарахування при ритраї.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати мерчанта/v1/operator/merchants/{merchant_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false,
"external_id": "customer-1042"
}Поля відповіді
Примітки до використання
- Потребує merchants.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити мерчанта/v1/operator/merchants/{merchant_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"payments_paused": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"payments_paused": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"payments_paused": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"payments_paused": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
namefieldsнеобов'язковоВимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.Деталі
Вимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.
enabledfieldsнеобов'язковоВимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.Деталі
Вимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.
payments_pausedfieldsнеобов'язковоВимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.Деталі
Вимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.
fee_bpsfieldsнеобов'язковоВимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.Деталі
Вимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.
external_idfieldsнеобов'язковоВимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.Деталі
Вимкнення відкликає сеанси. payments_paused блокує нові рахунки, а не сканування наявних платежів. Зміни комісій потребують fees.write та діють на майбутні рахунки; валюту акаунта змінити не можна.
Відповідь 200 application/json
Приклад відповіді
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false
}Поля відповіді
Примітки до використання
- Потребує merchants.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок користувачів/v1/operator/merchants/{merchant_id}/usersЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує users.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити користувача/v1/operator/merchants/{merchant_id}/usersЧитання + запис
Додай адміністратора мерчанта або користувача, обмеженого вибраними проєктами.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"email": "staff@example.test",
"display_name": "Store team",
"onboarding": "invitation",
"access_level": "projects",
"project_ids": [
"11111111-1111-4111-8111-111111111111"
],
"send_invitation_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
require_password_changesame as merchant creationСтворення запрошення додатково потребує invitations.write.
send_invitation_emailsame as merchant creationСтворення запрошення додатково потребує invitations.write.
access_leveladmin | projectsнеобов'язковоadmin - адміністратор лише цього мерчанта, ніколи не інсталяції/оператора.
project_ids[]UUID[]Лише проєкти цього мерчанта. Обов'язковий вибір для обмеженого проєктами доступу; ніколи не між клієнтами.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"user": {
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
},
"user_id": "22222222-2222-4222-8222-222222222222",
"access_link": null,
"email_delivery": {
"status": "not_requested"
},
"merchant_id": "11111111-1111-4111-8111-111111111111"
}Поля відповіді
userobject
user_idstringaccess_linkJSON | nullmerchant_idstringПримітки до використання
- Потребує users.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати користувача/v1/operator/merchants/{merchant_id}/users/{user_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
}Поля відповіді
Примітки до використання
- Потребує users.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити користувача/v1/operator/merchants/{merchant_id}/users/{user_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"display_name": "Store manager"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"display_name": "Store manager"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"display_name": "Store manager"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"display_name": "Store manager"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
emailfieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
display_namefieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
enabledfieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
access_levelfieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
project_idsfieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
default_timezonefieldsнеобов'язковоОновлює надані поля; захист останнього адміністратора залишається. Для паролів окрема операція users.security.
Відповідь 200 application/json
Приклад відповіді
{
"id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"email": "admin@example.test",
"display_name": "Shop administrator",
"access_level": "admin",
"project_ids": [],
"enabled": true,
"password_setup_required": false,
"custody_acceptance_required": true,
"password_change_required": true
}Поля відповіді
Примітки до використання
- Потребує users.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTЗадати пароль користувача/v1/operator/merchants/{merchant_id}/users/{user_id}/passwordЧитання + запис
Задай пароль хостованого акаунта й відклич сеанси. Наявний TOTP зберігається.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"password": "REPLACE_WITH_A_NEW_UNIQUE_PASSWORD",
"require_password_change": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/password",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"user_id": "11111111-1111-4111-8111-111111111111",
"sessions_revoked": true,
"totp_preserved": true
}Поля відповіді
Примітки до використання
- Потребує users.security; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTВідкликати сеанси користувача/v1/operator/merchants/{merchant_id}/users/{user_id}/revoke-sessionsЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/users/YOUR_USER_ID/revoke-sessions",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"user_id": "11111111-1111-4111-8111-111111111111",
"sessions_revoked": true,
"totp_preserved": true
}Поля відповіді
Примітки до використання
- Потребує users.security; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок запрошень/v1/operator/merchants/{merchant_id}/invitationsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує invitations.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити запрошення/v1/operator/merchants/{merchant_id}/invitationsЧитання + запис
Створи або заміни одноразове запрошення чи посилання скидання пароля.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"user_id": "11111111-1111-4111-8111-111111111111",
"send_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/invitations",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
user_idUUID, booleanВидай/заміни одноразове посилання для наявного акаунта. Активовані користувачі отримують посилання скидання на одну годину й потребують users.security.
send_emailUUID, booleanВидай/заміни одноразове посилання для наявного акаунта. Активовані користувачі отримують посилання скидання на одну годину й потребують users.security.
new user fieldsalternative to user_idДля створення запрошеного користувача використовуй email, display_name, access_level і project_ids; потрібен users.write.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"user_id": "22222222-2222-4222-8222-222222222222",
"email": "admin@example.test",
"kind": "invitation",
"expires_at": "2026-10-03T12:00:00Z",
"url": "https://merchant.example.com/account-access.html#token=YOUR_PRIVATE_INVITATION_TOKEN"
}Поля відповіді
Примітки до використання
- Потребує invitations.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати запрошення/v1/operator/invitations/{invitation_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
invitation_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"user_id": "22222222-2222-4222-8222-222222222222",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"kind": "invitation",
"status": "pending",
"created_at": "2026-10-01T12:00:00Z",
"expires_at": "2026-10-03T12:00:00Z"
}Поля відповіді
Примітки до використання
- Потребує invitations.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTПовторно надіслати запрошення/v1/operator/invitations/{invitation_id}/resendЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
invitation_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"send_email": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"send_email": false
}`;
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"send_email": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"send_email": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/resend",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
send_emailbooleanнеобов'язковоЗамінює попередній токен, ніколи не додає кошти. Повертає нове посилання один раз. Уже активований акаунт потребує users.security.
Відповідь 200 application/json
Приклад відповіді
{
"user_id": "22222222-2222-4222-8222-222222222222",
"email": "admin@example.test",
"kind": "invitation",
"expires_at": "2026-10-03T12:00:00Z",
"url": "https://merchant.example.com/account-access.html#token=YOUR_PRIVATE_INVITATION_TOKEN"
}Поля відповіді
Примітки до використання
- Потребує invitations.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTВідкликати запрошення/v1/operator/invitations/{invitation_id}/revokeЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
invitation_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/invitations/YOUR_INVITATION_ID/revoke",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"revoked": true,
"invitation_id": "44444444-4444-4444-8444-444444444444"
}Поля відповіді
Примітки до використання
- Потребує invitations.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати передплачений баланс/v1/operator/merchants/{merchant_id}/creditsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Example shop",
"currency": "EUR",
"balance": "10",
"fee_bps": 300,
"enabled": true,
"payments_paused": false,
"external_id": "customer-1042"
}Поля відповіді
Примітки до використання
- Потребує credits.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок записів балансу/v1/operator/merchants/{merchant_id}/credits/ledgerЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
qнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/ledger",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує credits.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСкоригувати передплачений баланс/v1/operator/merchants/{merchant_id}/credits/adjustmentsЧитання + запис
Додай обґрунтоване нарахування або коригування до передплаченого обліку цього мерчанта.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "10.00",
"note": "Promotional credit",
"request_id": "11111111-1111-4111-8111-111111111111"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/credits/adjustments",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
amountsigned decimal stringобов'язковоДодатне нарахування чи від'ємне коригування, до шести десяткових знаків у валюті балансу мерчанта. Це не переказ у блокчейні.
Відповідь 200 application/json
Приклад відповіді
{
"balance": "25"
}Поля відповіді
balancestringПримітки до використання
- Потребує credits.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок поповнень/v1/operator/merchants/{merchant_id}/topupsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує topups.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити поповнення/v1/operator/merchants/{merchant_id}/topupsЧитання + запис
Створи сторінку оплати поповнення балансу; ніколи не позначай її оплаченою вручну.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "25.00",
"request_id": "11111111-1111-4111-8111-111111111111"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 201 or 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"invoice_id": "33333333-3333-4333-8333-333333333333",
"checkout_url": "https://pay.example.com/invoice/33333333-3333-4333-8333-333333333333"
}Поля відповіді
Примітки до використання
- Потребує topups.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати поповнення/v1/operator/merchants/{merchant_id}/topups/{topup_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/topups/YOUR_TOPUP_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"merchant_id": "11111111-1111-4111-8111-111111111111",
"invoice_id": "33333333-3333-4333-8333-333333333333",
"amount": "25",
"currency": "EUR",
"status": "pending",
"invoice_status": "new",
"checkout_url": "https://pay.example.com/invoice/33333333-3333-4333-8333-333333333333"
}Поля відповіді
Примітки до використання
- Потребує topups.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETЗвіти/v1/operator/reportsЛише читання
Прочитай фінансовий огляд оператора. Потребує доступу до всіх хостованих мерчантів.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри запиту
periodнеобов'язковоФінансові фільтри. period типово last30; використовуй custom із start/end у YYYY-MM-DD. Лише облікові дані з доступом до всіх мерчантів.
startнеобов'язковоФінансові фільтри. period типово last30; використовуй custom із start/end у YYYY-MM-DD. Лише облікові дані з доступом до всіх мерчантів.
endнеобов'язковоФінансові фільтри. period типово last30; використовуй custom із start/end у YYYY-MM-DD. Лише облікові дані з доступом до всіх мерчантів.
currencyнеобов'язковоФінансові фільтри. period типово last30; використовуй custom із start/end у YYYY-MM-DD. Лише облікові дані з доступом до всіх мерчантів.
merchant_idнеобов'язковоФінансові фільтри. period типово last30; використовуй custom із start/end у YYYY-MM-DD. Лише облікові дані з доступом до всіх мерчантів.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/reports" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/reports", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/reports");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/reports",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"summary": {
"fees": "10",
"costs": "3",
"margin": "7",
"credits": "25",
"pending": 0,
"missing_rates": 0
},
"merchants": [],
"filters": {
"period": "last30",
"currency": "EUR",
"timezone": "UTC"
},
"basis": "first_settlement_latest_net_fees"
}Поля відповіді
Примітки до використання
- Потребує reports.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Рядки, витрати й кількості власного бізнесу виключаються до підрахунку підсумків. Фільтр merchant_id власного бізнесу повертає 404. Звіти використовують часовий пояс інсталяції.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок записів аудиту/v1/operator/auditЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри запиту
merchant_idнеобов'язковоФільтруй дозволеного мерчанта, точний тип події (events) або текст дії (audit). Події зберігаються 30 днів.
searchнеобов'язковоФільтруй дозволеного мерчанта, точний тип події (events) або текст дії (audit). Події зберігаються 30 днів.
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/audit" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/audit", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/audit");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/audit",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує audit.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок подій/v1/operator/eventsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри запиту
merchant_idнеобов'язковоФільтруй дозволеного мерчанта, точний тип події (events) або текст дії (audit). Події зберігаються 30 днів.
event_typeнеобов'язковоФільтруй дозволеного мерчанта, точний тип події (events) або текст дії (audit). Події зберігаються 30 днів.
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/events" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/events", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/events");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/events",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок вебхуків/v1/operator/webhooksЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/webhooks",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити вебхук/v1/operator/webhooksЧитання + запис
Підпишись на майбутні події життєвого циклу оператора. Це не платіжний вебхук магазину.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"url": "https://shop.example.test/operator-events",
"events": [
"merchant.created",
"topup.settled"
],
"merchant_ids": [],
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
urlpublic HTTPS URLобов'язковоБез облікових даних, приватних IP або перенаправлень. DNS/IP знову перевіряються при доставленні.
events[]string[]обов'язковоВибирай події життєвого циклу з посібника оператора, а не колбеки рахунків.
merchant_ids[]UUID[]необов'язковоПорожній список означає всіх мерчантів, дозволених цими обліковими даними. Поточні обмеження області доступу перевіряються повторно.
enabledbooleanнеобов'язковоПризупинені ендпоїнти зберігають чергу; повторне ввімкнення відновлює придатну збережену роботу.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"id": "11111111-1111-4111-8111-111111111111",
"signing_secret": "wco_whsec_EXAMPLE_ONLY_SAVE_ONCE"
}Поля відповіді
Примітки до використання
- Потребує webhooks.write + events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити вебхук/v1/operator/webhooks/{webhook_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
webhook_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"url": "https://shop.example.test/operator-events",
"events": [
"topup.settled"
],
"merchant_ids": [],
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
urlpublic HTTPS URLобов'язковоБез облікових даних, приватних IP або перенаправлень. DNS/IP знову перевіряються при доставленні.
events[]string[]обов'язковоВибирай події життєвого циклу з посібника оператора, а не колбеки рахунків.
merchant_ids[]UUID[]необов'язковоПорожній список означає всіх мерчантів, дозволених цими обліковими даними. Поточні обмеження області доступу перевіряються повторно.
enabledbooleanнеобов'язковоПризупинені ендпоїнти зберігають чергу; повторне ввімкнення відновлює придатну збережену роботу.
Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"signing_secret": null
}Поля відповіді
Примітки до використання
- Потребує webhooks.write + events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTЗамінити секрет вебхука/v1/operator/webhooks/{webhook_id}/rotateЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
webhook_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/rotate",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "11111111-1111-4111-8111-111111111111",
"signing_secret": "wco_whsec_EXAMPLE_ONLY_SAVE_ONCE"
}Поля відповіді
Примітки до використання
- Потребує webhooks.write + events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок доставлень вебхуків/v1/operator/webhooks/{webhook_id}/deliveriesЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
webhook_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/webhooks/YOUR_WEBHOOK_ID/deliveries",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує events.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок проєктів/v1/operator/merchants/{merchant_id}/projectsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити проєкт/v1/operator/merchants/{merchant_id}/projectsЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Online shop",
"slug": "online-shop",
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
namestringsобов'язковоНазва й унікальний стабільний ідентифікатор проєкту. Створює локальні гаманці через наявну ініціалізацію проєкту, ніколи не переказує кошти.
slugstringsобов'язковоНазва й унікальний стабільний ідентифікатор проєкту. Створює локальні гаманці через наявну ініціалізацію проєкту, ніколи не переказує кошти.
enabledнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
reporting_timezoneнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
checkout_titleнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
checkout_descriptionнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
checkout_themeнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
checkout_accent_colorнеобов'язковоenabled типово true; рекомендовано створити призупиненим і спочатку налаштувати магазин.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати проєкт/v1/operator/merchants/{merchant_id}/projects/{project_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити проєкт/v1/operator/merchants/{merchant_id}/projects/{project_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
reporting_currencyнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
reporting_timezoneнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
checkout_titleнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
checkout_descriptionнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
checkout_themeнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
checkout_accent_colorнеобов'язковоЧасткове оновлення. Ідентифікатор і належність мерчанту змінити не можна.
Відповідь 200 application/json
Приклад відповіді
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "example-shop",
"name": "Example shop",
"enabled": false,
"reporting_currency": "EUR",
"reporting_timezone": "Europe/Berlin",
"stores": []
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок магазинів/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/storesЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Web checkout",
"slug": "web-checkout",
"default_currency": "EUR",
"enabled": false
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
default_currencyнеобов'язковоДля відсотків використовуй десяткові рядки. Нові магазини успадковують оформлення магазину за замовчуванням проєкту.
invoice_expiry_minutesнеобов'язковоДля відсотків використовуй десяткові рядки. Нові магазини успадковують оформлення магазину за замовчуванням проєкту.
exchange_rate_spread_percentнеобов'язковоДля відсотків використовуй десяткові рядки. Нові магазини успадковують оформлення магазину за замовчуванням проєкту.
underpayment_tolerance_percentнеобов'язковоДля відсотків використовуй десяткові рядки. Нові магазини успадковують оформлення магазину за замовчуванням проєкту.
enabledнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
is_defaultнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
allow_zero_amount_invoicesнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
allow_underpaymentsнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
allow_overpaymentsнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
allowed_chain_slugsнеобов'язковоНалаштуй прийняті активи через payment-assets; рахунки з нульовою сумою типово вимкнені.
ipn_enabledнеобов'язковоIPN і URL повернення проходять наявну перевірку URL. Без довільного HTML/JavaScript.
default_ipn_urlнеобов'язковоIPN і URL повернення проходять наявну перевірку URL. Без довільного HTML/JavaScript.
default_redirect_urlнеобов'язковоIPN і URL повернення проходять наявну перевірку URL. Без довільного HTML/JavaScript.
default_cancel_urlнеобов'язковоIPN і URL повернення проходять наявну перевірку URL. Без довільного HTML/JavaScript.
redirect_automaticallyнеобов'язковоIPN і URL повернення проходять наявну перевірку URL. Без довільного HTML/JavaScript.
checkout_languageнеобов'язковоВикористовуй підтримувану мову й активні домени ролей; явно задавай origin для вбудовування.
embed_enabledнеобов'язковоВикористовуй підтримувану мову й активні домени ролей; явно задавай origin для вбудовування.
allowed_embed_originsнеобов'язковоВикористовуй підтримувану мову й активні домени ролей; явно задавай origin для вбудовування.
domainsнеобов'язковоВикористовуй підтримувану мову й активні домени ролей; явно задавай origin для вбудовування.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити магазин/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"slug": "online",
"name": "Online shop",
"enabled": false,
"default_currency": "EUR",
"invoice_expiry_minutes": 60
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати оформлення магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearanceЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"revision": 1,
"settings": {
"inherit_default_store": true
},
"effective": {
"title": "Pay securely"
}
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити оформлення магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/checkout-appearanceЧитання + запис
Збережи перевірене оформлення магазину із захистом ревізією.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"revision": 1,
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
}
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/checkout-appearance",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
revisionintegerобов'язковоСпочатку прочитай поточну ревізію через GET. Застаріла ревізія дасть помилку без перезапису змін іншого редактора.
settingsobjectобов'язково
Перевірене оформлення оплати, включно з inherit_default_store, брендингом, вступом/завершенням, розмірами шрифтів і видимістю. Без довільного HTML/JavaScript. Завантаження байтів зображень - лише через панель.Деталі
Перевірене оформлення оплати, включно з inherit_default_store, брендингом, вступом/завершенням, розмірами шрифтів і видимістю. Без довільного HTML/JavaScript. Завантаження байтів зображень - лише через панель.
Відповідь 200 application/json
Приклад відповіді
{
"settings": {
"inherit_default_store": false,
"title": "Pay securely",
"theme": "light"
},
"revision": 2
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок платіжних активів магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": []
}Поля відповіді
data[]arrayПримітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити платіжні активи магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/payment-assetsЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"assets": [
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"display_order": 0
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
assets[]object[]обов'язково
Повна заміна on-chain способів: UUID asset_id і display_order. [] очищує прийняті on-chain активи. Лише перевірені активи проєкту; Lightning не налаштовує.Деталі
Повна заміна on-chain способів: UUID asset_id і display_order. [] очищує прийняті on-chain активи. Лише перевірені активи проєкту; Lightning не налаштовує.
Відповідь 200 application/json
Приклад відповіді
{
"data": []
}Поля відповіді
data[]arrayПримітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок вебхуків магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує projects.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити вебхук магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooksЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": true,
"automatic_redelivery": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
namestrings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
urlstrings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
event_types[]strings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
enabledbooleansнеобов'язковоСтворення повертає секрет підпису один раз. Це платіжні колбеки магазину, а не події життєвого циклу оператора.
automatic_redeliverybooleansнеобов'язковоСтворення повертає секрет підпису один раз. Це платіжні колбеки магазину, а не події життєвого циклу оператора.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"signing_secret": "EXAMPLE_ONLY_SAVE_ONCE",
"endpoint": {
"id": "44444444-4444-4444-8444-444444444444",
"name": "Orders",
"enabled": true
},
"secret_visible_once": true
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити вебхук магазину/v1/operator/merchants/{merchant_id}/projects/{project_id}/stores/{store_id}/webhooks/{webhook_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
store_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
webhook_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Orders",
"url": "https://shop.example.test/payments",
"event_types": [
"invoice.settled"
],
"enabled": false,
"automatic_redelivery": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/webhooks/YOUR_WEBHOOK_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
namestrings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
urlstrings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
event_types[]strings / arrayобов'язковоПублічний HTTPS-приймач і назви подій рахунків із документації IPN та вебхуків.
enabledbooleansнеобов'язковоСтворення повертає секрет підпису один раз. Це платіжні колбеки магазину, а не події життєвого циклу оператора.
automatic_redeliverybooleansнеобов'язковоСтворення повертає секрет підпису один раз. Це платіжні колбеки магазину, а не події життєвого циклу оператора.
Відповідь 200 application/json
Приклад відповіді
{
"id": "44444444-4444-4444-8444-444444444444",
"name": "Orders",
"enabled": true
}Поля відповіді
Примітки до використання
- Потребує projects.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок рахунків/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoicesЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Параметри запиту
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"limit": 25,
"offset": 0,
"total": 0,
"has_more": false
}
}Поля відповіді
Примітки до використання
- Потребує reports.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETОтримати рахунок/v1/operator/merchants/{merchant_id}/projects/{project_id}/invoices/{invoice_id}Лише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
invoice_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/invoices/YOUR_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"invoice_id": "44444444-4444-4444-8444-444444444444",
"project_id": "33333333-3333-4333-8333-333333333333",
"amount": "25",
"currency": "EUR",
"status": "new",
"metadata": {},
"payment_intents": []
}Поля відповіді
Примітки до використання
- Потребує reports.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
- invoice_id - публічний ID рахунку зі створення й колбеків, не внутрішній id.
Помилки
GETСписок гаманців/v1/operator/merchants/{merchant_id}/projects/{project_id}/walletsЛише читання
Читай кешовані публічні баланси гаманців, ніколи приватні ключі чи фрази відновлення.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує reports.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Баланси - кешовані спостереження з полями свіжості, не гарантія доступної до витрачання суми. Надсилання й експорт ключів через цей API недоступні.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок адрес гаманця/v1/operator/merchants/{merchant_id}/projects/{project_id}/wallets/{wallet_id}/addressesЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
project_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
wallet_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
limitнеобов'язковоЛіміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.Деталі
Ліміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.
beforeнеобов'язковоЛіміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.Деталі
Ліміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.
searchнеобов'язковоЛіміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.Деталі
Ліміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.
has_balanceнеобов'язковоЛіміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.Деталі
Ліміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.
hide_small_balancesнеобов'язковоЛіміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.Деталі
Ліміт 1–50, типово 25. Для наступної сторінки передай next_cursor як before. Для сторінки 1 пропусти before. has_balance=false і hide_small_balances=false включають порожні/малі баланси.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/projects/YOUR_PROJECT_ID/wallets/YOUR_WALLET_ID/addresses",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"wallet": {
"id": "22222222-2222-4222-8222-222222222222",
"chain_slug": "ethereum"
},
"items": [],
"total": 0,
"total_pages": 1,
"next_cursor": null,
"reporting_currency": "EUR",
"has_balance": true,
"hide_small_balances": true,
"small_balance_threshold": {
"amount": "0.20",
"currency": "EUR"
}
}Поля відповіді
Примітки до використання
- Потребує reports.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETСписок облікових даних мерчанта/v1/operator/merchants/{merchant_id}/api-credentialsЛише читання
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Параметри запиту
pageнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
searchнеобов'язковоСторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.Деталі
Сторінки з 1, по 25 записів. Пошук є для мерчантів, користувачів, проєктів, магазинів, гаманців, облікових даних і вебхуків; списки нативних подій мають власні фільтри.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"page": 1,
"page_size": 25,
"total": 0
}Поля відповіді
Примітки до використання
- Потребує merchant_credentials.read; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTСтворити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentialsЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
merchant_idUUIDобов'язковоКанонічний UUID ресурсу малими літерами; має належати області мерчантів облікових даних.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Store integration",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"11111111-1111-4111-8111-111111111111"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
access_levelread_only | read_writeнеобов'язковоЧитання/запис дозволяє наявний контракт API мерчанта.
project_ids[]UUID[]Лише проєкти вибраного мерчанта; порожній список дотримується наявної політики всіх проєктів мерчанта.
enabledнеобов'язковоНаявні засоби керування ключем мерчанта. Секрет повертається лише раз; потрібен merchant_credentials.write.
ip_restriction_enabledнеобов'язковоНаявні засоби керування ключем мерчанта. Секрет повертається лише раз; потрібен merchant_credentials.write.
allowed_ips[]необов'язковоНаявні засоби керування ключем мерчанта. Секрет повертається лише раз; потрібен merchant_credentials.write.
requests_per_minuteнеобов'язковоНаявні засоби керування ключем мерчанта. Секрет повертається лише раз; потрібен merchant_credentials.write.
Відповідь 201 or 200 application/json
Приклад відповіді
{
"credential": {
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
},
"token": "wc_live_EXAMPLE_ONLY_SAVE_ONCE"
}Поля відповіді
Примітки до використання
- Потребує merchant_credentials.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTОновити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}Читання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"name": "Checkout",
"access_level": "read_only",
"enabled": true,
"ip_restriction_enabled": false,
"allowed_ips": [],
"project_ids": [
"33333333-3333-4333-8333-333333333333"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
namefieldsобов'язковоНадішли повну поточну конфігурацію облікових даних зі змінами. project_ids типово []; requests_per_minute типово дорівнює квоті API мерчанта.
access_levelfieldsобов'язковоНадішли повну поточну конфігурацію облікових даних зі змінами. project_ids типово []; requests_per_minute типово дорівнює квоті API мерчанта.
enabledfieldsобов'язковоНадішли повну поточну конфігурацію облікових даних зі змінами. project_ids типово []; requests_per_minute типово дорівнює квоті API мерчанта.
ip_restriction_enabledfieldsобов'язковоНадішли повну поточну конфігурацію облікових даних зі змінами. project_ids типово []; requests_per_minute типово дорівнює квоті API мерчанта.
allowed_ips[]fieldsобов'язковоНадішли повну поточну конфігурацію облікових даних зі змінами. project_ids типово []; requests_per_minute типово дорівнює квоті API мерчанта.
project_ids[]arrayВідповідь 200 application/json
Приклад відповіді
{
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
}Поля відповіді
Примітки до використання
- Потребує merchant_credentials.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTЗамінити облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/rotateЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/rotate",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"credential": {
"id": "22222222-2222-4222-8222-222222222222",
"name": "Checkout",
"access_level": "read_only",
"project_ids": [
"33333333-3333-4333-8333-333333333333"
],
"enabled": true
},
"token": "wc_live_EXAMPLE_ONLY_SAVE_ONCE"
}Поля відповіді
Примітки до використання
- Потребує merchant_credentials.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTВідкликати облікові дані мерчанта/v1/operator/merchants/{merchant_id}/api-credentials/{credential_id}/revokeЧитання + запис
Керуй указаним ресурсом хостованого мерчанта чи переглядай його окремими обліковими даними оператора.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_OPERATOR_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережений для цієї операції |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: operator-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{}`;
const response = await fetch("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{}
JSON;
$ch = curl_init("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: operator-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "operator-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{}""".encode("utf-8")
request = Request("https://api.example.com/v1/operator/merchants/YOUR_MERCHANT_ID/api-credentials/YOUR_CREDENTIAL_ID/revoke",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"revoked": true
}Поля відповіді
revokedbooleanПримітки до використання
- Потребує merchant_credentials.write; лише дозволені хостовані мерчанти. Ключі оператора не мають доступу до простору власного бізнесу власника.
- Збережи унікальний Idempotency-Key і точне тіло перед надсиланням. Повтори не виконують зафіксовану дію вдруге. Секретні поля пропускаються при повторі; якщо відповідь із секретом втрачено, перевір створений ресурс і явно заміни/перевидай його. 409 operator_request_in_progress може означати перерваний запит із невідомим результатом: перевір ресурс/аудит; не повторюй навмання з новим ключем.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTПеревірити токен запрошення/v1/onboarding/invitations/checkПублічний
Початок роботи лише за токеном. Не приймає ключ оператора й не входить автоматично. Для входу в панель далі потрібні Basic Auth сайту та наявний TOTP.
Автентифікація та заголовки
Публічний
Запит
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/onboarding/invitations/check" \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}'// Node.js 18+ · run on your server, never in browser code.
const body = `{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}`;
const response = await fetch("https://api.example.com/v1/onboarding/invitations/check", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$body = <<<'JSON'
{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}
JSON;
$ch = curl_init("https://api.example.com/v1/onboarding/invitations/check");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
body = """{
"token": "YOUR_PRIVATE_INVITATION_TOKEN"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/onboarding/invitations/check",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"kind": "invitation",
"email": "admin@example.test",
"merchant_name": "Example shop"
}Поля відповіді
Примітки до використання
- Запрошення на 48 годин; скидання пароля на одну годину. Одноразові хешовані токени. Повторна видача відкликає попереднє посилання. Прийняття зберігає TOTP і відкликає старі сеанси.
- Без автоматичних повторів. Якщо прийняття завершилося таймаутом, перевір стан посилання й спробуй увійти; не вважай його невдалим. Частота обмежується за спостереженим IP джерела. Одержувач має сам підтвердити розуміння доступу хоста до коштів.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
POSTПрийняти запрошення або скидання пароля/v1/onboarding/invitations/acceptПублічний
Початок роботи лише за токеном. Не приймає ключ оператора й не входить автоматично. Для входу в панель далі потрібні Basic Auth сайту та наявний TOTP.
Автентифікація та заголовки
Публічний
Запит
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/onboarding/invitations/accept" \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}'// Node.js 18+ · run on your server, never in browser code.
const body = `{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}`;
const response = await fetch("https://api.example.com/v1/onboarding/invitations/accept", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$body = <<<'JSON'
{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/onboarding/invitations/accept");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
body = """{
"token": "YOUR_PRIVATE_INVITATION_TOKEN",
"password": "REPLACE_WITH_YOUR_OWN_UNIQUE_PASSWORD",
"custody_acknowledged": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/onboarding/invitations/accept",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"password_set": true
}Поля відповіді
password_setbooleanПримітки до використання
- Запрошення на 48 годин; скидання пароля на одну годину. Одноразові хешовані токени. Повторна видача відкликає попереднє посилання. Прийняття зберігає TOTP і відкликає старі сеанси.
- Без автоматичних повторів. Якщо прийняття завершилося таймаутом, перевір стан посилання й спробуй увійти; не вважай його невдалим. Частота обмежується за спостереженим IP джерела. Одержувач має сам підтвердити розуміння доступу хоста до коштів.
- Приклади відповідей показують вибрані поля. Сприймай додаткові поля відповіді як сумісні доповнення.
Помилки
GETМожливості/v1/marketplace/capabilitiesЛише читання
Магазини-учасники, налаштовані активи, підтримувані канали виплат, нативний актив комісії та причини готовності. Тимчасова доступність сканера не розширює набір дозволених активів.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/capabilities?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/capabilities?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/capabilities?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/capabilities?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETЗвіт Marketplace/v1/marketplace/overviewЛише читання
Фільтри store_id, asset_id, from і to (включні YYYY-MM-DD, UTC; типово останні 30 днів; до десяти років). Точні баланси на кінцеву дату й зміни за період. Без орієнтовного фіатного доходу. Фільтр магазину виключає загальнопроєктні комісії без рахунку.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/overview?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/overview?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/overview?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/overview?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETНалаштування проєкту/v1/marketplace/settingsЛише читання
Повертає enabled, payouts_paused, commission_percent, revision та магазини-учасники.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/settings?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/settings?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/settings?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/settings?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTЗберегти налаштування проєкту/v1/marketplace/settingsЧитання + запис
Заміни вибір магазинів-учасників. revision 0 ініціалізує налаштування; наступні зміни потребують повернуту ревізію. Комісія - десятковий відсоток 0–100 із максимум двома знаками після крапки.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | policies.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/settings" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 0,
"enabled": true,
"payouts_paused": true,
"commission_percent": "4",
"stores": [
{
"store_id": "YOUR_STORE_ID",
"enabled": true,
"commission_percent": null
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 0,
"enabled": true,
"payouts_paused": true,
"commission_percent": "4",
"stores": [
{
"store_id": "YOUR_STORE_ID",
"enabled": true,
"commission_percent": null
}
]
}`;
const response = await fetch("https://api.example.com/v1/marketplace/settings", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 0,
"enabled": true,
"payouts_paused": true,
"commission_percent": "4",
"stores": [
{
"store_id": "YOUR_STORE_ID",
"enabled": true,
"commission_percent": null
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/settings");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 0,
"enabled": true,
"payouts_paused": true,
"commission_percent": "4",
"stores": [
{
"store_id": "YOUR_STORE_ID",
"enabled": true,
"commission_percent": null
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/settings",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує policies.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETСписок продавців/v1/marketplace/vendorsЛише читання
Продавці з пагінацією. Пошук q за назвою, зовнішнім ID або email; status active, suspended або archived.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/vendors?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/vendors?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/vendors?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/vendors?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСтворити продавця/v1/marketplace/vendorsЧитання + запис
Name обов'язковий (160 символів); external_id необов'язковий та унікальний у проєкті (128); email необов'язковий (254); description до 2000. commission_percent null успадковує магазин. Перевизначення, відмінне від null, також потребує commissions.override. Продавці - не акаунти хостованих мерчантів.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | vendors.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує vendors.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETОтримати продавця/v1/marketplace/vendors/{vendor_id}Лише читання
Поверни одного продавця, ревізію й перевизначення комісії.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTОновити продавця/v1/marketplace/vendors/{vendor_id}/updateЧитання + запис
Онови дані продавця; status active або suspended. Зміна чи видалення commission_percent також потребує commissions.override; незмінні значення - лише vendors.write. Відновлення архівованого продавця також потребує reconciliation.write. Фінансові зміни в панелі потребують повторної автентифікації. Наявні частки зберігають початкову комісію й адреси.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | vendors.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/update" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null,
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null,
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/update", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null,
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/update");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"name": "Example vendor",
"external_id": "vendor-1042",
"email": "vendor@example.com",
"description": "",
"status": "active",
"commission_percent": null,
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/update",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує vendors.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTАрхівувати продавця/v1/marketplace/vendors/{vendor_id}/archiveЧитання + запис
Архівуй лише після закриття неоплачених і відкритих зобов'язань рахунків; інакше 409 vendor_has_obligations. Історія зберігається. Тимчасово використовуй suspended або віднови старого архівованого продавця маршрутом оновлення з reconciliation.write.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | vendors.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/archive" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/archive", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/archive");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/archive",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує vendors.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETАдреси призначення продавця/v1/marketplace/vendors/{vendor_id}/destinationsЛише читання
Версійовані адреси зі станами pending/approved/disabled. Схвалення не доводить володіння.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTДодати адресу для виплат/v1/marketplace/vendors/{vendor_id}/destinationsЧитання + запис
Зареєструй дійсну mainnet BTC або підтримувану EVM-адресу, що чекає схвалення. Адреси самого проєкту, неправильна мережа й нульові EVM-адреси відхиляються.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | destinations.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"chain_slug": "bitcoin",
"network": "mainnet",
"address": "VERIFIED_VENDOR_BTC_ADDRESS",
"label": "Vendor BTC"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"chain_slug": "bitcoin",
"network": "mainnet",
"address": "VERIFIED_VENDOR_BTC_ADDRESS",
"label": "Vendor BTC"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"chain_slug": "bitcoin",
"network": "mainnet",
"address": "VERIFIED_VENDOR_BTC_ADDRESS",
"label": "Vendor BTC"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"chain_slug": "bitcoin",
"network": "mainnet",
"address": "VERIFIED_VENDOR_BTC_ADDRESS",
"label": "Vendor BTC"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує destinations.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСхвалити адресу призначення/v1/marketplace/vendors/{vendor_id}/destinations/{destination_id}/approveЧитання + запис
Спочатку незалежно перевір володіння. Спершу вимкни наявну схвалену адресу цього продавця/мережі; старі знімки не перенаправляються.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | destinations.approve |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/approve" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/approve", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/approve");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/approve",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує destinations.approve. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTВимкнути адресу призначення/v1/marketplace/vendors/{vendor_id}/destinations/{destination_id}/disableЧитання + запис
Зупини нову/ненадіслану роботу з цією версією. Підписану транзакцію не можна відкликати.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | destinations.approve |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/disable" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/disable", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/disable");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/destinations/YOUR_DESTINATION_ID/disable",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує destinations.approve. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETБаланси продавця/v1/marketplace/vendors/{vendor_id}/balancesЛише читання
Точні збережені суми облікової книги за незмінною ідентичністю активу й типом рахунку; не поточні доступні баланси гаманців.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/balances?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/balances?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/balances?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/vendors/YOUR_VENDOR_ID/balances?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETРахунки Marketplace/v1/marketplace/invoicesЛише читання
Рахунки з пагінацією; q шукає замовлення, email, опис, метадані та UUID рахунку. Фільтри store_id, vendor_id і статус Marketplace. Звичайні рахунки виключені.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/invoices?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/invoices?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/invoices?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/invoices?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСтворити рахунок для кількох продавців/v1/marketplace/invoicesЧитання + запис
Повторно використовуй звичайні поля InvoiceCreateInput плюс store_id і allocations. Кожен продавець один раз, 1–100 додатних часток, сума точно дорівнює amount. Необов'язковий commission_percent рахунку/частки потребує commissions.override та повторної автентифікації панелі для сеансових запитів. Повертає data.invoice_id і links.checkout. Відсутність спільного сумісного способу дає докладну помилку; переходу на несумісний актив немає.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | invoices.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"store_id": "YOUR_STORE_ID",
"amount": "300.00",
"currency": "USD",
"order_id": "cart-1042",
"allocations": [
{
"vendor_id": "VENDOR_A_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_B_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_C_UUID",
"gross_amount": "100.00"
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"store_id": "YOUR_STORE_ID",
"amount": "300.00",
"currency": "USD",
"order_id": "cart-1042",
"allocations": [
{
"vendor_id": "VENDOR_A_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_B_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_C_UUID",
"gross_amount": "100.00"
}
]
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"store_id": "YOUR_STORE_ID",
"amount": "300.00",
"currency": "USD",
"order_id": "cart-1042",
"allocations": [
{
"vendor_id": "VENDOR_A_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_B_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_C_UUID",
"gross_amount": "100.00"
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"store_id": "YOUR_STORE_ID",
"amount": "300.00",
"currency": "USD",
"order_id": "cart-1042",
"allocations": [
{
"vendor_id": "VENDOR_A_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_B_UUID",
"gross_amount": "100.00"
},
{
"vendor_id": "VENDOR_C_UUID",
"gross_amount": "100.00"
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
amountstringобов'язковоЗвичайний десятковий рядок без знака чи експоненти, до 48 цілих і 30 дробових знаків. Типово має бути додатним. Магазин може дозволити нульові рахунки в Магазини → Рахунок; нульові суми завершуються без отримання коштів, виділення адрес чи плати за обробку.Деталі
Звичайний десятковий рядок без знака чи експоненти, до 48 цілих і 30 дробових знаків. Типово має бути додатним. Магазин може дозволити нульові рахунки в Магазини → Рахунок; нульові суми завершуються без отримання коштів, виділення адрес чи плати за обробку.
currencystring | nullнеобов'язковоПідтримувана трилітерна фіатна валюта, нормалізується до великих літер. Якщо пропущено чи null, успадковує валюту рахунків магазину. Створення також потребує незалежно доступного курсу білінгової конвертації.Деталі
Підтримувана трилітерна фіатна валюта, нормалізується до великих літер. Якщо пропущено чи null, успадковує валюту рахунків магазину. Створення також потребує незалежно доступного курсу білінгової конвертації.
payment_methods[]object[] | nullнеобов'язково
Вибери ввімкнені в магазині способи для рахунку. Версія мерчанта 5.4.0+: ігнорує невідомі/неактивні/неприйняті варіанти; якщо нічого не збігається, бере типові способи магазину. Пропущене/null також бере типові; [] недійсне. Ніколи не вмикає спосіб і не змінює магазин. Дивись схему вибору нижче.Деталі
Вибери ввімкнені в магазині способи для рахунку. Версія мерчанта 5.4.0+: ігнорує невідомі/неактивні/неприйняті варіанти; якщо нічого не збігається, бере типові способи магазину. Пропущене/null також бере типові; [] недійсне. Ніколи не вмикає спосіб і не змінює магазин. Дивись схему вибору нижче.
chain_slugstringобов'язковоСкопіюй chain_slug у Проєкт → Магазини → Способи оплати або прочитай GET /v1/projects/{project_id}/stores/{store_id}/payment-assets, наприклад ethereum, base або bitcoin. Пара мережа/канал може траплятися лише раз.Деталі
Скопіюй chain_slug у Проєкт → Магазини → Способи оплати або прочитай GET /v1/projects/{project_id}/stores/{store_id}/payment-assets, наприклад ethereum, base або bitcoin. Пара мережа/канал може траплятися лише раз.
asset_ids[]UUID[] | nullнеобов'язковоUUID asset.id on-chain активів, не адреси контрактів чи ID платіжного способу рахунку. Використовуй це АБО asset_tickers. Пропусти обидва селектори для всіх активних прийнятих активів мережі. [] і повторні/nil ID недійсні. У 5.4.0+ неактивні/неприйняті ID цієї мережі в магазині ігноруються; повна відсутність збігів бере типові способи магазину.Деталі
UUID asset.id on-chain активів, не адреси контрактів чи ID платіжного способу рахунку. Використовуй це АБО asset_tickers. Пропусти обидва селектори для всіх активних прийнятих активів мережі. [] і повторні/nil ID недійсні. У 5.4.0+ неактивні/неприйняті ID цієї мережі в магазині ігноруються; повна відсутність збігів бере типові способи магазину.
asset_tickers[]string[] | nullнеобов'язковоВерсія мерчанта 5.3.0+. Символи BTC, USDC або PEPE в межах chain_slug і магазину. 1–64 унікальні тикери; обрізання пробілів/без урахування регістру, 1–40 ASCII-літер/цифр/крапок/підкреслень/дефісів. Використовуй це АБО asset_ids. У 5.4.0+ невідомі/неактивні/неприйняті тикери ігноруються. Неоднозначні прийняті символи все ще дають помилку: використовуй asset_ids. Вибрані активні способи потребують дійсних гаманців і ціни; тимчасові збої on-chain сканера не блокують створення з 6.0.6. Lightning опційно приймає лише BTC.Деталі
Версія мерчанта 5.3.0+. Символи BTC, USDC або PEPE в межах chain_slug і магазину. 1–64 унікальні тикери; обрізання пробілів/без урахування регістру, 1–40 ASCII-літер/цифр/крапок/підкреслень/дефісів. Використовуй це АБО asset_ids. У 5.4.0+ невідомі/неактивні/неприйняті тикери ігноруються. Неоднозначні прийняті символи все ще дають помилку: використовуй asset_ids. Вибрані активні способи потребують дійсних гаманців і ціни; тимчасові збої on-chain сканера не блокують створення з 6.0.6. Lightning опційно приймає лише BTC.
payment_railonchain | lightningнеобов'язковоТипово onchain. Для Bitcoin Lightning використовуй {chain_slug: bitcoin, payment_rail: lightning} без asset_ids; asset_tickers опційно може бути [BTC]. Bitcoin on-chain не включає Lightning. Lightning-підключення магазину вже має бути ввімкнене й готове.Деталі
Типово onchain. Для Bitcoin Lightning використовуй {chain_slug: bitcoin, payment_rail: lightning} без asset_ids; asset_tickers опційно може бути [BTC]. Bitcoin on-chain не включає Lightning. Lightning-підключення магазину вже має бути ввімкнене й готове.
order_idstring | nullнеобов'язковоРеференс замовлення мерчанта, 1–128 символів після обрізання пробілів; керівні символи відхиляються.
emailstring | nullнеобов'язковоEmail покупця лише для мерчанта, нормалізований до практичної ASCII-адреси до 254 символів. Пропущене чи null не зберігає email.
descriptionstring | nullнеобов'язковоОпис для покупця, 1–500 символів; переноси рядків і табуляції дозволені.
expires_in_secondsinteger | nullнеобов'язковоСтрок котировки рахунку від 300 до 86 400 секунд; пропущене чи null успадковує політику магазину.
exchange_rate_spread_percentdecimal string | nullнеобов'язковоНацінка котировки від 0 до 100, до двох десяткових знаків. Пропущене чи null успадковує магазин; "0" вимикає для цього рахунку. Застосовується перед округленням вгору, потім фіксується. Не змінює фіатну суму рахунку чи основу комісії за обробку.Деталі
Націнка котировки від 0 до 100, до двох десяткових знаків. Пропущене чи null успадковує магазин; "0" вимикає для цього рахунку. Застосовується перед округленням вгору, потім фіксується. Не змінює фіатну суму рахунку чи основу комісії за обробку.
underpayment_tolerance_percentdecimal string | nullнеобов'язковоДопустима недоплата від 0 до 99.99, до двох десяткових знаків. Пропущене чи null успадковує магазин.
ipn_urlstring | nullнеобов'язковоПублічний HTTPS-колбек до 2 048 байтів, без облікових даних чи фрагмента. Перевизначає типовий URL магазину; null/пропущене успадковує його.
redirect_urlstring | nullнеобов'язковоHTTPS URL успіху після остаточної оплати, до 2 048 байтів і без вбудованих облікових даних. Пропущене чи null успадковує магазин і не очищує значення.
cancel_urlstring | nullнеобов'язковоHTTPS URL повернення, коли оплата завершується без успішного платежу. Пропущене чи null успадковує магазин і не очищує значення.
redirect_automaticallyboolean | nullнеобов'язковоПропущене чи null успадковує політику магазину. true потребує фактичного redirect_url.
languagestring | nullнеобов'язковоМова покупця: en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja. pt означає бразильську португальську, zh - спрощену китайську. Підтримувані регіональні теги, як de-DE, нормалізуються до вказаної мови. Пропущене чи null успадковує мову магазину. Мова панелі окрема.Деталі
Мова покупця: en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja. pt означає бразильську португальську, zh - спрощену китайську. Підтримувані регіональні теги, як de-DE, нормалізуються до вказаної мови. Пропущене чи null успадковує мову магазину. Мова панелі окрема.
checkout_appearanceobject | nullнеобов'язково
Часткові налаштування показу цього рахунку. Пропущене/null використовує поточне оформлення магазину. Об'єкт, включно з {}, фіксує визначене оформлення й зображення при створенні. Дивись схему перевизначення нижче; без фінансових налаштувань, HTML, CSS, JavaScript чи віддалених URL зображень.Деталі
Часткові налаштування показу цього рахунку. Пропущене/null використовує поточне оформлення магазину. Об'єкт, включно з {}, фіксує визначене оформлення й зображення при створенні. Дивись схему перевизначення нижче; без фінансових налаштувань, HTML, CSS, JavaScript чи віддалених URL зображень.
inherit_default_storebooleanнеобов'язковоtrue бере за основу оформлення магазину за замовчуванням проєкту; інакше фактичне оформлення цільового магазину. Потім застосовуються перевизначення й зберігаються незалежно; остаточний прапорець рахунку - false.Деталі
true бере за основу оформлення магазину за замовчуванням проєкту; інакше фактичне оформлення цільового магазину. Потім застосовуються перевизначення й зберігаються незалежно; остаточний прапорець рахунку - false.
titlestringнеобов'язковоЗаголовок оплати, до 120 символів. Порожній використовує стандартний заголовок.
introstringнеобов'язковоЗвичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.Деталі
Звичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.
outrostringнеобов'язковоЗвичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.Деталі
Звичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.
intro_font_sizeintegerнеобов'язковоПікселі: 12, 14, 16, 18, 20 або 24. Типово 16, якщо не успадковано інше.
outro_font_sizeintegerнеобов'язковоПікселі: 12, 14, 16, 18, 20 або 24. Типово 16, якщо не успадковано інше.
themesystem | light | dim | darkнеобов'язковоСлідуй пристрою покупця або використовуй фіксовану тему.
accent_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
background_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
card_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
button_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
imagesobjectнеобов'язково
Ключі logo_light, logo_dark, favicon. Пропущений ключ залишає базове зображення; null видаляє. Об'єкт {store_id: UUID, kind?: logo_light|logo_dark|favicon} повторно використовує фактично завантажене зображення цього магазину в ТОМУ САМОМУ проєкті. kind типово дорівнює цільовому ключу. Спочатку завантаж у Магазин → Оформлення оплати; скопіюй ID магазину для API з Основне → ID для API. Відсутні зображення чи ID іншого проєкту повертають 400. Зовнішні URL або дані зображень не приймаються.Деталі
Ключі logo_light, logo_dark, favicon. Пропущений ключ залишає базове зображення; null видаляє. Об'єкт {store_id: UUID, kind?: logo_light|logo_dark|favicon} повторно використовує фактично завантажене зображення цього магазину в ТОМУ САМОМУ проєкті. kind типово дорівнює цільовому ключу. Спочатку завантаж у Магазин → Оформлення оплати; скопіюй ID магазину для API з Основне → ID для API. Відсутні зображення чи ID іншого проєкту повертають 400. Зовнішні URL або дані зображень не приймаються.
logo_lightobject | nullнеобов'язково
logo_darkobject | nullнеобов'язково
show_order_idbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
show_descriptionbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
details_expandedbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
show_project_namebooleanнеобов'язковоВерсія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.Деталі
Версія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.
show_store_namebooleanнеобов'язковоВерсія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.Деталі
Версія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.
featured_chains[]string[]необов'язковоУпорядковані slug мереж, до 60 унікальних значень (малі літери, цифри, дефіси; до 64 символів). [] очищує. Порядок змінюється лише для доступних способів рахунку.Деталі
Упорядковані slug мереж, до 60 унікальних значень (малі літери, цифри, дефіси; до 64 символів). [] очищує. Порядок змінюється лише для доступних способів рахунку.
featured_asset_ids[]UUID[]необов'язковоДо 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.Деталі
До 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.
default_asset_idUUID|nullнеобов'язковоДо 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.Деталі
До 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.
messagesobjectнеобов'язково
Мовні об'єкти з ключами en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja та звичайними рядками waiting, confirming, paid, underpaid, expired (до 500 символів кожен). Змінюються лише передані мови/стани; {} очищає всі повідомлення, {en:{}} очищає англійські, а порожній рядок стану очищає цей стан. Резервна мова - англійська. Фактичний статус не змінюється.Деталі
Мовні об'єкти з ключами en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja та звичайними рядками waiting, confirming, paid, underpaid, expired (до 500 символів кожен). Змінюються лише передані мови/стани; {} очищає всі повідомлення, {en:{}} очищає англійські, а порожній рядок стану очищає цей стан. Резервна мова - англійська. Фактичний статус не змінюється.
enobjectнеобов'язково
deobjectнеобов'язково
esobjectнеобов'язково
pt-BRobjectнеобов'язково
itobjectнеобов'язково
ruobjectнеобов'язково
zh-CNobjectнеобов'язково
frobjectнеобов'язково
koobjectнеобов'язково
support_emailstringнеобов'язковоEmail у форматі ASCII, до 254 символів. Порожнє значення очищає поле.
support_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
terms_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
privacy_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
return_button_textstringнеобов'язковоНапис до 60 символів. Для поведінки рахунку використовуй поля верхнього рівня redirect_url/cancel_url/redirect_automatically/language.
show_return_buttonbooleanнеобов'язковоПоказувати кнопку повернення до мерчанта/скасування на сторінці оплати, зокрема в кінцевих станах. Не передавай поле, щоб успадкувати оформлення магазину (типово true); false приховує кнопку. Це не скасовує рахунок, не приховує URL у JSON і не вимикає автоматичне перенаправлення після успіху. За потреби окремо встанови redirect_automatically верхнього рівня у false. Потрібна версія мерчанта 8.1.4 або новіша.Деталі
Показувати кнопку повернення до мерчанта/скасування на сторінці оплати, зокрема в кінцевих станах. Не передавай поле, щоб успадкувати оформлення магазину (типово true); false приховує кнопку. Це не скасовує рахунок, не приховує URL у JSON і не вимикає автоматичне перенаправлення після успіху. За потреби окремо встанови redirect_automatically верхнього рівня у false. Потрібна версія мерчанта 8.1.4 або новіша.
metadataobject | nullнеобов'язково
JSON-об'єкт лише для мерчанта; відсутнє поле або null стає {}, максимум 4096 байтів у закодованому вигляді та п'ять рівнів вкладеності. firstname, lastname, street, street2, zip, city, country, countryiso2, company і vatid перевіряються, нормалізуються та відображаються в зведених полях клієнта.Деталі
JSON-об'єкт лише для мерчанта; відсутнє поле або null стає {}, максимум 4096 байтів у закодованому вигляді та п'ять рівнів вкладеності. firstname, lastname, street, street2, zip, city, country, countryiso2, company і vatid перевіряються, нормалізуються та відображаються в зведених полях клієнта.
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
allocations[]object[]
[{"vendor_id":"VENDOR_A_UUID","gross_amount":"100.00"},{"vendor_id":"VENDOR_B_UUID","gross_amount":"100.00"},{"vendor_id":"VENDOR_C_UUID","gross_amount":"100.00"}]Деталі
[{"vendor_id":"VENDOR_A_UUID","gross_amount":"100.00"},{"vendor_id":"VENDOR_B_UUID","gross_amount":"100.00"},{"vendor_id":"VENDOR_C_UUID","gross_amount":"100.00"}]
Відповідь 200 application/json
Приклад відповіді
{
"data": {
"invoice_id": "YOUR_INVOICE_ID",
"status": "new",
"marketplace": {
"state": "pending",
"allocations": []
}
},
"links": {
"checkout": "https://pay.example.com/invoice/YOUR_INVOICE_ID"
}
}Поля відповіді
Примітки до використання
- Потрібен дозвіл invoices.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETРахунок і розподілені частки/v1/marketplace/invoices/{invoice_id}Лише читання
Звичайні дані рахунку плюс стан маркетплейсу, revision, hold_reason, зафіксовані частки, знімок політики, останні 200 платежів і останні 100 пов'язаних виплат із прапорцями обрізання. Публічна сторінка оплати не розкриває дані продавців.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETДокази оплати рахунку/v1/marketplace/invoices/{invoice_id}/paymentsЛише читання
Звичайні підтвердження платежів із page/per_page. Спостереження за платежами - не виплати продавцям.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/payments?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/payments?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/payments?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/payments?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETРозподілені частки рахунку/v1/marketplace/invoices/{invoice_id}/allocationsЛише читання
Незмінні знімки часток, комісій і адрес призначення та точні атомарні значення загальної суми, комісії й чистої суми після належного підтвердження оплати.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСкасувати неоплачений рахунок/v1/marketplace/invoices/{invoice_id}/cancelЧитання + запис
Лише неоплачений рахунок у стані new або expired. Пізні надходження затримуються для перевірки. Revision - це версія рахунку маркетплейсу.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | invoices.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/cancel" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/cancel", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/cancel");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/cancel",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл invoices.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTЗаблокувати розподілені частки/v1/marketplace/invoices/{invoice_id}/allocations/holdЧитання + запис
Призупинити непідписані частки, не стираючи зобов'язань. Підписані виплати або виплати з невизначеним станом залишаються під наглядом.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | reconciliation.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/hold" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verify customer request"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verify customer request"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/hold", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verify customer request"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/hold");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verify customer request"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/hold",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл reconciliation.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПеревірити й розблокувати частки/v1/marketplace/invoices/{invoice_id}/allocations/releaseЧитання + запис
Повторно перевірити забезпечення коштами та остаточність. Необов'язкове approved_amount_atomic явно погоджує зменшений, повністю забезпечений розподіл перед фіксацією часток; воно ніколи не створює вигаданих надходжень.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | reconciliation.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/release" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verified payment evidence"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verified payment evidence"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/release", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verified payment evidence"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/release");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"reason": "Verified payment evidence"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/release",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл reconciliation.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTЗмінити адресу для ще не виплачених коштів/v1/marketplace/invoices/{invoice_id}/allocations/{allocation_id}/destinationЧитання + запис
Потрібна версія частки. Лише незарезервована/непідписана робота та окремо схвалена версія для того самого продавця в початковій мережі. Дія журналюється; підписану роботу змінити не можна.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | reconciliation.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/YOUR_ALLOCATION_ID/destination" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"destination_id": "YOUR_DESTINATION_ID",
"reason": "Vendor verified replacement address"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"destination_id": "YOUR_DESTINATION_ID",
"reason": "Vendor verified replacement address"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/YOUR_ALLOCATION_ID/destination", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"destination_id": "YOUR_DESTINATION_ID",
"reason": "Vendor verified replacement address"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/YOUR_ALLOCATION_ID/destination");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"destination_id": "YOUR_DESTINATION_ID",
"reason": "Vendor verified replacement address"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/allocations/YOUR_ALLOCATION_ID/destination",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл reconciliation.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПідготувати повне повернення/v1/marketplace/invoices/{invoice_id}/refundЧитання + запис
Підготувати окремо схвалене повернення всієї отриманої суми в тому самому активі. До виплати продавцям зарезервувати невиплачені кошти й сторнувати комісію після підтвердження. Після всіх виплат продавцям використати окремі вільні кошти основної адреси. Ніколи не визначай адресу повернення клієнту за адресою відправника.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | reconciliation.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/refund" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"payment_method_id": "YOUR_PAYMENT_METHOD_ID",
"destination_address": "VERIFIED_CUSTOMER_REFUND_ADDRESS",
"reason": "Customer cancellation",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"payment_method_id": "YOUR_PAYMENT_METHOD_ID",
"destination_address": "VERIFIED_CUSTOMER_REFUND_ADDRESS",
"reason": "Customer cancellation",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/refund", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"payment_method_id": "YOUR_PAYMENT_METHOD_ID",
"destination_address": "VERIFIED_CUSTOMER_REFUND_ADDRESS",
"reason": "Customer cancellation",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/refund");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"payment_method_id": "YOUR_PAYMENT_METHOD_ID",
"destination_address": "VERIFIED_CUSTOMER_REFUND_ADDRESS",
"reason": "Customer cancellation",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/invoices/YOUR_INVOICE_ID/refund",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл reconciliation.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETЗнайти частки для виплати/v1/marketplace/allocationsЛише читання
Кандидати з пагінацією; фільтри status (available тощо), asset_id, vendor_id, store_id і q (продавець/замовлення/рахунок).
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/allocations?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/allocations?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/allocations?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/allocations?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETБаланси облікової книги проєкту/v1/marketplace/balancesЛише читання
Точні підсумки, згруповані за активом і рахунком обліку: затримано, доступно, зарезервовано, виплачено, комісії, повернення й мережеві комісії. Зовнішній балансувальний рахунок не враховується.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/balances?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/balances?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/balances?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/balances?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETНезмінний журнал/v1/marketplace/ledgerЛише читання
Незмінюваний журнал рухів із пагінацією; q шукає посилання/рахунок обліку, також є фільтри asset_id і vendor_id. Суми - атомарні рядки; жоден запис не можна редагувати чи вручну позначати оплаченим.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/ledger?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/ledger?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/ledger?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/ledger?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETІсторія виплат/v1/marketplace/payoutsЛише читання
Батьківські записи з пагінацією; фільтри state, asset_id, vendor_id або q за ID/символом. Оплачено означає незалежне підтвердження, а не лише передавання в мережу.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/payouts?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/payouts?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/payouts?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/payouts?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПереглянути план розподілу/v1/marketplace/payouts/previewЧитання + запис
Обліковий план лише для читання, без резервування коштів чи дозволу на витрату. Максимальна комісія - ліміт користувача, а не оцінка фактичної комісії. Перевірки поточного стану виконуються пізніше під час підготовки.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | payouts.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/payouts/preview" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/payouts/preview", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/payouts/preview");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/payouts/preview",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл payouts.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПідготувати виплату/v1/marketplace/payoutsЧитання + запис
Зарезервувати 1–100 доступних ID часток одного активу/гаманця. Для BTC усі невиплачені частки кожного вибраного рахунку мають входити до одного пакета з кількома виходами. Бюджети - атомарні рядки в нативному активі комісій. Створює план awaiting_approval, але не передає транзакції в мережу.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | payouts.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/payouts" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}`;
const response = await fetch("https://api.example.com/v1/marketplace/payouts", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/payouts");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"allocation_ids": [
"YOUR_ALLOCATION_ID"
],
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"fee_tier": "medium"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/payouts",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {
"id": "YOUR_PAYOUT_ID",
"state": "awaiting_approval",
"revision": 1,
"plan_hash": "RETAINED_PLAN_HASH",
"plan": {
"amount_atomic": "28800000",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"items": []
},
"transactions": []
}
}Поля відповіді
Примітки до використання
- Потрібен дозвіл payouts.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETДеталі виплати/v1/marketplace/payouts/{payout_id}Лише читання
Незмінний план/хеш, версія, термін дії, отримувачі, збережені дочірні спроби, прогрес, точні комісії та посилання на оглядач. Ніколи не містить приватних ключів чи підписаних байтів.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"id": "YOUR_PAYOUT_ID",
"state": "awaiting_approval",
"revision": 1,
"plan_hash": "RETAINED_PLAN_HASH",
"plan": {
"amount_atomic": "28800000",
"maximum_network_fee_atomic": "10000",
"maximum_gas_funding_atomic": "0",
"items": []
},
"transactions": []
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСхвалити й надіслати/v1/marketplace/payouts/{payout_id}/approveЧитання + запис
Явно дозволити саме збережений план до завершення його терміну дії. Поставити в чергу фонове фінансування газу в межах лімітів і транзакції продавцям.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | payouts.approve |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/approve" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}`;
const response = await fetch("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/approve", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/approve");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/approve",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл payouts.approve. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПеревірити й відновити виплату/v1/marketplace/payouts/{payout_id}/resumeЧитання + запис
Лише needs_attention. Повторно використовує збережений план/хеш; підтвердженим отримувачам ніколи не надсилають кошти вдруге. Два незалежні провайдери мають довести канонічний, достатньо підтверджений відкат EVM, перш ніж невдалу дочірню транзакцію можна замінити. Попередні комісії все одно витрачають схвалений бюджет, а всі хеші залишаються в історії. Невідома/часткова доставка токенів повертає payout_recovery_unverified; резерви залишаються заблокованими.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | payouts.approve |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/resume" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}`;
const response = await fetch("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/resume", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/resume");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"expected_plan_hash": "COPY_EXACT_PLAN_HASH_FROM_PREPARE",
"confirm": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/resume",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл payouts.approve. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСкасувати непідписану роботу/v1/marketplace/payouts/{payout_id}/cancelЧитання + запис
Звільнити лише резерви, які безпечно залишаються непідписаними й не переданими в мережу. Підтверджені отримувачі та журнал аудиту зберігаються. Підписану роботу або роботу з невизначеним станом скасувати не можна. Явно відновлений, доведений відкат більше не блокує скасування решти непідписаної роботи.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | payouts.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/cancel" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/cancel", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/cancel");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/payouts/YOUR_PAYOUT_ID/cancel",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл payouts.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETПолітики автоматичних виплат/v1/marketplace/policiesЛише читання
Прочитати політики активів, revision, next_attempt_at, last_checked_at і безпечне last_error, якщо підготовка або авторизація потребує уваги.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/policies?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/policies?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/policies?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/policies?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": []
}Поля відповіді
data[]arrayПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTДозволити політику виплат/v1/marketplace/policiesЧитання + запис
Точні атомарні рядки; minimum <= transfer <= добовий ліміт основної суми, ліміти комісій/газу <= відповідні добові бюджети. interval_seconds 60–604800; minimum_confirmations 1–100000 з урахуванням мінімуму мережі. Версія 0 створює запис. Увімкнені політики можуть надсилати кошти без додаткових натискань; залиш false до перевірки.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | policies.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/policies" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"asset_id": "YOUR_ASSET_ID",
"revision": 0,
"enabled": false,
"minimum_atomic": "100000",
"transfer_limit_atomic": "10000000",
"daily_limit_atomic": "30000000",
"fee_limit_atomic": "10000",
"daily_fee_limit_atomic": "30000",
"gas_limit_atomic": "0",
"daily_gas_limit_atomic": "0",
"interval_seconds": 3600,
"minimum_confirmations": 2
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"asset_id": "YOUR_ASSET_ID",
"revision": 0,
"enabled": false,
"minimum_atomic": "100000",
"transfer_limit_atomic": "10000000",
"daily_limit_atomic": "30000000",
"fee_limit_atomic": "10000",
"daily_fee_limit_atomic": "30000",
"gas_limit_atomic": "0",
"daily_gas_limit_atomic": "0",
"interval_seconds": 3600,
"minimum_confirmations": 2
}`;
const response = await fetch("https://api.example.com/v1/marketplace/policies", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"asset_id": "YOUR_ASSET_ID",
"revision": 0,
"enabled": false,
"minimum_atomic": "100000",
"transfer_limit_atomic": "10000000",
"daily_limit_atomic": "30000000",
"fee_limit_atomic": "10000",
"daily_fee_limit_atomic": "30000",
"gas_limit_atomic": "0",
"daily_gas_limit_atomic": "0",
"interval_seconds": 3600,
"minimum_confirmations": 2
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/policies");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"asset_id": "YOUR_ASSET_ID",
"revision": 0,
"enabled": false,
"minimum_atomic": "100000",
"transfer_limit_atomic": "10000000",
"daily_limit_atomic": "30000000",
"fee_limit_atomic": "10000",
"daily_fee_limit_atomic": "30000",
"gas_limit_atomic": "0",
"daily_gas_limit_atomic": "0",
"interval_seconds": 3600,
"minimum_confirmations": 2
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/policies",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує policies.write. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETВебхуки Marketplace/v1/marketplace/webhooksЛише читання
До 20 адрес отримання подій та підтримувані event_types. Ніколи не повертає секрети підпису ні в зашифрованому, ні у відкритому вигляді.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/webhooks?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/webhooks?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/webhooks?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/webhooks?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"endpoints": [],
"event_types": [
"marketplace.invoice.created",
"marketplace.allocations.available",
"marketplace.allocations.held",
"marketplace.payout.approved",
"marketplace.payout.broadcast",
"marketplace.payout.confirmed",
"marketplace.payout.partial",
"marketplace.payout.failed",
"marketplace.payout.cancelled",
"marketplace.refund.prepared",
"marketplace.refund.confirmed"
]
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTСтворити вебхук Marketplace/v1/marketplace/webhooksЧитання + запис
Лише публічний HTTPS, без облікових даних, приватних адрес чи перенаправлень. Повертає signing_secret один раз у збереженій ідемпотентній відповіді створення; збережи його безпечно. Він окремий від IPN-секрету магазину.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | webhooks.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/webhooks" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed",
"marketplace.payout.failed"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed",
"marketplace.payout.failed"
]
}`;
const response = await fetch("https://api.example.com/v1/marketplace/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed",
"marketplace.payout.failed"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed",
"marketplace.payout.failed"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/webhooks",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл webhooks.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTОновити вебхук Marketplace/v1/marketplace/webhooks/{webhook_id}/updateЧитання + запис
Зміни скасовують старі невідправлені сповіщення. Секрет не змінюється; старі незмінні дані подій ніколи не перенаправляються на новий URL.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | webhooks.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/update" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed"
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed"
]
}`;
const response = await fetch("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/update", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed"
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/update");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1,
"url": "https://shop.example.com/marketplace-events",
"enabled": true,
"events": [
"marketplace.payout.confirmed"
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/update",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл webhooks.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTВимкнути вебхук Marketplace/v1/marketplace/webhooks/{webhook_id}/disableЧитання + запис
Зупинити нові надсилання; збережена історія подій залишається.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | webhooks.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/disable" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}`;
const response = await fetch("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/disable", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/disable");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"revision": 1
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/webhooks/YOUR_WEBHOOK_ID/disable",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл webhooks.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETПодії Marketplace/v1/marketplace/eventsЛише читання
Незмінні посилання на події з пагінацією. q шукає за типом/посиланням; status фільтрує event_type.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/events?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/events?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/events?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/events?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETПрочитати збережену подію/v1/marketplace/events/{event_id}Лише читання
Повертає незмінні початкові дані події, а не відтворену версію з поточних балансів.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/events/YOUR_EVENT_ID?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/events/YOUR_EVENT_ID?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/events/YOUR_EVENT_ID?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/events/YOUR_EVENT_ID?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"event_id": "11111111-1111-4111-8111-111111111111",
"event_type": "marketplace.payout.confirmed",
"payload_version": 1,
"project_id": "YOUR_PROJECT_ID",
"occurred_at": "2026-10-06T12:00:00Z",
"data": {
"payout_id": "YOUR_PAYOUT_ID",
"asset_id": "YOUR_ASSET_ID",
"amount_atomic": "28800000",
"transactions": [
{
"transaction_id": "EXAMPLE_TRANSACTION_ID",
"explorer_url": "https://mempool.space/tx/EXAMPLE_TRANSACTION_ID"
}
]
}
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETІсторія доставлення Marketplace/v1/marketplace/webhook-deliveriesЛише читання
Надсилання з пагінацією, тип події, спроби та останній результат. Фільтр status: pending/sending/succeeded/failed/cancelled; q шукає тип події.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/webhook-deliveries?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/webhook-deliveries?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/webhook-deliveries?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/webhook-deliveries?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [],
"pagination": {
"page": 1,
"per_page": 25,
"total": 0,
"pages": 1
}
}Поля відповіді
Примітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETДеталі доставлення/v1/marketplace/webhook-deliveries/{delivery_id}Лише читання
Початковий URL, збережені дані, HTTP-результат і безпечна помилка; без секрету підпису.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | marketplace.read |
Параметри запиту
project_idUUIDобов'язковоАвторизований проєкт. Обов'язковий у кожному запиті, включно з URL окремих записів.
pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
per_pageнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
qнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
statusнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
store_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
vendor_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
asset_idнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
fromнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
toнеобов'язковоВикористовуй лише задокументовані для ресурсу фільтри. Списки з пагінацією типово мають 25 і допускають до 100 рядків.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID?project_id=YOUR_PROJECT_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID?project_id=YOUR_PROJECT_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID?project_id=YOUR_PROJECT_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID?project_id=YOUR_PROJECT_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потребує marketplace.read. Приклади відповіді показують вибрані поля; отримай ресурс через GET для всіх збережених доказів.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
POSTПовторно доставити ту саму подію/v1/marketplace/webhook-deliveries/{delivery_id}/resendЧитання + запис
Лише завершені надсилання та незмінена активна адреса; до 20 ручних повторів. Повторно використовує event_id. Невдале сповіщення ніколи не дозволяє повторну виплату.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MARKETPLACE_API_TOKEN |
| Idempotency-Key | обов'язково | 16–128 літер, цифр, -, _ або .; збережи з цим точним запитом |
| Параметр | Тип / розташування | Правило |
|---|---|---|
| permission | credential scope | webhooks.write |
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new operation.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID/resend" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: marketplace-request-1042' \
--header 'Content-Type: application/json' \
--data-raw '{
"project_id": "YOUR_PROJECT_ID",
"confirm": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new operation.
const body = `{
"project_id": "YOUR_PROJECT_ID",
"confirm": true
}`;
const response = await fetch("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID/resend", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new operation.
$body = <<<'JSON'
{
"project_id": "YOUR_PROJECT_ID",
"confirm": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID/resend");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: marketplace-request-1042", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new operation.
headers = {
"Idempotency-Key": "marketplace-request-1042",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"project_id": "YOUR_PROJECT_ID",
"confirm": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/marketplace/webhook-deliveries/YOUR_DELIVERY_ID/resend",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": {}
}Поля відповіді
dataobjectПримітки до використання
- Потрібен дозвіл webhooks.write. Приклади відповідей показують вибрані поля; виконай GET ресурсу, щоб отримати всі збережені підтвердження.
- Кожен POST потребує збереженого Idempotency-Key з 16–128 символів (літери, цифри, -, _ або .). Після таймауту повторюй той самий ключ та JSON-інструкції. Інші інструкції повертають 409. Завершені відповіді зберігаються 30 днів; старі ключі стають незворотно непридатними для повторного використання. Ніколи не змінюй ключ лише для обходу невизначеного результату.
- Ключі мають списки проєктів, необов'язкові обмеження магазинів для рахунків, строк дії, список IP та квоту 1–600/хвилину (типово 60). HTTP 429 містить Retry-After. Обмежені магазинами ключі не бачать продавців, балансів проєкту, облікової книги, виплат чи налаштувань. Ключі витрачання тримай лише на довірених серверах, ніколи в браузерах чи розповсюджуваних мобільних застосунках.
Помилки
GETСписок платіжних винятків/v1/projects/{project_id}/reconciliationЛише читання
Єдина черга перевірки з пагінацією для недоплат, переплат, пізніх платежів, реорганізацій або неоднозначних платежів, невдалих сповіщень і вимкнених/прострочених способів. Справи, які оператор позначив перевіреними, відкриваються знову після появи нових підтверджень.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
Параметри шляху
Параметри запиту
reasonstringunderpaid, overpaid, late, reorged, ambiguous, delivery_failed, disabled_method або expired_method.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation?status=open&page=1",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{"data":[],"pagination":{"page":1,"per_page":25,"total":0,"has_more":false},"counts":{"open":0,"resolved":0}}Поля відповіді
data[]object[]завжди
Спочатку справи з найсвіжішими змінами. У URL даних мерчанта використовуй invoice_id, а не внутрішній id.
idUUIDзавждиВнутрішній ID запису / UUID рахунку для клієнта. invoice_id збігається з даними callback.
invoice_idUUIDзавждиВнутрішній ID запису / UUID рахунку для клієнта. invoice_id збігається з даними callback.
paginationobjectзавжди
page (1–40001), per_page (25), total відповідних рядків, has_more.
Примітки до використання
- Лише читання, у межах проєкту та квоти облікових даних. Фінансові рішення й повернення коштів залишаються доступними лише в панелі.
- Рядки містять id (внутрішній UUID), invoice_id (публічний UUID, як у callback), дані магазину, початкову фіатну суму/валюту, invoice_status, статус справи, причини, revision і updated_at. У запиті даних мерчанта використовуй invoice_id.
- Автоматичне виявлення працює в початковому вікні спостереження за рахунком; повторне сканування подовжує спостереження на годину, не вмикаючи оплату. Способи після завершення оплати/скасування залишаються під наглядом у межах цього вікна.
Помилки
GETПереглянути докази для звіряння/v1/projects/{project_id}/reconciliation/{invoice_id}Лише читання
Повертає рахунок, справу, точні підсумки способів і доступні суми повернення, помічені транзакції, історію сповіщень, рішення мерчанта та пов'язані перекази повернення. Ніколи не розкриває ключі підпису чи секрети callback.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
Параметри шляху
Параметри запиту
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/reconciliation/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{"invoice":{"invoice_id":"YOUR_PUBLIC_INVOICE_ID","status":"processing"},"case":{"status":"open","reasons":["underpaid"],"revision":1},"methods":[],"history":[],"history_pagination":{"page":1,"per_page":25,"total":0},"refunds":[],"observations":[],"deliveries":[]}Поля відповіді
invoiceobjectзавжди
Повний рахунок мерчанта: зведені поля, приватні метадані та payment_intents. Без обгортки data.
idUUIDзавждиВнутрішній UUID рахунку. Не використовуй його в шляхах даних мерчанта чи сторінки оплати.
emailstring | nullзавждиEmail клієнта лише для мерчанта. Публічна сторінка оплати його ніколи не повертає.
customer_namestring | nullзавждиВідображуване ім'я, сформоване з приватних метаданих firstname, lastname і company.
customer_addressstring | nullзавждиОднорядкова адреса для мерчанта, сформована з приватних метаданих company, street, street2, zip, city, country, countryiso2 і vatid.
exchange_rate_spread_percentdecimal stringзавждиЗафіксована курсова надбавка: значення при створенні або стандартне значення магазину, якщо поле не передано. Застосовується перед округленням угору; ніколи не змінюється для цього рахунку.
underpayment_tolerance_percentdecimal stringзавждиНезмінний допустимий відсоток недоплати, збережений під час створення рахунку.
amount_statusamount statusзавждиnone, partial, paid або overpaid. Явно дозволений рахунок із нульовою сумою завершується з none і без способів оплати.
monitoring_expires_atRFC 3339 timestampзавждиНайпізніший налаштований кінець спостереження за пізніми платежами серед способів оплати.
ipn_urlstring | nullзавждиДієва IPN-адреса цього рахунку. Лише у відповіді мерчанту; відсутня в публічній сторінці оплати.
cancel_urlstring | nullзавждиДієвий URL повернення, коли оформлення закінчується без успішної оплати.
metadataobjectзавждиМетадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.Деталі
Метадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.
payment_intents[]object[]завжди
Способи оплати з котируваннями та станом спостереження.
idUUIDзавждиІдентифікатор платіжного наміру; також використовується як intent_id QR-коду на сторінці оплати.
payment_railonchain | lightningзавждиСпосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.Деталі
Спосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.
bolt11string | nullзавждиПлатіжний запит Lightning або null. Оплачуй його гаманцем Lightning; ніколи не надсилай кошти в блокчейні на його хеш платежу.
asset_decimalsintegerзавждиТочність найменших одиниць. BTC у Lightning використовує 11 знаків (мілісатоші), а не 8, як Bitcoin у блокчейні. Котирування задаються цілими сатоші; надходження зберігають точність до мілісатоші.
quote_ratedecimal stringзавждиОдиниці активу за одну одиницю валюти рахунку, включно із зафіксованим спредом. Наприклад, 1.02 USDC за USD. Не зворотний курс.
quote_detailsobject | nullзавждиПоходження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.Деталі
Походження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.
expected_amountdecimal stringзавждиТочна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.Деталі
Точна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.
minimum_payment_amountdecimal stringзавждиНайменша сума, яку приймають як сплачену після застосування допуску рахунку.
minimum_payment_amount_atomicinteger stringзавждиТочний поріг прийняття в найменших одиницях активу.
destination_addressstringзавждиАдреса отримання в блокчейні або 64-символьний хеш платежу Lightning. Для оплати Lightning використовуй bolt11; його хеш не є адресою Bitcoin.
destination_tagstring | nullзавждиОбов’язковий публічний реквізит платежу для каналів, які його використовують: destination tag XRP, memo ID Stellar або коментар рахунку TON. Null для каналів з унікальними адресами.
derivation_indexintegerзавждиЗарезервований індекс дочірньої адреси гаманця; лише в деталях для мерчанта.
monitoring_expires_atRFC 3339 timestampзавждиКінець спостереження за пізніми платежами для цього способу.
caseobject | nullзавжди
Поточний випадок зі status, reasons, revision і часовими позначками; null, якщо винятку немає. Внутрішні докази не включаються.
methods[]object[]завждиid, wallet_id, asset_id, symbol, chain, decimals, expected_atomic, received_atomic, confirmed_atomic, refundable_atomic, address, tag, monitor_error, last_checked_at, monitoring_expires_at і spending_supported. Суми в найменших одиницях - рядки.Деталі
id, wallet_id, asset_id, symbol, chain, decimals, expected_atomic, received_atomic, confirmed_atomic, refundable_atomic, address, tag, monitor_error, last_checked_at, monitoring_expires_at і spending_supported. Суми в найменших одиницях - рядки.
history[]object[]завждиОстанні 25 рішень для цієї сторінки: id, action, note, actor, result, created_at.
history_paginationobjectзавжди
page, per_page (25), total. Лише історія рішень має пагінацію через page.
refunds[]object[]завждиОстанні 100 повернень: id, payment_intent_id, amount_atomic, destination, status, request, treasury_intent_id, transfer_status, created_at і transactions (id/status). Подати повернення можна лише в панелі.Деталі
Останні 100 повернень: id, payment_intent_id, amount_atomic, destination, status, request, treasury_intent_id, transfer_status, created_at і transactions (id/status). Подати повернення можна лише в панелі.
observations[]object[]завждиОстанні 100: payment_intent_id, transaction_id, event_index, amount, status, confirmations, observed_at, symbol, chain і disabled_at_detection. За підтримки включаються explorer_name/explorer_url.Деталі
Останні 100: payment_intent_id, transaction_id, event_index, amount, status, confirmations, observed_at, symbol, chain і disabled_at_detection. За підтримки включаються explorer_name/explorer_url.
deliveries[]object[]завждиОстанні 50: id, kind, status, attempts, response_status, error, next_attempt_at, event_type і created_at. Без секретів callback.
Примітки до використання
- case має значення null, якщо рахунок не створив винятку. Повертаються останні 100 спостережень і 50 доставок; історія рішень має пагінацію.
- refundable_atomic потребує щонайменше одного підтвердження мережі, не включає наявні резерви повернень і не гарантує доступні для витрачання кошти гаманця. Актуальне котирування додатково перевіряє готовність гаманця, баланси джерел і комісії.
- Повернення зі статусом broadcast означає подання до вузла блокчейну, а не незалежно підтверджене отримання клієнтом. Комісії сплачуються додатково, а фіатні комісії за обробку не зараховуються назад автоматично через повернення.
- Меню проєкту в панелі → Потребує уваги дає змогу скасувати, прийняти, відхилити, відкрити знову, перевірити, додати нотатки, виконати Rescan, повторити доставку й повернути кошти в підтримуваних мережах. Рішення використовують сесії із захистом CSRF, унікальний request_id, поточну revision випадку, обов’язкову примітку та явне підтвердження; bearer-токени не можуть викликати ці зміни.
Помилки
GETВиявлення сервісу API/Публічний
Відповідь керованого проксі на API-хості, яка підтверджує роль публічного API v1. Її створює керований проксі, а не маршрутизатор Axum мерчанта.
Автентифікація та заголовки
Публічний
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/"// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://api.example.com/", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://api.example.com/");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://api.example.com/",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"service": "Wholly Crypto API",
"status": "ready",
"version": "v1"
}Поля відповіді
Примітки до використання
- Bearer-токен не потрібен.
- Лише кероване ім’я API-хоста гарантує саме таку відповідь кореневого шляху.
Помилки
GETСтан сервісу/healthzПублічний
Перевіряє доступність застосунку й ping бази даних із лімітом дві секунди. Використовуй для моніторингу, а не замість статусу рахунку.
Автентифікація та заголовки
Публічний
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/healthz"// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://api.example.com/healthz", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://api.example.com/healthz");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://api.example.com/healthz",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 healthy; 503 database unavailable
Приклад відповіді
{
"status": "ok",
"database": "ok",
"version": "0.1.0"
}Поля відповіді
Примітки до використання
- Bearer-токен не потрібен.
- Значення version - це версія запущеного пакета, а не версія шляху API.
Помилки
GETСписок платіжних активів проєкту/v1/projects/{project_id}/payment-assetsЛише читання
Список нативних активів і перевірених токенів із політикою проєкту, готовністю гаманця мережі та встановленими можливостями сканера/балансів. scanner_ready - ознака наявності адаптера в збірці, а не результат поточного кворуму вузлів. З 6.0.6 створення зберігає налаштовані способи під час простою сканера. Перевірка надходження все одно потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1).
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [
{
"asset": {
"id": "10000000-0000-4000-8000-000000000003",
"asset_key": "eip155:1/slip44:60",
"chain_slug": "ethereum",
"network": "mainnet",
"caip_network_id": "eip155:1",
"caip_asset_id": "eip155:1/slip44:60",
"asset_kind": "native",
"payment_rail": "evm-native",
"symbol": "ETH",
"name": "Ethereum",
"decimals": 18,
"contract_address": null,
"coingecko_id": "ethereum",
"icon_path": "/assets/coingecko/ethereum.png",
"token_standard": null,
"metadata_verified_at": null,
"payment_supported": true,
"scanner_ready": true,
"balance_ready": true,
"default_finality_mode": "confirmations",
"default_required_confirmations": 12,
"default_monitoring_minutes": 60
},
"policy": {
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 12,
"monitoring_minutes": 60,
"late_monitoring_days": 30
},
"wallet": null,
"wallet_readiness": "wallet_missing",
"receive_readiness": { "ready": false, "invoice_creatable": false, "checked_at": "2026-09-16T09:00:00Z", "issues": [{ "chain_slug": "ethereum", "asset_id": "10000000-0000-4000-8000-000000000003", "asset_ticker": "ETH", "reason_code": "wallet_missing", "message": "ethereum / ETH: Create a project wallet for this chain.", "action": "wallets" }] }
}
]
}Поля відповіді
data[]object[]
assetobjectзавжди
Постійний запис нативного активу або перевіреного токена.
idUUIDзавждиПостійний ідентифікатор платіжного активу, який використовують маршрути політик проєкту й магазину.
asset_kindnative | tokenзавждиЧи остаточна оплата використовує валюту мережі або перевірений контракт/mint.
payment_railstringзавждиКанал виконання: utxo, evm-native, solana-native, account-native, privacy-native або token-transfer.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативних активів.
coingecko_idstring | nullзавждиІдентифікатор пошуку/ціноутворення. Null для власних контрактів; ніколи не визначай ринкову ціну лише за їхнім тикером. Самі метадані CoinGecko не роблять токен доступним для вибору.
custom_tokenbooleanзавждиВласний контракт, перевірений у блокчейні, з фіксованою ціною USD або ціною вибраного DEX-пулу в межах проєкту.
token_standarderc20 | spl-token | nullзавждиПеревірений стандарт токена для виконання; null для нативних активів.
metadata_verified_attimestamp | nullзавждиЧас перевірки метаданих у блокчейні для зареєстрованих токенів.
payment_supportedbooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
scanner_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
balance_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
default_finality_modeconfirmations | finalizedзавждиСтандартна модель фінальності, яку успадковує нова політика проєкту.
policyobject | nullзавжди
Політика активації/фінальності проєкту або null, якщо не налаштована. Містить custom_price_mode (fixed/dex), custom_price_usd (рядок фіксованої десяткової ціни або null), custom_dex_pair (вибраний пул або null) і custom_dex (dex_id, quote_symbol, поточна price_usd або null, liquidity_usd, fetched_at, last_error). Власне ціноутворення спільне для магазинів цього проєкту.Деталі
Політика активації/фінальності проєкту або null, якщо не налаштована. Містить custom_price_mode (fixed/dex), custom_price_usd (рядок фіксованої десяткової ціни або null), custom_dex_pair (вибраний пул або null) і custom_dex (dex_id, quote_symbol, поточна price_usd або null, liquidity_usd, fetched_at, last_error). Власне ціноутворення спільне для магазинів цього проєкту.
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
walletobject | nullзавжди
Некастодіальний гаманець проєкту для мережі. Токени використовують спільний гаманець її нативного активу.
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
wallet_readinessreadiness enumзавждиunsupported, project_disabled, project_asset_disabled, store_disabled, store_asset_disabled, wallet_missing, wallet_pending, wallet_disabled, wallet_error, backup_required, account_activation_required, external_wallet_rpc_required або ready.Деталі
unsupported, project_disabled, project_asset_disabled, store_disabled, store_asset_disabled, wallet_missing, wallet_pending, wallet_disabled, wallet_error, backup_required, account_activation_required, external_wallet_rpc_required або ready.
receive_readinessobject | null5.5.0+
Спільна оцінка налаштування приймання проєкту. Включає перевірки гаманця й незалежних провайдерів сканера, окремо від свіжості балансу та газу для надсилання. Null, якщо немає політики проєкту. Валюта/курси рахунку перевіряються під час його створення.Деталі
Спільна оцінка налаштування приймання проєкту. Включає перевірки гаманця й незалежних провайдерів сканера, окремо від свіжості балансу та газу для надсилання. Null, якщо немає політики проєкту. Валюта/курси рахунку перевіряються під час його створення.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
Примітки до використання
- Токен може бути в загальному списку, але залишатися недоступним для вибору, коли scanner_ready або payment_supported має значення false.
- Матриця можливостей оператора також потребує точної ролі API сканера; справний вузол із несумісним API не враховується.
- Токени використовують гаманець проєкту своєї нативної мережі; нова seed-фраза для них не створюється.
- Вбудовані зведення гаманців показують лише готовність і залишають баланси порожніми; для розширених балансів використовуй GET /v1/projects/{project_id}/wallets.
Помилки
PUTОновити політику активів проєкту/v1/projects/{project_id}/payment-assets/{asset_id}Читання + запис
Створює або замінює політику проєкту для одного постійного активу й повертає оновлений список активів. Вимкнення нативної мережі робить її нативний актив і токени недоступними для нових рахунків, але зберігає політики токенів, гаманці та вибір магазинів для подальшого відновлення.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | обов'язково | application/json |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"enabled": true,
"finality_mode": "confirmations",
"required_confirmations": 2,
"monitoring_minutes": 60,
"late_monitoring_days": 30
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-assets/YOUR_ASSET_ID",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
Відповідь 200 application/json
Приклад відповіді
{
"data": [
{ "asset": { "id": "ASSET_UUID", "symbol": "USDC", "asset_kind": "token", "scanner_ready": true }, "policy": { "enabled": true, "finality_mode": "confirmations", "required_confirmations": 2, "monitoring_minutes": 60, "late_monitoring_days": 30 }, "wallet_readiness": "ready" }
]
}Поля відповіді
data[]object[]
assetobjectзавжди
Постійний запис нативного активу або перевіреного токена.
idUUIDзавждиПостійний ідентифікатор платіжного активу, який використовують маршрути політик проєкту й магазину.
asset_kindnative | tokenзавждиЧи остаточна оплата використовує валюту мережі або перевірений контракт/mint.
payment_railstringзавждиКанал виконання: utxo, evm-native, solana-native, account-native, privacy-native або token-transfer.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативних активів.
coingecko_idstring | nullзавждиІдентифікатор пошуку/ціноутворення. Null для власних контрактів; ніколи не визначай ринкову ціну лише за їхнім тикером. Самі метадані CoinGecko не роблять токен доступним для вибору.
custom_tokenbooleanзавждиВласний контракт, перевірений у блокчейні, з фіксованою ціною USD або ціною вибраного DEX-пулу в межах проєкту.
token_standarderc20 | spl-token | nullзавждиПеревірений стандарт токена для виконання; null для нативних активів.
metadata_verified_attimestamp | nullзавждиЧас перевірки метаданих у блокчейні для зареєстрованих токенів.
payment_supportedbooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
scanner_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
balance_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
default_finality_modeconfirmations | finalizedзавждиСтандартна модель фінальності, яку успадковує нова політика проєкту.
policyobject | nullзавжди
Політика активації/фінальності проєкту або null, якщо не налаштована. Містить custom_price_mode (fixed/dex), custom_price_usd (рядок фіксованої десяткової ціни або null), custom_dex_pair (вибраний пул або null) і custom_dex (dex_id, quote_symbol, поточна price_usd або null, liquidity_usd, fetched_at, last_error). Власне ціноутворення спільне для магазинів цього проєкту.Деталі
Політика активації/фінальності проєкту або null, якщо не налаштована. Містить custom_price_mode (fixed/dex), custom_price_usd (рядок фіксованої десяткової ціни або null), custom_dex_pair (вибраний пул або null) і custom_dex (dex_id, quote_symbol, поточна price_usd або null, liquidity_usd, fetched_at, last_error). Власне ціноутворення спільне для магазинів цього проєкту.
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
walletobject | nullзавжди
Некастодіальний гаманець проєкту для мережі. Токени використовують спільний гаманець її нативного активу.
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
wallet_readinessreadiness enumзавждиunsupported, project_disabled, project_asset_disabled, store_disabled, store_asset_disabled, wallet_missing, wallet_pending, wallet_disabled, wallet_error, backup_required, account_activation_required, external_wallet_rpc_required або ready.Деталі
unsupported, project_disabled, project_asset_disabled, store_disabled, store_asset_disabled, wallet_missing, wallet_pending, wallet_disabled, wallet_error, backup_required, account_activation_required, external_wallet_rpc_required або ready.
receive_readinessobject | null5.5.0+
Спільна оцінка налаштування приймання проєкту. Включає перевірки гаманця й незалежних провайдерів сканера, окремо від свіжості балансу та газу для надсилання. Null, якщо немає політики проєкту. Валюта/курси рахунку перевіряються під час його створення.Деталі
Спільна оцінка налаштування приймання проєкту. Включає перевірки гаманця й незалежних провайдерів сканера, окремо від свіжості балансу та газу для надсилання. Null, якщо немає політики проєкту. Валюта/курси рахунку перевіряються під час його створення.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
Примітки до використання
- Тіло повністю замінює політику; невідомі поля відхиляються.
- Увімкнення в проєкті саме по собі не вибирає актив для жодного магазину.
Помилки
GETПереглянути токени-кандидати для оплати/v1/projects/{project_id}/payment-token-candidatesЛише читання
Шукає локально кешовані зіставлення контрактів CoinGecko лише в мережах із реалізованими сканером токен-рахунків та адаптером балансів. Результати - кандидати пошуку, а не довірені платіжні активи.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Параметри запиту
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-candidates?chain_slug=ethereum&q=USDC&limit=50",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [
{
"coingecko_id": "usd-coin",
"chain_slug": "ethereum",
"symbol": "USDC",
"name": "USDC",
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"market_cap_rank": 7,
"icon_path": "/assets/coingecko/usd-coin.png",
"current_price_usd": "1.0001",
"token_standard": "erc20",
"scanner_ready": true,
"registered_asset_id": null,
"project_enabled": false
}
]
}Поля відповіді
data[]object[]
contract_addressstringзавждиЗіставлений контракт або mint; перед реєстрацією перевіряється в блокчейні.
Примітки до використання
- Підтримувані адаптери токенів: ERC-20 в Ethereum, Base, BNB Chain, HyperEVM, Avalanche, Polygon, Arbitrum та Optimism; SPL у Solana.
- Непідтримувані мережі каталогу відхиляються, а не показуються доступними для вибору.
- Рейтинг, іконка й ціна CoinGecko - довідкові пошукові дані.
Помилки
POSTПеревірити й зареєструвати токен/v1/projects/{project_id}/payment-token-assetsЧитання + запис
Додає одного поточного кандидата до постійного платіжного реєстру лише після перевірки налаштованими вузлами ідентичності мережі, контракту/mint, точності й робочого запиту балансу. Реєстрація ніколи не довіряє лише метаданим CoinGecko; кожен проєкт обмежений 20 зареєстрованими токен-активами.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | обов'язково | application/json |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"enabled": true
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
chain_slugstringобов'язковоethereum, base, bnb-chain, hyperliquid, avalanche, polygon, arbitrum, optimism або solana.
coingecko_idstringобов'язковоТочний ідентифікатор кандидата з пошуку токенів. Зберігай початкові підкреслення чи дефіси, наприклад _ або -6. Не виводь цей ID із назви чи тикера токена.Деталі
Точний ідентифікатор кандидата з пошуку токенів. Зберігай початкові підкреслення чи дефіси, наприклад _ або -6. Не виводь цей ID із назви чи тикера токена.
Відповідь 201 application/json
Приклад відповіді
{
"data": {
"asset_id": "44444444-4444-4444-8444-444444444444",
"chain_slug": "ethereum",
"coingecko_id": "usd-coin",
"contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"token_standard": "erc20",
"symbol": "USDC",
"name": "USDC",
"decimals": 6,
"enabled": true,
"metadata_verified_at": "2026-08-31T18:00:00Z"
}
}Поля відповіді
dataobject
Примітки до використання
- Перед реєстрацією токенів увімкни нативний актив мережі в проєкті.
- Проєкт може зареєструвати щонайбільше 20 токен-активів; новий кандидат понад ліміт повертає token_chain_not_ready (409). Повторне використання зареєстрованого активу не займає ще одне місце.
- Перевірка вузлів може тривати довше за читання каталогу; явно встанови тайм-аут клієнта.
- Після реєстрації вибери актив для кожного магазину, який має його пропонувати.
Помилки
GETЗнайти DEX-пули власного токена/v1/projects/{project_id}/payment-token-dex-poolsЛише читання
Знаходить до 12 придатних пулів за точною мережею й контрактом базового токена через DEX Screener, у порядку ліквідності. Це не реєструє й не вмикає токен.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
Параметри шляху
Параметри запиту
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-dex-pools?chain_slug=ethereum&contract_address=YOUR_TOKEN_CONTRACT",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{"data":[{"pair_address":"0x2222222222222222222222222222222222222222","dex_id":"uniswap","quote_symbol":"WETH","price_usd":"0.25","liquidity_usd":"250000.00","fetched_at":"2026-09-09T12:00:00Z","url":"https://dexscreener.com/ethereum/0x2222222222222222222222222222222222222222"}]}Поля відповіді
data[]object[]
pair_addressstringзавждиТочний ідентифікатор пулу, ID біржі (наприклад uniswap/pancakeswap) і тикер парного активу лише для відображення.
dex_idstringзавждиТочний ідентифікатор пулу, ID біржі (наприклад uniswap/pancakeswap) і тикер парного активу лише для відображення.
quote_symbolstringзавждиТочний ідентифікатор пулу, ID біржі (наприклад uniswap/pancakeswap) і тикер парного активу лише для відображення.
price_usddecimal stringзавждиЦіна запитаного базового токена в USD і загальна ліквідність пулу. Потрібні ліквідність щонайменше $10,000 та угода протягом останньої години.
liquidity_usddecimal stringзавждиЦіна запитаного базового токена в USD і загальна ліквідність пулу. Потрібні ліквідність щонайменше $10,000 та угода протягом останньої години.
fetched_atRFC 3339 timestampзавждиЧас отримання сервером спостереження провайдера, а не час угоди в блокчейні.
Примітки до використання
- Порожній масив data означає, що придатний пул не знайдено. Повертаються лише пули, де точний запитаний контракт є базовим токеном; ціни USD для котирувальної сторони не припускаються.
- Наявність на DEX не є аудитом безпеки. Мінімальна ліквідність і недавня активність зменшують кількість непридатних котирувань, але не запобігають маніпуляціям ринком.
- Uniswap, PancakeSwap та інші індексовані DEX підтримуються там, де наявний сканер мережі підтримує токени. Доступ до API залишається обмеженим проєктом і частотою. Виклики провайдера також виконуються послідовно й з обмеженням частоти.
Помилки
POSTДодати власний токен або змінити його ціну/v1/projects/{project_id}/payment-token-assets/customЧитання + запис
Перевіряє власний контракт через налаштовані вузли мережі й реєструє його без вимоги бути в CoinGecko. Фіксована ціна USD або вибраний автоматичний DEX-пул належить цьому проєкту, а не тикеру чи іншим проєктам. Повторення тієї ж ідентичності оновлює ціну проєкту, не змінюючи наявну політику ввімкнення/вимкнення.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | обов'язково | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"chain_slug": "ethereum",
"contract_address": "YOUR_VERIFIED_TOKEN_CONTRACT",
"name": "Example token",
"symbol": "EXAMPLE",
"price_usd": "0.25"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/payment-token-assets/custom",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
chain_slugstringобов'язковоethereum, base, bnb-chain, hyperliquid, avalanche, polygon, arbitrum, optimism або solana. Фіксується для цього контракту.
contract_addressstringобов'язковоКонтракт ERC-20 (0x і 40 шістнадцяткових символів) або mint класичного SPL. Вузли перевіряють ідентичність мережі й точну кількість знаків; передані клієнтом decimals та URL RPC відхиляються.Деталі
Контракт ERC-20 (0x і 40 шістнадцяткових символів) або mint класичного SPL. Вузли перевіряють ідентичність мережі й точну кількість знаків; передані клієнтом decimals та URL RPC відхиляються.
namestringобов'язковоВідображувана назва (1–80 символів) і тикер (1–16 літер/цифр/крапок/підкреслень/дефісів, перший символ - літера або цифра). Цей ендпойнт не може перейменувати наявні ідентичності.Деталі
Відображувана назва (1–80 символів) і тикер (1–16 літер/цифр/крапок/підкреслень/дефісів, перший символ - літера або цифра). Цей ендпойнт не може перейменувати наявні ідентичності.
symbolstringобов'язковоВідображувана назва (1–80 символів) і тикер (1–16 літер/цифр/крапок/підкреслень/дефісів, перший символ - літера або цифра). Цей ендпойнт не може перейменувати наявні ідентичності.Деталі
Відображувана назва (1–80 символів) і тикер (1–16 літер/цифр/крапок/підкреслень/дефісів, перший символ - літера або цифра). Цей ендпойнт не може перейменувати наявні ідентичності.
price_modefixed | dexнеобов'язковоТипово fixed для зворотної сумісності. DEX використовує конкретний пул, знайдений для точної мережі й контракту.
price_usddecimal stringрежим fixedФіксована вартість ОДНОГО токена в USD, додатна, щонайбільше 30 десяткових знаків, максимум 1000000000000000000000000. Без експоненти чи чисел із рухомою комою. Не передавай у режимі dex.
dex_pair_addressstringрежим dexАдреса пулу з payment-token-dex-pools. Обов’язкова в режимі dex; не передавай у fixed. Під час кожного збереження сервер повторно перевіряє ідентичність пулу, ціну, ліквідність і активність.Деталі
Адреса пулу з payment-token-dex-pools. Обов’язкова в режимі dex; не передавай у fixed. Під час кожного збереження сервер повторно перевіряє ідентичність пулу, ціну, ліквідність і активність.
Відповідь 200 application/json
Приклад відповіді
{"data":{"asset_id":"44444444-4444-4444-8444-444444444444"}}Поля відповіді
Примітки до використання
- Після реєстрації вибери asset_id через ендпойнт payment-assets магазину; сама реєстрація ніколи не вмикає спосіб оплати магазину.
- Власні токени й токени каталогу мають спільний ліміт 20 токенів на проєкт. Той самий контракт у різних мережах - різні платіжні активи.
- Наявні контракти каталогу повертають 409: використовуй реєстрацію з каталогу, щоб зберегти автоматичні ринкові курси. Власний тикер ніколи не запозичує ціну однойменного токена.
- Фіксовані ціни - оцінки оператора. Автоматичні DEX-ціни - спотові спостереження вибраного пулу через DEX Screener, а не стійкий до маніпуляцій оракул. Спред магазину й округлення вгору й далі застосовуються зі свіжими фіатними курсами. Уже видані котирування не змінюються.
- Для режиму DEX спочатку знайди пул, потім передай price_mode: dex і dex_pair_address без price_usd. Спільне фонове завдання оновлює вибрані пули щохвилини. Невдалі перевірки або ціни старші п’яти хвилин виключають цей токен із нових котирувань; прихованої підміни фіксованою ціною чи тикером немає.
- Приймаються лише стандартні ERC-20 і класичні SPL. Token-2022/розширення та мережі лише з нативними активами відхиляються. Технічна перевірка не є аудитом безпеки емітента/контракту; токени з комісією за переказ, ребейзингом чи чорними списками можуть поводитися несумісно.
- Використовуй тайм-аут клієнта щонайменше 60 секунд. Перевірка обмежена й може спробувати резервні вузли. Неправильні дані повертають 400; невдалі перевірки мережі/контракту - 422; конфлікти ідентичності чи ліміти - 409.
Помилки
GETСписок способів оплати магазину/v1/projects/{project_id}/stores/{store_id}/payment-assetsЛише читання
Показує активи блокчейну в data та окрему готовність Lightning у lightning. Способи в блокчейні потребують готових гаманців мережі. Lightning використовує перевірене зовнішнє підключення для приймання, вибране в магазині, незалежно від Bitcoin-гаманця в блокчейні.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [
{ "asset": { "id": "ASSET_UUID", "chain_slug": "ethereum", "symbol": "USDC", "asset_kind": "token", "token_standard": "erc20", "scanner_ready": true }, "project_policy": { "enabled": true, "required_confirmations": 12 }, "selected": true, "display_order": 0, "confirmation_policy": { "finality_mode": "confirmations", "project_required_confirmations": 12, "override_required_confirmations": 3, "effective_required_confirmations": 3, "editable": true, "minimum_required_confirmations": 0, "maximum_required_confirmations": 48 }, "wallet": { "id": "WALLET_UUID", "status": "active" }, "wallet_readiness": "ready" }
],
"lightning": { "payment_rail": "lightning", "symbol": "BTC", "asset_decimals": 11, "enabled": true, "ready": true }
}Поля відповіді
data[]object[]
assetobjectзавжди
Нативний актив або перевірений токен, видимий проєкту.
idUUIDзавждиПостійний ідентифікатор платіжного активу, який використовують маршрути політик проєкту й магазину.
asset_kindnative | tokenзавждиЧи остаточна оплата використовує валюту мережі або перевірений контракт/mint.
payment_railstringзавждиКанал виконання: utxo, evm-native, solana-native, account-native, privacy-native або token-transfer.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативних активів.
coingecko_idstring | nullзавждиІдентифікатор пошуку/ціноутворення. Null для власних контрактів; ніколи не визначай ринкову ціну лише за їхнім тикером. Самі метадані CoinGecko не роблять токен доступним для вибору.
custom_tokenbooleanзавждиВласний контракт, перевірений у блокчейні, з фіксованою ціною USD або ціною вибраного DEX-пулу в межах проєкту.
token_standarderc20 | spl-token | nullзавждиПеревірений стандарт токена для виконання; null для нативних активів.
metadata_verified_attimestamp | nullзавждиЧас перевірки метаданих у блокчейні для зареєстрованих токенів.
payment_supportedbooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
scanner_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
balance_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
default_finality_modeconfirmations | finalizedзавждиСтандартна модель фінальності, яку успадковує нова політика проєкту.
project_policyobject | nullзавжди
Батьківська політика проєкту.
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
selectedbooleanзавждиЧи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.Деталі
Чи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.
confirmation_policyobject | nullзавжди
Чинна політика магазину для налаштованого в проєкті активу. Null, якщо політики проєкту немає.
finality_modeconfirmations | finalizedзавждиЧи остаточна оплата використовує налаштовувану кількість блоків або фінальність мережі.
project_required_confirmationsintegerзавждиПоточне стандартне значення проєкту для майбутніх рахунків, якщо магазин не має перевизначення.
override_required_confirmationsinteger | nullзавждиКількість для цього магазину або null, щоб успадкувати стандарт проєкту.
effective_required_confirmationsintegerзавждиКількість, яку зафіксують нові рахунки цього магазину й активу.
minimum_required_confirmationsintegerзавждиВключна нижня межа для мережі; 0 показується лише для каналів, які підтримують прийняття під час виявлення.
walletobject | nullзавжди
Гаманець мережі, спільний для нативних активів і токенів.
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
wallet_readinessreadiness enumзавждиЛише статус гаманця/політики; передумови сканера дивись у receive_readiness.
receive_readinessobject | null5.5.0+
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.Деталі
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
Примітки до використання
- selected - конфігурація для блокчейну; wallet_readiness - її поточна умова придатності.
- Поле lightning у відповіді містить payment_rail: lightning, symbol: BTC, asset_decimals: 11, enabled і ready. Воно ніколи не містить облікових даних вузла. Налаштовуй цей спосіб у панелі магазину; оновлення масиву assets не змінює Lightning.
- confirmation_policy стосується лише способів у блокчейні. Lightning завершує оплату без підтверджень блоків і потребує повної суми BOLT11 без допуску часткової оплати.
- Нативні й токен-способи однієї мережі використовують ту саму адресу рахунку для гаманця цієї мережі.
- Вбудовані зведення гаманців показують лише готовність і залишають баланси порожніми; поточні значення отримуй через окремий маршрут гаманців проєкту.
Помилки
PUTЗамінити способи оплати магазину/v1/projects/{project_id}/stores/{store_id}/payment-assetsЧитання + запис
Атомарно замінює весь упорядкований набір активів магазину й повертає оновлений список. Пропущені активи більше не вибрані.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | обов'язково | application/json |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"assets": [
{
"asset_id": "YOUR_ASSET_ID",
"display_order": 0
}
]
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": [
{ "asset": { "id": "44444444-4444-4444-8444-444444444444", "symbol": "USDC" }, "selected": true, "display_order": 0, "confirmation_policy": { "finality_mode": "confirmations", "project_required_confirmations": 12, "override_required_confirmations": null, "effective_required_confirmations": 12, "editable": true, "minimum_required_confirmations": 0, "maximum_required_confirmations": 48 }, "wallet_readiness": "ready" }
]
}Поля відповіді
data[]object[]
assetobjectзавжди
Нативний актив або перевірений токен, видимий проєкту.
idUUIDзавждиПостійний ідентифікатор платіжного активу, який використовують маршрути політик проєкту й магазину.
asset_kindnative | tokenзавждиЧи остаточна оплата використовує валюту мережі або перевірений контракт/mint.
payment_railstringзавждиКанал виконання: utxo, evm-native, solana-native, account-native, privacy-native або token-transfer.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативних активів.
coingecko_idstring | nullзавждиІдентифікатор пошуку/ціноутворення. Null для власних контрактів; ніколи не визначай ринкову ціну лише за їхнім тикером. Самі метадані CoinGecko не роблять токен доступним для вибору.
custom_tokenbooleanзавждиВласний контракт, перевірений у блокчейні, з фіксованою ціною USD або ціною вибраного DEX-пулу в межах проєкту.
token_standarderc20 | spl-token | nullзавждиПеревірений стандарт токена для виконання; null для нативних активів.
metadata_verified_attimestamp | nullзавждиЧас перевірки метаданих у блокчейні для зареєстрованих токенів.
payment_supportedbooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
scanner_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
balance_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
default_finality_modeconfirmations | finalizedзавждиСтандартна модель фінальності, яку успадковує нова політика проєкту.
project_policyobject | nullзавжди
Батьківська політика проєкту.
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
selectedbooleanзавждиЧи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.Деталі
Чи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.
confirmation_policyobject | nullзавжди
Чинна політика магазину для налаштованого в проєкті активу. Null, якщо політики проєкту немає.
finality_modeconfirmations | finalizedзавждиЧи остаточна оплата використовує налаштовувану кількість блоків або фінальність мережі.
project_required_confirmationsintegerзавждиПоточне стандартне значення проєкту для майбутніх рахунків, якщо магазин не має перевизначення.
override_required_confirmationsinteger | nullзавждиКількість для цього магазину або null, щоб успадкувати стандарт проєкту.
effective_required_confirmationsintegerзавждиКількість, яку зафіксують нові рахунки цього магазину й активу.
minimum_required_confirmationsintegerзавждиВключна нижня межа для мережі; 0 показується лише для каналів, які підтримують прийняття під час виявлення.
walletobject | nullзавжди
Гаманець мережі, спільний для нативних активів і токенів.
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
wallet_readinessreadiness enumзавждиЛише статус гаманця/політики; передумови сканера дивись у receive_readiness.
receive_readinessobject | null5.5.0+
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.Деталі
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
Примітки до використання
- Масив приймає щонайбільше 64 унікальні активи й порядкові номери.
- Вибір - збережена бажана конфігурація; його можна підготувати до резервного копіювання гаманця або під час паузи мережі. Під час створення рахунку все одно пропонуються лише способи з готовими політикою проєкту, політикою батьківського нативного активу, гаманцем і перевірками виконання.
- Передай порожній масив assets, щоб не налаштовувати жодного способу оплати.
Помилки
PUTЗадати політику підтверджень магазину/v1/projects/{project_id}/stores/{store_id}/payment-assets/{asset_id}/confirmation-policyЧитання + запис
Задає або скидає одне перевизначення підтверджень магазину й повертає оновлений список способів оплати. Актив уже має бути вибраний у магазині. Налаштування доступне й під час паузи проєкту, магазину, мережі чи гаманця.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Content-Type | обов'язково | application/json |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request PUT \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"strategy": "custom",
"required_confirmations": 0
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const body = `{
"strategy": "custom",
"required_confirmations": 0
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy", {
method: "PUT",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$body = <<<'JSON'
{
"strategy": "custom",
"required_confirmations": 0
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"strategy": "custom",
"required_confirmations": 0
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/payment-assets/YOUR_ASSET_ID/confirmation-policy",
method="PUT", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
Відповідь 200 application/json
Приклад відповіді
{
"data": [
{
"asset": { "id": "YOUR_ASSET_ID", "chain_slug": "bitcoin", "symbol": "BTC" },
"selected": true,
"display_order": 0,
"confirmation_policy": {
"finality_mode": "confirmations",
"project_required_confirmations": 2,
"override_required_confirmations": 0,
"effective_required_confirmations": 0,
"editable": true,
"minimum_required_confirmations": 0,
"maximum_required_confirmations": 10000
},
"wallet_readiness": "ready"
}
]
}Поля відповіді
data[]object[]
assetobjectзавжди
Нативний актив або перевірений токен, видимий проєкту.
idUUIDзавждиПостійний ідентифікатор платіжного активу, який використовують маршрути політик проєкту й магазину.
asset_kindnative | tokenзавждиЧи остаточна оплата використовує валюту мережі або перевірений контракт/mint.
payment_railstringзавждиКанал виконання: utxo, evm-native, solana-native, account-native, privacy-native або token-transfer.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативних активів.
coingecko_idstring | nullзавждиІдентифікатор пошуку/ціноутворення. Null для власних контрактів; ніколи не визначай ринкову ціну лише за їхнім тикером. Самі метадані CoinGecko не роблять токен доступним для вибору.
custom_tokenbooleanзавждиВласний контракт, перевірений у блокчейні, з фіксованою ціною USD або ціною вибраного DEX-пулу в межах проєкту.
token_standarderc20 | spl-token | nullзавждиПеревірений стандарт токена для виконання; null для нативних активів.
metadata_verified_attimestamp | nullзавждиЧас перевірки метаданих у блокчейні для зареєстрованих токенів.
payment_supportedbooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
scanner_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
balance_readybooleanзавждиУмови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.Деталі
Умови реєстру на етапі збірки. scanner_ready означає, що модуль сканера платежів встановлено; підтвердження платежу потребує налаштованої кількості справних провайдерів точної ролі (типово 2, за вибором 1); тимчасова недоступність сканера не блокує створення рахунків з 6.0.6. balance_ready має значення true лише для реалізованих адаптерів балансів.
default_finality_modeconfirmations | finalizedзавждиСтандартна модель фінальності, яку успадковує нова політика проєкту.
project_policyobject | nullзавжди
Батьківська політика проєкту.
enabledbooleanобов'язковоВмикає або вимикає актив для проєкту. Перед будь-яким токеном треба ввімкнути його нативну мережу.
finality_modeconfirmations | finalizedобов'язковоПолітика фінальності, яку підтримує канал активу. finalized потребує required_confirmations=1.
required_confirmationsintegerобов'язковоКанали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.Деталі
Канали Bitcoin та EVM допускають нуль; інші канали з підтвердженнями потребують щонайменше одного, канали лише finalized - рівно одного, а EVM обмежені 0–48, щоб кожен переказ залишався у вікні повторного відтворення транзакцій.
selectedbooleanзавждиЧи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.Деталі
Чи цей спосіб входить до збереженої бажаної конфігурації магазину. Він пропонується, коли політика проєкту, гаманець, встановлений адаптер і ціноутворення дійсні. Тимчасові збої сканера не виключають його з нових рахунків.
confirmation_policyobject | nullзавжди
Чинна політика магазину для налаштованого в проєкті активу. Null, якщо політики проєкту немає.
finality_modeconfirmations | finalizedзавждиЧи остаточна оплата використовує налаштовувану кількість блоків або фінальність мережі.
project_required_confirmationsintegerзавждиПоточне стандартне значення проєкту для майбутніх рахунків, якщо магазин не має перевизначення.
override_required_confirmationsinteger | nullзавждиКількість для цього магазину або null, щоб успадкувати стандарт проєкту.
effective_required_confirmationsintegerзавждиКількість, яку зафіксують нові рахунки цього магазину й активу.
minimum_required_confirmationsintegerзавждиВключна нижня межа для мережі; 0 показується лише для каналів, які підтримують прийняття під час виявлення.
walletobject | nullзавжди
Гаманець мережі, спільний для нативних активів і токенів.
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
wallet_readinessreadiness enumзавждиЛише статус гаманця/політики; передумови сканера дивись у receive_readiness.
receive_readinessobject | null5.5.0+
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.Деталі
Спільне налаштування приймання плюс дозвіл магазину. Використовує кешовані спостереження; це не резервування чи гарантія. Створення повторно перевіряє вимоги та фактичний курс рахунку.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
Примітки до використання
- Використовуй {"strategy":"inherit"}, щоб прибрати перевизначення магазину й застосовувати поточний стандарт проєкту до майбутніх рахунків.
- Мережі finalized повертають editable false і використовують фінальність мережі; власне перевизначення кількості блоків не приймають.
- Значення 0 означає прийняття після виявлення без підтверджень мережі й захисту від реорганізації. Дозволене лише там, де minimum_required_confirmations дорівнює 0.
- Зміни політики впливають лише на нові рахунки. Наявні зберігають знімок політики підтверджень проєкту/магазину, зроблений під час створення.
- Оновлення виконуються по одному активу; послідовно обробляй одночасні зміни того самого активу магазину й використовуй оновлену відповідь як поточний стан.
Помилки
GETСписок гаманців і балансів проєкту/v1/projects/{project_id}/walletsЛише читання
Повертає публічні метадані гаманця та всі зареєстровані активи з підтримкою балансів у точному блокчейні й мережі гаманця. Охоплено всі 30 нативних каналів; перевірені ERC-20 і SPL також відстежуються. Активи з’являються одразу, навіть до першого сканування або якщо їх не приймають для оплати. project_enabled показує приймання платежів; tracking_active незалежно показує придатність до оновлення лише для читання. Monero потребує прив’язаного до проєкту зовнішнього wallet-RPC лише для перегляду. Сканування балансів у панелі надає пріоритет обмеженим читанням із прогресом/помилками для кожного активу; свіжі підсумки оновлюються лише після повного циклу. Остаточну оплату рахунку й далі визначають моніторинг транзакцій і політика підтверджень, а не ці кешовані баланси.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets" \
--header "Authorization: Bearer $WHOLLY_TOKEN"// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/wallets",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [
{
"id": "55555555-5555-4555-8555-555555555555",
"project_id": "11111111-1111-4111-8111-111111111111",
"native_asset_id": "10000000-0000-4000-8000-000000000003",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_symbol": "ETH",
"asset_name": "Ethereum",
"status": "active",
"label": "Primary Ethereum wallet",
"public_key": "0x…",
"primary_address": "0x…",
"derivation_scheme": "bip44",
"address_format": "eip55",
"backup_confirmed_at": "2026-08-31T17:00:00Z",
"last_secret_revealed_at": null,
"secret_reveal_count": 0,
"next_receive_index": 43,
"last_scanned_height": 23123456,
"last_scanned_at": "2026-08-31T18:05:00Z",
"last_error": null,
"balances": [
{ "wallet_id": "55555555-5555-4555-8555-555555555555", "asset_id": "10000000-0000-4000-8000-000000000003", "project_enabled": true, "tracking_active": true, "asset_kind": "native", "contract_address": null, "symbol": "ETH", "name": "Ethereum", "decimals": 18, "coingecko_id": "ethereum", "balance": "0.125", "balance_atomic": "125000000000000000", "price_usd": "4500", "value_usd": "562.50", "status": "fresh", "checked_at": "2026-08-31T18:05:00Z", "last_error": null },
{ "wallet_id": "55555555-5555-4555-8555-555555555555", "asset_id": "10000000-0000-4000-8000-000000000099", "project_enabled": false, "tracking_active": true, "asset_kind": "token", "contract_address": "0xA0b86991c6218b36c1d19d4a2e9eb0cE3606eB48", "symbol": "USDC", "name": "USDC", "decimals": 6, "coingecko_id": "usd-coin", "balance": null, "balance_atomic": null, "price_usd": "1", "value_usd": null, "status": "pending", "checked_at": null, "last_error": null }
],
"total_value_usd": "562.50",
"balance_status": "fresh",
"balance_checked_at": "2026-08-31T18:05:00Z",
"recent_payments": [
{ "invoice_public_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50", "chain_slug": "ethereum", "symbol": "USDC", "transaction_id": "0x…", "event_index": 0, "amount": "25", "status": "final", "confirmations": 12, "observed_at": "2026-08-31T18:04:00Z" }
],
"created_at": "2026-08-31T16:00:00Z",
"updated_at": "2026-08-31T18:05:00Z"
}
]
}Поля відповіді
data[]object[]
public_keystring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
primary_addressstring | nullзавждиПублічна ідентичність гаманця; seed-фраза й приватний ключ не розкриваються.
backup_confirmed_attimestamp | nullзавждиНе null після підтвердження оператором резервної копії для відновлення.
activation_requiredbooleanзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
activation_verified_attimestamp|nullзавждиСпільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.Деталі
Спільні рахунки XRP і Stellar залишаються недоступними, доки оператор не поповнить показану адресу, а налаштовані провайдери сканера не перевірять саме цей рахунок. Постійний доказ не має строку дії; поточний стан сканера перевіряється окремо для верифікації платежів, а не створення рахунків.
receive_readinessobject | null5.5.0+
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.Деталі
Включається до списків гаманців: налаштування приймання проєкту й передумови сканера мережі. Окремо від балансів, газу токенів і готовності до надсилання. В інших відповідях гаманців може бути null.
readybooleanзавждиПеревірки налаштування приймання пройдено. Не описує готовність витрачати, газ, оновлення балансу чи гарантоване майбутнє котирування.
invoice_creatableboolean6.0.6+Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.Деталі
Налаштування дозволяє спосіб оплати рахунку попри тимчасові попередження сканера. Курс валюти перевіряється під час створення. Це не перевірка платежу: ready може бути false, коли invoice_creatable - true. Відсутні гаманці, вимкнена політика й непідтримувані адаптери й далі безпечно блокують операцію.
checked_attimestampзавждиЧас оцінки. Отримання списку не робить мережевих запитів і не виділяє адрес.
issues[]object[]завжди
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.Деталі
Порожньо, коли все готово; інакше - попередження приймання або перешкода в налаштуваннях. Перевір invoice_creatable, щоб відрізнити тимчасові попередження сканера від помилок налаштування рахунку.
chain_slugstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
asset_tickerstringякщо відомоВказує відповідний блокчейн і актив. Lightning може не містити asset_id.
reason_codestringзавждиscanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.Деталі
scanner_provider_quorum, scanner_not_checked, scanner_unavailable, wallet_missing, wallet_disabled, wallet_backup_required, wallet_key_unavailable, wallet_activation_required, monero_binding_unavailable, rate_unavailable, custom_rate_unavailable, lightning_unavailable, project_disabled, store_disabled, chain_disabled, asset_disabled або asset_not_accepted.
messagestringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
actionstringякщо доступноПояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.Деталі
Пояснення для мерчанта й ідентифікатор дії: chain_connections, wallets, rates, payment_methods, project_settings або store_settings. Без облікових даних і приватних URL провайдерів.
required_endpoint_rolestring | nullу блокчейніБажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.Деталі
Бажана роль API сканера (застаріле поле). Повний список сумісності дивись в accepted_endpoint_roles. Справність базових функцій вузла не доводить підтримку історії платежів.
accepted_endpoint_roles[]string[] | nullу блокчейніСумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.Деталі
Сумісні діалекти API, а не доказ наявності історії чи достатньої потужності вузла. Сирий node-rpc підтримує BTC/BCH/LTC/DOGE/DASH і прозорий ZEC (повні декодовані блоки, 1–48 підтверджень), solidified нативний TRX, нативний ALGO через algod, XTZ через Octez, finalized DOT Asset Hub через метадані SCALE та нативний XLM через Stellar RPC із memo ID рахунку. Обрізана чи неповна історія не підходить. Ці сирі адаптери не додають токен-каналів. Індексовані API залишаються альтернативами; дивись таблицю каналів нижче. Змішані сирі/індексовані джерела незалежно перевіряють обмежені вікна; типово залишаються два незалежні провайдери, а не псевдоніми одного оператора. Базова висота вузла, інформація про мережу ORDnet та EVM relay для не-EVM каналу не є доказами приймання. Monero все одно потребує прив’язаного до проєкту wallet-RPC лише для перегляду.
healthy_endpointsintegerу блокчейніСправні відповідні вузли, а не кількість незалежних провайдерів.
usable_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
required_independent_providersintegerу блокчейніДоступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.Деталі
Доступні слоти перевірки, не більше двох. required_independent_providers - налаштування мережі: типово 2 або 1 після явного вибору адміністратора. У режимі двох провайдерів потрібні різні ключі провайдерів І хости. Вимкнені, застарілі (понад десять хвилин) або тимчасово обмежені джерела не займають слот. Lightning використовує власні правила підключення.
last_checked_attimestamp | nullу блокчейніОстання перевірка справності відповідного вузла, окремо від часу оцінки.
monero_wallet_rpcMoneroWalletRpcBinding | nullзавждиОчищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.Деталі
Очищений від секретів стан прив’язки зовнішнього wallet-RPC лише для перегляду Monero. Містить адресу сервісу, режим автентифікації, основну адресу account-0, прапорці/висоти технічних доказів і час підтверджень оператора; облікові дані, ключі та файли гаманця ніколи не серіалізуються.
balances[]object[]завжди
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.Деталі
Кешовані баланси для всіх 30 каналів нативних мереж, а також перевірених активів ERC-20 і SPL. Для Monero потрібен налаштований зовнішній wallet-RPC лише для перегляду.
active_store_countintegerзавждиКількість увімкнених магазинів, які зараз вибрали цей актив. Це подання приймання; відстеження балансу лише для читання залишається незалежним.
active_store_ids[]UUID[]завждиУвімкнені магазини цього проєкту, які зараз приймають актив. Це дозволяє точно фільтрувати магазини локально без додаткового API-запиту.
tracking_activebooleanзавждиЧи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.Деталі
Чи гаманець із можливістю читання й зареєстрований актив тієї ж мережі підлягають фоновому оновленню балансів. Перемикачі приймання проєкту та способів оплати не зупиняють відстеження лише для читання.
balancedecimal string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
balance_atomicinteger string|nullзавждиТочний баланс у відображуваних і найменших одиницях для основної адреси гаманця та виданих адрес рахунків разом. Null, поки повне значення недоступне.
statuspending | refreshing | fresh | stale | errorзавждиКешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.Деталі
Кешований стан сканування. refreshing може зберігати завершений баланс: його вік визначай за checked_at. Pending означає відсутність завершеного знімка. Жоден із цих станів не доводить, що переказ очікує виконання чи рахунок остаточно оплачений.
balance_statuspending | refreshing | fresh | stale | error | unknownзавждиСукупна свіжість кешу; unknown - захисне резервне значення, і жоден із цих станів не доводить остаточну оплату рахунку.
balance_checked_attimestamp | nullзавждиНайстаріша відповідна успішна перевірка балансу, представлена в сукупному значенні.
recent_payments[]object[]завжди
До трьох найновіших дійсних спостережень detected, confirming або final, віднесених саме до цього гаманця.
statusdetected | confirming | finalзавждиПоточний дійсний стан спостереження. Спостереження reorged, replaced та invalid виключено.
Примітки до використання
- Цей bearer-маршрут ніколи не повертає фразу відновлення, приватний ключ, зашифрований секрет або спосіб витрачання.
- Щойно зареєстрований актив тієї ж мережі до першого завершеного сканування повертається з балансами null і статусом pending; вигаданий нуль ніколи не повідомляється.
- Вимкнення проєкту, гаманця для приймання платежів, нативного каналу або окремого активу не зупиняє відстеження балансів лише для читання: активні й вимкнені гаманці з основною адресою продовжують оновлювати всі зареєстровані підтримувані активи тієї ж мережі. Гаманці pending та error не скануються.
- project_enabled показує лише політику приймання активу проєкту й може бути false, поки tracking_active залишається true.
- balance і balance_atomic - точні рядки; price_usd, value_usd та total_value_usd - довідкові й можуть бути null. Свіжий статус балансу не гарантує свіжої ринкової ціни.
- Оцінка віддає перевагу цінам CoinGecko віком до двох годин. Нативні монети й перевірені канонічні USDC/USDT можуть резервно використовувати ввімкнені USD-котирування Kraken/Binance віком до п’яти хвилин, спочатку основного провайдера. Немає припущення про прив’язку до долара чи ціни власного токена лише за тикером; фіксовані/DEX-ціни проєкту залишаються окремими. Котирування рахунків не змінюються.
- Pending не має повного знімка. Refreshing зберігає останню завершену суму та checked_at; це не означає очікування переказу в блокчейні. Суми stale/error також можуть зберігати старі значення. Ніколи не вважай недоступний кеш нулем або відсутнім платежем. Звичайні оновлення EVM/Solana повторно використовують нещодавно перевірені порожні адреси до 30 хвилин між повними перевірками, а поповнені, нові та змінені адреси перевіряються знову. Явне сканування балансів у панелі запитує повне сканування.
- recent_payments обмежено трьома спостереженнями на гаманець; скасована історія виключається.
Помилки
POSTСтворити рахунок/v1/projects/{project_id}/stores/{store_id}/invoicesЧитання + запис
Атомарно створює рахунок з адресами гаманців, свіжими точними котируваннями, історією аудиту й записами черги сповіщень. Повторення ідентичних байтів тіла з тими самими обліковими даними та Idempotency-Key повертає початковий рахунок.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Idempotency-Key | обов'язково | Унікальні 1–128 видимих ASCII-символів без пробільних символів. |
| Content-Type | рекомендовано | application/json. Поточний обробник сирого тіла розбирає JSON без примусової перевірки типу вмісту. |
| Accept | рекомендовано | application/json |
Параметри шляху
project_idUUIDобов'язковоСкопіюй Project API ID з Проєкт → Налаштування → API IDs. Проєкт має бути призначений обліковим даним; читабельний ідентифікатор не приймається.
store_idUUIDобов'язковоСкопіюй Store API ID з Проєкт → Магазини → вибери магазин → Основне → API IDs. Обов’язковий навіть для стандартного магазину; магазин має бути ввімкнений і належати project_id.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": "49.90",
"currency": "USD"
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"amount": "49.90",
"currency": "USD"
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"amount": "49.90",
"currency": "USD"
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"amount": "49.90",
"currency": "USD"
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response)): "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
# Keep this key and the exact body for retries; use a new key for each new invoice.
curl --fail-with-body --max-time 30 \
--request POST \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Idempotency-Key: order-1042-attempt-1' \
--header 'Content-Type: application/json' \
--data-raw '{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
// Keep this key and the exact body for retries; use a new key for each new invoice.
const body = `{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}`;
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices", {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
},
body,
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
// Keep this key and the exact body for retries; use a new key for each new invoice.
$body = <<<'JSON'
{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}
JSON;
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Idempotency-Key: order-1042-attempt-1", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
# Keep this key and the exact body for retries; use a new key for each new invoice.
headers = {
"Idempotency-Key": "order-1042-attempt-1",
"Content-Type": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
body = """{
"payment_methods": [
{
"chain_slug": "bitcoin",
"asset_tickers": [
"BTC"
]
}
],
"amount": "49.90",
"currency": "USD",
"order_id": "order-1042",
"email": "ada@example.com",
"description": "Annual plan",
"underpayment_tolerance_percent": "1",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"language": "en",
"metadata": {
"cart_id": "cart-681",
"firstname": "Ada",
"lastname": "Lovelace",
"street": "12 Example Street",
"street2": "Suite 2",
"zip": "10115",
"city": "Berlin",
"country": "Germany",
"countryiso2": "DE",
"company": "Example GmbH",
"vatid": "DE123456789"
},
"exchange_rate_spread_percent": "0.5",
"checkout_appearance": {
"title": "Complete your order",
"intro": "Thanks for choosing our annual plan.",
"outro": "Questions? https://merchant.example/help",
"intro_font_size": 18,
"outro_font_size": 14,
"theme": "light",
"accent_color": "#1768CE",
"messages": {
"en": {
"paid": "Your order is ready."
}
}
}
}""".encode("utf-8")
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/invoices",
method="POST", headers=headers, data=body)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Тіло запиту
amountstringобов'язковоЗвичайний десятковий рядок без знака чи експоненти, до 48 цілих і 30 дробових знаків. Типово має бути додатним. Магазин може дозволити нульові рахунки в Магазини → Рахунок; нульові суми завершуються без отримання коштів, виділення адрес чи плати за обробку.Деталі
Звичайний десятковий рядок без знака чи експоненти, до 48 цілих і 30 дробових знаків. Типово має бути додатним. Магазин може дозволити нульові рахунки в Магазини → Рахунок; нульові суми завершуються без отримання коштів, виділення адрес чи плати за обробку.
currencystring | nullнеобов'язковоПідтримувана трилітерна фіатна валюта, нормалізується до великих літер. Якщо пропущено чи null, успадковує валюту рахунків магазину. Створення також потребує незалежно доступного курсу білінгової конвертації.Деталі
Підтримувана трилітерна фіатна валюта, нормалізується до великих літер. Якщо пропущено чи null, успадковує валюту рахунків магазину. Створення також потребує незалежно доступного курсу білінгової конвертації.
payment_methods[]object[] | nullнеобов'язково
Вибери ввімкнені в магазині способи для рахунку. Версія мерчанта 5.4.0+: ігнорує невідомі/неактивні/неприйняті варіанти; якщо нічого не збігається, бере типові способи магазину. Пропущене/null також бере типові; [] недійсне. Ніколи не вмикає спосіб і не змінює магазин. Дивись схему вибору нижче.Деталі
Вибери ввімкнені в магазині способи для рахунку. Версія мерчанта 5.4.0+: ігнорує невідомі/неактивні/неприйняті варіанти; якщо нічого не збігається, бере типові способи магазину. Пропущене/null також бере типові; [] недійсне. Ніколи не вмикає спосіб і не змінює магазин. Дивись схему вибору нижче.
chain_slugstringобов'язковоСкопіюй chain_slug у Проєкт → Магазини → Способи оплати або прочитай GET /v1/projects/{project_id}/stores/{store_id}/payment-assets, наприклад ethereum, base або bitcoin. Пара мережа/канал може траплятися лише раз.Деталі
Скопіюй chain_slug у Проєкт → Магазини → Способи оплати або прочитай GET /v1/projects/{project_id}/stores/{store_id}/payment-assets, наприклад ethereum, base або bitcoin. Пара мережа/канал може траплятися лише раз.
asset_ids[]UUID[] | nullнеобов'язковоUUID asset.id on-chain активів, не адреси контрактів чи ID платіжного способу рахунку. Використовуй це АБО asset_tickers. Пропусти обидва селектори для всіх активних прийнятих активів мережі. [] і повторні/nil ID недійсні. У 5.4.0+ неактивні/неприйняті ID цієї мережі в магазині ігноруються; повна відсутність збігів бере типові способи магазину.Деталі
UUID asset.id on-chain активів, не адреси контрактів чи ID платіжного способу рахунку. Використовуй це АБО asset_tickers. Пропусти обидва селектори для всіх активних прийнятих активів мережі. [] і повторні/nil ID недійсні. У 5.4.0+ неактивні/неприйняті ID цієї мережі в магазині ігноруються; повна відсутність збігів бере типові способи магазину.
asset_tickers[]string[] | nullнеобов'язковоВерсія мерчанта 5.3.0+. Символи BTC, USDC або PEPE в межах chain_slug і магазину. 1–64 унікальні тикери; обрізання пробілів/без урахування регістру, 1–40 ASCII-літер/цифр/крапок/підкреслень/дефісів. Використовуй це АБО asset_ids. У 5.4.0+ невідомі/неактивні/неприйняті тикери ігноруються. Неоднозначні прийняті символи все ще дають помилку: використовуй asset_ids. Вибрані активні способи потребують дійсних гаманців і ціни; тимчасові збої on-chain сканера не блокують створення з 6.0.6. Lightning опційно приймає лише BTC.Деталі
Версія мерчанта 5.3.0+. Символи BTC, USDC або PEPE в межах chain_slug і магазину. 1–64 унікальні тикери; обрізання пробілів/без урахування регістру, 1–40 ASCII-літер/цифр/крапок/підкреслень/дефісів. Використовуй це АБО asset_ids. У 5.4.0+ невідомі/неактивні/неприйняті тикери ігноруються. Неоднозначні прийняті символи все ще дають помилку: використовуй asset_ids. Вибрані активні способи потребують дійсних гаманців і ціни; тимчасові збої on-chain сканера не блокують створення з 6.0.6. Lightning опційно приймає лише BTC.
payment_railonchain | lightningнеобов'язковоТипово onchain. Для Bitcoin Lightning використовуй {chain_slug: bitcoin, payment_rail: lightning} без asset_ids; asset_tickers опційно може бути [BTC]. Bitcoin on-chain не включає Lightning. Lightning-підключення магазину вже має бути ввімкнене й готове.Деталі
Типово onchain. Для Bitcoin Lightning використовуй {chain_slug: bitcoin, payment_rail: lightning} без asset_ids; asset_tickers опційно може бути [BTC]. Bitcoin on-chain не включає Lightning. Lightning-підключення магазину вже має бути ввімкнене й готове.
order_idstring | nullнеобов'язковоРеференс замовлення мерчанта, 1–128 символів після обрізання пробілів; керівні символи відхиляються.
emailstring | nullнеобов'язковоEmail покупця лише для мерчанта, нормалізований до практичної ASCII-адреси до 254 символів. Пропущене чи null не зберігає email.
descriptionstring | nullнеобов'язковоОпис для покупця, 1–500 символів; переноси рядків і табуляції дозволені.
expires_in_secondsinteger | nullнеобов'язковоСтрок котировки рахунку від 300 до 86 400 секунд; пропущене чи null успадковує політику магазину.
exchange_rate_spread_percentdecimal string | nullнеобов'язковоНацінка котировки від 0 до 100, до двох десяткових знаків. Пропущене чи null успадковує магазин; "0" вимикає для цього рахунку. Застосовується перед округленням вгору, потім фіксується. Не змінює фіатну суму рахунку чи основу комісії за обробку.Деталі
Націнка котировки від 0 до 100, до двох десяткових знаків. Пропущене чи null успадковує магазин; "0" вимикає для цього рахунку. Застосовується перед округленням вгору, потім фіксується. Не змінює фіатну суму рахунку чи основу комісії за обробку.
underpayment_tolerance_percentdecimal string | nullнеобов'язковоДопустима недоплата від 0 до 99.99, до двох десяткових знаків. Пропущене чи null успадковує магазин.
ipn_urlstring | nullнеобов'язковоПублічний HTTPS-колбек до 2 048 байтів, без облікових даних чи фрагмента. Перевизначає типовий URL магазину; null/пропущене успадковує його.
redirect_urlstring | nullнеобов'язковоHTTPS URL успіху після остаточної оплати, до 2 048 байтів і без вбудованих облікових даних. Пропущене чи null успадковує магазин і не очищує значення.
cancel_urlstring | nullнеобов'язковоHTTPS URL повернення, коли оплата завершується без успішного платежу. Пропущене чи null успадковує магазин і не очищує значення.
redirect_automaticallyboolean | nullнеобов'язковоПропущене чи null успадковує політику магазину. true потребує фактичного redirect_url.
languagestring | nullнеобов'язковоМова покупця: en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja. pt означає бразильську португальську, zh - спрощену китайську. Підтримувані регіональні теги, як de-DE, нормалізуються до вказаної мови. Пропущене чи null успадковує мову магазину. Мова панелі окрема.Деталі
Мова покупця: en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja. pt означає бразильську португальську, zh - спрощену китайську. Підтримувані регіональні теги, як de-DE, нормалізуються до вказаної мови. Пропущене чи null успадковує мову магазину. Мова панелі окрема.
checkout_appearanceobject | nullнеобов'язково
Часткові налаштування показу цього рахунку. Пропущене/null використовує поточне оформлення магазину. Об'єкт, включно з {}, фіксує визначене оформлення й зображення при створенні. Дивись схему перевизначення нижче; без фінансових налаштувань, HTML, CSS, JavaScript чи віддалених URL зображень.Деталі
Часткові налаштування показу цього рахунку. Пропущене/null використовує поточне оформлення магазину. Об'єкт, включно з {}, фіксує визначене оформлення й зображення при створенні. Дивись схему перевизначення нижче; без фінансових налаштувань, HTML, CSS, JavaScript чи віддалених URL зображень.
inherit_default_storebooleanнеобов'язковоtrue бере за основу оформлення магазину за замовчуванням проєкту; інакше фактичне оформлення цільового магазину. Потім застосовуються перевизначення й зберігаються незалежно; остаточний прапорець рахунку - false.Деталі
true бере за основу оформлення магазину за замовчуванням проєкту; інакше фактичне оформлення цільового магазину. Потім застосовуються перевизначення й зберігаються незалежно; остаточний прапорець рахунку - false.
titlestringнеобов'язковоЗаголовок оплати, до 120 символів. Порожній використовує стандартний заголовок.
introstringнеобов'язковоЗвичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.Деталі
Звичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.
outrostringнеобов'язковоЗвичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.Деталі
Звичайний текст, до 2 000 символів кожен. Вступ угорі, завершення внизу в кожному стані. Переноси зберігаються; безпечні текстові URL стають посиланнями. Порожній рядок очищує. Старий customer_message приймається як псевдонім вступу; не надсилай обидва.
intro_font_sizeintegerнеобов'язковоПікселі: 12, 14, 16, 18, 20 або 24. Типово 16, якщо не успадковано інше.
outro_font_sizeintegerнеобов'язковоПікселі: 12, 14, 16, 18, 20 або 24. Типово 16, якщо не успадковано інше.
themesystem | light | dim | darkнеобов'язковоСлідуй пристрою покупця або використовуй фіксовану тему.
accent_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
background_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
card_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
button_colorstringнеобов'язково#RRGGBB. Фон, картка й кнопка можуть бути порожні для автоматичних кольорів. Контраст тексту автоматичний.
imagesobjectнеобов'язково
Ключі logo_light, logo_dark, favicon. Пропущений ключ залишає базове зображення; null видаляє. Об'єкт {store_id: UUID, kind?: logo_light|logo_dark|favicon} повторно використовує фактично завантажене зображення цього магазину в ТОМУ САМОМУ проєкті. kind типово дорівнює цільовому ключу. Спочатку завантаж у Магазин → Оформлення оплати; скопіюй ID магазину для API з Основне → ID для API. Відсутні зображення чи ID іншого проєкту повертають 400. Зовнішні URL або дані зображень не приймаються.Деталі
Ключі logo_light, logo_dark, favicon. Пропущений ключ залишає базове зображення; null видаляє. Об'єкт {store_id: UUID, kind?: logo_light|logo_dark|favicon} повторно використовує фактично завантажене зображення цього магазину в ТОМУ САМОМУ проєкті. kind типово дорівнює цільовому ключу. Спочатку завантаж у Магазин → Оформлення оплати; скопіюй ID магазину для API з Основне → ID для API. Відсутні зображення чи ID іншого проєкту повертають 400. Зовнішні URL або дані зображень не приймаються.
logo_lightobject | nullнеобов'язково
logo_darkobject | nullнеобов'язково
show_order_idbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
show_descriptionbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
details_expandedbooleanнеобов'язковоПоказуй деталі ID замовлення й звичайний текст опису під заголовком. details_expanded спочатку розгортає деталі ID замовлення. Лише показ, не вилучення даних.
show_project_namebooleanнеобов'язковоВерсія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.Деталі
Версія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.
show_store_namebooleanнеобов'язковоВерсія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.Деталі
Версія мерчанта 5.6.0+: показати або приховати кожну назву в заголовку оплати покупця. Обидва типово true. Також у Магазин → Оформлення оплати; успадковуються й фіксуються в рахунку, як інші параметри оформлення. Лише показ, не вилучення даних.
featured_chains[]string[]необов'язковоУпорядковані slug мереж, до 60 унікальних значень (малі літери, цифри, дефіси; до 64 символів). [] очищує. Порядок змінюється лише для доступних способів рахунку.Деталі
Упорядковані slug мереж, до 60 унікальних значень (малі літери, цифри, дефіси; до 64 символів). [] очищує. Порядок змінюється лише для доступних способів рахунку.
featured_asset_ids[]UUID[]необов'язковоДо 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.Деталі
До 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.
default_asset_idUUID|nullнеобов'язковоДо 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.Деталі
До 100 унікальних упорядкованих ID активів; [] очищує. Типовий актив може бути null. ID беруться з payment-assets, не з платіжних намірів. Вони не вмикають способи; отримані платежі й дійсні вподобання покупця мають пріоритет.
messagesobjectнеобов'язково
Мовні об'єкти з ключами en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja та звичайними рядками waiting, confirming, paid, underpaid, expired (до 500 символів кожен). Змінюються лише передані мови/стани; {} очищає всі повідомлення, {en:{}} очищає англійські, а порожній рядок стану очищає цей стан. Резервна мова - англійська. Фактичний статус не змінюється.Деталі
Мовні об'єкти з ключами en, de, es, pt-BR, it, ru, zh-CN, fr, ko або ja та звичайними рядками waiting, confirming, paid, underpaid, expired (до 500 символів кожен). Змінюються лише передані мови/стани; {} очищає всі повідомлення, {en:{}} очищає англійські, а порожній рядок стану очищає цей стан. Резервна мова - англійська. Фактичний статус не змінюється.
enobjectнеобов'язково
deobjectнеобов'язково
esobjectнеобов'язково
pt-BRobjectнеобов'язково
itobjectнеобов'язково
ruobjectнеобов'язково
zh-CNobjectнеобов'язково
frobjectнеобов'язково
koobjectнеобов'язково
support_emailstringнеобов'язковоEmail у форматі ASCII, до 254 символів. Порожнє значення очищає поле.
support_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
terms_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
privacy_urlstringнеобов'язковоHTTPS-адреси до 2048 символів, без облікових даних. Порожнє значення очищає поле. Посилання відкриваються в новому вікні.
return_button_textstringнеобов'язковоНапис до 60 символів. Для поведінки рахунку використовуй поля верхнього рівня redirect_url/cancel_url/redirect_automatically/language.
show_return_buttonbooleanнеобов'язковоПоказувати кнопку повернення до мерчанта/скасування на сторінці оплати, зокрема в кінцевих станах. Не передавай поле, щоб успадкувати оформлення магазину (типово true); false приховує кнопку. Це не скасовує рахунок, не приховує URL у JSON і не вимикає автоматичне перенаправлення після успіху. За потреби окремо встанови redirect_automatically верхнього рівня у false. Потрібна версія мерчанта 8.1.4 або новіша.Деталі
Показувати кнопку повернення до мерчанта/скасування на сторінці оплати, зокрема в кінцевих станах. Не передавай поле, щоб успадкувати оформлення магазину (типово true); false приховує кнопку. Це не скасовує рахунок, не приховує URL у JSON і не вимикає автоматичне перенаправлення після успіху. За потреби окремо встанови redirect_automatically верхнього рівня у false. Потрібна версія мерчанта 8.1.4 або новіша.
metadataobject | nullнеобов'язково
JSON-об'єкт лише для мерчанта; відсутнє поле або null стає {}, максимум 4096 байтів у закодованому вигляді та п'ять рівнів вкладеності. firstname, lastname, street, street2, zip, city, country, countryiso2, company і vatid перевіряються, нормалізуються та відображаються в зведених полях клієнта.Деталі
JSON-об'єкт лише для мерчанта; відсутнє поле або null стає {}, максимум 4096 байтів у закодованому вигляді та п'ять рівнів вкладеності. firstname, lastname, street, street2, zip, city, country, countryiso2, company і vatid перевіряються, нормалізуються та відображаються в зведених полях клієнта.
Відповідь 201 new invoice; 200 exact idempotent replay
Приклад відповіді
{
"data": {
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "new",
"amount_status": "none",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 1,
"winning_payment_intent_id": null,
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": null,
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:00:00Z",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"metadata": { "cart_id": "cart-681", "firstname": "Ada", "lastname": "Lovelace", "street": "12 Example Street", "street2": "Suite 2", "zip": "10115", "city": "Berlin", "country": "Germany", "countryiso2": "DE", "company": "Example GmbH", "vatid": "DE123456789" },
"payment_intents": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_id": "10000000-0000-4000-8000-000000000001",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"symbol": "BTC",
"asset_decimals": 8,
"status": "pending",
"finality_mode": "confirmations",
"required_confirmations": 1,
"quote_rate": "0.000009218",
"quote_details": null,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0",
"received_amount_atomic": "0",
"confirmed_amount": "0",
"confirmed_amount_atomic": "0",
"destination_address": "bc1q…example",
"destination_tag": null,
"derivation_index": 42,
"quote_expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"next_check_at": "2026-08-31T18:00:00Z",
"last_checked_at": null,
"last_chain_height": null,
"last_anchor_hash": null,
"last_monitor_error": null,
"first_payment_at": null,
"fully_paid_at": null,
"finalized_at": null
}
]
},
"links": {
"checkout": "https://pay.example.com/invoice/0a6a98db-d93d-48ee-8c3c-fd45f90c4a50"
}
}Поля відповіді
dataobject
idUUIDзавждиВнутрішній UUID рахунку. Не використовуй його в шляхах даних мерчанта чи сторінки оплати.
emailstring | nullзавждиEmail клієнта лише для мерчанта. Публічна сторінка оплати його ніколи не повертає.
customer_namestring | nullзавждиВідображуване ім'я, сформоване з приватних метаданих firstname, lastname і company.
customer_addressstring | nullзавждиОднорядкова адреса для мерчанта, сформована з приватних метаданих company, street, street2, zip, city, country, countryiso2 і vatid.
exchange_rate_spread_percentdecimal stringзавждиЗафіксована курсова надбавка: значення при створенні або стандартне значення магазину, якщо поле не передано. Застосовується перед округленням угору; ніколи не змінюється для цього рахунку.
underpayment_tolerance_percentdecimal stringзавждиНезмінний допустимий відсоток недоплати, збережений під час створення рахунку.
amount_statusamount statusзавждиnone, partial, paid або overpaid. Явно дозволений рахунок із нульовою сумою завершується з none і без способів оплати.
monitoring_expires_atRFC 3339 timestampзавждиНайпізніший налаштований кінець спостереження за пізніми платежами серед способів оплати.
ipn_urlstring | nullзавждиДієва IPN-адреса цього рахунку. Лише у відповіді мерчанту; відсутня в публічній сторінці оплати.
cancel_urlstring | nullзавждиДієвий URL повернення, коли оформлення закінчується без успішної оплати.
metadataobjectзавжди
Метадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.Деталі
Метадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.
payment_intents[]object[]завжди
Способи оплати з котируваннями та станом спостереження.
idUUIDзавждиІдентифікатор платіжного наміру; також використовується як intent_id QR-коду на сторінці оплати.
payment_railonchain | lightningзавждиСпосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.Деталі
Спосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.
bolt11string | nullзавждиПлатіжний запит Lightning або null. Оплачуй його гаманцем Lightning; ніколи не надсилай кошти в блокчейні на його хеш платежу.
asset_decimalsintegerзавждиТочність найменших одиниць. BTC у Lightning використовує 11 знаків (мілісатоші), а не 8, як Bitcoin у блокчейні. Котирування задаються цілими сатоші; надходження зберігають точність до мілісатоші.
quote_ratedecimal stringзавждиОдиниці активу за одну одиницю валюти рахунку, включно із зафіксованим спредом. Наприклад, 1.02 USDC за USD. Не зворотний курс.
quote_detailsobject | nullзавждиПоходження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.Деталі
Походження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.
expected_amountdecimal stringзавждиТочна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.Деталі
Точна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.
minimum_payment_amountdecimal stringзавждиНайменша сума, яку приймають як сплачену після застосування допуску рахунку.
minimum_payment_amount_atomicinteger stringзавждиТочний поріг прийняття в найменших одиницях активу.
destination_addressstringзавждиАдреса отримання в блокчейні або 64-символьний хеш платежу Lightning. Для оплати Lightning використовуй bolt11; його хеш не є адресою Bitcoin.
destination_tagstring | nullзавждиОбов’язковий публічний реквізит платежу для каналів, які його використовують: destination tag XRP, memo ID Stellar або коментар рахунку TON. Null для каналів з унікальними адресами.
derivation_indexintegerзавждиЗарезервований індекс дочірньої адреси гаманця; лише в деталях для мерчанта.
monitoring_expires_atRFC 3339 timestampзавждиКінець спостереження за пізніми платежами для цього способу.
Примітки до використання
- payment_methods фільтрує ввімкнені способи магазину лише для цього рахунку. Пропущене/null зберігає всі способи магазину; [] недійсний. Підказку chain_slug і показані тикери активів знайдеш у Проєкт → Магазини → Способи оплати. Список API payment-assets дає chain_slug, asset.symbol та asset.id. Для прийнятих Ethereum-токенів використовуй {chain_slug: ethereum, asset_tickers: [USDC, USDT]}; BTC і PEPE працюють так само у вибраних мережах. Тикери нечутливі до регістру, обмежені мережею й визначаються лише всередині магазину. Два прийняті контракти з однаковим тикером повертають 400 замість вибору одного, навіть якщо один не готовий; у такому разі використовуй asset_ids. Нативні активи, токени каталогу й власні токени мають однакові правила. Кожна пара мережа/канал може бути один раз; щонайбільше 64 кінцеві способи. Merchant 5.4.0+: невідомі, вимкнені, з іншої мережі чи неприйняті варіанти ігноруються. Якщо весь вибір не має активних прийнятих збігів, застосовуються стандартні способи магазину; інакше - лише збіги. Запис лише з мережею включає всі її активні прийняті активи блокчейну. Активні вибрані способи потребують дійсних гаманців, установлених адаптерів сканера й надійних курсів. З 6.0.6 недоступні сканери, періоди очікування та незавершені/застарілі перевірки справності не блокують створення рахунку й не прибирають налаштовані способи блокчейну. Виявлення повторюється автоматично; остаточна оплата все одно потребує кворуму провайдерів і підтверджень. Стеж за receive_readiness і доступністю провайдерів: рахунок може лишатися неперевіреним до відновлення сканерів. Виділення subaddress Monero й створення BOLT11 Lightning усе ще потребують зовнішнього сервісу гаманця/вузла. Помилки повертають error.message та error.details.payment_methods із chain_slug, asset_ticker, reason_code, а для діагностики сканера - required_endpoint_role, healthy_endpoints і required_independent_providers. TRON приймає індексовану історію або підтримувані сирі API solidified-блоків нативного активу; базова справність сама по собі не доводить сумісність зі сканером. Помилки ціни вказують актив/валюту. Ніщо не вмикає неприйнятий актив і не змінює політику магазину. У версіях merchant до 5.4.0 невідомі/неактивні явно вибрані способи натомість спричиняють помилку. Способи наявного рахунку ніколи не розширюються після зміни налаштувань магазину. Lightning треба вибирати окремо. Повторні запити зберігають початкові способи, а зміна вибору з тим самим Idempotency-Key повертає 409.
- checkout_appearance підтримує всі перелічені вище параметри оформлення. Пропущені поля успадковуються, масиви замінюються, а вкладені поля повідомлень об’єднуються; порожній об’єкт повідомлень очищує цю область. Обчислений дизайн і зображення зберігаються для рахунку без зміни магазину. Переглянь appearance у публічному JSON форми оплати, щоб перевірити результат. Увесь запит обмежений 32 KiB, а обчислені налаштування - 20 KiB.
- Зміна checkout_appearance з тим самим Idempotency-Key повертає 409; повторюй з ідентичними сирими байтами. Оформлення не змінює суми, курси, прийняті активи, вимоги підтверджень, реальний статус чи дозволи вбудовування. Без HTML, CSS, скриптів і завантаження зовнішніх зображень.
- exchange_rate_spread_percent перевизначає стандарт магазину для цього рахунку: пропусти або передай null для успадкування чи "0" для вимкнення. Наявні котирування рахунку ніколи не змінюються.
- Спред застосовується перед округленням вгору. Комісії й далі ґрунтуються на початковій фіатній сумі рахунку без спреду.
- Завжди надсилай повернуту expected_amount або expected_amount_atomic. Округлення виконується вгору й обмежене точністю активу, 0.1% суми та однією найменшою фіатною одиницею.
- Повторні запити мають зберігати ті самі облікові дані, Idempotency-Key і точні байти тіла. Зміна спреду з тим самим ключем повертає 409 idempotency_conflict.
- Точний повтор перевіряється до підготовки нового котирування, DNS callback або адреси. Обсяг доступу облікових даних і авторизація проєкту/магазину перевіряються в кожному запиті.
- Чинний ipn_url потребує секрету підписування IPN магазину. Невідомі поля тіла відхиляються.
Помилки
GETСписок рахунків/v1/projects/{project_id}/invoicesЛише читання
Повертає компактну сторінку зведень рахунків у межах доступу, від найновіших, включно з email лише для мерчанта й полями клієнта з розпізнаних метаданих. Пошук, статус і магазин фільтруються на сервері; відповідь містить total та has_more для передбачуваної пагінації.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Параметри запиту
searchstringНеобов’язковий нечутливий до регістру початок invoice-id, order-id або email; точний UUID рахунку; або підрядок опису та розпізнаних полів клієнта. Усі ключі метаданих і текстові, числові та булеві значення (включно з вкладеними об’єктами/масивами) також підтримують індексований пошук за початком слів: кожне слово має збігтися, розділові знаки вважаються роздільниками. Пробіли по краях обрізаються, щонайбільше 100 символів, без керівних символів. Збіги метаданих не додають сирі метадані до списку; читай їх у деталях рахунку.Деталі
Необов’язковий нечутливий до регістру початок invoice-id, order-id або email; точний UUID рахунку; або підрядок опису та розпізнаних полів клієнта. Усі ключі метаданих і текстові, числові та булеві значення (включно з вкладеними об’єктами/масивами) також підтримують індексований пошук за початком слів: кожне слово має збігтися, розділові знаки вважаються роздільниками. Пробіли по краях обрізаються, щонайбільше 100 символів, без керівних символів. Збіги метаданих не додають сирі метадані до списку; читай їх у деталях рахунку.
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices?search=order-1042&status=processing&limit=50&offset=0",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": [
{
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "processing",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 3,
"winning_payment_intent_id": "33333333-3333-4333-8333-333333333333",
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": null,
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:04:10Z"
}
],
"pagination": {
"limit": 50,
"offset": 0,
"total": 143,
"has_more": true
}
}Поля відповіді
data[]object[]
idUUIDзавждиВнутрішній UUID рахунку. Не використовуй його в шляхах даних мерчанта чи сторінки оплати.
emailstring | nullзавждиEmail клієнта лише для мерчанта. Публічна сторінка оплати його ніколи не повертає.
customer_namestring | nullзавждиВідображуване ім'я, сформоване з приватних метаданих firstname, lastname і company.
customer_addressstring | nullзавждиОднорядкова адреса для мерчанта, сформована з приватних метаданих company, street, street2, zip, city, country, countryiso2 і vatid.
exchange_rate_spread_percentdecimal stringзавждиЗафіксована курсова надбавка: значення при створенні або стандартне значення магазину, якщо поле не передано. Застосовується перед округленням угору; ніколи не змінюється для цього рахунку.
underpayment_tolerance_percentdecimal stringзавждиНезмінний допустимий відсоток недоплати, збережений під час створення рахунку.
amount_statusamount statusзавждиnone, partial, paid або overpaid. Явно дозволений рахунок із нульовою сумою завершується з none і без способів оплати.
monitoring_expires_atRFC 3339 timestampзавждиНайпізніший налаштований кінець спостереження за пізніми платежами серед способів оплати.
paginationobject
totalintegerзавждиЗагальна кількість рядків, що відповідають фільтрам проєкту, магазину, статусу й пошуку у знімку сторінки.
Примітки до використання
- Сортування за спаданням created_at, потім за спаданням внутрішнього id.
- Елементи списку - об’єкти InvoiceSummary; email, customer_name та customer_address лише для мерчанта. За сирими метаданими й payment intents звертайся до деталей.
- Для наступної сторінки встанови offset у pagination.offset + pagination.limit лише коли has_more має значення true.
- Кількість і сторінка читаються з одного знімка бази даних repeatable-read; одночасні записи з’являться в наступному запиті.
Помилки
GETОтримати рахунок/v1/projects/{project_id}/invoices/{invoice_id}Лише читання
Повертає повні деталі рахунку мерчанта й поточний активний URL форми оплати. Використовуй цей маршрут для опитування та звіряння.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"id": "2f798f9f-01f2-42f0-9d10-5581d6116b4c",
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"project_id": "11111111-1111-4111-8111-111111111111",
"store_id": "22222222-2222-4222-8222-222222222222",
"source": "api",
"order_id": "order-1042",
"email": "ada@example.com",
"customer_name": "Ada Lovelace · Example GmbH",
"customer_address": "Example GmbH · 12 Example Street · Suite 2 · 10115 Berlin · Germany (DE) · VAT DE123456789",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "settled",
"amount_status": "paid",
"timing_status": "on_time",
"resolution": "automatic",
"sequence": 4,
"winning_payment_intent_id": "33333333-3333-4333-8333-333333333333",
"expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"settled_at": "2026-08-31T18:05:00Z",
"cancelled_at": null,
"archived_at": null,
"created_at": "2026-08-31T18:00:00Z",
"updated_at": "2026-08-31T18:05:00Z",
"ipn_url": "https://merchant.example/wholly/ipn",
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"metadata": { "cart_id": "cart-681", "firstname": "Ada", "lastname": "Lovelace", "street": "12 Example Street", "street2": "Suite 2", "zip": "10115", "city": "Berlin", "country": "Germany", "countryiso2": "DE", "company": "Example GmbH", "vatid": "DE123456789" },
"payment_intents": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_id": "10000000-0000-4000-8000-000000000001",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"symbol": "BTC",
"asset_decimals": 8,
"status": "paid",
"finality_mode": "confirmations",
"required_confirmations": 1,
"quote_rate": "0.000009218",
"quote_details": null,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0.0004554",
"received_amount_atomic": "45540",
"confirmed_amount": "0.0004554",
"confirmed_amount_atomic": "45540",
"destination_address": "bc1q…example",
"destination_tag": null,
"derivation_index": 42,
"quote_expires_at": "2026-08-31T18:15:00Z",
"monitoring_expires_at": "2026-09-07T18:15:00Z",
"next_check_at": null,
"last_checked_at": "2026-08-31T18:05:00Z",
"last_chain_height": 912345,
"last_anchor_hash": "000000000000000000example",
"last_monitor_error": null,
"first_payment_at": "2026-08-31T18:03:00Z",
"fully_paid_at": "2026-08-31T18:03:00Z",
"finalized_at": "2026-08-31T18:05:00Z"
}
]
},
"links": {
"checkout": "https://pay.example.com/invoice/0a6a98db-d93d-48ee-8c3c-fd45f90c4a50"
}
}Поля відповіді
dataobject
idUUIDзавждиВнутрішній UUID рахунку. Не використовуй його в шляхах даних мерчанта чи сторінки оплати.
emailstring | nullзавждиEmail клієнта лише для мерчанта. Публічна сторінка оплати його ніколи не повертає.
customer_namestring | nullзавждиВідображуване ім'я, сформоване з приватних метаданих firstname, lastname і company.
customer_addressstring | nullзавждиОднорядкова адреса для мерчанта, сформована з приватних метаданих company, street, street2, zip, city, country, countryiso2 і vatid.
exchange_rate_spread_percentdecimal stringзавждиЗафіксована курсова надбавка: значення при створенні або стандартне значення магазину, якщо поле не передано. Застосовується перед округленням угору; ніколи не змінюється для цього рахунку.
underpayment_tolerance_percentdecimal stringзавждиНезмінний допустимий відсоток недоплати, збережений під час створення рахунку.
amount_statusamount statusзавждиnone, partial, paid або overpaid. Явно дозволений рахунок із нульовою сумою завершується з none і без способів оплати.
monitoring_expires_atRFC 3339 timestampзавждиНайпізніший налаштований кінець спостереження за пізніми платежами серед способів оплати.
ipn_urlstring | nullзавждиДієва IPN-адреса цього рахунку. Лише у відповіді мерчанту; відсутня в публічній сторінці оплати.
cancel_urlstring | nullзавждиДієвий URL повернення, коли оформлення закінчується без успішної оплати.
metadataobjectзавжди
Метадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.Деталі
Метадані мерчанта. Публічна сторінка оплати їх ніколи не повертає. Платіжні інструменти панелі додають дані походження payment_tool (id, kind, title, pricing, requested_amount, request_id); це не підтвердження оплати. Перевіряй справжність callback і виконуй замовлення за invoice.settled лише раз для кожного invoice_id.
payment_intents[]object[]завжди
Способи оплати з котируваннями та станом спостереження.
idUUIDзавждиІдентифікатор платіжного наміру; також використовується як intent_id QR-коду на сторінці оплати.
payment_railonchain | lightningзавждиСпосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.Деталі
Спосіб передавання платежу рахунку. Bitcoin у блокчейні й Lightning можуть мати однаковий asset_id; використовуй id наміру разом із цим полем, а не лише символ. Це відрізняється від scanner payment_rail у каталозі активів.
bolt11string | nullзавждиПлатіжний запит Lightning або null. Оплачуй його гаманцем Lightning; ніколи не надсилай кошти в блокчейні на його хеш платежу.
asset_decimalsintegerзавждиТочність найменших одиниць. BTC у Lightning використовує 11 знаків (мілісатоші), а не 8, як Bitcoin у блокчейні. Котирування задаються цілими сатоші; надходження зберігають точність до мілісатоші.
quote_ratedecimal stringзавждиОдиниці активу за одну одиницю валюти рахунку, включно із зафіксованим спредом. Наприклад, 1.02 USDC за USD. Не зворотний курс.
quote_detailsobject | nullзавждиПоходження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.Деталі
Походження зафіксованого котирування: reference_rate до спреду, unrounded_payment_amount, rounding_adjustment, pricing_provider, asset_provider, pricing_fetched_at і asset_fetched_at. Для старих рахунків - null; історичні значення не вигадуються.
expected_amountdecimal stringзавждиТочна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.Деталі
Точна зафіксована сума активу до оплати після спреду й округлення вгору. Починаючи з 4.1.1, розпізнані перевірені фіатні стейблкоїни (як-от USDC, USDT, DAI, USDS, EURC) округлюються вгору до щонайбільше двох знаків; 1.321 стає 1.33, а не 1.32. Це очікувана сума навіть за нульового допуску. Інші активи зберігають адаптивну точність. Ціна наявних рахунків ніколи не перераховується.
minimum_payment_amountdecimal stringзавждиНайменша сума, яку приймають як сплачену після застосування допуску рахунку.
minimum_payment_amount_atomicinteger stringзавждиТочний поріг прийняття в найменших одиницях активу.
destination_addressstringзавждиАдреса отримання в блокчейні або 64-символьний хеш платежу Lightning. Для оплати Lightning використовуй bolt11; його хеш не є адресою Bitcoin.
destination_tagstring | nullзавждиОбов’язковий публічний реквізит платежу для каналів, які його використовують: destination tag XRP, memo ID Stellar або коментар рахунку TON. Null для каналів з унікальними адресами.
derivation_indexintegerзавждиЗарезервований індекс дочірньої адреси гаманця; лише в деталях для мерчанта.
monitoring_expires_atRFC 3339 timestampзавждиКінець спостереження за пізніми платежами для цього способу.
Примітки до використання
- Пошук у межах доступу навмисно повертає invoice_not_found, коли публічний ID не належить дозволеному проєкту.
- links.checkout використовує Магазин → Основне → Домени магазину: активне ім’я pay-хоста цього магазину, потім вибір стандартного магазину, потім основне системне. Виведені з ужитку/чернеткові хости або хости іншої служби ігноруються. Це також стосується відповідей створення й MCP; посилання визначаються під час відповіді, включно з ідемпотентними повторами. Підписані callback-посилання фіксуються під час створення події й не переписуються при повторах. Ці налаштування лише генерують посилання; вони не перенаправляють трафік і не змінюють IP-обмеження.
Помилки
GETСписок платежів рахунку/v1/projects/{project_id}/invoices/{invoice_id}/paymentsЛише читання
Повна поточна історія переказів, включно зі скасованими спостереженнями. Використовуй, коли callback позначає payments_truncated. Це поточний стан, а не відтворення старої події.
Автентифікація та заголовки
| Заголовок | Наявність | Правило |
|---|---|---|
| Authorization | обов'язково | Bearer YOUR_MERCHANT_API_TOKEN |
| Accept | рекомендовано | application/json |
Параметри шляху
Параметри запиту
Запит
: "${WHOLLY_TOKEN:?Set WHOLLY_TOKEN to your server-side API token}"
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0" \
--header "Authorization: Bearer $WHOLLY_TOKEN" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const token = process.env.WHOLLY_TOKEN;
if (!token) throw new Error("Set WHOLLY_TOKEN");
const response = await fetch("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$token = getenv('WHOLLY_TOKEN');
if (!$token) { throw new RuntimeException('Set WHOLLY_TOKEN'); }
$ch = curl_init("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token, "Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
import os
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
headers["Authorization"] = "Bearer " + os.environ["WHOLLY_TOKEN"]
request = Request("https://api.example.com/v1/projects/YOUR_PROJECT_ID/invoices/YOUR_PUBLIC_INVOICE_ID/payments?limit=25&offset=0",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"invoice_id": "11111111-2222-4333-8444-555555555555",
"data": [{
"payment_id": "44444444-4444-4444-8444-444444444444",
"payment_method_id": "33333333-3333-4333-8333-333333333333",
"transaction_id": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"payment_hash": null,
"event_index": 12,
"payment_rail": "onchain",
"chain_slug": "ethereum",
"network": "mainnet",
"asset_id": "55555555-5555-4555-8555-555555555555",
"asset_key": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"caip_asset_id": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"symbol": "USDC",
"asset_decimals": 6,
"amount": "58.17342",
"amount_atomic": "58173420",
"status": "final",
"counts_towards_received": true,
"confirmations": 2,
"block_height": 25975377,
"observed_at": "2026-09-14T12:03:00Z",
"chain_time": "2026-09-14T12:02:48Z",
"finalized_at": "2026-09-14T12:04:00Z",
"explorer_name": "Etherscan",
"explorer_url": "https://etherscan.io/tx/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}],
"pagination": {"limit": 25, "offset": 0, "total": 1, "has_more": false}
}Поля відповіді
invoice_idstringdata[]object[]
payment_idstringpayment_method_idstringtransaction_idstringpayment_hashJSON | nullevent_indexintegerpayment_railstringchain_slugstringnetworkstringasset_idstringasset_keystringcaip_asset_idstringsymbolstringasset_decimalsintegeramountstringamount_atomicstringstatusstringcounts_towards_receivedbooleanconfirmationsintegerblock_heightintegerobserved_atstringchain_timestringfinalized_atstringexplorer_namestringexplorer_urlstringПримітки до використання
- Спостереження - це лог токена, вихід UTXO або переказ іншого каналу, не обов’язково унікальний хеш транзакції. Усувай дублікати за payment_id; transaction_id разом з event_index визначає переказ у блокчейні.
- status - detected, confirming, final, reorged, replaced або invalid. Лише спостереження counts_towards_received враховуються в отриманих сумах. Ніколи не додавай суми різних активів.
- Записи Lightning використовують payment_hash із null у transaction_id, confirmations і посиланнях explorer; точність BTC - 11 (мілісатоші). Preimage, BOLT11 і секрети гаманця не розкриваються.
- Сортування за спаданням observed_at, потім payment_id. Кількість і сторінка використовують один знімок repeatable-read; наступні сторінки можуть змінюватися з надходженням платежів. Під час пагінації активного рахунку усувай дублікати за payment_id.
- Застосовуються наявний доступ лише для читання в межах проєкту, IP-обмеження й ліміти запитів облікових даних. Ніколи не переходь за посиланням callback зі своїм токеном, якщо його origin не збігається з налаштованим API-хостом.
Помилки
GETОболонка сторінки оплати/Публічний
Кореневий маршрут керованого хоста форми оплати, що віддає платіжний застосунок без вибору рахунку. Клієнтські інтеграції зазвичай мають використовувати links.checkout.
Автентифікація та заголовки
Публічний
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/" \
--output 'checkout.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout.html").write_bytes(response.read())Відповідь 200 text/html
Приклад відповіді
<!doctype html>
<!-- Hosted Wholly Crypto checkout shell -->Примітки до використання
- Bearer-токен не потрібен.
- Керований проксі форми оплати дозволяє GET/HEAD і відхиляє інші методи.
Помилки
GETРозміщена сторінка оплати/invoice/{invoice_id}Публічний
HTML-форма оплати для клієнта. Сторінка отримує безпечний для неї JSON із того самого хоста. Вбудовування заборонене, якщо магазин не ввімкнув його й явно не дозволив HTTPS origin батьківської сторінки.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID" \
--output 'checkout.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/invoice/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout.html").write_bytes(response.read())Відповідь 200 text/html
Приклад відповіді
<!doctype html>
<!-- Hosted Wholly Crypto checkout application -->Примітки до використання
- Bearer-токен не приймається й не потрібен.
- Сама HTML-оболонка повертає 200 навіть за відсутності рахунку; її запит JSON форми оплати тоді отримує invoice_not_found.
- Відповідь має no-store, noindex і CSP frame-ancestors для конкретного рахунку.
- Вимкнений проєкт/магазин або невідомий рахунок не розкриває дані форми оплати.
Помилки
GETБезпечні для сторінки оплати дані рахунку/checkout-api/invoices/{invoice_id}Публічний
Повертає лише поля для показу форми оплати. Навмисно пропускає внутрішні ID, email клієнта й похідні поля адреси, IPN URL, метадані мерчанта, ID гаманців, шляхи деривації та діагностику монітора.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID", {
method: "GET",
headers: {
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"invoice_id": "0a6a98db-d93d-48ee-8c3c-fd45f90c4a50",
"order_id": "order-1042",
"description": "Annual plan",
"amount": "49.9",
"currency": "USD",
"exchange_rate_spread_percent": "0.5",
"underpayment_tolerance_percent": "1",
"status": "processing",
"amount_status": "partial",
"timing_status": "on_time",
"sequence": 3,
"active_payment_method_id": "33333333-3333-4333-8333-333333333333",
"payment_method_locked": true,
"server_time": "2026-08-31T18:10:00Z",
"expires_at": "2026-08-31T18:15:00Z",
"expires_in_seconds": 300,
"payment_open": true,
"redirect_url": "https://merchant.example/orders/1042",
"cancel_url": "https://merchant.example/cart",
"redirect_automatically": true,
"checkout_language": "en",
"project": {
"name": "Example project",
"checkout_title": "Complete your payment",
"checkout_description": "Send the exact amount shown.",
"theme": "system",
"accent_color": "#42e39b",
"logo_url": "/checkout-api/invoices/…/logo/…/image.png"
},
"store": { "name": "Online shop" },
"payment_methods": [
{
"id": "33333333-3333-4333-8333-333333333333",
"asset_key": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"chain_slug": "bitcoin",
"chain_name": "Bitcoin",
"network": "mainnet",
"caip_network_id": "bip122:000000000019d6689c085ae165831e93",
"caip_asset_id": "bip122:000000000019d6689c085ae165831e93/slip44:0",
"asset_name": "Bitcoin",
"symbol": "BTC",
"asset_icon_url": "/assets/coingecko/bitcoin.png",
"asset_kind": "native",
"contract_address": null,
"token_standard": null,
"asset_decimals": 8,
"status": "partial",
"payable": true,
"finality_mode": "confirmations",
"required_confirmations": 1,
"expected_amount": "0.00046",
"expected_amount_atomic": "46000",
"minimum_payment_amount": "0.0004554",
"minimum_payment_amount_atomic": "45540",
"received_amount": "0.0002",
"received_amount_atomic": "20000",
"remaining_amount": "0.0002554",
"remaining_amount_atomic": "25540",
"confirmed_amount": "0",
"confirmed_amount_atomic": "0",
"destination_address": "bc1q…example",
"destination_tag": null,
"quote_expires_at": "2026-08-31T18:15:00Z",
"payment_uri": "bitcoin:bc1q…example?amount=0.00026",
"qr_url": "/checkout-api/invoices/…/payment-methods/…/qr.svg?sequence=3&amount_atomic=26000",
"address_explorer_name": "mempool.space",
"address_explorer_url": "https://mempool.space/address/…",
"transaction_count": 0,
"transactions_truncated": false,
"transactions": []
}
]
}
}Поля відповіді
dataobject
exchange_rate_spread_percentdecimal stringзавждиЧинний спред котирування, зафіксований під час створення, включно з перевизначенням для рахунку.
amount_statusamount statusзавждиnone, partial, paid або overpaid. Явно дозволений рахунок із нульовою сумою завершується з none і без способів оплати.
active_payment_method_idUUID | nullзавждиСпосіб зі списку, який отримав кошти. Форма оплати залишається на ньому, щоб недоплату не доплачували несумісним активом.
payment_method_lockedbooleanзавждиTrue після того, як дійсний платіж вибрав active_payment_method_id.
server_timeRFC 3339 timestampзавждиЧас сервера, зафіксований для цієї відповіді; використовуй із expires_at, щоб уникнути похибки годинника пристрою клієнта.
expires_in_secondsintegerзавждиЦілі секунди, що залишаються на server_time, округлені вгору й обмежені знизу нулем.
payment_openbooleanзавждиTrue лише поки рахунок new або processing не прострочений і має щонайменше один доступний для оплати спосіб із залишком.
projectobjectзавжди
name, checkout_title, checkout_description, theme, accent_color і logo_url.
appearanceobjectзавжди
Чинне оформлення: зафіксоване перевизначення рахунку, якщо задане, інакше поточний дизайн магазину. Ніколи не змінює фінансові поля чи попередження безпеки.
inherit_default_storebooleanзавждиTrue, коли це оформлення надає стандартний магазин проєкту. False для незалежних магазинів і зафіксованих перевизначень рахунку.
invoice_overridebooleanзавждиTrue, якщо checkout_appearance передано під час створення рахунку. Пропущене/null залишає false.
titlestringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
introstringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
outrostringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
customer_messagestringзавждиЗастарілий псевдонім intro для сумісності. У нових інтеграціях використовуй intro.
accent_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
background_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
card_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
button_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
logo_sizestringзавждиsmall, medium або large; left або center. Зображення вписуються повністю, а не обрізаються.
logo_alignmentstringзавждиsmall, medium або large; left або center. Зображення вписуються повністю, а не обрізаються.
imagesobjectзавждиНеобов’язкові URL logo_light, logo_dark і favicon: нормалізовані PNG у межах доступу з того самого origin.
show_order_idbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
show_descriptionbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
details_expandedbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
show_project_namebooleanзавждиMerchant 5.6.0+: видимість назв у заголовку. Обидва значення типово true. Ідентичність проєкту/магазину залишається в JSON.
show_store_namebooleanзавждиMerchant 5.6.0+: видимість назв у заголовку. Обидва значення типово true. Ідентичність проєкту/магазину залишається в JSON.
featured_chains[]arrayзавждиУпорядковані налаштування, що застосовуються лише до способів, уже наявних у рахунку. Відсутні чи вимкнені способи ігноруються.
featured_asset_ids[]arrayзавждиУпорядковані налаштування, що застосовуються лише до способів, уже наявних у рахунку. Відсутні чи вимкнені способи ігноруються.
default_asset_idUUID | nullзавждиРекомендований початковий спосіб. Дійсний збережений вибір клієнта або спосіб, що вже отримує кошти, має пріоритет.
messagesobjectзавжди
Звичайний текст для en, de, es, pt-BR, it, ru, zh-CN, fr, ko та ja з ключами waiting, confirming, paid, underpaid і expired. За відсутності повідомлень мерчанта використовується англійська. Це доповнення, а не заміна фактичного статусу. Написаний мерчантом текст не перекладається автоматично.Деталі
Звичайний текст для en, de, es, pt-BR, it, ru, zh-CN, fr, ko та ja з ключами waiting, confirming, paid, underpaid і expired. За відсутності повідомлень мерчанта використовується англійська. Це доповнення, а не заміна фактичного статусу. Написаний мерчантом текст не перекладається автоматично.
support_emailstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
support_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
terms_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
privacy_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
return_button_textstringзавждиЛише необов’язкова мітка. Адреси успіху/скасування й політика перенаправлення й далі належать рахунку.
show_return_buttonbooleanзавждиВидимість ручної кнопки повернення/скасування; типово true. Стосується активних і кінцевих станів, а не автоматичного перенаправлення після успіху. Доступна з merchant 8.1.4.
payment_methods[]object[]завжди
Безпечні для публічної форми оплати способи.
payment_railonchain | lightningзавждиLightning залишається способом Bitcoin, окремим від BTC у блокчейні. Визначай вибір за intent id і каналом, а не лише asset_id.
bolt11string | nullзавждиПідписаний запит Lightning; null для способів у блокчейні. Ніколи не плати після того, як payable стане false.
payment_hashstring | nullзавждиХеш платежу Lightning для звіряння, а не адреса отримання. Null для способів у блокчейні.
asset_idUUIDзавждиUUID активу для налаштувань оформлення; відрізняється від payment intent id цього рахунку.
caip_network_idstringзавждиКанонічний ідентифікатор мережі для однозначного визначення вибраного блокчейну.
caip_asset_idstring | nullзавждиКанонічна точна ідентичність активу, включно з перевіреним контрактом токена або mint, якщо застосовно.
asset_icon_urlstring | nullзавждиЛокально кешована іконка активу з того самого origin або null, якщо немає перевіреного зіставлення CoinGecko.
contract_addressstring | nullзавждиКанонічний контракт ERC-20 або mint SPL для токенів; null для нативної валюти.
token_standarderc20 | spl-token | nullзавждиПеревірений модуль виконання токена або null для нативної валюти.
asset_decimalsintegerзавждиТочність найменших одиниць: 11 для мілісатоші BTC Lightning, 8 для сатоші BTC у блокчейні.
payablebooleanзавждиTrue лише коли саме цей спосіб зараз може прийняти платіж; false для неактивних способів після отримання коштів іншим активом.
expected_amountdecimalзавждиПовне зафіксоване котирування у відображуваних і фактичних одиницях блокчейну. Розпізнані фіатні стейблкоїни використовують щонайбільше два десяткові знаки котирування з округленням вгору після спреду; інші активи - адаптивну точність. Фактична точність токена, отримані кошти й залишки часткової оплати лишаються точними. Використовуй повернуті суми без змін.Деталі
Повне зафіксоване котирування у відображуваних і фактичних одиницях блокчейну. Розпізнані фіатні стейблкоїни використовують щонайбільше два десяткові знаки котирування з округленням вгору після спреду; інші активи - адаптивну точність. Фактична точність токена, отримані кошти й залишки часткової оплати лишаються точними. Використовуй повернуті суми без змін.
expected_amount_atomicinteger stringзавждиПовне зафіксоване котирування у відображуваних і фактичних одиницях блокчейну. Розпізнані фіатні стейблкоїни використовують щонайбільше два десяткові знаки котирування з округленням вгору після спреду; інші активи - адаптивну точність. Фактична точність токена, отримані кошти й залишки часткової оплати лишаються точними. Використовуй повернуті суми без змін.Деталі
Повне зафіксоване котирування у відображуваних і фактичних одиницях блокчейну. Розпізнані фіатні стейблкоїни використовують щонайбільше два десяткові знаки котирування з округленням вгору після спреду; інші активи - адаптивну точність. Фактична точність токена, отримані кошти й залишки часткової оплати лишаються точними. Використовуй повернуті суми без змін.
minimum_payment_amountdecimalзавждиПоріг прийнятої остаточної оплати після застосування допуску недоплати.
minimum_payment_amount_atomicinteger stringзавждиПоріг прийнятої остаточної оплати після застосування допуску недоплати.
remaining_amountdecimal stringзавждиТочна відображувана сума, якої ще бракує до прийнятого порога, обмежена знизу нулем.
remaining_amount_atomicinteger stringзавждиНедостача до прийнятого порога в найменших одиницях. Це не запитана сума платежу: допуск впливає лише на прийняття.
destination_addressstringзавждиАдреса призначення в блокчейні й необов’язковий реквізит. Для Lightning це хеш платежу без tag; натомість оплачуй bolt11/payment_uri.
destination_tagstring|nullзавждиАдреса призначення в блокчейні й необов’язковий реквізит. Для Lightning це хеш платежу без tag; натомість оплачуй bolt11/payment_uri.
payment_uristring | nullзавждиЗапит відповідно до мережі: ERC-681, Solana Pay, нативний URI або lightning:<bolt11>. Запити із сумою використовують повну очікувану суму мінус отримані кошти, а не поріг допуску. Null, коли payable дорівнює false, зокрема після прийняття допустимої недоплати. QR Lightning кодує повний запит Lightning, а не хеш платежу.Деталі
Запит відповідно до мережі: ERC-681, Solana Pay, нативний URI або lightning:<bolt11>. Запити із сумою використовують повну очікувану суму мінус отримані кошти, а не поріг допуску. Null, коли payable дорівнює false, зокрема після прийняття допустимої недоплати. QR Lightning кодує повний запит Lightning, а не хеш платежу.
qr_urlpath | nullзавждиШлях до SVG QR з того самого origin, версійований за sequence і точним залишком, або null, коли payable дорівнює false. SVG має no-store.
transaction_countintegerзавждиЗагальна кількість різних публічних дійсних транзакцій, виявлених для цього способу.
transactions_truncatedbooleanзавждиTrue, коли transaction_count перевищує повернутий список останніх транзакцій.
transactions[]object[]завжди
До 10 найновіших публічних дійсних транзакцій. Точні підсумки надходжень не залежать від цієї межі показу.
Примітки до використання
- Bearer-токен не потрібен.
- Cache-Control має значення no-store, пошукову індексацію вимкнено.
- Стався до invoice_id як до даних, що надають доступ клієнтові; не публікуй без потреби.
- asset_icon_url - локальний ресурс із того самого origin; формі оплати клієнта не потрібно звертатися до CoinGecko для його показу.
- Коли destination_tag не null, показуй і копіюй його поряд з адресою: це обов’язковий destination tag XRP, memo ID Stellar або коментар рахунку TON, який треба передати точно.
- Для перевірених токенів asset_kind має значення token, contract_address визначає точний контракт ERC-20 або mint SPL, token_standard визначає канал, а payment_uri містить ідентичність токена.
Помилки
GETПерегляд сторінки оплати магазину/invoice/preview/{project_id}Публічний
Показує збережене оформлення магазину з демонстраційною сумою та реальними метаданими прийнятих активів. Перемикай приклади waiting, confirming, paid, underpaid та expired без створення платежів.
Автентифікація та заголовки
Публічний
Параметри шляху
project_idUUIDобов'язковоUUID проєкту, скопійований у посилання попереднього перегляду автентифікованою панеллю.
Параметри запиту
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming" \
--output 'checkout-preview.html'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-preview.html", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-preview.html", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/invoice/preview/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID&state=confirming",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-preview.html").write_bytes(response.read())Відповідь 200 text/html
Приклад відповіді
<!doctype html>
<!-- Hosted branding preview; no invoice is created -->Примітки до використання
- Попередній перегляд лише демонструє брендинг; його не можна надсилати клієнту як запит на оплату.
- Без адреси отримання, QR для оплати, дій гаманця, перенаправлення чи опитування платежів. Приклади не змінюють фактичний статус рахунку.
- Відповідь має no-store, noindex і не може вбудовуватися.
Помилки
GETДані попереднього перегляду оплати/checkout-api/previews/{project_id}Публічний
Повертає чинне оформлення магазину й безпечні метадані прийнятих активів. payment_methods залишається порожнім; preview_methods не містить платіжних адрес, котирувань чи приватних даних гаманця.
Автентифікація та заголовки
Публічний
Параметри шляху
Параметри запиту
store_idUUID,необов'язковоМає належати цьому проєкту; невідповідні ID повертають 404. Невідомі поля запиту відхиляються.
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID" \
--header 'Accept: application/json'// Node.js 18+ · run on your server, never in browser code.
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID", {
method: "GET",
headers: {
"Accept": "application/json"
},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ["Accept: application/json"],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
print_r(json_decode($response, true, 512, JSON_THROW_ON_ERROR));# Python 3 · standard library; run on your server.
import json
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {
"Accept": "application/json"
}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID?store_id=YOUR_STORE_ID",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(json.load(response))Відповідь 200 application/json
Приклад відповіді
{
"data": {
"preview": true,
"invoice_id": "YOUR_PROJECT_ID",
"amount": "100.00",
"currency": "USD",
"project": {
"name": "Example project",
"checkout_title": "Complete your payment",
"checkout_description": "Choose a network and send the exact amount shown.",
"theme": "system",
"accent_color": "#42e39b",
"logo_url": "/checkout-api/previews/…/logo/…/image.png"
},
"appearance": {"inherit_default_store": true, "theme": "system", "accent_color": "#42E39B", "images": {}},
"preview_methods": [],
"payment_methods": []
}
}Поля відповіді
dataobject
previewbooleaninvoice_idstringamountstringcurrencystringprojectobject
appearanceobject
inherit_default_storebooleanзавждиTrue, коли це оформлення надає стандартний магазин проєкту. False для незалежних магазинів і зафіксованих перевизначень рахунку.
invoice_overridebooleanзавждиTrue, якщо checkout_appearance передано під час створення рахунку. Пропущене/null залишає false.
titlestringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
introstringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
outrostringзавждиЗвичайний заголовок мерчанта, верхнє й нижнє повідомлення. intro замінює customer_message; старий збережений текст залишається. Ніколи не обробляй як розмітку.
customer_messagestringзавждиЗастарілий псевдонім intro для сумісності. У нових інтеграціях використовуй intro.
accent_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
background_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
card_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
button_colorstringзавждиКольори строго у форматі #RRGGBB. Необов’язкові кольори порожні для автоматичних значень; контраст переднього плану обчислюється.
logo_sizestringзавждиsmall, medium або large; left або center. Зображення вписуються повністю, а не обрізаються.
logo_alignmentstringзавждиsmall, medium або large; left або center. Зображення вписуються повністю, а не обрізаються.
imagesobjectзавждиНеобов’язкові URL logo_light, logo_dark і favicon: нормалізовані PNG у межах доступу з того самого origin.
show_order_idbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
show_descriptionbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
details_expandedbooleanзавждиВидимість ID замовлення, опис під заголовком і початкове розгортання ID. Сума залишається видимою; це керування показом, а не приховування даних.
show_project_namebooleanзавждиMerchant 5.6.0+: видимість назв у заголовку. Обидва значення типово true. Ідентичність проєкту/магазину залишається в JSON.
show_store_namebooleanзавждиMerchant 5.6.0+: видимість назв у заголовку. Обидва значення типово true. Ідентичність проєкту/магазину залишається в JSON.
featured_chains[]arrayзавждиУпорядковані налаштування, що застосовуються лише до способів, уже наявних у рахунку. Відсутні чи вимкнені способи ігноруються.
featured_asset_ids[]arrayзавждиУпорядковані налаштування, що застосовуються лише до способів, уже наявних у рахунку. Відсутні чи вимкнені способи ігноруються.
default_asset_idUUID | nullзавждиРекомендований початковий спосіб. Дійсний збережений вибір клієнта або спосіб, що вже отримує кошти, має пріоритет.
messagesobjectзавжди
Звичайний текст для en, de, es, pt-BR, it, ru, zh-CN, fr, ko та ja з ключами waiting, confirming, paid, underpaid і expired. За відсутності повідомлень мерчанта використовується англійська. Це доповнення, а не заміна фактичного статусу. Написаний мерчантом текст не перекладається автоматично.Деталі
Звичайний текст для en, de, es, pt-BR, it, ru, zh-CN, fr, ko та ja з ключами waiting, confirming, paid, underpaid і expired. За відсутності повідомлень мерчанта використовується англійська. Це доповнення, а не заміна фактичного статусу. Написаний мерчантом текст не перекладається автоматично.
support_emailstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
support_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
terms_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
privacy_urlstringзавждиНеобов’язкові контакти й HTTPS-посилання без облікових даних у URL. Зовнішні посилання відкриваються в новому вікні.
return_button_textstringзавждиЛише необов’язкова мітка. Адреси успіху/скасування й політика перенаправлення й далі належать рахунку.
show_return_buttonbooleanзавждиВидимість ручної кнопки повернення/скасування; типово true. Стосується активних і кінцевих станів, а не автоматичного перенаправлення після успіху. Доступна з merchant 8.1.4.
preview_methods[]arraypayment_methods[]arrayПримітки до використання
- Bearer-токен не приймається й не потрібен.
- Не повертаються рахунок, адреса призначення, гаманець, транзакція, IPN, webhook або метадані мерчанта.
- Отримай правильне посилання попереднього перегляду на pay-домені через автентифіковану панель.
Помилки
GETЗображення сторінки оплати магазину/checkout-api/invoices/{invoice_id}/appearance-images/{kind}/{revision}/image.pngПублічний
Повертає нормалізований логотип магазину або favicon цього рахунку. Використовуй URL appearance.images із даних форми оплати.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png" \
--output 'store-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("store-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("store-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("store-logo.png").write_bytes(response.read())Відповідь 200 image/png
Приклад відповіді
(binary PNG response)Примітки до використання
- Використовуй appearance.images із JSON форми оплати. Зафіксовані зображення рахунку продовжують працювати після заміни чи видалення завантаження у вихідному магазині. Явно видалені зображення, неправильний рахунок, вид або невідома редакція повертають 404; знімок ніколи не підміняється поточним зображенням магазину.
- Без перевизначення рахунку використовується поточне чинне зображення магазину, а замінені/видалені редакції повертають 404. Лише PNG, nosniff і приватне кешування.
- Зображення магазину завантажуються в автентифікованій панелі як PNG, JPEG або WebP обмеженого розміру; SVG, HTML і URL зовнішніх зображень не приймаються.
Помилки
GETЗображення попереднього перегляду магазину/checkout-api/previews/{project_id}/stores/{store_id}/appearance-images/{kind}/{revision}/image.pngПублічний
Повертає нормалізоване зображення попереднього перегляду лише за збігу проєкту, магазину, виду й поточної редакції.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png" \
--output 'store-preview-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("store-preview-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("store-preview-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/stores/YOUR_STORE_ID/appearance-images/logo_light/YOUR_IMAGE_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("store-preview-logo.png").write_bytes(response.read())Відповідь 200 image/png
Приклад відповіді
(binary PNG response)Примітки до використання
- Використовуй appearance.images із даних попереднього перегляду. Невідомі або невідповідні ID повертають 404. Інформація гаманця чи платежу не розкривається.
Помилки
GETЛоготип попереднього перегляду з версією/checkout-api/previews/{project_id}/logo/{revision}/image.pngПублічний
Повертає нормалізований логотип проєкту лише за збігу проєкту й безпечної для кешування редакції логотипа. Використовуй project.logo_url із даних попереднього перегляду замість самостійного складання URL.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png" \
--output 'checkout-preview-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-preview-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-preview-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/previews/YOUR_PROJECT_ID/logo/YOUR_LOGO_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-preview-logo.png").write_bytes(response.read())Відповідь 200 image/png
Приклад відповіді
(binary PNG response)Примітки до використання
- Невідомі проєкти й застарілі редакції логотипа повертають invoice_not_found, не розкриваючи, який компонент відсутній.
- Успішно повернуте версійоване зображення незмінне й може кешуватися.
Помилки
GETЗображення QR-коду оплати/checkout-api/invoices/{invoice_id}/payment-methods/{intent_id}/qr.svgПублічний
Створює SVG QR 512×512 для точного платіжного payload відповідно до мережі способу оплати рахунку.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg" \
--output 'payment-qr.svg'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("payment-qr.svg", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("payment-qr.svg", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/payment-methods/YOUR_INTENT_ID/qr.svg",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("payment-qr.svg").write_bytes(response.read())Відповідь 200 image/svg+xml
Приклад відповіді
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">…</svg>Примітки до використання
- Bearer-токен не потрібен.
- Використовуй qr_url, версійований за sequence і залишком, із JSON форми оплати; SVG має private і no-store.
- Після часткової оплати запитує точний залишок і залишається прив’язаним до цього активу.
- Повертає 409 після закінчення строку, завершення або коли активний інший спосіб; payment_qr_unavailable (422), якщо запит завеликий для кодування.
Помилки
GETЛоготип сторінки оплати з версією/checkout-api/invoices/{invoice_id}/logo/{revision}/image.pngПублічний
Повертає нормалізований логотип форми оплати проєкту лише за збігу рахунку й поточної редакції логотипа. Надавай перевагу project.logo_url із JSON форми оплати замість самостійного складання маршруту.
Автентифікація та заголовки
Публічний
Параметри шляху
Запит
curl --fail-with-body --max-time 30 \
--request GET \
--url "https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png" \
--output 'checkout-logo.png'// Node.js 18+ · run on your server, never in browser code.
import { writeFile } from "node:fs/promises";
const response = await fetch("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png", {
method: "GET",
headers: {},
redirect: "error",
signal: AbortSignal.timeout(30000)
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
await writeFile("checkout-logo.png", Buffer.from(await response.arrayBuffer()));<?php
// PHP 8+ with the cURL extension; run on your server.
$ch = curl_init("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) { throw new RuntimeException(curl_error($ch)); }
curl_close($ch);
if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $response"); }
file_put_contents("checkout-logo.png", $response);# Python 3 · standard library; run on your server.
import json
from pathlib import Path
from urllib.request import Request, build_opener, HTTPRedirectHandler
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
headers = {}
request = Request("https://pay.example.com/checkout-api/invoices/YOUR_PUBLIC_INVOICE_ID/logo/YOUR_LOGO_REVISION/image.png",
method="GET", headers=headers)
# Non-2xx responses raise HTTPError. Do not retry writes with a new key.
with build_opener(NoRedirect()).open(request, timeout=30) as response:
Path("checkout-logo.png").write_bytes(response.read())Відповідь 200 image/png
Приклад відповіді
(binary PNG response)Примітки до використання
- Bearer-токен не потрібен.
- Публічний кеш діє один рік з immutable, оскільки редакція адресує стан за вмістом.
- Невідомі/невідповідні редакції повертають invoice_not_found.
Помилки
Довідник для Wholly Crypto 8.3.2. Для встановленої версії відкрий Налаштування → Доступ до API → Документація у своїй панелі. Переглянути випуски.