Invoice Webhook

An invoice webhook is an HTTP POST message sent from the BitPay server to the merchant’s eCommerce server.

The primary purpose of an IPN is to alert the merchant’s ecommerce server that a BitPay invoice status has changed.

Example 1

Invoice paid with BCH - JSON body of the IPN sent for “status” : “paid”.

{
  "id":"SkdsDghkdP3D3qkj7bLq3",
  "url":"https://bitpay.com/invoice?id=SkdsDghkdP3D3qkj7bLq3",
  "status":"paid",
  "price":10,
  "currency":"EUR",
  "invoiceTime":1520373130312,
  "expirationTime":1520374030312,
  "currentTime":1520373179327,
  "exceptionStatus":false,
  "buyerFields":{
    "buyerEmail":"test@bitpay.com",
  },
  "paymentSubtotals": {
    "BCH":1025900,
    "BTC":114700
  },
  "paymentTotals": {
    "BCH":1025900,
    "BTC":118400
  },
  "transactionCurrency": "BCH",
  "amountPaid": "1025900",
  "exchangeRates": {
    "BTC": {
      "EUR": 8721.690715789999,
      "USD": 10817.99,
      "BCH": 8.911763736716368
  },
    "BCH": {
      "EUR": 974.721189,
      "USD": 1209,
      "BTC": 0.11173752310536043
    }
  }
}

Example 2

Invoice paid with BTC - JSON body of the IPN sent for “status” : “confirmed”.

{
  "id":"9E8qPC3zsvXRcA3tsbRLnC",
  "url":"https://bitpay.com/invoice?id=9E8qPC3zsvXRcA3tsbRLnC",
  "status":"confirmed",
  "price":"19537.1",
  "currency":"USD",
  "invoiceTime":1520417833546,
  "expirationTime":1520418733546,
  "currentTime":1520417905248,
  "exceptionStatus":false,
  "buyerFields": {
    "buyerEmail":"test@bitpay.com",
  },
  "paymentSubtotals": {
    "BCH":1664857265,
    "BTC":185406100
  },
  "paymentTotals": {
    "BCH":1664857265,
    "BTC":185409800
  },
  "transactionCurrency": "BTC",
  "amountPaid": "185409800",
  "exchangeRates": {
    "BTC": {
      "USD": 10537.46373483771,
      "BCH": 8.979517456188931
    },
    "BCH": {
      "USD": 1173.50,
      "BTC": 0.111364558828356
    }
  }
}

How merchants should handle invoice callbacks

  1. IPNs are HTTP POST messages sent to the URL provided in the notificationURL field when creating the invoice object. 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. BitPaydoes notsign IPNs, so the information in the payloadshould notbe trusted outright.

  4. The IPN shall be used as a trigger to verify the status of a specific invoice. This can be done by sending a GET to /invoices/:invoiceId since the invoiceId is provided in the body of the IPN. 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". Learn more about BitPay invoice states.

  5. The BitPay server expects a HTTP 200 as a response by your server. Any other HTTP response is considered by BitPay as a failed delivery.

  6. The BitPay server attempts to send IPNs multiple times until the send is either successful or the BitPay server gives up. The BitPay server attempts retries using an exponential back on the following schedule:

    • 1 minute delay
    • 2 minute delay
    • 4 minute delay
    • 8 minute delay
    • 16 minute delay
    • 32 minute delay
    • 64 mintue delay
    • 128 minute delay
    • 256 minute delay
    • Retry attempt times double for up to 3 days

IPN Troubleshooting

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

  • Verify that your callback 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.