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
andcomplete
, it is however possible for merchants to receive IPNs for other invoice statuses. Please refer to the Invoices for more information
Example
body of an IPN sent for "status" : "confirmed"
.
{
"id": "Hpqc62dfE1ZjzeeH4kEycF",
"url": "https://bitpay.com/invoice?id=Hpqc62dfE1ZjzeeH4kEycF",
"status": "confirmed",
"price": 10,
"currency": "USD",
"invoiceTime": 1620669854224,
"expirationTime": 1620670754224,
"currentTime": 1620671313184,
"exceptionStatus": false,
"buyerFields": {
"buyerName": "John Doe",
"buyerAddress1": "2630 Hegal Place",
"buyerAddress2": "Apt 42",
"buyerCity": "Alexandria",
"buyerState": "VA",
"buyerZip": "23242",
"buyerCountry": "US",
"buyerPhone": "555-123-456",
"buyerNotify": true,
"buyerEmail": "[email protected]"
},
"paymentSubtotals": {
"BTC": 17500,
"BCH": 700700,
"ETH": 2406000000000000,
"GUSD": 1000,
"PAX": 10000000000000000000,
"BUSD": 10000000000000000000,
"USDC": 10000000,
"XRP": 6668704,
"DOGE": 2077327700,
"DAI": 9990000000000000000,
"WBTC": 17500
},
"paymentTotals": {
"BTC": 29800,
"BCH": 700700,
"ETH": 2406000000000000,
"GUSD": 1000,
"PAX": 10000000000000000000,
"BUSD": 10000000000000000000,
"USDC": 10000000,
"XRP": 6668704,
"DOGE": 2077327700,
"DAI": 9990000000000000000,
"WBTC": 17500
},
"exchangeRates": {
"BTC": {
"USD": 57204.993195,
"EUR": 47077.319565,
"BCH": 39.966599499063804,
"ETH": 13.755531957178825,
"GUSD": 57204.993195,
"PAX": 57204.993195,
"BUSD": 57204.993195,
"USDC": 57204.993195,
"XRP": 38003.14441595195,
"DOGE": 118682.55849585062,
"DAI": 57120.83386098427,
"WBTC": 1.0001084497591646
},
"BCH": {
"USD": 1427.1930750000001,
"EUR": 1173.9677250000002,
"BTC": 0.024936271286002874,
"ETH": 0.3431833281634361,
"GUSD": 1427.1930750000001,
"PAX": 1427.1930750000001,
"BUSD": 1427.1930750000001,
"USDC": 1427.1930750000001,
"XRP": 948.1309499292485,
"DOGE": 2960.981483402489,
"DAI": 1425.0934048139654,
"WBTC": 0.02495145570387066
},
"ETH": {
"USD": 4156.600660000002,
"EUR": 3418.000145000001,
"BTC": 0.07262515738127348,
"BCH": 2.904033102311154,
"GUSD": 4156.600660000002,
"PAX": 4156.600660000002,
"BUSD": 4156.600660000002,
"USDC": 4156.600660000002,
"XRP": 2761.365509177756,
"DOGE": 8623.652821576765,
"DAI": 4150.4855164823275,
"WBTC": 0.0726693809431983
},
"GUSD": {
"USD": 1,
"EUR": 0.822741,
"BTC": 0.000017472247954960737,
"BCH": 0.0006986557862672219,
"ETH": 0.00024046033726966907,
"PAX": 1,
"BUSD": 1,
"USDC": 1,
"XRP": 0.664332644641825,
"DOGE": 2.0746887966804977,
"DAI": 0.9985288113971301,
"WBTC": 0.000017482887312826024
},
"PAX": {
"USD": 1,
"EUR": 0.822741,
"BTC": 0.000017472247954960737,
"BCH": 0.0006986557862672219,
"ETH": 0.00024046033726966907,
"GUSD": 1,
"BUSD": 1,
"USDC": 1,
"XRP": 0.664332644641825,
"DOGE": 2.0746887966804977,
"DAI": 0.9985288113971301,
"WBTC": 0.000017482887312826024
},
"BUSD": {
"USD": 1,
"EUR": 0.822741,
"BTC": 0.000017472247954960737,
"BCH": 0.0006986557862672219,
"ETH": 0.00024046033726966907,
"GUSD": 1,
"PAX": 1,
"USDC": 1,
"XRP": 0.664332644641825,
"DOGE": 2.0746887966804977,
"DAI": 0.9985288113971301,
"WBTC": 0.000017482887312826024
},
"USDC": {
"USD": 1,
"EUR": 0.822741,
"BTC": 0.000017472247954960737,
"BCH": 0.0006986557862672219,
"ETH": 0.00024046033726966907,
"GUSD": 1,
"PAX": 1,
"BUSD": 1,
"XRP": 0.664332644641825,
"DOGE": 2.0746887966804977,
"DAI": 0.9985288113971301,
"WBTC": 0.000017482887312826024
},
"XRP": {
"USD": 1.4995417500000001,
"EUR": 1.2359324250000001,
"BTC": 0.00002620036527481575,
"BCH": 0.0010476635203867759,
"ETH": 0.0003605803149549498,
"GUSD": 1.4995417500000001,
"PAX": 1.4995417500000001,
"BUSD": 1.4995417500000001,
"USDC": 1.4995417500000001,
"DOGE": 3.111082468879668,
"DAI": 1.4973356412678729,
"WBTC": 0.000026216319436127937
},
"DOGE": {
"USD": 0.48138770000000003,
"EUR": 0.3960573976857,
"BTC": 0.000008410925256868251,
"BCH": 0.0003363243020428695,
"ETH": 0.00011575464869947028,
"GUSD": 0.48138770000000003,
"PAX": 0.48138770000000003,
"BUSD": 0.48138770000000003,
"USDC": 0.48138770000000003,
"XRP": 0.31980156383904546,
"DAI": 0.4806794879021982,
"WBTC": 0.0000084160469128805
},
"DAI": {
"USD": 1.001472,
"EUR": 0.8239520747519998,
"BTC": 0.00001749796710395044,
"BCH": 0.0006996842075846071,
"ETH": 0.00024081429488613,
"GUSD": 1.001472,
"PAX": 1.001472,
"BUSD": 1.001472,
"USDC": 1.001472,
"XRP": 0.6653105422947376,
"DOGE": 2.0777427385892113,
"WBTC": 0.000017508622122950502
},
"WBTC": {
"USD": 57151.869999999995,
"EUR": 47021.18667566999,
"BTC": 0.9985716437296819,
"BCH": 39.92948467149204,
"ETH": 13.74275793579228,
"GUSD": 57151.869999999995,
"PAX": 57151.869999999995,
"BUSD": 57151.869999999995,
"USDC": 57151.869999999995,
"XRP": 37967.85294332578,
"DOGE": 118572.34439834024,
"DAI": 57067.78882022329
}
},
"amountPaid": 700700,
"orderId": "20210510_fghij",
"transactionCurrency": "BCH"
}
How merchants should handle IPNs
- Make sure to not rely on whitelisting BitPay’s sending IP addresses, as these IP addresses are subject to change without notice.
- Make sure to use HTTPS for your
notificationURL
. - BitPay does not sign IPNs, so the information in the payload should not be trusted outright.
- 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 theinvoiceId
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 statusconfirmed
orcomplete
. Learn more about BitPay invoice states. - Merchants who rely on the invoice status
confirmed
to fulfill orders also need to monitor IPNs for thecomplete
status, as in some cases the IPN for the statusconfirmed
may not be sent (for instance: node outage or network errors). - The BitPay server expects an HTTP 200 response with an empty body. Any other HTTP response is considered by BitPay as a failed delivery.
- 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 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.
Updated 8 months ago