Invoice Webhooks

Webhooks are HTTP POST messages sent from the BitPay server to the merchant’s eCommerce server.

Instant Payment Notifications

The only webhook available at the moment is the Instant Payment Notification (IPN). The primary purpose of an IPN is to alert the merchant’s ecommerce server that the status a of BitPay invoice has changed.

  • IPNs are sent to the notificationURL provided by merchants when creating the invoice.
  • The body of the IPNs sent by BitPay is a JSON-formatted string (content-Type: application/json).
  • By default, BitPay only sends IPNs for the invoice statuses paid, confirmed and complete, it is however possible for merchants to receive IPNs for other invoice statuses. Please refer to the full API documentation for more information

Example

body of an IPN sent for "status" : "confirmed".

{
  "id": "Ttg4UeM9jnjdh8vbMzbiW4",
  "url": "https://test.bitpay.com/invoice?id=Ttg4UeM9jnjdh8vbMzbiW4",
  "posData": "tx46518",
  "status": "confirmed",
  "price": 10,
  "currency": "EUR",
  "invoiceTime": 1588318118648,
  "expirationTime": 1588319018648,
  "currentTime": 1588318236317,
  "exceptionStatus": false,
  "buyerFields": {
    "buyerName": "Fox Mulder",
    "buyerAddress1": "2630 Hegal Place",
    "buyerAddress2": "Apt 42",
    "buyerCity": "Alexandria",
    "buyerState": "VA",
    "buyerZip": "23242",
    "buyerCountry": "US",
    "buyerPhone": "555-123-456",
    "buyerNotify": true,
    "buyerEmail": "fox.mulder@trustno.one"
  },
  "paymentSubtotals": {
    "BTC": 125200,
    "BCH": 4288500,
    "ETH": 51862000000000000,
    "GUSD": 1096,
    "PAX": 10960000000000000000,
    "BUSD": 10960000000000000000,
    "USDC": 10960000,
    "XRP": 50042536
  },
  "paymentTotals": {
    "BTC": 125300,
    "BCH": 4288500,
    "ETH": 51862000000000000,
    "GUSD": 1096,
    "PAX": 10960000000000000000,
    "BUSD": 10960000000000000000,
    "USDC": 10960000,
    "XRP": 50042536
  },
  "exchangeRates": {
    "BTC": {
      "EUR": 7989.24,
      "USD": 8744.400000000001,
      "BCH": 34.2112676056338,
      "ETH": 41.37010928703222,
      "GUSD": 8744.400000000001,
      "PAX": 8744.400000000001,
      "BUSD": 8744.400000000001,
      "USDC": 8744.400000000001,
      "XRP": 39967.09173179761
    },
    "BCH": {
      "EUR": 233.18,
      "USD": 255.30000000000004,
      "BTC": 0.029195794799191713,
      "ETH": 1.2078346028291622,
      "GUSD": 255.30000000000004,
      "PAX": 255.30000000000004,
      "BUSD": 255.30000000000004,
      "USDC": 255.30000000000004,
      "XRP": 1166.8723433429316
    },
    "ETH": {
      "EUR": 192.81780992000003,
      "USD": 211.36000000000004,
      "BTC": 0.024170870304571723,
      "BCH": 0.8269170579029735,
      "GUSD": 211.36000000000004,
      "PAX": 211.36000000000004,
      "BUSD": 211.36000000000004,
      "USDC": 211.36000000000004,
      "XRP": 966.0404954522603
    },
    "GUSD": {
      "EUR": 0.912272,
      "USD": 1,
      "BTC": 0.00011435877320482457,
      "BCH": 0.003912363067292645,
      "ETH": 0.0047310403557742345,
      "PAX": 1,
      "BUSD": 1,
      "USDC": 1,
      "XRP": 4.570592805886924
    },
    "PAX": {
      "EUR": 0.912272,
      "USD": 1,
      "BTC": 0.00011435877320482457,
      "BCH": 0.003912363067292645,
      "ETH": 0.0047310403557742345,
      "GUSD": 1,
      "BUSD": 1,
      "USDC": 1,
      "XRP": 4.570592805886924
    },
    "BUSD": {
      "EUR": 0.912272,
      "USD": 1,
      "BTC": 0.00011435877320482457,
      "BCH": 0.003912363067292645,
      "ETH": 0.0047310403557742345,
      "GUSD": 1,
      "PAX": 1,
      "USDC": 1,
      "XRP": 4.570592805886924
    },
    "USDC": {
      "EUR": 0.912272,
      "USD": 1,
      "BTC": 0.00011435877320482457,
      "BCH": 0.003912363067292645,
      "ETH": 0.0047310403557742345,
      "GUSD": 1,
      "PAX": 1,
      "BUSD": 1,
      "XRP": 4.570592805886924
    },
    "XRP": {
      "EUR": 0.19983,
      "USD": 0.21869999999999998,
      "BTC": 0.00002501026369989513,
      "BCH": 0.0008556338028169013,
      "ETH": 0.001034678525807825,
      "GUSD": 0.21869999999999998,
      "PAX": 0.21869999999999998,
      "BUSD": 0.21869999999999998,
      "USDC": 0.21869999999999998
    }
  },
  "amountPaid": 51862000000000000,
  "orderId": "MerchantOrder10112",
  "transactionCurrency": "ETH"
}

How merchants should handle IPNs

  1. Make sure to not rely on whitelisting BitPay’s sending IP addresses, as these IP addresses are subject to change without notice.

  2. Make sure to use HTTPS for your notificationURL.

  3. BitPay  does not  sign IPNs, so the information in the payload  should not  be trusted outright.

  4. The IPN shall be used as a trigger to verify the status of a specific invoice. This can be done via the GET /invoices/:invoiceId API endpoint since the invoiceId is provided in the body of the IPN.

  5. The invoice status paid does not  represent a payment guarantee, so merchants should only process an order after the corresponding BitPay invoice has reached the status confirmed or complete. Learn more about BitPay invoice states.

  6. Merchants who rely on the invoice status confirmed to fulfil orders also need to monitor IPNs for the complete status, as in some cases the IPN for the status confirmed may not be sent (for instance: node outage or network errors).

  7. The BitPay server expects an HTTP 200 response with an empty body. Any other HTTP response is considered by BitPay as a failed delivery.

  8. The BitPay server attempts to send IPNs multiple times until the send is either successful or the BitPay server gives up.

IPN Troubleshooting

In the event that IPNs are not being received or processed as expected, please check the following:

  • Verify that your webhook handler at the notificationURL is properly receiving POSTs. See this page to see how to manually test your notification URL.
  • Verify that the POST data received is properly parsed. See this page when getting blank IPNs using PHP.
  • Verify that your firewall is not blocking POSTs from servers it may not recognize.

IPNs can be resent by sending a POST to /invoices/:invoiceId/notifications accompanied by the token associated with the specified invoice.

Invoice States