Collect payments
Share a payment link with your buyer; once they pay — by card (Flitt, with 3-D Secure) or crypto/USDT (KemApp) — the net amount (what was paid, minus the gateway's fee) is credited to your office wallet in USD.
How it works
- Create a transaction for an amount in any currency and get back a
payment_url. - Send the payer to
payment_url(onpayment.skygate.travel). They pick a method — or go straight to one if you forced it — and pay. - We verify the payment server-to-server (card payments must pass full 3-D Secure), then credit your wallet once, with the fee deducted.
- Poll the transaction (or read your wallet) to see it credited.
Fees
The fee is set per gateway by the platform and applied when the payment is credited: credited = amount × (1 − fee%). Current live fees:
| Gateway | Method | Fee | Status |
|---|---|---|---|
flitt — Flitt (card · 3-D Secure) |
Card · 3-D Secure | 0% | Not configured |
kemapp — KemApp (crypto · USDT) |
Crypto · USDT | 0% | Not configured |
Example: a 1000.00 USD payment through a gateway with a 4% fee credits 960.00 USD to your wallet.
Create a transaction
Requires the payments:write scope. Send an Idempotency-Key header to make retries safe.
curl -X POST https://api.hermeseus.com/v3/HAPI/payments \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000,
"currency": "USD",
"description": "Invoice #2043",
"customer_email": "buyer@example.com",
"return_url": "https://yourshop.example/thanks",
"callback_url": "https://yourshop.example/webhooks/skygate",
"forced_gateway": null,
"purpose": "topup",
"booking_ref": null
}'| Field | Req | Description |
|---|---|---|
amount | yes | Amount to collect, in currency (> 0). |
currency | yes | 3–4 letter currency code. Converted to the gateway's charge currency, then credited to your wallet in USD. |
forced_gateway | no | flitt or kemapp. When set, the payer skips the method-picker and goes straight to that gateway. |
description | no | Shown to the payer and on the gateway. Max 255 chars. |
customer_email | no | The payer's email. |
return_url | no | Where the payer is offered to return after paying. |
callback_url | no | Your server endpoint; we POST a signed event there when the transaction reaches a terminal state (see Webhooks below). |
purpose | no | topup (default) credits your wallet; booking collects for a specific order — the payer bears the gateway fee so the net equals the booking price. |
booking_ref | no | With purpose: booking, the order id to settle (e.g. ord_…, hord_…, abk_…). The collected net then covers that booking from your wallet. |
Response 201
{
"object": "payment_transaction",
"id": "9f1c0b64-5b2e-4a1e-9b1a-2c3d4e5f6a7b",
"status": "created",
"environment": "live",
"payment_url": "https://payment.skygate.travel/pay/9f1c0b64-5b2e-4a1e-9b1a-2c3d4e5f6a7b",
"amount": { "amount": "1000.00", "currency": "USD" },
"purpose": "topup",
"forced_gateway": null,
"gateway": null,
"fee_percent": null,
"credited": null,
"three_ds_verified": false,
"gateways": [
],
"expires_at": "2026-01-01T12:00:00+00:00",
"created_at": "2026-01-01T11:00:00+00:00"
}Give payment_url to your buyer. gateways lists the methods they can choose (with each fee), or the single forced one.
Get a transaction
Requires payments:read. Poll it to watch the status move to credited.
curl https://api.hermeseus.com/v3/HAPI/payments/9f1c0b64-5b2e-4a1e-9b1a-2c3d4e5f6a7b \ -H "Authorization: Bearer $ACCESS_TOKEN"
Statuses
| Status | Meaning |
|---|---|
created | Link issued; the payer has not started a gateway yet. |
pending | Payer was sent to a gateway; awaiting the result. |
credited | Paid and credited to your wallet (terminal, success). See credited for the net USD. |
failed | Declined, or a card payment that did not pass full 3-D Secure (terminal). |
expired | The link expired before payment (terminal). |
failed. Crypto (KemApp) has no 3DS step.
Webhooks
If you pass a callback_url, we POST a JSON event to it when a transaction reaches a terminal state (credited, failed, expired, canceled). We retry with backoff until your endpoint returns 2xx.
POST {your callback_url}
X-Skygate-Event: payment.credited
X-Skygate-Signature: t=1767225600,v1=9a0f…c21
{
"event": "payment.credited",
"sent_at": "2026-01-01T12:00:00+00:00",
"data": {
"id": "9f1c0b64-…",
"status": "credited",
"purpose": "topup",
"environment": "live",
"amount": "1000.00",
"currency": "USD",
"credited_usd": "960.00",
"fee_percent": 4,
"gateway": "flitt",
"three_ds_verified": true,
"booking_ref": null,
"credited_at": "2026-01-01T12:00:00+00:00"
}
}Verify the signature
The header is t={timestamp},v1={hmac}. Compute HMAC-SHA256 over the string "{t}.{raw request body}" using your webhook signing secret (find it in the console under Wallet → Webhooks), and compare it, in constant time, to v1. Reject stale timestamps. A webhook is a nudge — always re-read GET /payments/{id} and confirm status: credited before you fulfil anything.
$sig = /* v1 from X-Skygate-Signature */;
$ts = /* t from X-Skygate-Signature */;
$calc = hash_hmac('sha256', $ts.'.'.$rawBody, $secret);
if (!hash_equals($calc, $sig)) abort(400);