Payment Howto


You need to setup an url in your shop system which accepts http POST. The post body contains information about incoming payment and number of confirmations.

You need to connect each order in your shop to one bitcoin address. Each address should be marked as "used" in your system until the payment is received. If a payment notification comes in, you can look up the belonging order based on the bitcoin address. If the amount is fine and the order can be processed you can fulfill the order and "release" the bitcoin address for the next incoming order.

This means, you have to set up as many bitcoin addresses as you want to support parallel open orders. And you have to stop accepting additional orders if all bitcoin addresses in your system are linked to an open order.

There are two ways to setup you bitcoin addresses with your agent:

  1. Static: Manually add all related addresses directly to the agent using the dashboard. Recommended for low-volume sites with only a few addresses which don't change often.
  2. Dynamic: Add or remove bitcoin addresses from your agent on demand using the API. Recommended for sites which need a lot of bitcoin addresses or with frequently changing addresses.
Note that both options can be combined; you can mix & match dashboard and API usage as you like.

For perfect customer support you should also handle correctly partial payments: If the amount received is not sufficient the order should stay open and the address still be reserved for the same order until the required amount is received.

You can look at tx4coin's sysinfo page as an example: Currently the site has 12 bitcoin addresses in the system. For each SMS ordered but not yet paid the "addresses in use" will increase. If all available addresses are in use, the system will not accept new SMS orders. If a SMS is paid completely, the associated bitcoin address is released again, decreasing the "addresses in use" reading. also supports partial payments. Give it a try - If you order a SMS and only pay partly the site keeps track of the missing amount and shows the according status on the order page.


To make sure that the POSTed information is authentic, a signature is added to the data. The signature is calculated by concatenating all parameters and your http security token into one long string. Then the md5 hash of this string is calculated and provided in signature. As only you and know your security token, no one else can create a valid signature.

The information in the post body is formatted in json.

Provided data in POST body
Amount received (unit: Satoshi)
Amount received (unit: Bitcoin)
Reserved for later use. At some time you will be able to set up additional information to be included in this parameter.
Number of confirmations for this transaction. "0" for unconfirmed transactions
Bitcoin address which received the payment
timestamp when transaction was received
Hash of transaction which includes this payment
Name of the agent who triggered this notification
Example POST body
    "signed_data": {
        "amount": 122678000,
        "userdata": "",
        "confirmations": 2,
        "amount_btc": "1.22678000",
        "address": "12r9JzPNnyWs2j1s9KLW5keqBr4kbJjxz6",
        "created": "2012-02-19 10:37:20.203541",
        "txhash": "e0c84120068bfefddab051e751f3df963c4ed29e7b13eadac026e6f17f55fb06",
        "agent": "callback_test"
    "signature": "38a25ec14b9ffcfe98938f3e35ac9cf41de2a971"
Authenticate incoming payment notification

To check that the signature is valid you have to perform the following steps (pseudocode):

  1. Concatenate contents of signed_data in exactly the following order (and make sure to use the string representation of each value!):
  2. concatenated_data = address + agent + amount + amount_btc + confirmations + created + userdata + txhash
  3. Append your http security token:
  4. concatenated_data = concatenated_data + http_security_token
  5. Calculate the md5 hash:
  6. my_signature = md5(concatenated_data).hexdigest()
  7. Compare your calculated md5 hash with the hash provided in signature. Only accept the payment if the signatures are equal.
Django/Python Example
import hashlib
from django.utils import simplejson

json_data = simplejson.loads(request.raw_post_data)

tx_hash = json_data[u'signed_data'][u'txhash']
address = json_data[u'signed_data'][u'address']
created = json_data[u'signed_data'][u'created']
confirmations = json_data[u'signed_data'][u'confirmations']
userdata = json_data[u'signed_data'][u'userdata']
amount = json_data[u'signed_data'][u'amount']
agent = json_data[u'signed_data'][u'agent']
amount_btc = json_data[u'signed_data'][u'amount_btc']
signature = json_data[u'signature']

sigstring = address + agent + str(amount) + str(amount_btc)+ str(confirmations) + created + str(userdata) + str(tx_hash) + <your token>

my_signature = md5(sigstring).hexdigest()

if my_signature == signature:
    # Accept payment


How is the behaviour of during downtimes?
If you have set up your agent to trigger a notification e.g. at 0 and at 6 confirmations it is guaranteed that both notifications are performed. Even when bitcoinmonitor is down and misses the initial confirmation, so the transaction is spotted only late with e.g. 10 confirmations, you will get immediately two calls: The first with 0 confirmations, the second with 6 confirmations.
Retry policy
In case a notification event can not be delivered, the agents will retry up to 5 times, waiting 30 seconds between each try. During this phase you will see the according notification history entry in state "RETRY". In case also the last try has failed the agents will give up and the notification history entry will change to state "FAILURE".
Expected response codes
If your server responds to the url callback with an error (any 4xx or 5xx code) the notification will be retried according to the retry policy. If your server responds with a success code (2xx) the notification is considered to be successfully delivered.
Compromised token
Whoever knows your token can trigger fake payments on your site. If your token has been compromised you should change it in the dashboard.

Question not answered here? Drop me a mail at

test http callback

You need to be logged to test http callbacks.

test xmpp/jabber notification

You need to be logged to test http callbacks.