/v1/webhook
Notifications about status updates.
A request is sent when the order status or order operation status changes.
Supported events:
ORDER_STATUS_UPDATED: Update of the order status.OPERATION_STATUS_UPDATED: Status updated for charge, refund, or cancellation operations.
Request format
A request is received in application/octet-stream format as a JWT token signed by the ES256 algorithm. Before handling the request, validate it. To learn how to do this, see Authentication.
The payload of a validated and decoded JWT token contains JSON with event data. See sample events.
If a token contains no request body
- Make sure that your store's backend can accept messages with the
Content-Type: application/octet-streamheader. - Check that the firewall doesn't block incoming requests or truncate the request body.
See details of other errors in Troubleshooting webhook issues.
Operation idempotency
When performing operations with an order, such as making a refund via the /v2/orders/{order_id}/refund method call, be sure to pass the unique operation ID in the externalOperationId parameter.
This allows you to:
- Understand what operation you received a notification for.
- Check the operation status by calling the v1/operations/{external_operation_id} method.
- Prevent duplication.
If you repeat a request with the same externalOperationId value, you'll get the following:
- Information about the current operation if it's in progress.
- An error with the
reasonCode: "DUPLICATE_EXTERNAL_OPERATION_ID"if the operation is complete.
Sample events
Paying for an order
{
"merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx",
"event": "ORDER_STATUS_UPDATED",
"eventTime": "2023-11-26T08:11:09.359370+00:00",
"order":{
"orderId": "700aa3f04df64b3b8712d6b51f752e8b",
"paymentStatus": "CAPTURED"
}
}
See JWT token examples on jwt.io.
Sample request from Yandex to the store backend:
curl -X POST https://test.uz/some/prefix/v1/webhook \
--header 'User-Agent: YandexPay/1.0' \
--header 'Accept: \*/\*' \
--header 'Content-Type: application/octet-stream' \
--header 'X-Request-Id: ff2a54885c4e45309853d2e33af1d63b\\_3a70f3062db640fcb2f3c34de1a27bd5' \
--header 'X-Request-Timeout: 13970' \
--compressed \
-d eyJhbGciOiJFUzI1NiIsImV4cCI6MTcwMDk4NzYwMCwiaWF0IjoxNzAwOTg3MzAwLCJraWQiOiIxLW1lcmNoYW50LWFwaSIsInR5cCI6IkpXVCJ9.eyJtZXJjaGFudElkIjoieHh4eHh4eHh4LXh4eC01eHh4LXh4eHh4LXh4eHh4eHh4IiwiZXZlbnQiOiJPUkRFUl9TVEFUVVNfVVBEQVRFRCIsImV2ZW50VGltZSI6IjIwMjMtMTEtMjZUMDg6MTE6MDkuMzU5MzcwKzAwOjAwIiwib3JkZXIiOnsib3JkZXJJZCI6IjcwMGFhM2YwNGRmNjRiM2I4NzEyZDZiNTFmNzUyZThiIiwicGF5bWVudFN0YXR1cyI6IkNBUFRVUkVEIn19.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx",
"event": "ORDER_STATUS_UPDATED",
"eventTime": "2024-04-25T07:56:29.974810+00:00",
"order":{
"orderId": "253222_1714029088",
"paymentStatus": "FAILED"
}
}
See JWT token examples on jwt.io.
Return
Tip
First, see /v2/orders/{order_id}/refund to learn how refunds are made.
Full refund
Regardless of whether the order status changes, two notifications are sent: one for the operation and one for the order.
-
OPERATION_STATUS_UPDATED: Refund has been successfully completed:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "OPERATION_STATUS_UPDATED", "eventTime": "2024-04-19T10:27:53.323878+00:00", "operation":{ "operationId": "73dec2cd-db5c-4386-be6d-10c5b5a2ee09", "orderId": "86283", "status": "SUCCESS", "operationType": "REFUND" } } -
ORDER_STATUS_UPDATED: The order is now in theREFUNDEDterminal status. You can no longer call refund methods.{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "ORDER_STATUS_UPDATED", "eventTime": "2024-04-19T12:16:28.766392+00:00", "order":{ "orderId": "86283", "paymentStatus": "REFUNDED" } }See JWT token examples on jwt.io.
-
OPERATION_STATUS_UPDATED: Refund has failed:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "OPERATION_STATUS_UPDATED", "eventTime": "2024-06-13T22:27:53.323878+00:00", "operation":{ "operationId": "73dec2cd-db5c-4386-be6d-10c5b5a2ee08", "orderId": "9c8aed6d-a8e5-4c6a-acd8-645538173f66", "status": "FAIL", "operationType": "REFUND" } }See JWT token examples on jwt.io.
-
ORDER_STATUS_UPDATED: The order is still in the previousCAPTUREDstatus:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "ORDER_STATUS_UPDATED", "eventTime": "2024-06-13T22:27:54.323878+00:00", "order":{ "orderId": "9c8aed6d-a8e5-4c6a-acd8-645538173f66", "paymentStatus": "CAPTURED" } }
Partial refund
You can refund the order amount as multiple partial refunds. Once the sum of all refunds reaches the total order value, the order switches to the REFUNDED terminal status. After that, you can no longer call refund methods.
Regardless of whether the order status changes, two notifications are sent: one for the operation and one for the order.
Let's take an example of an order of three cartons of juice.
-
A partial refund is made for one carton of juice. You'll get two notifications:
-
OPERATION_STATUS_UPDATED: Refund has been successfully completed:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "OPERATION_STATUS_UPDATED", "eventTime": "2024-04-19T10:27:53.323878+00:00", "operation":{ "operationId": "73dec3cs-sd5t-4356-ne6d-10c79b5d2ee09", "externalOperationId": "123-partial-refund-1", "orderId": "123", "status": "SUCCESS", "operationType": "REFUND" } } -
ORDER_STATUS_UPDATED: The order is now in thePARTIALLY_REFUNDEDstatus.{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "ORDER_STATUS_UPDATED", "eventTime": "2024-04-19T12:16:28.766392+00:00", "order":{ "orderId": "123", "paymentStatus": "PARTIALLY_REFUNDED" } }
-
-
Another partial refund is made for one carton of juice. You'll get two notifications:
-
OPERATION_STATUS_UPDATED: Refund has been successfully completed:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "OPERATION_STATUS_UPDATED", "eventTime": "2024-04-19T13:27:53.323878+00:00", "operation":{ "operationId": "28fba9ds-kl2m-7891-qw3r-45e82c7f1bb12", "externalOperationId": "123-partial-refund-2", "orderId": "123", "status": "SUCCESS", "operationType": "REFUND" } } -
ORDER_STATUS_UPDATED: The order is still in thePARTIALLY_REFUNDEDstatus:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "ORDER_STATUS_UPDATED", "eventTime": "2024-04-19T13:27:54.321878+00:00", "order":{ "orderId": "123", "paymentStatus": "PARTIALLY_REFUNDED" } }
-
-
A third partial refund is issued. The sum of all refunds is now equal to the total order value. You'll get two notifications:
-
OPERATION_STATUS_UPDATED: Refund has been successfully completed:{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "OPERATION_STATUS_UPDATED", "eventTime": "2024-04-19T13:40:51.323878+00:00", "operation":{ "operationId": "64abc2ts-rj4y-3187-mf5g-56b71e9a4dd67", "externalOperationId": "123-partial-refund-3", "orderId": "123", "status": "SUCCESS", "operationType": "REFUND" } } -
ORDER_STATUS_UPDATED: The order is now in theREFUNDEDterminal status. You can no longer call refund methods.{ "merchantId": "xxxxxxxxx-xxx-5xxx-xxxxx-xxxxxxxx", "event": "ORDER_STATUS_UPDATED", "eventTime": "2024-04-19T14:16:28.766392+00:00", "order":{ "orderId": "123", "paymentStatus": "REFUNDED" } }
-
Request
POST
https://example.merchant.uz/v1/webhook
Production
POST
https://sandbox.example.merchant.uz/v1/webhook
Sandbox
Body
application/json
{
"event": "TRANSACTION_STATUS_UPDATE",
"eventTime": "2025-05-26T21:00:36.08847+00:00",
"merchantId": "123e4567-e89b-12d3-a456-426614174000",
"operation": {
"externalOperationId": "example",
"operationId": "5d32f295-8723-457d-81f9-ab13f17b7bd6",
"operationType": "AUTHORIZE",
"orderId": "example",
"status": "PENDING"
},
"order": {
"cartUpdated": true,
"orderId": "example",
"paymentStatus": "PENDING"
},
"subscription": {
"customerSubscriptionId": "123e4567-e89b-12d3-a456-426614174000",
"nextWriteOff": "2025-01-01T00:00:00Z",
"status": "NEW",
"subscriptionPlanId": "123e4567-e89b-12d3-a456-426614174000"
}
}
|
Name |
Description |
||||||||||
|
event |
Type: string Event type:
Enum: |
||||||||||
|
eventTime |
Type: string<date-time> Event time in Example: |
||||||||||
|
merchantId |
Type: string<uuid> Merchant ID. Example: |
||||||||||
|
operation |
All of 1 type
Operation details. Received along with the Example
|
||||||||||
|
order |
All of 1 type
Order details. Received along with the Example
|
||||||||||
|
subscription |
All of 1 type
Subscription status. Example
|
Responses
200 OK
Webhook received and processed.
The response body can be any value. We recommend sending {"status": "success"}.
If the status code 200 is received, Yandex stops sending repeat webhooks.
Body
application/json
{
"status": "success"
}
|
Name |
Description |
|
status |
Type: string Default: |
400 Bad Request
Webhook processing error.
If no response or any status except 200 is received, Yandex generates a new JWT token and retries the webhook:
- The first 10 attempts occur every 5 ms.
- Then the interval increases exponentially up to 15 minutes.
- After that, retries occur every 15 minutes for 24 hours. The total retry period is 24 hours. After that, the webhook is considered undelivered.
Body
application/json
{
"reason": "example",
"reasonCode": "FORBIDDEN",
"status": "fail"
}
|
Name |
Description |
|
reasonCode |
Type: string Error code:
Enum: |
|
reason |
Type: string Error cause description. Example: |
|
status |
Type: string Default: |