Instant Payment Notifications (IPN)

Introduction

The IPN system will notify your server when you receive a payment and when a payment status changes. This is a easy and useful way to integrate our payments into your software to automate order completion, digital downloads, accounting, or whatever you can think up.
It is implemented by making a standard HTTP POST (application/x-www-form-urlencoded) call over a https:// or http:// URL to a script or CGI program on your server.

IPN Setup

The first step is to go to the My Settings page and set a IPN Secret. Your IPN Secret is a string of your choosing that is used to verify that an IPN was really sent from our servers (recommended to be a random string of letters, numbers, and special characters). Our system will not send any IPNs unless you have an IPN Secret set. See the "Authenticating IPNs" section for more details.

At the same time you can optionally set an IPN URL; this is the URL that will be called when sending you IPN notifications. You can also set an IPN URL in your Buy Now and Cart buttons that will be used instead of this one.

IPN Retries / Duplicate IPNs

If there is an error sending your server an IPN, we will retry up to 10 times. Because of this you are not guaranteed to receive every IPN (if all 10 tries fail) or that your server will receive them in order.
Your IPN handler must always check to see if a payment has already been handled before to avoid double-crediting users, etc. in the case of duplicate IPNs.

Authenticating IPNs

We use your IPN Secret as the HMAC shared secret key to generate an HMAC signature of the raw POST data. The HMAC signature is sent as a HTTP header called HMAC.
Here is what it would look like in PHP:
$merchant_id = 'Your_Merchant_ID';
$secret = 'Your_IPN_Secret';

if (!isset($_SERVER['HTTP_HMAC']) || empty($_SERVER['HTTP_HMAC'])) {
  die("No HMAC signature sent");
}

$merchant = isset($_POST['merchant']) ? $_POST['merchant']:'';
if (empty($merchant)) {
  die("No Merchant ID passed");
}

if ($merchant != $merchant_id) {
  die("Invalid Merchant ID");
}

$request = file_get_contents('php://input');
if ($request === FALSE || empty($request)) {
  die("Error reading POST data");
}

$hmac = hash_hmac("sha512", $request, $secret);
if ($hmac != $_SERVER['HTTP_HMAC']) {
  die("HMAC signature does not match");
}

//process IPN here

Payment Statuses

Payments will post with a 'status' field, here are the currently defined values:
  • -2 = PayPal Refund or Reversal
  • -1 = Cancelled / Timed Out
  • 0 = Waiting for buyer funds
  • 1 = We have confirmed coin reception from the buyer
  • 2 = Queued for nightly payout (if you have the Payout Mode for this coin set to Nightly)
  • 3 = PayPal Pending (eChecks or other types of holds)
  • 100 = Payment Complete. We have sent your coins to your payment address or 3rd party payment system reports the payment complete
For future-proofing your IPN handler you can use the following rules:
  • <0 = Failures/Errors
  • 0-99 = Payment is Pending in some way
  • >=100 = Payment completed successfully
IMPORTANT: You should never ship/release your product until the status is >= 100 OR == 2 (Queued for nightly payout)!

Code Samples

A complete example of an IPN Handler can be found in: [PHP].
Example building Ripple transactions in response to IPNs with Quick Gateway Kit: https://github.com/whotooktwarden/rippled-sign-submit.
Handling IPNs for deposits with Quick Gateway Kit: https://github.com/whotooktwarden/QuickGatewayKit.

IPN POST Fields

Field NameDescriptionRequired?
Required Fields
These fields will be here for all IPN types.
ipn_version1.0Yes
ipn_typeCurrently: 'simple, 'button', 'cart', 'donation', 'deposit', 'withdrawal', or 'api'Yes
ipn_modeCurrently: 'hmac'Yes
ipn_idThe unique identifier of this IPNYes
merchantYour merchant ID (you can find this on the My Account page).Yes
Callback Address Deposit Information (ipn_type = 'deposit')
deposit_idA unique ID assigned by CoinPayments for this payment. This can be used for duplicate/uniqueness checking since it is possible to have multiple deposits with the same TXID but to different addresses in some coins.Yes
txn_idThe coin transaction ID of the payment.Yes
addressCoin address the payment was received on.Yes
dest_tagFor coins that use an extra tag it will include it here. For example Ripple Destination Tag, Monero Payment ID, etc.No
statusNumeric status of the payment, currently 0 = pending and 100 = confirmed/complete. For future proofing you should use the same logic as Payment Statuses.
IMPORTANT: You should never ship/release your product until the status is >= 100
Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
currencyThe coin the buyer paid with.Yes
confirmsThe number of confirms the payment has.Yes
amountThe total amount of the paymentYes
amountiThe total amount of the payment in SatoshisYes
feeThe fee deducted by CoinPayments (only sent when status >= 100)No
feeiThe fee deducted by CoinPayments in Satoshis (only sent when status >= 100)No
fiat_coinThe ticker code of the fiat currency you selected on the Merchant Settings tab of the Account Settings page (USD, EUR, etc.) Make sure to check this for accuracy for security in your IPN handler!Yes
fiat_amountThe total amount of the payment in the fiat currency you selected on the Merchant Settings tab of the Account Settings page.Yes
fiat_amountiThe total amount of the payment in the fiat currency you selected in SatoshisYes
fiat_feeThe fee deducted by CoinPayments in the fiat currency you selected (only sent when status >= 100)No
fiat_feeiThe fee deducted by CoinPayments in the fiat currency you selected in Satoshis (only sent when status >= 100)No
labelThe address label if you have one setNo
Withdrawal Information (ipn_type = 'withdrawal')
idThe ID of the withdrawal ('id' field returned from 'create_withdrawal'.)Yes
statusNumeric status of the withdrawal, currently <0 = failed, 0 = waiting email confirmation, 1 = pending, and 2 = sent/complete.Yes
status_textA text string describing the status of the withdrawal.Yes
addressCoin address the withdrawal was sent to.Yes
dest_tagFor coins that use an extra tag it will include it here if one was provided. For example Ripple Destination Tag, Monero Payment ID, etc.No
txn_idThe coin transaction ID of the withdrawal.No
currencyThe coin of the withdrawal.Yes
amountThe total amount of the withdrawalYes
amountiThe total amount of the withdrawal in SatoshisYes
noteThe note on the withdrawal (if set.)No
Buyer Information (ipn_type = 'simple','button','cart','donation')
first_nameBuyer's first name.
Note: Only first_name or last_name is required, either may be empty but not both.
Yes
last_nameBuyer's last name.
Note: Only first_name or last_name is required, either may be empty but not both.
Yes
companyBuyer's company name.No
emailBuyer's email address.Yes
Shipping Information (ipn_type = 'simple','button','cart','donation')
If 'want_shipping' was set to 1 we will collect and forward shipping information, but as always they could have manually messed with your button so be sure to verify it.
address1Street / address line 1No
address2Street / address line 2No
cityCityNo
stateState / ProvinceNo
zipZip / Postal CodeNo
countryCountry of Residence
This uses 2 digit ISO 3166 country codes.
No
country_nameCountry of Residence
This is a pretty version such as UNITED STATES or CANADA.
No
phonePhone NumberNo
Simple Button Fields (ipn_type = 'simple')
statusThe status of the payment. See Payment Statuses for details.Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
txn_idThe unique ID of the payment.
Your IPN handler should be able to handle a txn_id composed of any combination of a-z, A-Z, 0-9, and - up to 128 characters long for future proofing.
Yes
currency1The original currency/coin submitted in your button.
Note: Make sure you check this, a malicious user could have changed it manually.
Yes
currency2The coin the buyer chose to pay with.Yes
amount1The total amount of the payment in your original currency/coin.Yes
amount2The total amount of the payment in the buyer's selected coin.Yes
subtotalThe subtotal of the order before shipping and tax in your original currency/coin.Yes
shippingThe shipping charged on the order in your original currency/coin.Yes
taxThe tax on the order in your original currency/coin.Yes
feeThe fee on the payment in the buyer's selected coin.Yes
netThe net amount you received of the buyer's selected coin after our fee and any coin TX fees to send the coins to you.Yes
item_amountThe amount of the item/order in the original currency/coin.Yes
item_nameThe name of the item that was purchased.Yes
item_descDescription of the item that was purchased.No
item_numberThis is a passthru variable for your own use. [visible to buyer]No
invoiceThis is a passthru variable for your own use. [not visible to buyer]No
customThis is a passthru variable for your own use. [not visible to buyer]No
on11st option name. This lets you pass through a buyer option like size or color.No
(unless ov1 set)
ov11st option value. This would be the buyer's selection such as small, large, red, white.No
on22nd option name. This lets you pass through a buyer option like size or color.No
(unless ov2 set)
ov22nd option value. This would be the buyer's selection such as small, large, red, white.No
send_txThe TX ID of the payment to the merchant. Only included when 'status' >= 100 and if the payment mode is set to ASAP or Nightly or if the payment is PayPal Passthru.No
received_amountThe amount of currency2 received at the time the IPN was generated.No
received_confirmsThe number of confirms of 'received_amount' at the time the IPN was generated.No
Advanced Button Fields (ipn_type = 'button')
statusThe status of the payment. See Payment Statuses for details.Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
txn_idThe unique ID of the payment.
Your IPN handler should be able to handle a txn_id composed of any combination of a-z, A-Z, 0-9, and - up to 128 characters long for future proofing.
Yes
currency1The original currency/coin submitted in your button.
Note: Make sure you check this, a malicious user could have changed it manually.
Yes
currency2The coin the buyer chose to pay with.Yes
amount1The total amount of the payment in your original currency/coin.Yes
amount2The total amount of the payment in the buyer's selected coin.Yes
subtotalThe subtotal of the order before shipping and tax in your original currency/coin.Yes
shippingThe shipping charged on the order in your original currency/coin.Yes
taxThe tax on the order in your original currency/coin.Yes
feeThe fee on the payment in the buyer's selected coin.Yes
netThe net amount you received of the buyer's selected coin after our fee and any coin TX fees to send the coins to you.Yes
item_amountThe amount per-item in the original currency/coin.Yes
item_nameThe name of the item that was purchased.Yes
quantityThe quantity of items bought.Yes
item_numberThis is a passthru variable for your own use. [visible to buyer]No
invoiceThis is a passthru variable for your own use. [not visible to buyer]No
customThis is a passthru variable for your own use. [not visible to buyer]No
on11st option name. This lets you pass through a buyer option like size or color.No
(unless ov1 set)
ov11st option value. This would be the buyer's selection such as small, large, red, white.No
on22nd option name. This lets you pass through a buyer option like size or color.No
(unless ov2 set)
ov22nd option value. This would be the buyer's selection such as small, large, red, white.No
extraA note from the buyer.No
send_txThe TX ID of the payment to the merchant. Only included when 'status' >= 100 and if the payment mode is set to ASAP or Nightly or if the payment is PayPal Passthru.No
received_amountThe amount of currency2 received at the time the IPN was generated.No
received_confirmsThe number of confirms of 'received_amount' at the time the IPN was generated.No
Shopping Cart Button Fields (ipn_type = 'cart')
statusThe status of the payment. See Payment Statuses for details.Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
txn_idThe unique ID of the payment.
Your IPN handler should be able to handle a txn_id composed of any combination of a-z, A-Z, 0-9, and - up to 128 characters long for future proofing.
Yes
currency1The original currency/coin submitted in your button.
Note: Make sure you check this, a malicious user could have changed it manually.
Yes
currency2The coin the buyer chose to pay with.Yes
amount1The total amount of the payment in your original currency/coin.Yes
amount2The total amount of the payment in the buyer's selected coin.Yes
subtotalThe subtotal of the order before shipping and tax in your original currency/coin.Yes
shippingThe shipping charged on the order in your original currency/coin.Yes
taxThe tax on the order in your original currency/coin.Yes
feeThe fee on the payment in the buyer's selected coin.Yes
item_name_#The name of the item that was purchased. The # starts with 1.Yes
item_amount_#The amount per-item in the original currency/coin.Yes
item_quantity_#The quantity of items bought.Yes
item_number_#This is a passthru variable for your own use. [visible to buyer]No
item_on1_#1st option name. This lets you pass through a buyer option like size or color.No
(unless ov1 set)
item_ov1_#1st option value. This would be the buyer's selection such as small, large, red, white.No
item_on2_#2nd option name. This lets you pass through a buyer option like size or color.No
(unless ov2 set)
item_ov2_#2nd option value. This would be the buyer's selection such as small, large, red, white.No
invoiceThis is a passthru variable for your own use. [not visible to buyer]No
customThis is a passthru variable for your own use. [not visible to buyer]No
extraA note from the buyer.No
send_txThe TX ID of the payment to the merchant. Only included when 'status' >= 100 and if the payment mode is set to ASAP or Nightly or if the payment is PayPal Passthru.No
received_amountThe amount of currency2 received at the time the IPN was generated.No
received_confirmsThe number of confirms of 'received_amount' at the time the IPN was generated.No
Donation Button Fields (ipn_type = 'donation')
statusThe status of the payment. See Payment Statuses for details.Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
txn_idThe unique ID of the payment.
Your IPN handler should be able to handle a txn_id composed of any combination of a-z, A-Z, 0-9, and - up to 128 characters long for future proofing.
Yes
currency1The original currency/coin submitted in your button.
Note: Make sure you check this!
Yes
currency2The coin the donator chose to pay with.Yes
amount1The total amount of the payment in your original currency/coin.Yes
amount2The total amount of the payment in the donator's selected coin.Yes
subtotalThe subtotal of the order before shipping and tax in your original currency/coin.Yes
shippingThe shipping charged on the order in your original currency/coin.Yes
taxThe tax on the order in your original currency/coin.Yes
feeThe fee on the payment in the donator's selected coin.Yes
netThe net amount you received of the buyer's selected coin after our fee and any coin TX fees to send the coins to you.Yes
item_nameThe name of the donation.Yes
item_numberThis is a passthru variable for your own use. [not visible to donator]No
invoiceThis is a passthru variable for your own use. [not visible to donator]No
customThis is a passthru variable for your own use. [not visible to donator]No
on11st option name. This lets you pass through a donator option like size or color.No
(unless ov1 set)
ov11st option value. This would be the donator's selection such as small, large, red, white.No
on22nd option name. This lets you pass through a donator option like size or color.No
(unless ov2 set)
ov22nd option value. This would be the donator's selection such as small, large, red, white.No
extraA note from the donator.No
send_txThe TX ID of the payment to the merchant. Only included when 'status' >= 100 and if the payment mode is set to ASAP or Nightly or if the payment is PayPal Passthru.No
received_amountThe amount of currency2 received at the time the IPN was generated.No
received_confirmsThe number of confirms of 'received_amount' at the time the IPN was generated.No
API Generated Transaction Fields ('create_transaction' API call) (ipn_type = 'api')
statusThe status of the payment. See Payment Statuses for details.Yes
status_textA text string describing the status of the payment. (useful for displaying in order comments)Yes
txn_idThe unique ID of the payment.
Your IPN handler should be able to handle a txn_id composed of any combination of a-z, A-Z, 0-9, and - up to 128 characters long for future proofing.
Yes
currency1The original currency/coin submitted.Yes
currency2The coin the buyer paid with.Yes
amount1The amount of the payment in your original currency/coin.Yes
amount2The amount of the payment in the buyer's coin.Yes
feeThe fee on the payment in the buyer's selected coin.Yes
buyer_nameThe name of the buyer.No
emailBuyer's email address.No
item_nameThe name of the item that was purchased.No
item_numberThis is a passthru variable for your own use.No
invoiceThis is a passthru variable for your own use.No
customThis is a passthru variable for your own use.No
send_txThe TX ID of the payment to the merchant. Only included when 'status' >= 100 and if the payment mode is set to ASAP or Nightly or if the payment is PayPal Passthru.No
received_amountThe amount of currency2 received at the time the IPN was generated.No
received_confirmsThe number of confirms of 'received_amount' at the time the IPN was generated.No