Webhooks

Receive and process Rekaz business-event notifications safely.

Rekaz can send business-event notifications to one HTTPS endpoint configured for a tenant.

Configure a receiver

Open Settings > API Keys in the Rekaz dashboard, open the webhook tab, enter a publicly reachable HTTPS URL, enable outbound webhooks, and save. Copy the webhook signing secret and store it only on your server.

The receiver must accept JSON POST requests and should return a 2xx response quickly. Queue real processing and acknowledge first.

Every delivery includes Content-Type: application/json, User-Agent: RekazWebhookClient/1.0, and X-Rekaz-Signature. The signature is a lowercase hexadecimal HMAC-SHA256 value.

Payload and casing

The outer webhook envelope uses PascalCase fields: Id, EventName, CreatedAt, and Data. Fields inside Data also use PascalCase, including nested objects and arrays. Transaction, reservation, subscription, and merchandise-order events expose customer details in Data.Customer, with Id, Name, MobileNumber, and Email. Gift events use BuyerCustomer and RecipientCustomer to distinguish their roles. Enum values are strings. Resource-specific fields differ by event family; route deliveries using EventName.

Id is the unique delivery ID and should be used for deduplication. EventName is the exact event type. CreatedAt is the UTC time when the webhook was created. Data is the current resource snapshot.

Ignore unknown fields and tolerate nullable properties so handlers remain forward-compatible. All date-time values are UTC.

Payload examples

Transaction webhook delivery

All five transaction event names use the Data shape below: PascalCase fields and a nested Customer object. Read the customer mobile number from Data.Customer.MobileNumber. Transaction REST API responses retain camelCase fields and flat customer details; they are a separate contract.

For booking confirmation messages, handle ReservationConfirmedEvent and read Data.Customer.MobileNumber. TransactionCreatedEvent means a transaction was created; ReservationUpdatedEvent means a reservation changed. Neither event alone confirms a booking. Deduplicate retries using the outer Id.

{
"Id": "083bc1f5-d7e9-44b2-9a53-94129a9f763a",
"EventName": "TransactionCreatedEvent",
"CreatedAt": "2026-08-25T10:00:00Z",
"Data": {
"Id": "4ef86c8e-2c63-4c73-a3f0-df124e71c210",
"TransactionNumber": 1254,
"InvoiceNumber": 987,
"Status": "Completed",
"PaymentStatus": "Paid",
"Source": "Internal",
"Customer": {
"Id": "69e943fc-5705-44d8-a2da-f23371a1625d",
"Name": "Ahmed Ali",
"MobileNumber": "+966500000000",
"Email": "[email protected]"
},
"BranchIds": [
"4c31f35e-7477-4887-8ea8-93a3d13581ec"
],
"Subtotal": 100,
"DiscountAmount": 10,
"TaxAmount": 13.5,
"FeesAmount": 0,
"TotalAmount": 103.5,
"PaidAmount": 103.5,
"RemainingAmount": 0,
"Currency": "SAR",
"ExchangeRateToSAR": 1,
"CreatedAt": "2026-08-25T10:00:00Z",
"UpdatedAt": "2026-08-25T10:05:00Z",
"Items": [
{
"Id": "b3ec6432-283f-4c69-8897-2791192ff1e0",
"Type": "Reservation",
"NameAr": "\u062d\u062c\u0632 \u0627\u0633\u062a\u0634\u0627\u0631\u0629",
"NameEn": "Consultation reservation",
"Sku": "CONSULT-01",
"ProductId": "ee73af19-cfb6-44b6-a06a-d9805112a80a",
"PriceId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
"Quantity": 1,
"UnitPrice": 100,
"Subtotal": 100,
"DiscountAmount": 10,
"TaxAmount": 13.5,
"TotalAmount": 103.5
}
],
"Payments": [
{
"Id": "bc908f57-0f5d-4178-8903-42d82a98c7ee",
"Type": "Payment",
"Status": "Confirmed",
"Method": "Online",
"CustomPaymentMethodId": null,
"Amount": 103.5,
"Currency": "SAR",
"PaymentDate": "2026-08-25T10:05:00Z"
}
]
}
}

Transaction REST API responses

Both API reference pages include complete 200 response examples with customer, totals, items, and payments.

Reservation webhook delivery

All reservation event names use this Data shape. EventName identifies the lifecycle change.

{
  "Id": "6c4a9c47-b9ec-4f5d-9fb7-8a356d577dc4",
  "EventName": "ReservationConfirmedEvent",
  "CreatedAt": "2026-08-25T10:02:00Z",
  "Data": {
    "Id": "4d5399df-58a5-4523-a347-f5cb691e42d1",
    "StartDate": "2026-08-25T10:00:00Z",
    "FromDay": "Monday",
    "FormattedFromDate": "2026-08-25",
    "FormattedFromTime": "10:00 AM",
    "EndDate": "2026-08-25T11:00:00Z",
    "EndDay": "Monday",
    "FormattedEndDate": "2026-08-25",
    "FormattedEndTime": "11:00 AM",
    "Status": "Confirmed",
    "CustomStatus": null,
    "Price": 103.5,
    "Discount": 10,
    "Customer": {
      "Id": "69e943fc-5705-44d8-a2da-f23371a1625d",
      "Name": "Ahmed Ali",
      "MobileNumber": "+966500000000",
      "Email": "[email protected]"
    },
    "ProductName": "Consultation",
    "PriceName": "Standard",
    "OptionName": "Standard",
    "Number": "4821",
    "CancellationReason": null,
    "Sku": "CONSULT-01",
    "Providers": [
      {
        "Name": "Sara Ahmed",
        "Number": 42,
        "Id": "b7e7f9ab-21a0-4d36-9958-e8cb0e4a6c14"
      }
    ],
    "BranchId": "4c31f35e-7477-4887-8ea8-93a3d13581ec",
    "BranchNameAr": "فرع الرياض",
    "BranchNameEn": "Riyadh Branch",
    "ProductId": "ee73af19-cfb6-44b6-a06a-d9805112a80a",
    "ProductCategoryId": "a27585a7-aef7-44f7-85a9-bebec6601ce4",
    "OptionId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
    "CustomFields": [
      {
        "Name": "notes",
        "Label": "Notes",
        "Type": "String",
        "Value": "First visit"
      }
    ],
    "Items": [
      {
        "PriceName": "Standard",
        "PriceId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
        "OptionName": "Standard",
        "OptionId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
        "Sku": "CONSULT-01",
        "Price": 103.5
      }
    ],
    "Order": {
      "Id": "4ef86c8e-2c63-4c73-a3f0-df124e71c210",
      "SequentialNumber": 1254,
      "Status": "Confirmed",
      "PaymentStatus": "Paid",
      "Currency": "SAR",
      "Subtotal": 100,
      "DiscountAmount": 10,
      "TaxAmount": 13.5,
      "TotalAmount": 103.5,
      "PaidAmount": 103.5,
      "RemainingAmount": 0,
      "Item": {
        "Id": "b3ec6432-283f-4c69-8897-2791192ff1e0",
        "ProductId": "ee73af19-cfb6-44b6-a06a-d9805112a80a",
        "PriceId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
        "ReferenceId": "4d5399df-58a5-4523-a347-f5cb691e42d1",
        "Sku": "CONSULT-01",
        "Quantity": 1,
        "UnitPrice": 100,
        "Subtotal": 100,
        "DiscountAmount": 10,
        "TaxAmount": 13.5,
        "TotalAmount": 103.5
      }
    },
    "InvoiceUrl": "https://platform.rekaz.io/orders/last/invoice?orderId=4ef86c8e-2c63-4c73-a3f0-df124e71c210&isPrint=false"
  }
}

Subscription webhook delivery

Subscription events use this Data shape. SubscriptionTransferedEvent additionally includes FromCustomer and ToCustomer; other subscription events omit those two fields.

{
  "Id": "763e88c8-5bc6-4f09-b90c-34ab7f34ad49",
  "EventName": "SubscriptionTransferedEvent",
  "CreatedAt": "2026-08-25T11:00:00Z",
  "Data": {
    "Id": "8e126099-555d-4a22-99e0-72b35c53e17d",
    "StartDate": "2026-08-01T00:00:00Z",
    "EndDate": "2026-09-01T00:00:00Z",
    "Status": "Transferred",
    "Price": 200,
    "Discount": 20,
    "Customer": {
      "Id": "23167f7e-64ac-499e-8991-dfa0d3876de0",
      "Name": "Mona Saleh",
      "MobileNumber": "+966511111111",
      "Email": "[email protected]"
    },
    "Name": "Monthly membership",
    "Number": "2084",
    "Code": "SUB-2084",
    "CustomFields": [
      {
        "Name": "goal",
        "Label": "Goal",
        "Type": "String",
        "Value": "Improve fitness"
      }
    ],
    "PausedAt": null,
    "ResumeAt": null,
    "BranchId": "4c31f35e-7477-4887-8ea8-93a3d13581ec",
    "BranchNameAr": "فرع الرياض",
    "BranchNameEn": "Riyadh Branch",
    "Items": [
      {
        "PriceName": "Monthly",
        "PriceId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
        "OptionName": "Monthly",
        "OptionId": "ec62375d-cd99-47ed-bb9c-b7027c195423",
        "Price": 200
      }
    ],
    "InvoiceUrl": "https://platform.rekaz.io/orders/last/invoice?orderId=1c7e068d-0152-4249-9fe1-c5baf2a8e939&isPrint=false",
    "FromCustomer": {
      "Id": "69e943fc-5705-44d8-a2da-f23371a1625d",
      "Name": "Ahmed Ali",
      "MobileNumber": "+966500000000",
      "Email": "[email protected]"
    },
    "ToCustomer": {
      "Id": "23167f7e-64ac-499e-8991-dfa0d3876de0",
      "Name": "Mona Saleh",
      "MobileNumber": "+966511111111",
      "Email": "[email protected]"
    }
  }
}

Merchandise order webhook delivery

All merchandise-order event names use this Data shape. EventName identifies whether the order was created, completed, or canceled.

{
  "Id": "9dcb11b9-1887-4b4d-8729-df8490a3fd18",
  "EventName": "MerchandiseOrderCreatedEvent",
  "CreatedAt": "2026-08-25T12:00:00Z",
  "Data": {
    "Id": "3ac6f6dd-8890-4c88-abf6-e27be67330ac",
    "BranchId": "4c31f35e-7477-4887-8ea8-93a3d13581ec",
    "BranchNameAr": "فرع الرياض",
    "BranchNameEn": "Riyadh Branch",
    "Status": "Pending",
    "CustomStatus": null,
    "TotalPrice": 230,
    "Discount": 20,
    "Code": "MER-3108",
    "Customer": {
      "Id": "69e943fc-5705-44d8-a2da-f23371a1625d",
      "Name": "Ahmed Ali",
      "MobileNumber": "+966500000000",
      "Email": "[email protected]"
    },
    "CreationTime": "2026-08-25T12:00:00Z",
    "Items": [
      {
        "Id": "8cf0a9b9-0de1-4664-b462-bef40a57fc33",
        "Name": "Black - Large",
        "ProductName": "Rekaz T-shirt",
        "ProductId": "dbef7a15-f3fb-4d58-bcf9-b86d92d21115",
        "PriceName": "Large",
        "PriceId": "54285793-ab49-4dc7-a1eb-f9dbf8a61da5",
        "Quantity": 2,
        "TotalPrice": 230,
        "Discount": 20,
        "CustomFields": [
          {
            "Name": "color",
            "Label": "Color",
            "Type": "List",
            "Value": "Black"
          }
        ]
      }
    ],
    "InvoiceUrl": "https://platform.rekaz.io/orders/last/invoice?orderId=45a92d55-38ed-4cf3-9e16-0246af07d8ce&isPrint=false"
  }
}

Gift webhook delivery

All gift event names use this Data shape. EventName identifies whether the gift was created, activated, redeemed, or cancelled.

{
  "Id": "bc28cb6d-9f97-4b84-8d9a-743a62af608d",
  "EventName": "GiftActivatedEvent",
  "CreatedAt": "2026-08-25T13:00:00Z",
  "Data": {
    "Id": "aa124ca3-4c63-4746-84c0-9403a5a50f1a",
    "BranchId": "4c31f35e-7477-4887-8ea8-93a3d13581ec",
    "BranchNameAr": "فرع الرياض",
    "BranchNameEn": "Riyadh Branch",
    "Status": "Active",
    "CustomStatus": null,
    "TotalPrice": 250,
    "CreationTime": "2026-08-25T13:00:00Z",
    "ProductId": "5f510bf2-cc24-4d09-a8a2-f2f7778f25d2",
    "ProductName": "Gift card",
    "PriceId": "79333b43-4e22-46ec-b9d0-65cbf668f158",
    "PriceName": "SAR 250",
    "Message": "Happy birthday!",
    "FromName": "Ahmed",
    "ToName": "Mona",
    "Language": "ar",
    "ShowBuyerInfo": true,
    "GiftThemeName": "Celebration",
    "GiftCardImageUrl": "https://cdn.rekaz.io/example/gift-card.png",
    "GiftCouponCode": "GIFT-7R2Q",
    "RedemptionUrl": "https://example.rekaz.io/gifts/redeem/example-token",
    "InvoiceUrl": "https://platform.rekaz.io/orders/last/invoice?orderId=f9743b47-2c5b-43cb-8e8f-2897eef1711d&isPrint=false",
    "BuyerCustomer": {
      "Id": "69e943fc-5705-44d8-a2da-f23371a1625d",
      "Name": "Ahmed Ali",
      "MobileNumber": "+966500000000",
      "Email": "[email protected]"
    },
    "RecipientCustomer": {
      "Id": "23167f7e-64ac-499e-8991-dfa0d3876de0",
      "Name": "Mona Saleh",
      "MobileNumber": "+966511111111",
      "Email": "[email protected]"
    },
    "CustomFields": []
  }
}

Transaction events

  • TransactionCreatedEvent — transaction created
  • TransactionUpdatedEvent — transaction or pending payment changed
  • TransactionPaidEvent — payment confirmed
  • TransactionRefundedEvent — payment refunded
  • TransactionCancelledEvent — transaction cancelled

TransactionUpdatedEvent is also emitted when a pending payment is created, edited, or deleted. Confirmed payments use TransactionPaidEvent.

Other event names

Reservation

  • ReservationCreatedEvent
  • ReservationConfirmedEvent
  • ReservationDoneEvent
  • ReservationCancelledEvent
  • ReservationUpdatedEvent

Subscription

  • SubscriptionCreatedEvent
  • SubscriptionActivatedEvent
  • SubscriptionCancelledEvent
  • SubscriptionExpiredEvent
  • SubscriptionPausedEvent
  • SubscriptionResumedEvent
  • SubscriptionPauseScheduledEvent
  • SubscriptionTransferedEvent
  • SubscriptionUpdatedEvent

SubscriptionTransferedEvent intentionally uses the existing spelling with one r in Transfered.

Merchandise orders

  • MerchandiseOrderCreatedEvent
  • MerchandiseOrderCompletedEvent
  • MerchandiseOrderCanceledEvent

Gifts

  • GiftCreatedEvent
  • GiftActivatedEvent
  • GiftRedeemedEvent
  • GiftCancelledEvent

Reservation pricing and order totals

Price and Items[].Price are the reservation line total after discount, including tax. These existing fields remain available for backward compatibility.

Reservation webhook payloads also include an additive Order object with Subtotal, DiscountAmount, TaxAmount, TotalAmount, PaidAmount, RemainingAmount, Currency, OrderStatus, OrderPaymentStatus, and the related Item breakdown.

Order.Item includes Quantity, UnitPrice, Subtotal, DiscountAmount, TaxAmount, and TotalAmount. The reservation Price matches Order.Item.TotalAmount. Order.TotalAmount can differ when the order contains other items.

Verify the signature

Read the request body as raw bytes before JSON parsing. Compute HMAC-SHA256 over those exact bytes using the webhook signing secret. Encode the result as lowercase hexadecimal and compare it with X-Rekaz-Signature using a constant-time comparison. Reject a missing or invalid signature before processing the payload.

Regenerating the secret in Settings > API Keys > Webhook immediately changes the secret used for new delivery attempts. Update your receiver before rotating when possible. Never log the secret or full customer payloads.

A valid signature confirms that Rekaz produced the request. It does not replace checking current resource state before sensitive actions.

Delivery behavior

Any 2xx response is treated as success. Failed delivery jobs can be retried, but retry timing is not a public contract. Duplicate deliveries are possible, and delivery order is not guaranteed.

Store Id with a unique constraint before applying side effects. When correctness depends on current state, fetch the resource through the authenticated API.


Did this page help you?