Bitcoin betalingen API documentatie en voorbeelden Bitcoin payments API documentation and examples

In het kort

  1. Roep de BitKassa API aan om een betaling te initiëren. Wij retourneren o.a. een URL naar een betaalpagina en een Bitcoin-adres en bedrag.
  2. Ofwel je redirect de klant door naar onze betaalpagina, ofwel je toont zelf een betaalpagina met het gegeven Bitcoin-adres en bedrag in bitcoins.
  3. Indien je onze betaalpagina gebruikt, redirecten wij de klant na de betaling weer terug naar je site of webshop, inclusief resultaat van de betaling.
  4. Daarnaast roepen wij een optionele callback URL aan waar we de status van de betaling doorgeven.

Summary

  1. Call the BitKassa API to initiate a payment. We return a URL to our payment page, as well as a Bitcoin address and amount.
  2. Either redirect your customer to our payment page, or host your own payment page using the specified Bitcoin address and amount.
  3. If you're using our payment page, we will return your customer back to your website after the payment, including details on the result.
  4. Besides, we also call an optional callback URL, through which we notify you of any payment status changes.

Technische specificatie

Bij het aanmaken van een BitKassa account krijg je een merchant ID en een secret API key (beide een alfanumerieke string).

Voor iedere API call roep je deze URL aan:

  https://www.bitkassa.nl/api/v1

met twee POST of GET parameters:

  p = base64-encoded json data
  a = authenticatie hash

Waarbij a = sha256( secret API key + json data + unixtime ) + unixtime

De json data moet altijd een element action bevatten met de API-functie die je wilt aanroepen, en een merchant_id met je merchant ID. De overige json data (verplicht of optioneel) hangt af van de action, zie onder.
Unixtime is de huidige unix timestamp als integer.
De + staat voor string concatenation (dus achter elkaar plakken).

Merk op:

  • Bedragen worden overal uitgedrukt als integer, in centen of satoshis (honderdmiljoenste bitcoins). Dus 29,50 euro wordt gespecificeerd als EUR 2950, en 0.0375 bitcoins wordt BTC 3750000.
  • Onze API heeft altijd een json resultaat, waarvan het laatste element een boolean genaamd success is. Deze is true indien de API call correct was verwerkt. En anders (als success false is) bevat de json ook een error element met een foutmelding.
  • Onze server geeft altijd een HTTP/1.1 200 OK status code in de headers, ook als de API call niet goed kon worden verwerkt en het json resultaat een foutmelding bevat.

Technical specifications

Upon signing up for your BitKassa account, you'll receive a merchant ID and a secret API key (both alphanumeric strings).

For every API function you need to call this URL:

https://www.bitkassa.nl/api/v1

with two POST or GET parameters:

  p = base64-encoded json data
  a = authentication hash

Where a = sha256(secret key + json data + unixtime) + unixtime

The json data should always contain an element action to identify which API function you're calling, and a merchant_id containing your merchant ID. Other parameters (required or optional) depend on the action, see below.
Unixtime is the current unix timestamp as integer.
The + means string concatenation (i.e. just append as strings).

Note:

  • Amounts are always expressed in cents or satoshis (one hundredmillionth of a bitcoin). So 29,50 euro is specified as EUR 2950, and 0.0375 bitcoins is specified as BTC 3750000.
  • Our API always returns a json result, of which the last element is a boolean named success. This is true if the API call was processed successfully. Otherwise (if success is false) the json will also contain an error element with an error message.
  • Our webserver's headers always contain a HTTP/1.1 200 OK status code, even if the API call couldn't be processed correctly and the json contains an error message.

Een betaling starten

Om een betaling te starten roep je de API aan met de volgende json data: (* = verplicht)

NaamTypeOmschrijvingVoorbeeld
action *stringDe API functionaliteit die je wilt aanroepen, in dit geval "start_payment"start_payment
merchant_id *stringJe merchant IDbanketbakkerhenk
currency *stringDe valuta van het te betalen bedrag (kan EUR of BTC zijn)EUR
amount *integerHet te betalen bedrag in centen of satoshi's1295
descriptionstringOmschrijving van het product of de betaling voor de klantChocoladetaart XL
return_urlstringDe URL waar wij de klant heen sturen na de betaling (als je onze betaalpagina gebruikt)https://www.bakkerhenk.nl/webshop/return.php
update_urlstringEen callback URL die wij aanroepen als de status van de betaling verandert (zie onder)https://www.bakkerhenk.nl/update_order.php
meta_infostringEen eigen referentie, bijvoorbeeld een ID in je eigen database, die wij meesturen met status updatesA947183352

De API call geeft een json resultaat terug, bij succes is dat:

NaamTypeOmschrijvingVoorbeeld
payment_idstringOnze ID voor deze betalingdhqe4cnj7f
payment_urlstringDe URL waar je de klant heen kunt sturen (als je onze betaalpagina wilt gebruiken)https://www.bitkassa.nl/tx/dhqe4cnj7f
addressstringHet Bitcoin-adres waar de klant het bedrag naartoe moet sturen1BK9imjqeziWixvD64XfYNye5rKi2HcN7P
amountintegerHet bedrag in satoshi's dat de klant moet betalen140000
bitcoin_urlstringEen complete Bitcoin-URL die je kunt tonen (als klikbare link en/of QR) waarmee de klant kan betalen vanuit zijn wallet (als je je eigen betaalpagina wilt hosten)bitcoin:1BK9imjqeziWixvD64XfYNye5rKi2HcN7P?amount=0.0014
expireintegerUnix timestamp wanneer de betaling verloopt (in principe 15 minuten na aanvang)1563534200
successbooleanBevestiging dat de API call correct is verwerkttrue

En anders:

NaamTypeOmschrijvingVoorbeeld
errorstringReden waarom de betaling niet kon worden gestartMissing amount
successbooleanIndicatie dat de API call niet correct is verwerktfalse

Voorbeeld aanroep

Als je het volgende stuurt:

{
 "action":       "start_payment",
 "merchant_id":  "schoenmakerpiet",
 "currency":     "EUR",
 "amount":       2250
}
                    

Geeft onze API bijvoorbeeld terug:

{
 "payment_id":    "r6fhp22x5c",
 "payment_url":   "https://www.bitkassa.nl/tx/r6fhp22x5c",
 "address":       "1BK9imjqeziWixvD64XfYNye5rKi2HcN7P",
 "amount":        240000,
 "bitcoin_url":   "bitcoin:1BK9imjqeziWixvD64XfYNye5rKi2HcN7P?amount=0.0024",
 "expire":        1563534200,
 "success":       true
}
                    

Starting a payment

To start a payment, call the API with the following json data: (* = required)

NameTypeDescriptionExample
action *stringThe API function you want to use, in this case "start_payment"start_payment
merchant_id *stringYour merchant IDjoesbakery
currency *stringThe currency of the amount to be paid (can be EUR or BTC)EUR
amount *integerThe amount to be paid in cents or satoshis1295
descriptionstringDescription for the customer of the product or service to be paidChocolate Pie XL
return_urlstringThe URL where we'll redirect your customer after the payment (if you use our payment page)https://www.joesbakery.uk/webshop/return.php
update_urlstringA callback URL that we'll call to notify you of any payment status changes (see below)https://www.joesbakery.uk/update_order.php
meta_infostringA reference string, such as an ID in your database, that we'll send along with status updatesA947183352

The API call returns a json result, if successful this will contain:

NameTypeDescriptionExample
payment_idstringOur ID for this paymentdhqe4cnj7f
payment_urlstringThe URL where you can redirect your customer to (if you want to use our payment page)https://www.bitkassa.nl/tx/dhqe4cnj7f
addressstringThe Bitcoin address where the customer is supposed to send his payment1BK9imjqeziWixvD64XfYNye5rKi2HcN7P
amountintegerThe amount in satoshis to be paid140000
bitcoin_urlstringThe Bitcoin payment URL which you can show (as link and/or QR) for the customer to pay from his wallet (if you're hosting your own payment page)bitcoin:1BK9imjqeziWixvD64XfYNye5rKi2HcN7P?amount=0.0014
expireintegerUnix timestamp when the payment expires (typically 15 minutes after start)1563534200
successbooleanConfirmation that the API call was processed successfullytrue

And otherwise:

NameTypeDescriptionExample
errorstringReason why the payment could not be initiatedMissing amount
successbooleanIndication that the API call was not processed correctlyfalse

Example API call

For example, you send:

{
 "action":       "start_payment",
 "merchant_id":  "shoemakerpete",
 "currency":     "EUR",
 "amount":       2250
}
                    

The BitKassa API returns:

{
 "payment_id":    "r6fhp22x5c",
 "payment_url":   "https://www.bitkassa.nl/tx/r6fhp22x5c",
 "address":       "1291C5pi4TPvjH5un89U4amTB8DhCHiTp3",
 "amount":        240000,
 "bitcoin_url":   "bitcoin:1BK9imjqeziWixvD64XfYNye5rKi2HcN7P?amount=0.0024",
 "expire":        1563534200,
 "success":       true
}
                    

Resultaat van een betaling verwerken

Indien je bij een betaling een update_url had meegegeven, roepen wij die aan wanneer de status van een order verandert. Dat doen we net als onze eigen API calls met twee POST parameters p en a, waarbij p een base64-encoded json object is, en a een authenticatie hash (op dezelfde manier gedefinieerd als hierboven, dit ter verificatie dat de callback echt van ons komt).

Indien je bij een betaling een return_url had meegegeven, redirecten we de de klant daarheen vanaf onze betaalpagina (nadat de betaling is voldaan of geannuleerd). Ook daarbij sturen we diezelfde twee parameters mee met de status van de betaling.

De json data (de p parameter) bij zo'n callback of redirect bevat:

NaamTypeOmschrijvingVoorbeeld
payment_idstringDe ID van de betaling waarvan we een update sturen of waarvandaan we de klant redirectendhqe4cnj7f
payment_statusstringDe status van de betaling (zie onder)pending
meta_infostringJe eigen referentie string, indien je die had meegegeven bij het starten van de betalingA947183352

Bijvoorbeeld, bij het aanroepen van de update_url en/of het redirecten van de klant naar return_url sturen wij mee:

{
 "payment_id":      "r6fhp22x5c",
 "payment_status":  "paid"
}
                    

Let op dat je de authenticatie hash (de a parameter) verifieert, anders zou iemand kunnen proberen om zelf zijn betalingsstatus naar 'paid' te veranderen. Zie ook het PHP voorbeeld 'Wrapper functie om de POST parameters te lezen' onderaan.

Processing a payment's result

If you specified a update_url when starting the payment, we'll call it whenever the status of a payment changes. We'll do this just like our own API calls with two POST parameters p and a, with p being a base64-encoded json object and a being an authentication hash (defined in the same way as above, to ensure the callback is actually coming from us).

If you specified a return_url when starting the payment, we'll redirect your customer there from our payment page after the payment is finished or cancelled. We also include the same two parameters here, containing the result of the payment.

The json data (the p parameter) with a callback or redirect contains:

NameTypeDescriptionExample
payment_idstringThe ID of the payment for which we're sending a status update or returning the customerdhqe4cnj7f
payment_statusstringThe payment status (see below)pending
meta_infostringYour own reference string, if you specified it when starting the paymentA947183352

For example, upon calling your update_url and/or redirecting the customer to return_url, we send:

{
 "payment_id":      "r6fhp22x5c",
 "payment_status":  "paid"
}
                    

Make sure to verify the authentication hash (the a parameter), otherwise someone could try and modify their own payment status into 'paid'. See also the PHP example 'Wrapper function to process the POST parameters' at the bottom.

Status van betaling

De status van een betaling kan het volgende zijn:

StatusOmschrijving
openDe betaling is net gestart en staat nog open, er heeft nog geen transactie plaatsgevonden
cancelledDe klant heeft de betaling geannuleerd
expiredDe betaling is verlopen (er zijn geen bitcoins verstuurd binnen de vereiste tijd)
pendingEr is een betaling onderweg, je kunt de klant eventueel informeren dat de betaling onderweg is en dat de bestelling wordt verwerkt zodra de transactie is bevestigd door het Bitcoin-netwerk
paidDe betaling is confirmed door het Bitcoin-netwerk, je kunt het product sturen of de dienst leveren

Een betaling begint altijd als open, en verandert naar cancelled als de klant annuleert, of expired als de klant te lang wacht en niets doet (of zijn browser afsluit), of pending zodra de klant zijn Bitcoin-betaling verstuurt. Na pending verandert de status vanzelf naar paid zodra er een confirmation (bevestiging) is van het Bitcoin-netwerk. In extreme gevallen waar de betaling niet binnen afzienbare tijd is confirmed en het onwaarschijnlijk is dat dit verandert, verandert de status alsnog naar expired. Zodra de status van een betaling eenmaal paid, cancelled, of expired is, verandert hij nooit meer.

Verschillende statussen van een betaling

Let op - wij garanderen pas uitbetaling als de status paid wordt, dus na een confirmation van het Bitcoin netwerk. Of dit gebeurt en hoe lang dit duurt heeft te maken met hoe druk het op het netwerk is en hoeveel fee de betalende klant bij zijn Bitcoin-transactie doet. Dit varieert tussen enkele minuten tot enkele weken, het is ook mogelijk dat een order te lang blijft hangen en nooit meer bevestigd wordt. Wij raden aan om zodra een betaling pending is, de klant te informeren "dank voor uw betaling, zodra uw transactie een bevestiging heeft gekregen van het Bitcoin-netwerk wordt uw order verwerkt", en daadwerkelijk de dienst te leveren of product te versturen zodra de status naar paid verandert.

Payment status

The status of a payment can be one of the following:

StatusDescription
openThe payment just started and is still open, no transaction has been done yet
cancelledThe customer cancelled the payment
expiredThe payment expired (no transaction was done within the required time)
pendingA payment is incoming, it isn't confirmed by the Bitcoin network yet, but you could inform your customer that his payment is being processed and his order will be handled as soon as the transaction gets confirmed by the Bitcoin network
paidThe payment is confirmed by the Bitcoin network, you can now send the product or deliver the service

A payment always starts as open, and changes to cancelled if the customer cancels, or expired if the customer waits too long and doesn't do anything (or closes his browser), or pending as soon as the customer sends a Bitcoin payment. After pending the status will automatically change to paid as soon as it's confirmed by the Bitcoin network. In extreme cases where a payment does not get confirmed and is unlikely to get confirmed within a foreseeable time, the status will change to expired. Once a payment becomes either paid, cancelled, or expired, it never changes anymore.

Payment status lifecycle

Please note - we only guarantee to pay out the money when the status becomes paid, i.e. after confirmation from the Bitcoin network. Whether or not this happens and how long it will take is dependent on how busy the Bitcoin-network is and how much fee your customer included in his transaction. It varies from a few minutes to a couple of weeks, it's also possible the transaction may never get confirmed. We recommend as soon as a payment is pending, to inform the customer "thanks for your payment, your order will be processed as soon as your transaction gets confirmed by the Bitcoin network", and actually ship the product or deliver the service as soon as the status changes to paid.

Status van een betaling opvragen

Behalve de status die wij doorsturen naar de return_url en update_url kun je ook zelf de status van een betaling opvragen, via een API call met de volgende json data: (* = verplicht)

NaamTypeOmschrijvingVoorbeeld
action *stringDe API functionaliteit die je wilt aanroepen, in dit geval "get_payment_status"get_payment_status
merchant_id *stringJe merchant IDbanketbakkerhenk
payment_id *stringDe ID van de betalingdhqe4cnj7f

Het resultaat dat je terugkrijgt bevat:

NaamTypeOmschrijvingVoorbeeld
payment_statusstringDe status van de betaling (zie boven)paid
successbooleanBevestiging dat de API call correct is verwerkttrue

Of als er een fout optrad:

NaamTypeOmschrijvingVoorbeeld
errorstringReden waarom de status van de betaling niet kon worden opgevraagdInvalid payment_id
successbooleanIndicatie dat de API call niet correct is verwerktfalse

Bijvoorbeeld, je stuurt:

{
 "action":       "get_payment_status",
 "merchant_id":  "schoenmakerpiet",
 "payment_id":   "r6fhp22x5c"
}
                    

Onze API geeft terug:

{
 "payment_status":  "paid",
 "success":         true
}
                    

Merk op dat het zelf opvragen van een betalingsstatus in principe niet noodzakelijk is, de status die wij doorgeven via de update_url en/of return_url (waarvan je er in de praktijk waarschijnlijk één of allebei meegeeft) is op zich voldoende om een betaling volledig te verwerken.

Retrieving the payment status

Besides the status info we're sending to you through return_url and update_url, you can also get the status for a payment yourself, through an API call with the following JSON data: (* = required)

NameTypeDescriptionExample
action *stringThe API function you want to use, in this case "get_payment_status"get_payment_status
merchant_id *stringYour merchant IDjoesbakery
payment_id *stringThe ID of the paymentdhqe4cnj7f

The result you're getting contains:

NameTypeDescriptionExample
payment_statusstringThe status of the payment (see above)paid
successbooleanConfirmation that the API call was processed successfullytrue

Or if an error occurred:

NameTypeDescriptionExample
errorstringReason why the payment status could not be retrievedInvalid payment_id
successbooleanIndication that the API call was not processed correctlyfalse

For example, you send:

{
 "action":       "get_payment_status",
 "merchant_id":  "joesbakery",
 "payment_id":   "r6fhp22x5c"
}
                    

Our API returns:

{
 "payment_status":  "paid",
 "success":         true
}
                    

Note that retrieving the payment status yourself is not necessary, the status we're passing through the update_url and/or return_url (of which you'll typically specify one or both in practice) is sufficient to completely process a payment.

PHP Voorbeelden

Wrapper functie om BitKassa API aan te roepen:

function CallBitKassaApi( $action, $params )
{
	$merchantId = 'banketbakkerhenk';
	$secretApiKey = 'abcde12345';

	// voeg action en merchant_id (vereist voor elke API call) toe aan de params array
	$params['action'] = $action;
	$params['merchant_id'] = $merchantId;

	// creeer json en authenticatie
	$jsonData = json_encode($params);
	$t = time();
	$a = hash('sha256',$secretApiKey.$jsonData.$t).$t; // authenticatie hash
	$p = base64_encode($jsonData);

	// roep API url (zou ook kunnen met curl e.d.)
	$jsonResult = file_get_contents("https://www.bitkassa.nl/api/v1?p=$p&a=$a");

	// retourneer resultaat als array (of breek af met foutmelding)
	if (!$jsonResult) die('Kon geen verbinding krijgen');
	$result = json_decode($jsonResult,true);
	if (!$result['success']) die('Error: '.$result['error']);
	return $result;
}
                    

Betaling starten:

$params = array(
	// verplicht:
	'currency' => 'EUR',
	'amount'   => 1295,

	// optioneel:
	'description' => 'Chocoladetaart XL',
	'return_url'  => 'https://www.bakkerhenk.nl/webshop/landingpage.php',
	'update_url'  => 'https://www.bakkerhenk.nl/update_order.php',
	'meta_info'   => '123456789', // kan bijvoorbeeld een order of klant ID zijn in je eigen database, voor je eigen referentie
);

$result = CallBitKassaApi('start_payment',$params);

// stuur klant door naar betaalpagina
header('Location: '.$result['payment_url']);
                    

Status van een betaling opvragen:

$params = array( 'payment_id' => 'abcdefghijk' );
$result = CallBitKassaApi('get_payment_status',$params);

print('De status van uw betaling is: '.$result['payment_status']);
                    

Wrapper functie om de POST parameters te lezen die wij meesturen met een callback of redirect:

function GetBitKassaParams()
{
	$mySecretApiKey = 'abcde12345';
	$p = $_POST['p'];
	$a = $_POST['a'];
	$jsonData = base64_decode($p);

	// controleer authentication hash (zodat je zeker weet dat deze request echt van ons kwam,
	// en niet van iemand die zijn order ten onrechte op 'paid' probeert te zetten)
	$t = substr($a,64);
	$verify = hash('sha256',$mySecretApiKey.$jsonData.$t).$t;
	if ($a!=$verify) die('Authentication error');

	return json_decode($jsonData,true);
}
                    

Callback script dat je zou kunnen meegeven als update_url:

$params = GetBitKassaParams();

$paymentId = $params['payment_id'];
$status = $params['payment_status'];
$myRef = $params['meta_info'];

if ($status=='paid')
{
	// (...verstuur product...)
}
                    

Terugkeer pagina die je zou kunnen meegeven als return_url, waarheen wij de klant redirecten na de betaling:

$params = GetBitKassaParams();

$paymentId = $params['payment_id'];
$status = $params['payment_status'];
$myRef = $params['meta_info'];

if ($status=='pending' || $status=='paid')
{
	print('Dank voor uw betaling, zodra deze een bevestiging vanuit het Bitcoin-netwerk krijgt gaan we uw order zo snel mogelijk verwerken!');
}
else if ($status=='expired') print('Er is geen betaling ontvangen :(');
else if ($status=='cancelled') print('U heeft de betaling geannuleerd :(');
                    

PHP Examples

Wrapper function to call the BitKassa API:

function CallBitKassaApi( $action, $params )
{
	$merchantId = 'joesbakery';
	$secretApiKey = 'abcde12345';

	// insert action and merchant_id (required for every API call) into the params array
	$params['action'] = $action;
	$params['merchant_id'] = $merchantId;

	// create json and authentication
	$jsonData = json_encode($params);
	$t = time();
	$a = hash('sha256',$secretApiKey.$jsonData.$t).$t; // authentication hash
	$p = base64_encode($jsonData);

	// call API url (also possible with cURL etc)
	$jsonResult = file_get_contents("https://www.bitkassa.nl/api/v1?p=$p&a=$a");

	// abort on error, or return result as associative array
	if (!$jsonResult) die('Could not connect');
	$result = json_decode($jsonResult,true);
	if (!$result['success']) die('Error: '.$result['error']);
	return $result;
}
                    

Start a payment:

$params = array(
	// required:
	'currency' => 'EUR',
	'amount'   => 1295,

	// optional:
	'description' => 'Chocolate Pie XL',
	'return_url'  => 'https://www.joesbakery.uk/webshop/landingpage.php',
	'update_url'  => 'https://www.joesbakery.uk/update_order.php',
	'meta_info'   => '123456789', // could be an order or customer ID within your own database, for your own reference
);

$result = CallBitKassaApi('start_payment',$params);

// redirect customer to payment page
header('Location: '.$result['payment_url']);
                    

Retrieve payment status:

$params = array( 'payment_id' => 'abcdefghijk' );
$result = CallBitKassaApi('get_payment_status',$params);

print('The status of your payment is: '.$result['payment_status']);
                    

Wrapper function to process the POST parameters we include with a callback or redirect:

function GetBitKassaParams()
{
	$mySecretApiKey = 'abcde12345';
	$p = $_POST['p'];
	$a = $_POST['a'];
	$jsonData = base64_decode($p);

	// verify authentication hash to be sure this request actually came from us,
	// and not someone trying to forge their payment status into 'paid'
	$t = substr($a,64);
	$verify = hash('sha256',$mySecretApiKey.$jsonData.$t).$t;
	if ($a!=$verify) die('Authentication error');

	return json_decode($jsonData,true);
}
                    

Callback script you could use as update_url:

$params = GetBitKassaParams();

$paymentId = $params['payment_id'];
$status = $params['payment_status'];
$myRef = $params['meta_info'];

if ($status=='paid')
{
	// (...send product...)
}
                    

Return page you could use as return_url, where we redirect the customer after the payment:

$params = GetBitKassaParams();

$paymentId = $params['payment_id'];
$status = $params['payment_status'];
$myRef = $params['meta_info'];

if ($status=='pending' || $status=='paid')
{
	print('Thanks for your payment, we will process your order as soon as your transaction gets confirmed by the Bitcoin network!');
}
else if ($status=='expired') print('No payment received :(');
else if ($status=='cancelled') print('You cancelled the payment :(');
                    

Overige platformen

Other platforms

Ruby interface Ruby interface
door Bèr Kessels by Bèr Kessels
Java library Java library
door Robbert Coeckelbergh by Robbert Coeckelbergh
Java library Java library
door Hackerspace Gent by Hackerspace Gent

BitKassa plugins voor webwinkels

Voor een klein aantal webwinkels hebben we plugins beschikbaar, maar let op: deze worden niet onderhouden! We kunnen hier slechts beperkte ondersteuning op verlenen.

BitKassa webshop plugins

For a small number of webshops we have plugins available, but please note: the plugins are not actively being developed! We can only provide limited technical support.

Vragen over de BitKassa API?

Stuur ons een mail op api@bitkassa.nl en we helpen je graag verder.

Questions about the BitKassa API?

Questions? Send us an email at api@bitkassa.nl, we are glad to help you out.