BTCex.cz api documentation

Overview

This page is documentation for RESTful API of project BTCex.cz

This API is mainly for our business partners, however, there are public methods which everybody can use and can be found useful.

If you are not a partner and want to be, please contact us at [email protected].

If you are a partner and need help with implementation or have improvement suggestions, please contact [email protected].

Technical details

Zalando RESTful API and Event Guidelines are followed.

For exact details of each endpoint please see >> OpenAPI specs <<.


🔑 Authentication

🐘 PHP example:

//these pamameters are for affiliate example.com and you are free to use them for your testing
$key = 'syoihuudkjqc3882';
$private = 'z2z77e0pl8rhtn9w';

$body = null;
$nonce = rand() << 32 | rand();//generates random long integer, for example: 1353154049963006992

//there are multiple supported body shapes, so please pick yours
$bodyJson = json_encode($body);//raw escaped
$bodyJson = json_encode($body ?: []);//array escaped
$bodyJson = json_encode($body ?: null);//null escaped
//default implementation of json_encode automatically escapes slashes, unlike json functions in other languages
//these options make it to behave more "standard"
$bodyJson = json_encode($body, JSON_UNESCAPED_SLASHES);//raw unescaped
$bodyJson = json_encode($body ?: [], JSON_UNESCAPED_SLASHES);//array unescaped
$bodyJson = json_encode($body ?: null, JSON_UNESCAPED_SLASHES);//null unescaped

$signature = hash_hmac('sha256',
    $key
    . "$"
    . $nonce
    . "$"
    . $bodyJson
    ,
    $private);

// curl call itself
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.btcex.cz/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);

if (!is_null($body)) {//post method if $body is not NULL
    curl_setopt($ch, CURLOPT_POST, true);
    //but there it is NOT required to have same shape as in signature
    $dataJson = json_encode($body);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $dataJson);
}

curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "btcex-key: $key",
    "btcex-nonce: $nonce",
    "btcex-signature: $signature",
    "btcex-test: 1",//request is run in test mode, which prevents from changing resources on our site
]);
$response = curl_exec($ch);
curl_close($ch);


$rType = (string)curl_getinfo($ch, CURLINFO_CONTENT_TYPE);//application/json
$rCode = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);//return code
$rData = json_decode($response, true);//json decoded data

var_dump($rType);
var_dump($rCode);
var_dump($rData);
die();

On successful call you should get partner example.com

See following input and output variables for signature function in order to test you have it right:

$nonce = 4835119959885924862;
$key = 'syoihuudkjqc3882';
$private = 'z2z77e0pl8rhtn9w';
//-----
$body = null;
$signatureList = [
    'raw_escaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
    'array_escaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'null_escaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
    'raw_unescaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
    'array_unescaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'null_unescaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
];
//-----
$body = [];
$signatureList = [
    'raw_escaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'array_escaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'null_escaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
    'raw_unescaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'array_unescaped' => [
        'json' => '[]',
        'signature' => 'cb11e4c0411ced017a6fda9df5c34cc78898685e488b2b05769acc01c9cdf5b6',
    ],
    'null_unescaped' => [
        'json' => 'null',
        'signature' => '126e70930a16cfea5f6c8d8cba64aa3e13b6a12a47c7e54532a6c58298dc433f',
    ],
];
//-----
$body = ['foo' => 'bar/baz']);
$signatureList = [
    'raw_escaped' => [
        'json' => '{"foo":"bar\\/baz"}',
        'signature' => '472254611513c81b11d4ee1c3b7ac9b30bb9266d0fb85f7d4cae4978e428b1a4',
    ],
    'array_escaped' => [
        'json' => '{"foo":"bar\\/baz"}',
        'signature' => '472254611513c81b11d4ee1c3b7ac9b30bb9266d0fb85f7d4cae4978e428b1a4',
    ],
    'null_escaped' => [
        'json' => '{"foo":"bar\\/baz"}',
        'signature' => '472254611513c81b11d4ee1c3b7ac9b30bb9266d0fb85f7d4cae4978e428b1a4',
    ],
    'raw_unescaped' => [
        'json' => '{"foo":"bar/baz"}',
        'signature' => '5fe2a575b88260ca5da7df1e985490cafe042847be35647104ca09d39682c10a',
    ],
    'array_unescaped' => [
        'json' => '{"foo":"bar/baz"}',
        'signature' => '5fe2a575b88260ca5da7df1e985490cafe042847be35647104ca09d39682c10a',
    ],
    'null_unescaped' => [
        'json' => '{"foo":"bar/baz"}',
        'signature' => '5fe2a575b88260ca5da7df1e985490cafe042847be35647104ca09d39682c10a',
    ],
];

🤡 JS example:

At first you need to install libraries yarn add crypto axios

//Include libraries
var crypto = require("crypto");
var axios = require("axios");
//Initialize parameters
var body = null;
var key = "syoihuudkjqc3882";
var privateKey = "z2z77e0pl8rhtn9w";
var nonce = "4835119959885924862";
//Create hash
var hasher = crypto.createHmac("sha256", privateKey);

var hashKey = key + "$" + nonce + "$" + JSON.stringify(body || []);
var hash = hasher.update(hashKey).digest("hex");

//Send request
var apiUrl = "https://api.btcex.cz/";
var headers = {
    "Content-Type": "application/json",
    "btcex-key": key,
    "btcex-nonce": nonce,
    "btcex-signature": hash,
    "btcex-test": "1"
};

if (body) {
    axios.post(apiUrl, body, {headers: headers})
        .then(function (res) { console.log(res) })
        .catch(function (err) { console.log(err) });
} else {
    axios.get(apiUrl, {headers: headers})
        .then(function (res) { console.log(res) })
        .catch(function (err) { console.log(err) });
}

🦩 C# signing example:

using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using NUnit.Framework;
 
namespace Btcex.Test;
 
public class Tests
{
    [Test]
    public void TestSignature()
    {
        var nonce = 4835119959885924862;
        var pubKey = "syoihuudkjqc3882";
        var prvKey = "z2z77e0pl8rhtn9w";
        var data = JsonConvert.SerializeObject(new { foo = "bar"});
 
        var sentence = $"{pubKey}${nonce}${data}";
        var bytesPrvKey = Encoding.UTF8.GetBytes(prvKey);
        using var hmacsha256 = new HMACSHA256(bytesPrvKey);
        var bytesSource = Encoding.UTF8.GetBytes(sentence);
        var hash = hmacsha256.ComputeHash(bytesSource);
        var signature = Convert.ToHexString(hash).ToLower();
        
        Assert.AreEqual("9eb77611ed3afdee9d864b72014213d3bea615422feac0fa74b985e9c5c40aeb", signature);
    }
}

🦺 Test mode

To implementation testing there is Test mode present.

It is activated by adding custom hearder: btcex-test: 1

When using, please have in mind following:

  • underlying resources are not changed (even responses says otherwise though)

  • when creating orders, their variable_symbol is always 0

  • you as partner might have test mode enforced (case for example.com for example)


    🚗🚀 Order flow


    Order Creation

    1. Data preparation

    First you need tell client parameters of his exchange, for this purpose you need 🌍 GET /price.

    Also we recommend using our crypto address validator, if client supplies one 🌍 GET /btc-address-validation/{address}.

    2. Order create

    After validating input data order creation endpoint is called.

    According to your implementation call one of the public GET endpoints (if done in browser):

    Or if done at backend, rather use one of private POST methods:

    If above action is successful, client is notified by email about order creation.


    Following cases are not required to have implemented - if you are providing only order creation and any other cases of flow go through our fallback website.

    About most cases bellow is client informed via email and provided with corresponding URLs to solve their situation.

    Each case solution consists of two or more API calls in set order. Generally GET confirms right condition and provides information. POST sends resolution of case.


    Verification

    Client can be prompted to prove his identity in one or more steps. About each step is informed in separated email.

    1. Verify Identity

    There is base information about person: name address, personal documents and phone number, etc...

    1. 🔒 GET /order/{id}/verify-identity - indicates case validity (and supplies needed information)
    2. 🔒 POST /order/{id}/verify-identity - resolves case

    2. Verify Phone

    Phone verification is more complex, since we need to send SMS code on demand.

    SMS endpoints can be omitted if client refuses.

    1. 🔒 GET /order/{id}/verify-phone - indicates case validity (and supplies needed information)
    2. 🔒 GET /order/{id}/verify-phone-sms - indicates if SMS code is already sent or not
    3. 🔒 POST /order/{id}/verify-phone-sms - request sending SMS code to client
    4. 🔒 POST /order/{id}/verify-phone - resolves case

    Deposit

    When client wants use his deposited funds, this case takes place. Please notice workflow is very similar to Verify Phone.

    1. 🔒 GET /order/{id}/deposit - indicates case validity (and supplies needed information)
    2. 🔒 GET /order/{id}/deposit-sms - indicates if SMS code is already sent or not
    3. 🔒 POST /order/{id}/deposit-sms - request sending SMS code to client
    4. 🔒 POST /order/{id}/deposit - resolves case

    Change

    In case input funds or exchange rate expires client is prompted to decide if they accept changed conditions.

    1. 🔒 GET /order/{id}/change - indicates case validity (and supplies needed information)
    2. 🔒 POST /order/{id}/change - resolves case

    Return

    In case we decide about cancellation of SELL order, we need information to whee to return crypto funds.

    1. 🔒 GET /order/{id}/return - indicates case validity (and supplies needed information)
    2. 🔒 POST /order/{id}/return - resolves case
  • Created by BTCex.cz, Copyright © 2022 All Rights Reserved.