# Bare Bitcoin public API Welcome to the Bare Bitcoin API documentation! Bare Bitcoin is a Bitcoin brokerage service available in Norway. This API is allows you to place orders, fetch price information, initiate bitcoin withdrawals as well as read out transaction data from your user. [Proceed to the endpoint explorer](/api/openapi) if you want to dig into the meat of the API! ## Features * **Price data**: Monitor current trading prices at the brokerage. * **Trading**: Execute market and limit orders with low latency. * **Withdrawals**: Initiate Bitcoin withdrawals securely to any onchain or Lightning destination. * **Deposits**: Receive bitcoin deposits to your Bare Bitcoin account ## Authentication All authenticated endpoints utilize API keys. These can be created from within your [profile settings](https://barebitcoin.no/innlogget/profil/nokler) on the signed-in section of our web platform. API keys have two distinct parts: 1. Public part. Starts with `bb/public/`. This should be included in the `x-bb-api-key` header. The API key is confidential, but it's not the end of the world if it gets leaked. 2. Secret part. Starts with `bb/apisecret/`. This is very sensitive! It is critical that this value **stays secret**. The secret should be used to construct a so called *HMAC*. Other crypto exchanges typically refers to this as the *signature*. Authentication is composed of three different headers: 1. API key (`x-bb-api-key`): the public part of your API key. 2. Nonce (`x-bb-api-nonce`): a positive integer you choose yourself. It has to **increase** for every request you make. You can typically set this to the current [epoch UNIX](https://www.epoch101.com/) timestamp. The purpose of this value is to make all API requests *single-use*. This makes it so you don't submit the same order twice by accident, for example. 3. HMAC (`x-bb-api-hmac`): an *HMAC* (or signature, as some people call it!), constructed using the secret part of your API key. Read-only requests (endpoints that use `GET`) can omit the second (`x-bb-api-nonce`) and third (`x-bb-api-hmac`) headers. Write requests (endpoints that use `POST`) *must* include all three. ### HMAC details The HMAC you need to generate is defined the following way: ``` HMAC-SHA256 of (URI path + SHA256(nonce + request body)) and base64 decoded secret API key ``` ### Examples The following is a specific example of a HMAC (*signature*) generated with a specific key, nonce, and request body corresponding to a new market order for 100 NOK. If your code produces a different HMAC (`x-bb-api-hmac`) you have a bug in your code. | Field | Value | | --- | --- | | Secret | bb/apisecret/ZZavHDgVRyGowg8blKfPDDRlN3+6h0/vOUA | | Nonce | 1733314678 | | Body | {"type": "ORDER_TYPE_MARKET", "direction": "DIRECTION_BUY", "amount": 100} | | URI | /v1/orders | | Method | POST | | HMAC | e6pQ5w9AqVhwHRWXuwS7ZwzRd0kH2GYpHSmtP0cTlSU= | #### JavaScript (Node.js) const crypto = require('crypto'); function createHmac(secret, { method, path, nonce, data }) { // Encode data: nonce and raw data const encodedData = `${nonce}${data.toString()}`; // SHA-256 hash of the encoded data const hashedData = crypto.createHash('sha256').update(encodedData).digest(); // Concatenate method, path, and hashed data const message = Buffer.concat([ Buffer.from(method), Buffer.from(path), hashedData ]); const decodedSecret = Buffer.from(secret, 'base64'); // Generate HMAC const hmac = crypto.createHmac('sha256', decodedSecret); hmac.update(message); const macsum = hmac.digest(); // Return base64-encoded HMAC return macsum.toString('base64'); } const components = { method: 'POST', path: '/v1/orders', nonce: 1733314678, data: '{"type": "ORDER_TYPE_MARKET", "direction": "DIRECTION_BUY", "amount": 100}' }; const secret = 'bb/apisecret/ZZavHDgVRyGowg8blKfPDDRlN3+6h0/vOUA'; const hmac = createHmac(secret, components); console.log(`x-bb-api-hmac: ${hmac}`); #### Go package main import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "fmt" "slices" ) type Components struct { Method string // HTTP method // URI path. If the request is for https://api.bb.no/v1/orders, this is "/v1/orders". Path string Nonce uint64 Data []byte // raw request data } func createHmac(secret string, components Components) (string, error) { encodedData := fmt.Sprintf("%d%s", components.Nonce, string(components.Data)) summed := sha256.Sum256([]byte(encodedData)) message := slices.Concat([]byte(components.Method), []byte(components.Path), summed[:]) // The secret is actually a base64-encoded byte slice! decodedSecret, err := base64.StdEncoding.DecodeString(secret) if err != nil { return "", fmt.Errorf("invalid HMAC secret: %w", err) } mac := hmac.New(sha256.New, decodedSecret) mac.Write(message) macsum := mac.Sum(nil) digest := base64.StdEncoding.EncodeToString(macsum) return digest, nil } func main() { components := Components{ Method: "POST", Path: "/v1/orders", Nonce: 1733314678, Data: []byte(`{"type": "ORDER_TYPE_MARKET", "direction": "DIRECTION_BUY", "amount": 100}`), } secret := "bb/apisecret/ZZavHDgVRyGowg8blKfPDDRlN3+6h0/vOUA" hmac, err := createHmac(secret, components) if err != nil { panic(err) } fmt.Printf("x-bb-api-hmac: %s\n", hmac) }