Callbacks

New callbacks for Coinbase Wallet API v2 are currently under development. In the meantime v1 callbacks can be used and their payloads have been augmented with new resource IDs (uuid field) and paths (resource_path).

Instant payment notifications to your website

Callbacks send an automated message to your website when you receive an order, payout, or bitcoin payment.

These can be useful in various integrations, such as to mark an order as “paid” in your own database when you’ve received a payment.

Usage

Callbacks are always POST requests in JSON format to a callback url that you set.

There are three types of notifications we can send to your website:

order these indicate the status of a merchant order has changed (such as to complete, mispaid, etc)
payout these indicate an automated merchant payout has been sent to your bank account via our instant exchange feature
address these notify you when an individual bitcoin address receives a payment

Setting A Callback URL

To receive order and payout callbacks you will need to set a callback URL on your merchant settings page.

Callback URL

You can use the “Test Now” button during integration to ensure your website is receiving and processing callbacks correctly. You can also view logs of callbacks we’ve sent to aid in the debug process.

Individual orders can also have a custom callback url set, if you’d like to change the callback url per order.

To receive address callbacks, you can visit the my bitcoin addresses page and click ‘Details’ next to one of your addresses to set a callback url on it.

Callback2

You can also set a callback url on an address when creating it through the Coinbase API.

Note that address callbacks are a lower level integration that is not compatible with our regular merchant tools. Using the regular merchant tools is required to have access to features such as instant exchange, accounting exports, and setting prices in your local currency.

Example Callbacks

Order Callback Example

Order callbacks update you when the status of a merchant order has changed.

{
"order": {
  "id": "5RTQNACF",
  "created_at": "2012-12-09T21:23:41-08:00",
  "status": "completed",
  "event": {
    "type": "completed"
  },
  "total_btc": {
    "cents": 100000000,
    "currency_iso": "BTC"
  },
  "total_native": {
    "cents": 1253,
    "currency_iso": "USD"
  },
  "total_payout": {
    "cents": 2345,
    "currency_iso": "USD"
  },
  "custom": "order1234",
  "receive_address": "1NhwPYPgoPwr5hynRAsto5ZgEcw1LzM3My",
  "button": {
    "type": "buy_now",
    "name": "Alpaca Socks",
    "description": "The ultimate in lightweight footwear",
    "id": "5d37a3b61914d6d0ad15b5135d80c19f"
  },
  "transaction": {
    "id": "514f18b7a5ea3d630a00000f",
    "hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
    "confirmations": 0
  },
  "refund_address": "1HcmQZarSgNuGYz4r7ZkjYumiU4PujrNYk"
},
"customer": {
  "email": "coinbase@example.com",
  "shipping_address": [
    "John Smith",
    "123 Main St.",
    "Springfield, OR 97477",
    "United States"
  ]
 }
}
Definitions
id Order number used to uniquely identify an order on Coinbase
completed_at ISO 8601 timestamp when the order completed
status Either completed, mispaid, expired.
event Contains data about the specific event the callback is being generated for. type will be either completed or mispayment. If mispayment, the ID of the mispayment will be included as mispayment_id. This is different than the status parameter, which will always contain the original status of the order. If an order receives a mispayment after moving to the completed status, for example, all callbacks will contain a status parameter of completed. The mispayment callback, however, will contain an event parameter of mispayment.
total_btc Total amount of the order in ‘satoshi’ (1 BTC = 100,000,000 Satoshi). Note the use of the word ‘cents’ in the callback really means satoshi in this context. The btc amount will be calculated at the current exchange rate at the time the order is placed (current to within 15 minutes).
total_native Total amount of the order in your local currency in cents (1 unit = 100 cents). This will be equal to the price you set when creating the button.
total_payout Total amount of the payout in your local currency in cents (1 unit = 100 cents) that was scheduled to be deposited to your bank account using instant payout.
custom The optional custom parameter you set on the payment button with the data-custom attribute or at the time you created the button. Usually an Order, User, or Product ID corresponding to a record in your database.
receive_address The bitcoin address associated with this order. This is where the payment was sent.
button The details of the button you created. The id here matches the data-code parameter in your embedded HTML code.
transaction The hash and number of confirmations of the underlying bitcoin transaction. The number of confirmations is typically zero at the time of the first callback. If this was an off-blockchain transaction (i.e. directly from another Coinbase account), the hash will be null.
customer Customer information collected in the order form. This can include an email address and/or a shipping address. You may choose to require this information when creating the button.
refund_address Experimental parameter that is subject to change. We only send these when a payment is made from a Coinbase account and is off-blockchain right now.

Merchant Discounts

When there is a merchant discount applied to an order, the “order” attribute of the callback will post with two additional fields: discount_percent and total_original. The field total_native will reflect the total amount after the discount is applied.

{
  "order": {
    .....
    "discount_percent": 3.0,
    "total_original": {
      "cents": 3169,
      "currency_iso": "USD"
    }
  }
}
Definitions
discount_percent The discount percent that was applied to this order.
total_original Total amount of the order (before discount) in your local currency in cents (1 unit = 100 cents). This will be equal to the price you set when creating the button.
Mispaid Orders When a user pays the wrong amount for an order, or makes a payment to an expired order, a “mispayment” will be added to the order, and the “order” attribute of the callback will contain an array of these mispayments.
{
  "order": {
    "event": {
      "type": "mispayment",
      "mispayment_id": "ABC123"
    },
    .....
    "mispayments": [
      {
        "id": "ABC123",
        "created_at": "2012-12-09T21:25:36-08:00",
        "total_btc": {
          "cents": 3950000,
          "currency_iso": "BTC"
        },
        "total_native": {
          "cents": 3169,
          "currency_iso": "USD"
        }
      }
    ]
  }
}
Definitions
event The event that the callback is being fired for. type will be “mispayment” and mispayment_id will be the ID of the specific mispayment that generated this callback. A mispayment with that ID will be present in the mispayments array.
mispayments Array of all mispayments this order has received.
mispayments[i][created_at] ISO 8601 timestamp when the mispayment was received
mispayments[i][id] ID used to uniquely identify a mispayment on Coinbase
mispayments[i][total_btc] Total amount of the mispayment in “satoshi” (1 BTC = 100,000,000 Satoshi). Note the use of the word ‘cents’ in the callback really means ‘satoshi’ in this context.

Payout Callback Example

Payout callbacks update you when a payout has been made to your primary payout method.

A payout is represented internally in Coinbase as a sale of bitcoin, so it shares many of the same fields as the transfers api call. Instead of a single transaction_id moving bitcoin as part of the sell, there is an array of order_codes representing the merchant orders which make up the payout.

{
  "payout": {
    "id": "532bdc501e14ffec57000248",
    "type": "Sell",
    "created_at": "2014-03-20T23:29:36-07:00",
    "payout_date": "2014-03-25T23:29:36-07:00",
    "fees": {
      "coinbase": {
        "cents": 57,
        "currency_iso": "USD"
      },
      "bank": {
        "cents": 15,
        "currency_iso": "USD"
      }
    },
    "transaction_id": null,
    "status": "Pending",
    "btc": {
      "amount": "0.00",
      "currency": "BTC"
    },
    "subtotal": {
      "amount": "56.74",
      "currency": "USD"
    },
    "total": {
      "amount": "56.02",
      "currency": "USD"
    },
    "description": "Sold 0.00 BTC for for $56.02.\n\nPayment will be sent to Your Bank ********1234 by Tuesday Mar 25, 2014.",
    "payment_method": {
      "id": "52cef45d9b6faee5170000b3",
      "type": "BankAccount",
      "customer_name": "John Doe",
      "obfuscated_name": "Your Bank ********1234"
    },
    "order_codes": [
      "BXKZCXPU",
      "R7FABJ6T",
      "NB6SG859"
    ],
    "mispayment_codes": [
      "THTM7XLBS"
    ]
  }
}
Definitions:
id Used to identify the payout on Coinbase.
type This will always be “Sell” for a merchant payout.
created_at ISO 8601 timestamp of when the payout was created.
payout_date ISO 8601 timestamp - the payout will arrive on or before this time.
fees Any fees the merchant paid as part of the payout.
transaction_id The associated bitcoin transaction ID if bitcoin was moved as part of the sell. For a merchant payout this will be null since bitcoin has already arrived throughout the day as part of merchant orders. These are represented by the order_codes.
status The status of the payout. It will move from Pending to Complete once the payout has arrived.
btc The amount of BTC sold. For a merchant payout this will be null since bitcoin has already arrived throughout the day as part of merchant orders. These are represented by the order_codes.
subtotal The subtotal amount of the payout.
total The total amount of the payout (subtotal minus fees).
description Plain text description of the payout.
payment_method Details of the payout method used.
order_codes These match the order ids received throughout the day from order callbacks.
mispayment_codes These match the mispayment ids received throughout the day from wrong amount sent to orders, if you have instant exchange of mispaid orders enabled.

Address Callback Example Address callbacks update you when a bitcoin transaction arrives to a bitcoin address.

{
  "address": "1AmB4bxKGvozGcZnSSVJoM6Q56EBhzMiQ5",
  "amount": 1.23456,
  "transaction": {
    "hash": "7b95769dce68b9aa84e4aeda8d448e6cc17695a63cc2d361318eb0f6efdf8f82"
  }
}
Definitions:
address The bitcoin address that received the transaction.
amount BTC amount
transaction[‘hash’] The hash of the bitcoin transaction that just arrived to this address. If this was an off-blockchain transaction (i.e. directly from another Coinbase account), the hash will be null.

Callback Retry Schedule

When posting callbacks, Coinbase expects to receive a 200 response code from your website.

If the response code is not 200, we will retry the callback at exponentially increasing times until your website successfully acknowledges the callback.

This ensures that if your site experiences downtime or there is a problem with your integration, payment updates will not be lost.

Retries happen on an exponentially increasing schedule (4 ^ n seconds for n = 0 through 10). This corresponds to roughly:

  • about 1 second for the first callback
  • 4 seconds
  • 16 seconds
  • 1 minute
  • 4 minutes
  • 17 minutes
  • about 1 hour
  • about 5 hours
  • about 18 hours
  • about 3 days
  • about 12 days

Most of the time your website will respond on the very first callback so subsequent callbacks will never need to be run.

Securing Callbacks

For order callbacks, you will most likely want to obfuscate your callback URL to prevent people from guessing it and passing bad data to your site. An easy way to do this is to include a secret parameter in your callback URL. For example if you set your callback URL to https://www.example.com/callback?secret=834u9hteruhgrghe0ugldrg8u4f487 then you can check to make sure that the secret param equals 834u9hteruhgrghe0ugldrg8u4f487 before processing the callback.

Your callback url should also use the https protocol for greater security. This ensures that url parameters (like the secret) cannot be seen as they go over the wire. Additionally, the callback url should reject all requests that do not originate from one of the following Coinbase callback IPs:

  • 54.243.226.26
  • 54.175.255.192/27

This will reduce the attack surface of your callback url as well as abuse of a compromised callback secret.

We may add a signing protocol in the future for additional security, but for now the above steps should be secure if you take care to keep your secret parameter safe.

Confirmations

Bitcoin transactions arrive usually within a few seconds, but can take anywhere from 10 minutes to 1 hour to become 100% confirmed in the blockchain (bitcoin’s public ledger system). While this may seem like a challenge, Coinbase has several measures in place to eliminate the effect on merchants.

When Coinbase sends an order callback with a status of completed, and you have instant-exchange enabled, it is safe to assume at this point that the payout is guaranteed by Coinbase. Even if the associated payment transaction does not confirm, Coinbase will always pay out an order after sending a completed callback.

Typically, Coinbase sends the callback within 1-2 seconds of the bitcoin transaction arriving. If we feel the transaction is at a higher risk for being double spent, we may delay sending the callback until we can be sure the transaction will be confirmed.