Hermeseus Docs
Legacy docs

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

  1. Create a transaction for an amount in any currency and get back a payment_url.
  2. Send the payer to payment_url (on payment.skygate.travel). They pick a method — or go straight to one if you forced it — and pay.
  3. We verify the payment server-to-server (card payments must pass full 3-D Secure), then credit your wallet once, with the fee deducted.
  4. Poll the transaction (or read your wallet) to see it credited.
Crediting is server-verified. A payment is only credited after a signature-verified gateway callback and a server-to-server status re-check — never because the payer's browser returned. Each transaction credits the wallet at most once.

Fees

The fee is set per gateway by the platform and applied when the payment is credited: credited = amount × (1 − fee%). Current live fees:

GatewayMethodFeeStatus
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

POST/v3/HAPI/payments

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
  }'
FieldReqDescription
amountyesAmount to collect, in currency (> 0).
currencyyes3–4 letter currency code. Converted to the gateway's charge currency, then credited to your wallet in USD.
forced_gatewaynoflitt or kemapp. When set, the payer skips the method-picker and goes straight to that gateway.
descriptionnoShown to the payer and on the gateway. Max 255 chars.
customer_emailnoThe payer's email.
return_urlnoWhere the payer is offered to return after paying.
callback_urlnoYour server endpoint; we POST a signed event there when the transaction reaches a terminal state (see Webhooks below).
purposenotopup (default) credits your wallet; booking collects for a specific order — the payer bears the gateway fee so the net equals the booking price.
booking_refnoWith 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

GET/v3/HAPI/payments/{id}

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

StatusMeaning
createdLink issued; the payer has not started a gateway yet.
pendingPayer was sent to a gateway; awaiting the result.
creditedPaid and credited to your wallet (terminal, success). See credited for the net USD.
failedDeclined, or a card payment that did not pass full 3-D Secure (terminal).
expiredThe link expired before payment (terminal).
3-D Secure (card / Flitt). Card payments are credited only when fully 3-D Secure authenticated. A non-3DS or attempted-only authentication is rejected and the transaction ends 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);