Webhooks

Receive real-time notifications about payment events

Overview#

Webhooks allow you to receive real-time notifications when events occur in your Yassir Payment account. Instead of polling our API for updates, we push event data to your server as they happen.

When you create a service during onboarding, you provide a webhookUrl. Yassir will send a POST request to this URL whenever a payment event occurs.

When Webhooks Fire#

Webhooks are sent after the following events:

EventDescription
Proceed (success)Payment completed successfully via Yassir Cash
Proceed (failure)Payment was rejected (e.g., insufficient balance)
Pre-authorizationFunds were successfully reserved
CaptureReserved funds were captured (full or partial)
ReleaseReserved funds were released back to the user
RefundA full or partial refund was processed

Webhook Payload#

All webhook events are sent as a POST request with a JSON body in the following format:

Webhook Payload
{
  "actionId": "order_12345",
  "remoteStatus": "The amount was deposited successfully",
  "remoteStatusCode": 2,
  "contextType": "ORDER",
  "orderId": "123e4567-e89b-12d3-a456-426614174000",
  "additionalData": {}
}

Payload Fields#

FieldTypeDescription
actionIdstringYour unique identifier from the original payment intent (e.g., your order ID)
remoteStatusstringHuman-readable status message
remoteStatusCodenumberNumeric status code (see table below)
contextTypestringAlways "ORDER"
orderIdstringThe Yassir payment ID
additionalDataobjectAdditional data (may be empty)

Status Codes (remoteStatusCode)#

CodeStatusDescription
2SucceededPayment completed or captured successfully
3RejectedPayment was rejected by the provider
4RefundedA refund was processed — full or partial. The code is the same for both; query the payment to compare the refunded amounts.
10Reversed / ReleasedPre-authorized funds were released
13Pre-AuthorizedFunds reserved, awaiting capture or release
14Auto-RefundedAn automatic refund was processed

Card payments

Card payments emit the same webhook payload. For a card payment, orderId is the card payment reference. The outbound webhook is sent once per state change and is not retried by Yassir, so also treat Check as your source of truth.

Example Payloads#

Payment Succeeded
// Payment succeeded
{
  "actionId": "order_12345",
  "remoteStatus": "The amount was deposited successfully",
  "remoteStatusCode": 2,
  "contextType": "ORDER",
  "orderId": "123e4567-e89b-12d3-a456-426614174000",
  "additionalData": {}
}
Pre-Authorized
// Pre-authorization completed
{
  "actionId": "order_12345",
  "remoteStatus": "Pre-authorized",
  "remoteStatusCode": 13,
  "contextType": "ORDER",
  "orderId": "123e4567-e89b-12d3-a456-426614174000",
  "additionalData": {}
}
Refund
// Refund processed — full and partial refunds both emit code 4.
// Query the payment to compare refundedAmount vs transactionAmount.
{
  "actionId": "order_12345",
  "remoteStatus": "Transaction was refunded",
  "remoteStatusCode": 4,
  "contextType": "ORDER",
  "orderId": "123e4567-e89b-12d3-a456-426614174000",
  "additionalData": {}
}

Setting Up Webhooks#

1

Configure your endpoint

Create an HTTP endpoint on your server to receive webhook events. The endpoint must be publicly accessible and use HTTPS.

2

Register the webhook URL

Provide your webhook URL as the webhookUrl when creating your service during merchant onboarding. All payment events for that service will be sent to this URL.

3

Handle events

Process the webhook event and return a 2xx response:

JavaScript
app.post('/webhooks/yassir', async (req, res) => {
  const event = req.body;

  switch (event.remoteStatusCode) {
    case 2: // Succeeded
      await handlePaymentSuccess(event.actionId, event.orderId);
      break;
    case 3: // Rejected
      await handlePaymentFailure(event.actionId);
      break;
    case 4: // Refunded (full or partial — fetch the payment for the amounts)
      await handleRefund(event.actionId);
      break;
    case 10: // Released
      await handleRelease(event.actionId);
      break;
    case 13: // Pre-authorized
      await handlePreAuth(event.actionId, event.orderId);
      break;
    case 14: // Auto-refunded
      await handleRefund(event.actionId);
      break;
  }

  res.status(200).send('OK');
});

Best Practices

  • Respond to webhooks within 30 seconds
  • Process webhook data asynchronously for long operations
  • Handle duplicate events using idempotency (use actionId + remoteStatusCode as a key)
  • Always use the remoteStatusCode (not the text status) for programmatic logic