Webhooks

Overview

Webhooks allow you to receive notifications of events that happen to your Xsolla transactions. Use webhooks to automate back-end and supplementary functions, such as providing status and other transaction-related information.

We use webhooks for payments, including purchases of virtual currency, items, games, physical goods and so on.

In most cases, webhooks are triggered by user actions on your website. But they can come from other actions, too. For example, a back-end process on your website may invoke an API method to refund a payment, or the payment system may send a notification about a disputed charge.

You must write or use a so-called listener, or handler, to receive and process webhooks. This is a program that waits for a webhook and usually passes it to an internal workflow of yours, which responds appropriately.

For example, you can do the following after receiving a webhook:

  • Filling up a user’s balance
  • Unlocking new item for a user
  • Delivering physical goods to a user

Listen to webhooks at the following IP addresses: 185.30.20.0/24, 185.30.21.0/24, 185.30.23.0/24.

Notice: Your database must NOT contain two successful transactions with the same ID. If your listener receives a webhook with an existing transaction ID, it must return the latest result for that transaction. Avoid charging the user twice or creating duplicate records in your database.

We cannot guarantee that your listener will receive all the webhooks we send. As internet connection is not 100% reliable, webhooks may fail to come on time or at all. Moreover, your listener may return a 5xx HTTP code for a temporary error on your server. For example, your listener returns a 500 HTTP response code in case a virtual item that a user purchased successfully was not added to the user's inventory.

To reduce the risk of lost messages, the Xsolla alert service uses a retry mechanism. For messages that don’t reach their destination, the service resends them per the following frequency:

  • 2 times with an interval of 5 minutes
  • 7 times with an interval of 15 minutes
  • 10 times with an interval of 60 minutes
A repeated webhook may be sent within 12 hours after the previous one. The maximum number of retries is 20.

Note: Although connection problems may indeed result in lost, delayed, or duplicate webhooks, the most common cause is faulty logic on the listener side.

Response Codes

Xsolla API accepts conventional HTTP response codes for successful and failed requests. Code 204 indicates successful processing. Return code 400 in case of an error in the provided information (e.g., a required parameter missing, a failed recharge, etc.). Use code 500 for temporary errors with your servers.

Sign Requests

Digital signatures enable secure data transmission. To generate the signature, (1) concatenate the request's JSON body with your project's secret key and (2) apply SHA-1 hashing to the resulting string.

Make sure that the created signature matches the one passed in the HTTP header.

Copy
Full screen
Small screen
http
  • http
  • curl
Request
POST /your_uri HTTP/1.1
Host: your.host
Accept: application/json
Content-Type: application/json
Content-Length: 165
Authorization: Signature 52eac2713985e212351610d008e7e14fae46f902

{
  "notification_type":"user_validation",
  "user":
    {
      "ip":"127.0.0.1",
      "phone":"18777976552",
      "email":"email@example.com",
      "id":1234567,
      "name":"Xsolla User",
      "country":"US"
    }
}
$curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'Authorization: Signature 52eac2713985e212351610d008e7e14fae46f902' \
-d '{
  "notification_type":
    "user_validation",
    "user":
      {
        "ip":"127.0.0.1",
        "phone":"18777976552",
        "email":"email@example.com",
        "id":1234567,
        "name":"Xsolla User",
        "country":"US"
      }
    }'
Response

Webhooks List

The type of notification is sent in the notification_type parameter.

Notification TypeDescription
order_paidNotification about getting the cart’s content when making a purchase.
order_canceledNotification about payment cancellation.

Getting Cart’s Content When Making Purchase

When the user confirms the cart’s content when making a purchase, Xsolla sends the order_paid notification to the webhook URL.

ParameterTypeDescription
items
arrayList of items purchased by a user.
items.sku
stringItem’s unique ID. Items with the game_key type use the value in the sku_drm format.
items.type
stringItems type. It can have the following values: virtual_good, virtual_currency, game_key, physical_good.
items.quantity
integerQuantity of items.
items.amount
stringTotal cost of items that considers their quantity. May differ from the item’s price due to changes of currency rates and commission.
items.promotions
arrayApplied promotions. If the promotion wasn’t applied, an empty array is written to the parameter.
items.promotions.amount_without_discount
stringTotal cost of items without a discount.
items.promotions.amount_with_discount
stringTotal cost of items with a discount.
items.promotions.sequence
integerID of the applied promotion.
items.is_pre_order
booleanIf true, the item is pre-order.
notification_type
stringNotification type. Required.
order
objectPayment information.
order.id
integerTransaction ID.
order.mode
stringPayment type. It can have the following values: default or sandbox.
order.currency_type
stringPayment type. It can have the following values: real for real currency or virtual for virtual currency.
order.currency
stringCurrency of order. Virtual currency uses the SKU and real currency uses a three-letter code per ISO 4217.
order.amount
stringThe total cost of a cart that considers a chosen currency.
order.status
stringOrder status.
order.platform
stringPayment platform. The xsolla value is used for payments via Xsolla. Other payments use the value that corresponds with the name of the integrated payment system.
order.comment
stringUser’s commentary to the order.
order.invoice_id
stringReal currency payments invoice ID. Virtual currency payments use the null value.
order.promotions
arrayApplied promotions. If the promotion wasn't applied, an empty array is written to the parameter.
order.promotions.amount_without_discount
stringOrder total cost without a discount.
order.promotions.amount_with_discount
stringOrder total cost with a discount.
order.promotions.sequence
stringID of the applied promotion.
user
objectUser information.
user.external_id
stringUser ID.
user.email
stringUser email address.
custom_parameters
objectAdditional information.
Copy
Full screen
Small screen
http
  • http
  • curl
Request
POST /your/uri HTTP/1.1
Host: your.hostname
Accept: application/json
Content-Type: application/json
Content-Length: 240
Authorization: Signature 13342703ccaca5064ad33ba451d800c5e823db8f

{
  "items": [
    {
      "sku": "virtual-good-item-sku",
      "type": "virtual_good",
      "quantity": 3,
      "amount": "100",
      "promotions": [
        {
          "amount_without_discount": "200",
          "amount_with_discount": "100",
          "sequence": 1
        }
      ]
    },
    {
      "sku": "game_sku_steam",
      "type": "game_key",
      "quantity": 1,
      "amount": "200",
      "promotions": []
    },
    {
      "sku": "gold",
      "type": "virtual_currency",
      "quantity": 1500,
      "amount": "100",
      "promotions": []
    }
  ],
  "notification_type": "order_paid",
  "order": {
    "id": 42,
    "mode": "default",
    "currency_type": "real",
    "currency": "USD",
    "amount": "200",
    "status": "paid",
    "platform": "xsolla",
    "comment": null,
    "invoice_id": "23444",
    "promotions": [
      {
        "amount_without_discount": "400",
        "amount_with_discount": "200",
        "sequence": 1
      }
    ]
  },
  "user": {
    "external_id": "gamer_external_id",
    "email": "gamer@email.com"
  }
}
$ curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Signature 13342703ccaca5064ad33ba451d800c5e823db8f' \
-d '{
  "items": [
    {
      "sku": "virtual-good-item-sku",
      "type": "virtual_good",
      "quantity": 3,
      "amount": "100",
      "promotions": [
        {
          "amount_without_discount": "200",
          "amount_with_discount": "100",
          "sequence": 1
        }
      ]
    },
    {
      "sku": "game_sku_steam",
      "type": "game_key",
      "quantity": 1,
      "amount": "200",
      "promotions": []
    },
    {
      "sku": "gold",
      "type": "virtual_currency",
      "quantity": 1500,
      "amount": "100",
      "promotions": []
    }
  ],
  "notification_type": "order_paid",
  "order": {
    "id": 42,
    "mode": "default",
    "currency_type": "real",
    "currency": "USD",
    "amount": "200",
    "status": "paid",
    "platform": "xsolla",
    "comment": null,
    "invoice_id": "23444",
    "promotions": [
      {
        "amount_without_discount": "400",
        "amount_with_discount": "200",
        "sequence": 1
      }
    ]
  },
  "user": {
    "external_id": "gamer_external_id",
    "email": "gamer@email.com"
  }
}'
Response
HTTP/1.1 204 No Content

Payment Cancellation

When the user cancels the payment, Xsolla sends the order_canceled notification to the webhook URL.

ParameterTypeDescription
items
arrayList of items purchased by a user.
items.sku
stringItem’s unique ID. Items with the game_key type use the value in the sku_drm format.
items.type
stringItems type. It can have the following values: virtual_good, virtual_currency, game_key, physical_good.
items.quantity
integerQuantity of items.
items.amount
stringTotal cost of items that considers their quantity. May differ from the items price due to changes of currency rates and commission.
items.promotions
arrayApplied promotions. If the promotion wasnt applied, an empty array is written to the parameter.
items.promotions.amount_without_discount
stringTotal cost of items without a discount.
items.promotions.amount_with_discount
stringTotal cost of items with a discount.
items.promotions.sequence
integerID of the applied promotion.
items.is_pre_order
booleanIf true, the item is pre-order.
notification_type
stringNotification type. Required.
order
objectPayment information.
order.id
integerTransaction ID.
order.mode
stringPayment type. It can have the following values: default or sandbox.
order.currency_type
stringPayment type. It can have the following values: real for real currency or virtual for virtual currency.
order.currency
stringCurrency of order. Virtual currency uses the SKU and real currency uses a three-letter code per ISO 4217.
order.amount
stringThe total cost of a cart that considers a chosen currency.
order.status
stringOrder status.
order.platform
stringPayment platform. The xsolla value is used for payments via Xsolla. Other payments use the value that corresponds with the name of the integrated payment system.
order.comment
stringUsers commentary to the order.
order.invoice_id
stringReal currency payments invoice ID. Virtual currency payments use the null value.
order.promotions
arrayApplied promotions. If the promotion wasnt applied, an empty array is written to the parameter.
order.promotions.amount_without_discount
stringOrder total cost without a discount.
order.promotions.amount_with_discount
stringOrder total cost with a discount.
order.promotions.sequence
stringID of the applied promotion.
user
objectUser information.
user.external_id
stringUser ID.
user.email
stringUser email address.
custom_parameters
objectAdditional information.
Copy
Full screen
Small screen
http
  • http
  • curl
Request
POST /your/uri HTTP/1.1
Host: your.hostname
Accept: application/json
Content-Type: application/json
Content-Length: 240
Authorization: Signature 13342703ccaca5064ad33ba451d800c5e823db8f

{
  "items": [
    {
      "sku": "virtual-good-item-sku",
      "type": "virtual_good",
      "quantity": 3,
      "amount": "100",
      "promotions": [
        {
          "amount_without_discount": "200",
          "amount_with_discount": "100",
          "sequence": 1
        }
      ]
    },
    {
      "sku": "game_sku_steam",
      "type": "game_key",
      "quantity": 1,
      "amount": "200",
      "promotions": []
    },
    {
      "sku": "gold",
      "type": "virtual_currency",
      "quantity": 1500,
      "amount": "100",
      "promotions": []
    }
  ],
  "notification_type": "order_canceled",
  "order": {
    "id": 42,
    "mode": "default",
    "currency_type": "real",
    "currency": "USD",
    "amount": "200",
    "status": "canceled",
    "platform": "xsolla",
    "comment": null,
    "invoice_id": "23444",
    "promotions": [
      {
        "amount_without_discount": "400",
        "amount_with_discount": "200",
        "sequence": 1
      }
    ]
  },
  "user": {
    "external_id": "gamer_external_id",
    "email": "gamer@email.com"
  }
}
$ curl -v 'https://your.hostname/your/uri' \
-X POST \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Signature 13342703ccaca5064ad33ba451d800c5e823db8f' \
-d '{
  "items": [
    {
      "sku": "virtual-good-item-sku",
      "type": "virtual_good",
      "quantity": 3,
      "amount": "100",
      "promotions": [
        {
          "amount_without_discount": "200",
          "amount_with_discount": "100",
          "sequence": 1
        }
      ]
    },
    {
      "sku": "game_sku_steam",
      "type": "game_key",
      "quantity": 1,
      "amount": "200",
      "promotions": []
    },
    {
      "sku": "gold",
      "type": "virtual_currency",
      "quantity": 1500,
      "amount": "100",
      "promotions": []
    }
  ],
  "notification_type": "order_canceled",
  "order": {
    "id": 42,
    "mode": "default",
    "currency_type": "real",
    "currency": "USD",
    "amount": "200",
    "status": "canceled",
    "platform": "xsolla",
    "comment": null,
    "invoice_id": "23444",
    "promotions": [
      {
        "amount_without_discount": "400",
        "amount_with_discount": "200",
        "sequence": 1
      }
    ]
  },
  "user": {
    "external_id": "gamer_external_id",
    "email": "gamer@email.com"
  }
}'
Response
HTTP/1.1 204 No Content
Was this article helpful?
Thank you!
Is there anything we can improve? Message
We're sorry to hear that
Please explain why this article wasn't helpful to you. Message
Thank you for your feedback!
We'll review your message and use it to help us improve your experience.