API для платформ-виконавців
Платформа бере виплати (Pay-out) зі стакану EmiPay, переказує кошти одержувачу і надсилає квитанцію. За кожну виконану виплату платформа отримує USDT на свій баланс в EmiPay.
Кабінет платформи залишається: оператори бачать заявки, статистику, баланс і спори та можуть узяти виплату вручну.
Ви отримуєте доступні виплати: список і вебхуки про появу та зникнення.
Перший, хто взяв виплату, отримує її разом з карткою одержувача.
Ви переказуєте гривню на картку одержувача.
Надсилаєте квитанцію — виплата завершується, USDT зараховано.
Доступ і ключ
| Базова адреса | https://partner.emipay.net/api/partner/v1 | Усі методи |
| API-ключ | Кабінет → «Інтеграція API» → ключ з правами read і execute | Заголовок Authorization: Bearer emi_…. Показується один раз. |
| Секрет вебхука | Кабінет → «Інтеграція API» → вебхук з вашою адресою | Перевірка підпису подій (whsec_…). Показується один раз. |
Ключі й вебхуки створює супервайзер платформи. Ключ можна обмежити IP-адресами ваших серверів. До 10 активних ключів на акаунт.
API — лише для запитів сервер-сервер. Не вставляйте ключ у код сторінки чи мобільного застосунку.
Формат запитів
- Тіло запитів і відповідей — JSON (
Content-Type: application/json). - Кожен
POST— із заголовкомIdempotency-Key(унікальний рядок): повтор з тим самим ключем не виконає дію вдруге, тому запит можна безпечно повторити після мережевої помилки. - Суми — рядки: гривня з 2 знаками (
"1800.00"), USDT з 6 ("38.730671"). Час — мілісекунди Unix. - Ліміт — 600 запитів на хвилину на акаунт. Залишок — у заголовку
X-RateLimit-Remaining, перевищення —429. - Помилка — HTTP 4xx і
{"error":"…","request_id":"…"}. Вказуйтеrequest_id, звертаючись у підтримку.
Увімкнути прийом
/api/partner/v1/intakeПоки прийом вимкнено, стакан порожній і взяти виплату не можна. GET /profile показує допуск (напрями й межі сум), стан прийому та баланс.
curl -X POST https://partner.emipay.net/api/partner/v1/intake \
-H "Authorization: Bearer $EMIPAY_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"enabled": true}'const r = await fetch('https://partner.emipay.net/api/partner/v1/intake', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.EMIPAY_KEY, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
body: JSON.stringify({"enabled": true}),
});
const data = await r.json();r = requests.post("https://partner.emipay.net/api/partner/v1/intake",
headers={"Authorization": "Bearer " + KEY, "Idempotency-Key": str(uuid.uuid4())},
json={"enabled": True},
timeout=30)
data = r.json()Стакан
/api/partner/v1/orders/available?page=1Початковий стан стакану — список доступних виплат, по 50 на сторінку. Даних одержувача в стакані немає: вони з’являються після взяття.
curl https://partner.emipay.net/api/partner/v1/orders/available?page=1 \ -H "Authorization: Bearer $EMIPAY_KEY"
const r = await fetch('https://partner.emipay.net/api/partner/v1/orders/available?page=1', {
headers: { Authorization: 'Bearer ' + process.env.EMIPAY_KEY },
});
const data = await r.json();r = requests.get("https://partner.emipay.net/api/partner/v1/orders/available?page=1",
headers={"Authorization": "Bearer " + KEY},
timeout=30)
data = r.json(){
"page": 1,
"total": 1,
"intake": true,
"rows": [
{
"id": "100edd64-1f20-42db-85a8-e52fc4896646",
"num": 102121,
"direction": "payout",
"status": "pending",
"currency": "UAH",
"settlement_currency": "USDT",
"amount": "1800.00",
"settlement_amount": "38.730671",
"reward": "0.000000",
"rate": "46.48",
"expires": 1793228865353,
"created": 1793217888298,
"updated": 1793217888298
}
]
}amount | Скільки гривень виплатити одержувачу |
settlement_amount | Скільки USDT отримає платформа за цю виплату |
rate | Ваш курс: amount ÷ settlement_amount |
expires | До коли виплата доступна / має бути виконана |
Далі тримайте стакан актуальним за вебхуками trade.available і trade.unavailable (див. «Вебхуки»). Раз на 1–2 хвилини звіряйте його з цим списком — на випадок втраченої доставки.
Взяти виплату
/api/partner/v1/orders/{id}/acceptПерший, хто взяв виплату (трейдер або платформа), отримує її. У відповіді — заявка зі статусом active і карткою одержувача recipient.
curl -X POST https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/accept \
-H "Authorization: Bearer $EMIPAY_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'const r = await fetch('https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/accept', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.EMIPAY_KEY, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
body: JSON.stringify({}),
});
const data = await r.json();r = requests.post("https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/accept",
headers={"Authorization": "Bearer " + KEY, "Idempotency-Key": str(uuid.uuid4())},
json={},
timeout=30)
data = r.json(){
"id": "100edd64-1f20-42db-85a8-e52fc4896646",
"num": 102121,
"direction": "payout",
"status": "active",
"amount": "1800.00",
"settlement_amount": "38.730671",
"rate": "46.48",
"recipient": "5375414112345672",
"expires": 1793228865353,
…
}200— виплата ваша: переказуйте наrecipientдоexpires.409— її вже взяли — приберіть зі стакану.{"ok":true,"result":"auction","auction_until":…}— на виплату кілька претендентів одночасно; доauction_untilвизначиться виконавець — прийдеtrade.accepted(ваша) абоtrade.unavailable(не ваша).
Квитанція
/api/partner/v1/orders/{id}/receiptПісля переказу надішліть квитанцію — PDF або фото, до 10 МБ, у base64. Заявка переходить у paid, ми підтверджуємо виплату в джерелі, і вона стає completed — USDT зараховано на баланс платформи. Усі квитанції перевіряє ШІ: переконайтеся, що реквізит одержувача (карта / IBAN) і сума збігаються із заявкою і їх добре видно.
curl -X POST https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/receipt \
-H "Authorization: Bearer $EMIPAY_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"filename": "receipt.pdf", "base64": "JVBERi0xLjQK…"}'const r = await fetch('https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/receipt', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.EMIPAY_KEY, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
body: JSON.stringify({"filename": "receipt.pdf", "base64": "JVBERi0xLjQK…"}),
});
const data = await r.json();r = requests.post("https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/receipt",
headers={"Authorization": "Bearer " + KEY, "Idempotency-Key": str(uuid.uuid4())},
json={"filename": "receipt.pdf", "base64": "JVBERi0xLjQK…"},
timeout=30)
data = r.json()Кілька файлів до однієї виплати: усі, крім останнього, надсилайте з "more": true — виплата закривається після останнього файлу.
POST /orders/{id}/receipt {"filename": "1.jpg", "base64": "…", "more": true}
POST /orders/{id}/receipt {"filename": "2.jpg", "base64": "…"}Відмова
/api/partner/v1/orders/{id}/declineНе можете виконати взяту виплату — відмовтеся з причиною:
curl -X POST https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/decline \
-H "Authorization: Bearer $EMIPAY_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"reason": "error", "comment": "…"}'const r = await fetch('https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/decline', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.EMIPAY_KEY, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
body: JSON.stringify({"reason": "error", "comment": "…"}),
});
const data = await r.json();r = requests.post("https://partner.emipay.net/api/partner/v1/orders/100edd64-1f20-42db-85a8-e52fc4896646/decline",
headers={"Authorization": "Bearer " + KEY, "Idempotency-Key": str(uuid.uuid4())},
json={"reason": "error", "comment": "…"},
timeout=30)
data = r.json()error— помилково взяли: виплата повертається в стакан для інших виконавців.wrong_requisite— реквізит одержувача неправильний (картка заблокована, не існує): виплату буде скасовано.
Ваші заявки й баланс
/api/partner/v1/orders?status=active&page=1/api/partner/v1/orders/{id}/api/partner/v1/balance/api/partner/v1/profile/api/partner/v1/events?after=0/api/partner/v1/pingВаші заявки за статусом (active, paid, review, disputed, completed, cancelled, expired), одна заявка, баланс і журнал подій — запасний варіант до вебхуків.
Події
EmiPay надсилає події на вашу адресу. Відповідайте 2xx протягом 10 с, інакше доставку буде повторено (10 с, 30 с, 2 хв, 10 хв, 30 хв, 1 год, 3 год, 6 год). Доставка «щонайменше один раз»: пропускайте повтори за EmiPay-Event-Id.
POST https://your-server/emipay
Content-Type: application/json
EmiPay-Event: trade.available
EmiPay-Event-Id: evt_3f2a…
EmiPay-Delivery: 7c1e…
EmiPay-Signature: t=1793218065,v1=<hex HMAC-SHA256(secret, t + "." + body)>
{"id":"evt_3f2a…","type":"trade.available","created":1793218065475,"data":{ …order… }}| Подія | Коли | Що зробити |
|---|---|---|
trade.available | Виплата з’явилася в стакані (нова або повернута в пул) у межах вашого допуску | Додати в стакан; data — заявка, як у списку |
trade.unavailable | Виплата зникла зі стакану: reason = taken (узяв інший виконавець), cancelled, expired | Прибрати зі стакану |
trade.accepted | Виплату закріплено за вами (зокрема після аукціону) | Виплатити до expires |
trade.deadline | Час на виплату спливає | Надіслати квитанцію або відмовитись |
trade.paid | Квитанцію прийнято, ідемо на підтвердження | — |
trade.completed | Виплату завершено, USDT зараховано | — |
trade.review, trade.disputed | Виплату передано на перевірку / відкрито спір | Зв’язатися з підтримкою, дослати докази в кабінеті |
trade.cancelled, trade.expired, trade.recalculated | Заявку скасовано / прострочено / перераховано | Оновити у себе |
{"id":"evt_…","type":"trade.unavailable","created":1793218065475,"data":{"id":"100edd64-…","num":102121,"reason":"taken"}}Перевірка підпису
Підпис — HMAC-SHA256 від t + "." + тіло секретом вебхука. Рахуйте його на сирому тілі запиту й відкидайте t, старший за 5 хвилин.
import { createHmac, timingSafeEqual } from 'node:crypto';
// rawBody — the request body exactly as received (string), header — EmiPay-Signature
function verify(rawBody, header, secret) {
const { t, v1 } = Object.fromEntries(header.split(',').map(p => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
return v1?.length === expected.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, v1 = parts.get("t", "0"), parts.get("v1", "")
if abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret.encode(), (t + ".").encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)Статуси заявки
| Статус | Значення |
|---|---|
pending | У стакані, ще ніхто не взяв |
active | Взята вами — виплатіть і надішліть квитанцію |
paid | Квитанцію отримано, підтверджуємо в джерелі |
review | На перевірці адміністрацією |
disputed | Відкрито спір |
completed | Виплату завершено, USDT зараховано |
cancelled | Скасовано |
expired | Час вийшов |
Коди помилок
| Код | Коли |
|---|---|
401 | Немає ключа, ключ неправильний, прострочений або відкликаний |
403 | Ключ без потрібного права, запит з недозволеного IP або прийом вимкнено адміністрацією |
404 | Заявку не знайдено (або вона не ваша) |
409 | Стан заявки не дозволяє дію — наприклад, її вже взяли |
413 | Файл квитанції завеликий |
422 | Неправильні дані запиту |
429 | Перевищено ліміт запитів |
Чекліст запуску
- Ключ з правами
readіexecuteзбережено в секретах сервера; задано IP ваших серверів. - Вебхук доступний з інтернету по HTTPS і відповідає 2xx за 10 секунд.
- Обробник перевіряє
EmiPay-Signatureна сирому тілі й пропускає повтори заEmiPay-Event-Id. - Стакан будується зі списку й оновлюється за
trade.available/trade.unavailable; раз на 1–2 хвилини — звірка зі списком. - Кожен
POSTмає унікальнийIdempotency-Key. - Оброблено
409на взятті (виплату взяв інший) і відповідьauction. - Квитанція надсилається лише після фактичного переказу; кілька файлів — з
"more": true. - Перша виплата — на невелику суму.
EmiPay