For the complete documentation index, see llms.txt. This page is also available as Markdown.

Webhooks

Real-time notifications for order and KYC status changes. The system sends a signed HTTP POST to your configured webhook URL on every relevant event.

Event model

Three event types are delivered:

Event type
Fired when

order.status.changed

An order transitions to a new status

order.refund.required

An order's crypto is stuck in escrow and only your signature can return it

user.kyc.updated

A user's KYC verification is approved or declined

All events share the same envelope (event_id, event_type, created_at, data) and the same signature scheme. The structure of the data object differs per event type.

Payload shape — order.status.changed

{
  "event_id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "event_type": "order.status.changed",
  "created_at": "2026-02-01T12:00:05Z",
  "data": {
    "order_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "status": "crypto_received",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "crypto_amount": "101.5",
    "crypto_currency": "USDT",
    "partner_fee": "1",
    "partner_fee_pct": 1,
    "fiat_amount": "152880.00",
    "fiat_currency": "NGN",
    "provider": "p2p",
    "payment_details_id": "987"
  }
}

Payload shape — order.refund.required

Fired when an off-ramp order has stopped without a payout and its crypto is still in escrow. This has its own event type because there is no status change to carry it: the order reads cancelled from the moment it stopped, exactly like an order whose refund was already paid out, so a listener filtering on status transitions would never learn that anything is owed. It is sent at most once per order, and the same information is on GET /orders/{order_id} for as long as it stays true.

The data object is the order.status.changed payload plus action_required.

Act on it with the refund pair: GET /orders/{order_id}/refund-authorization-parameters for the transaction to sign, then POST /orders/{order_id}/authorize-refund with the signature. Nobody else can produce that signature — the escrow needs two of its three owners, we hold one key and you hold the other.

Payload shape — user.kyc.updated

Fired when a user's KYC status changes — to verified, rejected, or to a manual compliance review hold (UNDER_REVIEW). Use this event to unlock order creation for the user on your side (only on VERIFIED; UNDER_REVIEW is not cleared).

When KYC is declined, rejection_reasons is included:

When a customer is placed on a manual compliance review hold, kyc_status is UNDER_REVIEW:

kyc_status values: VERIFIED | REJECTED | UNDER_REVIEW

UNDER_REVIEW is a manual compliance review: the customer is NOT cleared and can take up to 24 hours (unlike an automated check of a couple of minutes). Do not unlock order creation until VERIFIED.

Signature verification

Every delivery includes two headers for HMAC-SHA256 verification:

  • X-Unigox-Signature: sha256=<hex> — HMAC of "<timestamp>.<raw_body>"

  • X-Unigox-Timestamp: <unix_seconds>

Verification pseudocode:

Delivery guarantees

  • At-least-once delivery. Your endpoint may receive the same event more than once.

  • De-duplicate by event_id.

  • Respond with any 2xx status within 10 seconds to acknowledge receipt.

Retry policy

Failed deliveries (non-2xx or timeout) are retried with exponential backoff: 1 min → 5 min → 15 min → 1 h → 6 h → 12 h → 24 h (max 10 attempts over ~3.5 days).

Partner-facing statuses (order.status.changed)

Status
Description

created

Order created

awaiting_liquidity_provider

Waiting for vendor match

awaiting_crypto_transfer_authorization

Partner must authorize crypto transfer

crypto_received

Crypto received in escrow

fiat_payment_started

Buyer submitted fiat payment proof

fiat_payment_review_started

Payment proof under admin review

awaiting_fiat_received_confirmation

Proof approved, awaiting seller confirmation

completed

Order completed, crypto released

cancelled

Order cancelled or payment declined

failed

Escrow error, or fiat-anchored safety bound exceeded (see below)

dispute_started

Dispute opened

Fiat-anchored safety bound failure

For fiat-anchored off-ramp orders (anchor_type: "fiat"), if the crypto cost we quote exceeds 1.20× the expected amount at the time of settlement, the order moves to failed status asynchronously (not during /initiate). The deposit is automatically refunded from escrow back to the partner wallet. Create a new quote to retry the trade flow.

Settlement notifications (recipient received the fiat)

Some liquidity providers automatically confirm when the fiat payout reaches the recipient's bank account or mobile wallet. When the provider matched to an order supports this, the order moves to completed on its own and you receive an order.status.changed webhook with status=completed — that webhook is your signal that the recipient has actually received the money.

Whether the matched provider sends this is reported per order by the has_fiat_settlement_notification field on the quote and order responses:

  • true — the matched provider sends an automatic settlement confirmation. You will receive the completed webhook once fiat is delivered; no manual action is needed.

  • false — no automatic confirmation for this order. Confirm delivery yourself by calling confirm-fiat-received (or rely on your own banking/payment systems).

To match only providers that send settlement notifications, pass has_fiat_settlement_notification: true in the quote request — providers that can't offer it are then excluded from matching.

Availability is provider- and corridor-dependent: not every currency has a provider that sends settlement notifications, so always read the flag on each quote rather than assuming it. Manual confirm-fiat-received and the automatic confirmation are mutually idempotent — whichever happens first wins and the other is a safe no-op.

Get webhook config

get
/api/v1/partner/webhooks

Returns the current webhook configuration for your partner account, including the URL and whether the webhook is enabled.

Authorizations
X-API-KeystringRequired

Partner API key for authentication. Required for all partner account endpoints.

Responses
200

Webhook configuration retrieved

application/json
successbooleanRequired

Indicates if the request was successful

Example: true
get/api/v1/partner/webhooks
GET /api/v1/partner/webhooks HTTP/1.1
Host: api-staging.unigox.com
X-API-Key: YOUR_API_KEY
Accept: */*
{
  "success": true,
  "data": {
    "url": "https://partner.example.com/webhooks/unigox",
    "enabled": true
  }
}

Register webhook URL

post
/api/v1/partner/webhooks

Register or update the webhook URL for your partner account. The URL must use HTTPS. Once registered, the webhook is automatically enabled and will start receiving order status events.

Authorizations
X-API-KeystringRequired

Partner API key for authentication. Required for all partner account endpoints.

Body
urlstring · uriRequired

HTTPS URL that will receive webhook events

Example: https://partner.example.com/webhooks/unigox
Responses
200

Webhook registered successfully

application/json
successbooleanRequired

Indicates if the request was successful

Example: true
post/api/v1/partner/webhooks
POST /api/v1/partner/webhooks HTTP/1.1
Host: api-staging.unigox.com
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 53

{
  "url": "https://partner.example.com/webhooks/unigox"
}
{
  "success": true,
  "data": {
    "url": "https://partner.example.com/webhooks/unigox",
    "enabled": true
  }
}

Delete webhook

delete
/api/v1/partner/webhooks/{id}

Remove the webhook URL and disable webhook delivery for your partner account. No further events will be sent until a new URL is registered.

Authorizations
X-API-KeystringRequired

Partner API key for authentication. Required for all partner account endpoints.

Path parameters
idstringRequired

Webhook ID (any value accepted — the system uses the authenticated partner context)

Example: 1
Responses
200

Webhook deleted successfully

application/json
successbooleanRequired

Indicates if the request was successful

Example: true
delete/api/v1/partner/webhooks/{id}
DELETE /api/v1/partner/webhooks/{id} HTTP/1.1
Host: api-staging.unigox.com
X-API-Key: YOUR_API_KEY
Accept: */*
{
  "success": true,
  "data": {
    "message": "webhook deleted"
  }
}

Test webhook

post
/api/v1/partner/webhooks/test

Send a signed test event to your configured webhook URL. Uses the same HMAC-SHA256 signature scheme as production events. Use this to verify your endpoint is reachable and correctly validating signatures.

Authorizations
X-API-KeystringRequired

Partner API key for authentication. Required for all partner account endpoints.

Responses
200

Test event delivered successfully

application/json
successbooleanRequired

Indicates if the request was successful

Example: true
post/api/v1/partner/webhooks/test
POST /api/v1/partner/webhooks/test HTTP/1.1
Host: api-staging.unigox.com
X-API-Key: YOUR_API_KEY
Accept: */*
{
  "success": true,
  "data": {
    "delivered": true,
    "http_status": 200
  }
}

Last updated