# 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)
}
```