Skip to main content

Callbacks

This article contains information on callbacks, how they are created, structured and sent on the platform.

Callbacks are used to signal an event and provide data related to that event. This means that a callback returns information when an event occurs.

Callbacks are sent when the following events occur:

  • Deposit is created
  • Deposit is updated
  • Deposit status is updated
  • Exchange is created
  • Exchange is updated
  • Exchange status is updated
  • Payout is created
  • Payout is updated
  • Payout status is updated

Payout Callback Example

Below you can see an example of a callback for the CREATE PAYOUT endpoint:

{
"scope": "PAYOUT",
"event": "CREATED",
"project": "11111111-1598-4dc8-b976-75a7b310445d",
"data": {
"id": "11111111-6286-4d0c-80d0-aa819473f55c",
"destination": "11111111dc84b3F58d97a35d2D8Ee6397B11f4F146",
"amount": "0.004978999999727000",
"fee": "0.00009957999999454",
"feePriority": "MEDIUM",
"networkFee": "0.000021000000273",
"network": "ETH_TEST3",
"status": "APPROVED",
"note": null,
"asset": {
"id": "0b47a85e-a66a-461c-bb1a-e818def2ff82",
"name": "Ethereum Test (Goerli)",
"symbol": "ETH_TEST3",
"displayName": "Ethereum Test (Goerli)",
"displaySymbol": "ETH_TEST3",
"exchangeSymbol": "ETH",
"type": "CRYPTO",
"subType": "BASE_ASSET",
"token": false,
"contract": null,
"nativeAsset": "ETH_TEST3",
"decimals": 18,
"network": "ETH_TEST3"
},
"createdAt": "2023-09-27T15:08:13+00:00",
"updatedAt": null,
"externalId": null,
"operationLog": {
"operationId": "3ac4e92b-6286-4d0c-80d0-aa819473f55c",
"refId": "15986514455D5579",
"asset": "ETH_TEST3",
"amount": "0.004978999999727",
"status": "PENDING",
"subStatus": null,
"createdAt": "27-09-2023 15:08:13",
"type": "PAYOUT",
"clientEmail": null,
"assetFrom": null,
"amountFrom": null,
"context": {
"destination": "11111111dc84b3F58d97a35d2D8Ee6397B11f4F146"
},
"tx": null,
"children": []
}
}
}

Deposit Callback Example

Below you can see an example of a callback for the DEPOSIT CREATED event:

{
"scope": "DEPOSIT",
"event": "CREATED",
"project": "75b5b836-4cea-48de-954d-bc3f7e1ca720",
"data": {
"id": "20ea7d7f-5a88-42f6-8405-14ef7f92c1e2",
"toAsset": {
"id": "0b47a85e-a66a-461c-bb1a-e818def2ff82",
"name": "Ethereum Test (Goerli)",
"symbol": "ETH_TEST3",
"displayName": "Ethereum Test (Goerli)",
"displaySymbol": "ETH_TEST3",
"exchangeSymbol": "ETH",
"type": "CRYPTO",
"subType": "BASE_ASSET",
"token": false,
"contract": null,
"nativeAsset": "ETH_TEST3",
"decimals": 18,
"network": "ETH_TEST3"
},
"amount": "0",
"targetAmount": "0.006533374486117382",
"wallet": "0x62d9769f3D035b54586CAbb6B2668114BA6FE777",
"walletTag": null,
"asset": {
"id": "0b47a85e-a66a-461c-bb1a-e818def2ff82",
"name": "Ethereum Test (Goerli)",
"symbol": "ETH_TEST3",
"displayName": "Ethereum Test (Goerli)",
"displaySymbol": "ETH_TEST3",
"exchangeSymbol": "ETH",
"type": "CRYPTO",
"subType": "BASE_ASSET",
"token": false,
"contract": null,
"nativeAsset": "ETH_TEST3",
"decimals": 18,
"network": "ETH_TEST3"
},
"status": "PENDING",
"network": "ETH_TEST3",
"externalId": null,
"operationLog": {
"refId": "4CEA651FC1E62678",
"asset": {
"id": "0b47a85e-a66a-461c-bb1a-e818def2ff82",
"name": "Ethereum Test (Goerli)",
"symbol": "ETH_TEST3",
"displayName": "Ethereum Test (Goerli)",
"displaySymbol": "ETH_TEST3",
"exchangeSymbol": "ETH",
"type": "CRYPTO",
"subType": "BASE_ASSET",
"token": false,
"contract": null,
"nativeAsset": "ETH_TEST3",
"decimals": 18,
"network": "ETH_TEST3"
},
"amount": "0",
"status": "PENDING",
"subStatus": null,
"createdAt": "06-10-2023 08:14:30",
"clientEmail": null,
"assetFrom": null,
"amountFrom": null,
"context": [],
"tx": null,
"children": [],
"accountId": null
},
"createdAt": "2023-10-06T08:14:30+00:00",
"updatedAt": null,
"expireAt": "2023-10-06T08:44:19+00:00",
"paymentLink": {
"id": "0051f2ba-2243-4ac2-8136-ba1c06a28e75",
"amount": "10",
"asset": {
"id": "4dfb822a-2dc4-4907-9850-a7df41721fd8",
"name": "Euro",
"symbol": "EUR",
"displayName": "Euro",
"displaySymbol": "EUR",
"exchangeSymbol": "EUR",
"type": "FIAT",
"token": false,
"contract": null,
"nativeAsset": "EUR",
"decimals": 2,
"network": "FIAT"
}
},
"amountUsd": "1.33",
"amountEuro": "1.19"
}
}

On the deposit endpoint you can see:

  • targetAmount: 0.006533374486117382 (asset: Ethereum): this is the requested value (displayed in a certain amount for a specific asset) that the client had to pay.
  • paymentLink section > amount: 10 (asset: Euro): this means that, when creating the payment link, the amount was set in Euros.
  • Status_updated: Here you can see the data.operationLog.accountId field with ID of the Account, if the deposit was made to the wallet of some specific account. The client can pay in whatever asset you allow, as long as the converted amount matches the requested amount.

Callback Structure

As you can see from the example above, the callbacks have the following major fields:

  • Scope: Displays the endpoint where the event occurred (Deposit, Exchange or Payout).
  • Event: Displays the type of event that occurred (created, updated).
  • Project: Displays the project where the event occurred (the unique code that identifies your project).
  • Data: Displays the data concerning the event that occurred (the items form the request and outcome of the event).

Callback Signature Header

Each callback has a callback signature header that provides information concerning the server that sent the callback (and not the callback information itself):

"headers": [
{
"name": "content-length",
"value": "1787"
},
{
"name": "accept-encoding",
"value": "gzip"
},
{
"name": "accept",
"value": "*/*"
},
{
"name": "x-callback-signature",
"value": "ceCn/EbdB0J7ce/fqV+EZu7nRejHI6JS5JFdv7wkV18y1xxzNArmcvVduGvfDQXq2RehP0Z4gMThcd9TZcS6qodRmqwgcGQsy6KuLECDHU9fOW0JogGlcGMXJp/Yk5tYcMaLdp3VzmRBk4jzGIDqLO0C+KRZ4MNgAOC5mh5VeFvDeBhOKpuxARwNcyQNxXRyhJMMj4l+/jEXoDIUpDnctQNytp8TEcyGFqw2bYI0wzNlHV6sKvXxVYDVKaq0uIAtJ1d7ax4mNHARn0oBU4AF96sl6a6OeG73lg/R5cyfgiOUADE6oegtQElVqY05YDG7hUszexxsbBiHizl2NXefGQ=="
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "host",
"value": "webhook.site"
}
]

The most important section is the “x-callback-signature”. This allows you to validate the security of the callback. The “x-callback-signature” body is on a base64(RSA512(PRIVATE_KEY, SHA512(body))) signature.

Signature Verification

  1. Compute the RSA SHA512 hash of the callback body using the following public key:
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3MghCNi33O1w76iIUWiQdmk0XRcVognGjd/hMDZN5+40M71vlFq0QySjGYpbUS44/1EqkTIO8ozKrd20dZ9uAOAK+CO5F3ScUnSuXmG/ILvIZU00JrD1viLHwpHjkG/Hp2ZwUm63wap+Eq+MVofQioGLM6Yrxjt7wL7iJBn7/mJEPHoEvvYuT9YFe/9Y8fep5tGJdFG4i740LVlO7LG3xcTo9fQwqkhsZNSwt9UWhB/cvKXGyUGoSOGG5LpmlOaz3XNmvy416OULeOj048xCoytHS9wj2rCs09h2ZGcHj5keLGbOb7gbO+JT46xmVdQ20wRYU0cD71XZw7TRGfhnrwIDAQAB
    -----END PUBLIC KEY-----
  2. Compare it to the base64 decoded header value.

Callbacks are only sent from one of these two IPs:

  • 135.181.30.86
  • 5.75.236.125 You can whitelist these 2 IPs and drop ignore all other.

Callback Failed Scenario

If a callback receives a status other than 200 it means that the operation failed (was not successful).

When an operation fails:

  1. A retry process begins.
    • Each retry attempts to re-send the callback, with the following delay set on each next retry: 1,5,10,15,20,30,60,90,120,150,180,210,240m.
  2. After the "final" retry the callback is considered FAILED and it won't be retried any further.
    • From here on out, Callbacks can be scheduled for re-sending using the API endpoint (can be found inside API section):
      • For specific ones, via ID “Schedule to resend failed callbacks by id”
      • For all failed, via “Schedule to resend all failed callbacks”
    • Alternatively, this can also be done manually by our Support Team upon request.

Need further assistance?

If you didn't find what you were looking for, please contact our support team.