Webhooks

Instant notifications about user orders state changes

Use incoming webhooks to get real-time updates

Listen for events on your Blockchain.com Pay account so your integration can automatically trigger reactions.

Why to use webhooks

You might want your applications to receive events as they occur in Blockchain.com Pay accounts, so that your backend systems can execute actions accordingly.

Setup

To enable webhook events, you need to register webhook endpoints. This is now setup manually by the account manager, but it will soon be possible to manage it via Partner Dashboard.

Do you want to setup your webhook endpoint? Get in touch with an account manager by emailing pay@blockchain.com.

Events

After you register webhooks endpoint, Blockchain.com Pay can push real-time event data to your application’s webhook endpoint when events happen in Blockchain.com Pay accounts. Blockchain.com Pay uses HTTPS to send webhook events to your app as a POST request with JSON payload that includes an Event object.

Receiving webhook events are particularly useful for listening to asynchronous events, such as when a customer’s bank confirms a payment or crypto transaction bas been initiated to move funds to your customer's address.

Webhook events are delivered as HTTP POST request with JSON payload.

Payload

Event object JSON payload will be as follows:

{
  "eventId": "6733fc68-0dcb-421d-9bef-a50753853b67",
  "orderId": "f6fa33d1-b62c-4d59-8cbc-8e610020d635",
  "externalReference": "your-order-reference",
  "subPartnerId": "3rd-party-ref",
  "orderType": "BUY",
  "createdAt": "2023-11-15T14:43:06.894070237Z",
  "orderState": "COMPLETED",
  "orderStateUpdatedAt": "2023-11-15T14:44:06.894070237Z",
  "paymentMethod": "CARD",
  "inputCurrency": "EUR",
  "inputAmount": "100.00",
  "outputCurrency": "BTC",
  "outputAmount": "0.00000924",
  "processingFee": "0.10",
  "processingFeeUsd": "0.11",
  "partnerFee": "0.20",
  "partnerFeeUsd": "0.12",
  "networkFee": "1.50",
  "networkFeeUsd": "1.65",
  "userId": "16f59173-0607-40ed-92e2-6d4fc46d372c",
  "userCountry": "US",
  "userState": "US-FL",
  "targetWalletAddress": "bc1q6rru2g8w3r2ufxe76dal820tul5uhm7esystsv",
  "transactionHash": "385d7ec2e3be6650d487d7ede35e8ea33b889b49d2e04a522bce86608c1130dd"
}

Event payload will conform to JSON schema listed at the bottom of the page.

States

Please refer to below diagram to understand order state transitions:

Order state definitions:

  • PENDING Order has been created and the payment is being processed.

  • WITHDRAWING Order is in progress. Payment has completed and crypto transaction is in progress.

  • COMPLETED Order successfully executed. Payment has been processed and crypto transaction has been confirmed with at least 1 confirmation.

  • FAILED Order failed. The payment was rejected or never completed by the user.

Delivery behaviour

Quick processing

Your endpoint must quickly return a successful status code (2xx) prior to any complex logic that could cause a timeout.

Timeouts

Webhook events that take longer than 5 seconds before returning a successful HTTP response are considered not delivered and will be subject to retry mechanism.

Retries

If the webhook event fails delivery, it’s scheduled for retry for up to 3 days with an exponential back off. Other events won't be affected and will be delivered regardless of that.

Events ordering

Events for specific order will be delivered in the order of state changes. If there is a failed delivery in between, eg. event with PENDING state failed delivery, it will be scheduled for later retry. It may happen, that the order moves to COMPLETED state in the meantime. In this case, the COMPLETED state change webhook will be sent and you might observe PENDING state update to be delivered after COMPLETED.

Your endpoint shouldn’t expect delivery of webhooks events in order, and needs to handle delivery accordingly.

Duplicates

Webhook endpoints might occasionally receive the same event more than once. You can guard against duplicated event receipts by making your event processing idempotent. One way of doing this is logging the events you’ve processed, and then not processing already-logged events.

Example scenario is when webhook delivery is partially successful (recorded on partner side but timed out on Blockchain.com Pay side). In such a case, webhook is marked as undelivered and will be scheduled for delivery again.

Receive events with an HTTPS server

If you use an HTTPS URL for your webhook endpoint, Blockchain.com Pay validates that the connection to your server is secure before sending your webhook data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate.

Verify events are sent from Blockchain.com

Blockchain.com Pay sends webhook events from a set list of IP addresses. Only trust events coming from below list of IP addresses:

  • 34.76.54.194

  • 34.77.167.89

  • 35.187.43.203

  • 35.241.153.74

  • 35.241.224.80

Event payload JSON schema

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "$ref": "#/definitions/webhook-event-payload",
  "definitions": {
    "webhook-event-payload": {
      "type": "object",
      "title": "webhook-event-payload",
      "additionalProperties": false,
      "properties": {
        "eventId": {
          "type": "string",
          "format": "string",
          "description": "Unique identifier for the event"
        },
        "orderId": {
          "type": "string",
          "format": "string",
          "description": "Unique identifier for the order"
        },
        "externalReference": {
          "type": "string",
          "description": "An optional external order reference set by the partner. It is limited to 100 characters."
        },
        "subPartnerId": {
          "type": "string",
          "description": "An optional 3rd party reference set by the partner. It is limited to 50 characters."
        },
        "orderType": {
          "enum": [
            "BUY",
            "SELL"
          ],
          "description": "Type of the order. BUY for on-ramp, SELL for off-ramp"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp of the event creation"
        },
        "orderState": {
          "enum": [
            "PENDING",
            "WITHDRAWING",
            "COMPLETED",
            "FAILED"
          ],
          "description": "Current state of the order"
        },
        "orderStateUpdatedAt": {
          "type": "string",
          "format": "date-time",
          "description": "Timestamp of the last order state change"
        },
        "paymentMethod": {
          "enum": [
            "CARD",
            "APPLE_PAY",
            "GOOGLE_PAY"
          ],
          "description": "Payment method used for the order"
        },
        "inputCurrency": {
          "type": "string",
          "description": "Currency code used for funding the order"
        },
        "inputAmount": {
          "type": "number",
          "description": "Amount of the input currency used for the order"
        },
        "outputCurrency": {
          "type": "string",
          "description": "Currency code for the output currency"
        },
        "outputAmount": {
          "type": "number",
          "description": "Amount of the output currency"
        },
        "amountUsd": {
          "type": "number",
          "description": "Amount of the transaction denominated in USD. Will be an approximate value in case of `inputCurrency` different than USD."
        },
        "processingFee": {
          "type": "number",
          "description": "Blockchain.com Pay processing fee denominated in `inputCurrency`"
        },
        "processingFeeUsd": {
          "type": "number",
          "description": "Blockchain.com Pay processing fee denominated in USD. Will be an approximate value in case of `inputCurrency` different than USD."
        },
        "partnerFee": {
          "type": "number",
          "description": "Partner fee denominated in `inputCurrency`"
        },
        "partnerFeeUsd": {
          "type": "number",
          "description": "Partner fee denominated in USD. Will be an approximate value in case of `inputCurrency` different than USD."
        },
        "networkFee": {
          "type": "number",
          "description": "Transaction network fee denominated in `inputCurrency`"
        },
        "networkFeeUsd": {
          "type": "number",
          "description": "Transaction network fee denominated in USD. Will be an approximate value in case of `inputCurrency` different than USD."
        },
        "userId": {
          "type": "string",
          "description": "Unique identifier for the user"
        },
        "userCountry": {
          "type": "string",
          "description": "Country code of the user address (2 letter ISO 3166-1 alpha-2 code). Example: US, GB, FR, DE, etc."
        },
        "userState": {
          "type": "string",
          "description": "State code of the user address (2 letter code prefixed with 2 letter country code and a hyphen). Will only be present for users in the US. Example: US-FL"
        },
        "targetWalletAddress": {
          "type": "string",
          "description": "Target wallet address for the crypto transaction"
        },
        "transactionHash": {
          "type": "string",
          "description": "Transaction hash for the crypto transaction. Will only be present for orders in COMPLETED state"
        }
      },
      "required": [
        "eventId",
        "orderId",
        "externalReference",
        "orderType",
        "createdAt",
        "orderState",
        "orderStateUpdatedAt",
        "paymentMethod",
        "inputCurrency",
        "inputAmount",
        "outputCurrency",
        "outputAmount",
        "processingFee",
        "processingFeeUsd",
        "partnerFee",
        "partnerFeeUsd",
        "networkFee",
        "networkFeeUsd",
        "userId",
        "targetWalletAddress"
      ]
    }
  }
}

Last updated