Skip to main content

Overview

You can receive payout status change notifications at a URL you provide. When a payout’s status changes, we send an HTTP POST to your endpoint with the event payload. We use six consolidated statuses: PENDING, ADDITIONAL_INFO_REQUIRED, PROCESSING, SUCCESSFUL, FAILED, and REJECTED. The same webhook URL also receives wallet credit and debit notifications for your business (see Wallet credit and debit). You do not register a second URL.
  • One webhook URL per business — you can register a single HTTPS endpoint; we send payout status events and wallet movement events for your business to that URL.
  • Optional signing — you can provide a secret when registering; we then sign each request so you can verify it came from Yala. We strongly recommend setting a secret and verifying the signature to protect your endpoint against spoofed webhooks.
  • Use the same API key (and base URL) as for the rest of the Payout API when managing your webhook subscription.

Subscribe via API

Use the Payout API with your existing x-api-key to manage your webhook URL. Base path: Same as payouts — https://gateway.staging.useyala.com/v1/payout-api (sandbox) or https://gateway.useyala.com/v1/payout-api (production). Webhook endpoints live under /webhooks.

Register a webhook URL

Request body: Example:
Only one active webhook URL is allowed per business. To change it, update the existing subscription (PATCH) or delete and create a new one.

Payload we send

Each notification is an HTTP POST with:
  • Content-Type: application/json
  • Body: JSON object with the shape below.
  • Headers we add:
    • X-Yala-Delivery-Id — unique ID for this delivery (use it to deduplicate if you receive the same event more than once).
    • X-Yala-Signature — only present if you set a secret; format sha256=<hex>. See Verifying the signature.

Payload shape

When additional information has been submitted and is under review, newStatus is PENDING and newStatusDetail is ADDITIONAL_INFO_UNDER_REVIEW:
Status values — We send exactly six statuses so you can integrate simply:

Wallet credit and debit

When a wallet for your business is credited or debited, we POST to the same registered URL as payout webhooks. These messages are separate from payout status updates—check eventType and data.transactionType to route them in your handler.

Event names (eventType)

Direction (transactionType)

Use data.transactionType so you do not rely only on eventType:

Example payload (wallet)

Wallet data fields

Headers (X-Yala-Delivery-Id, X-Yala-Signature), retries, and verification work the same as for payout payloads.

Verifying the signature

If you registered a secret, we sign each request with HMAC-SHA256 of the raw request body (the exact JSON string we send). We send the hex-encoded digest in the header:
How to verify:
  1. Read the raw request body (do not parse and re-serialize; use the exact bytes received).
  2. Compute HMAC-SHA256(rawBody, yourSecret).
  3. Hex-encode the result.
  4. Compare with the value in X-Yala-Signature after the sha256= prefix.
If they match, the request came from Yala and the body was not modified in transit.
Use the raw body. Small differences in JSON formatting (e.g. key order or spacing) will change the signature. Always verify against the exact bytes you receive.

Best practices

  • Respond quickly — Return HTTP 2xx as soon as you have accepted the payload. Process the event asynchronously if needed so we don’t time out.
  • Deduplicate — Store deliveryId and ignore requests you have already processed so duplicate deliveries do not trigger duplicate actions.
  • Set a secret and verify the signature — We strongly recommend setting a secret when registering and always verifying X-Yala-Signature before trusting the payload. Without this, your endpoint could accept spoofed webhooks from third parties.
  • Use HTTPS only — We only send to HTTPS URLs. Keep your endpoint and secret secure.

Delivery retries

If your endpoint does not return HTTP 2xx, we retry delivery automatically.
  • Total attempts: 5
  • Backoff schedule: 1 minute, 5 minutes, 15 minutes, 1 hour, 4 hours
  • Stop condition: Any HTTP 2xx response marks the delivery as successful and stops retries
  • Final state: After the 5th failed attempt, the delivery is marked as failed

Managing your subscription

  • List: GET /v1/payout-api/webhooks returns your current subscription(s). The response does not include the secret.
  • Update: PATCH /v1/payout-api/webhooks/:id with url, secret, eventTypes, or isActive as needed.
  • Remove: DELETE /v1/payout-api/webhooks/:id stops notifications to that URL.
All of these use the same authentication as the rest of the Payout API (x-api-key).
You can also manage your webhook URL from the Yala app under Settings → Payout API Keys (webhook section). The API and the app stay in sync.