/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-stream header.
  • 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:

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.

  1. 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"
      }
    }
    
  2. ORDER_STATUS_UPDATED: The order is now in the REFUNDED terminal 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.

  1. 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.

  2. ORDER_STATUS_UPDATED: The order is still in the previous CAPTURED status:

    {
      "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.

  1. A partial refund is made for one carton of juice. You'll get two notifications:

    1. 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"
        }
      }
      
    2. ORDER_STATUS_UPDATED: The order is now in the PARTIALLY_REFUNDED status.

      {
        "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"
        }
      }
      
  2. Another partial refund is made for one carton of juice. You'll get two notifications:

    1. 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"
        }
      }
      
    2. ORDER_STATUS_UPDATED: The order is still in the PARTIALLY_REFUNDED status:

      {
        "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"
        }
      }
      
  3. A third partial refund is issued. The sum of all refunds is now equal to the total order value. You'll get two notifications:

    1. 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"
        }
      }
      
    2. ORDER_STATUS_UPDATED: The order is now in the REFUNDED terminal 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:

  • ORDER_STATUS_UPDATED: Update of the order status.
  • OPERATION_STATUS_UPDATED: Status updated for charge, refund, or cancellation operations.

Enum: TRANSACTION_STATUS_UPDATE, ORDER_STATUS_UPDATED, OPERATION_STATUS_UPDATED, SUBSCRIPTION_STATUS_UPDATED

eventTime

Type: string<date-time>

Event time in RFC 3339: YYYY-MM-DDThh:mm:ssTZD format.

Example: 2025-05-26T21:00:36.08847+00:00

merchantId

Type: string<uuid>

Merchant ID.

Example: 123e4567-e89b-12d3-a456-426614174000

operation

All of 1 type
  • Type: object

    operationId

    Type: string<uuid>

    Operation ID.

    Example: 5d32f295-8723-457d-81f9-ab13f17b7bd6

    operationType

    Type: string

    Operation type. To learn more about operation types, see Operation statuses.

    Enum: AUTHORIZE, BIND_CARD, REFUND, CAPTURE, VOID, RECURRING, PREPAYMENT, SUBMIT

    orderId

    Type: string

    Order ID provided in /v1/orders when creating the order.

    Example: example

    status

    Type: string

    Operation status. To learn more about operation statuses, see Operation statuses.

    Enum: PENDING, SUCCESS, FAIL

    externalOperationId

    Type: string

    Operation ID in the merchant system. Make sure it's unique.

    Pass this parameter to track a specific operation by calling the v1/operations/{external_operation_id} method.

    Example: example

    Example
    {
      "externalOperationId": "example",
      "operationId": "5d32f295-8723-457d-81f9-ab13f17b7bd6",
      "operationType": "AUTHORIZE",
      "orderId": "example",
      "status": "PENDING"
    }
    

Operation details. Received along with the OPERATION_STATUS_UPDATED event

Example
{
  "externalOperationId": "example",
  "operationId": "5d32f295-8723-457d-81f9-ab13f17b7bd6",
  "operationType": "AUTHORIZE",
  "orderId": "example",
  "status": "PENDING"
}

order

All of 1 type
  • Type: object

    orderId

    Type: string

    Order ID provided in /v1/orders when creating the order.

    Example: example

    paymentStatus

    Type: string

    Order status. For more information, see Order status.

    Enum: PENDING, AUTHORIZED, CAPTURED, VOIDED, REFUNDED, CONFIRMED, PARTIALLY_REFUNDED, FAILED

    cartUpdated

    Type: boolean

    Shows whether the cart has been updated. Returned if the order is paid for with Plus points. If set to true, the current cart info is provided.

    Example
    {
      "cartUpdated": true,
      "orderId": "example",
      "paymentStatus": "PENDING"
    }
    

Order details. Received along with the ORDER_STATUS_UPDATED event

Example
{
  "cartUpdated": true,
  "orderId": "example",
  "paymentStatus": "PENDING"
}

subscription

All of 1 type
  • Type: object

    customerSubscriptionId

    Type: string<uuid>

    Subscription ID. The SDK returns it when the subscription is created successfully. You can also save a subscription when you get the first notification on it. The same value will arrive in this field every time the subscription is updated.

    Example: 123e4567-e89b-12d3-a456-426614174000

    status

    Type: string

    Subscription type

    Enum: NEW, ACTIVE, CANCELLED, EXPIRED

    subscriptionPlanId

    Type: string<uuid>

    ID of the subscription plan created in the dashboard or over the API.

    Example: 123e4567-e89b-12d3-a456-426614174000

    nextWriteOff

    Type: string<date-time>

    Date of the next attempt to debit a subscription fee

    Example: 2025-01-01T00:00:00Z

    Example
    {
      "customerSubscriptionId": "123e4567-e89b-12d3-a456-426614174000",
      "nextWriteOff": "2025-01-01T00:00:00Z",
      "status": "NEW",
      "subscriptionPlanId": "123e4567-e89b-12d3-a456-426614174000"
    }
    

Subscription status.

Example
{
  "customerSubscriptionId": "123e4567-e89b-12d3-a456-426614174000",
  "nextWriteOff": "2025-01-01T00:00:00Z",
  "status": "NEW",
  "subscriptionPlanId": "123e4567-e89b-12d3-a456-426614174000"
}

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: success

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:

  • FORBIDDEN: The order exists, but it was not paid for via Yandex Split.
  • ORDER_NOT_FOUND: No order found in the merchant system.
  • ORDER_AMOUNT_MISMATCH: The order amount does not match the amount in the merchant system.
  • ORDER_DETAILS_MISMATCH: The order details differ from those in the merchant system.
  • OTHER: Generic error.
  • UNAUTHORIZED: JWT signature validation failed.
  • TOKEN_EXPIRED: The JWT token has expired.
  • CONFLICT: The notification data conflicts with the order state in the merchant system. For example, a notification about successful payment for a canceled order is received.

Enum: FORBIDDEN, ITEM_NOT_FOUND, ORDER_NOT_FOUND, ORDER_AMOUNT_MISMATCH, ORDER_DETAILS_MISMATCH, OUT_OF_INVENTORY, PICKUP_POINT_NOT_FOUND, SHIPPING_DETAILS_MISMATCH, OTHER, UNAUTHORIZED, TOKEN_EXPIRED, CONFLICT

reason

Type: string

Error cause description.

Example: example

status

Type: string

Default: fail