Balance Custody API
Balance CustodyAbout
  • Introduction
  • Authentication
  • V1
    • Wallets
    • Assets
    • Transaction fees
    • Stats
    • External accounts
    • Transactions
  • V2
    • Staking
    • Transactions
    • Assets
  • Regulatory Compliance
  • Webhooks
Powered by GitBook
On this page
  • How it works
  • Examples
  • Helper Libraries
  • Ruby
  • Postman

Authentication

This document describes the authentication scheme used in API endpoints that require it.

The authentication scheme used is based on HMAC, and follows a scheme similar to that of AWS.

You will get your ACCESS_ID and SECRET_KEY from your point of contact at Balance.

How it works

1. Create a canonical string for your request:

canonical_string = "#{http_method},#{content_type},#{request_uri},#{data_hash},#{timestamp}"

Details:

  • http_method is an upper case version of the full HTTP method. Supported methods for this API are: GET, POST, PUT, PATCH, DELETE

  • content_type is a copy of the Content-Type header. For this API, set this to application/json.

  • request_uri is the URI of the request. Do not include query params. For example: /api/v1/wallets

  • data_hash is a SHA-256 hash of the request body, encoded as a HEX string. If the body field is empty, leave this field as an empty string. For example, if the body is the following string: {"name": "foobar"}, the data_hash field should be set to: e684679449a32cb2477110ce15b02eace29dbfc89b9f8597a90d5702d5f60695

  • timestamp is a UNIX timestamp equivalent of the Date header. E.g. 1561661184 (equivalent to Thu, 27 Jun 2019 18:46:24 GMT). Note that if this date is more than 15 minutes behind or ahead of the server's current date, the request will be rejected.

2. Create a signature

The signature is a SHA-256 based HMAC signature, keyed on the SECRET_KEY provided to you by Balance. The signature must be HEX-encoded.

An example of this code in Ruby would be:

signature = OpenSSL::HMAC.digest("SHA256", SECRET_KEY, canonical_string).unpack("H*").first

3. Add headers to your request

Your request now requires the following headers:

  • User-Agent - must be included in all requests; choose a value that helps identify your integration.

  • Content-Type - this header should always be set to application/json for this API

  • Date - current date (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Date)

  • Authorization - should be constructed in the following way: BalanceAPIAuth #{ACCESS_ID}:#{signature}

Only Content-Type, Date, and Authorization are used in the signature generation. User-Agent is required, but not part of the signed headers.

Examples

For each example, assume that your authentication credentials are:

ACCESS_ID="eSKzYGehz5s8R9QJ3"
SECRET_KEY="3mUgEnXkm8UR57RaLycP9Cu7pga4PELdzu2mfbHv6r3E"

And the timestamp is the following:

Thu, 27 Jun 2019 18:46:24 GMT

which is equivalent to a UNIX epoch timestamp of:

1561661184

POST request with data:

The following is a valid curl POST request:

curl -XPOST \
     -H "User-Agent: custom_name" \
     -H "Content-Type: application/json" \
     -H "Date: Thu, 27 Jun 2019 18:46:24 GMT" \
     -H "Authorization: BalanceAPIAuth eSKzYGehz5s8R9QJ3:c3b2f03bb3334ea9a81c0fb1ae3d610a253cebe9b9b4bac62e404a245cf3363d" \
     -d '{"name": "foo", "description": "bar"}' \
     https://your_custom_subdomain.balancecustody.ca/api/v1/wallets

Note that this should produce the following canonical_string:

POST,application/json,/api/v1/wallets,bfb3244e37e4f79fd7aa50213fae150cae746f65b8194248b8c4b21c69f070f0,1561661184

GET request without data:

The following is a valid curl GET request:

curl -H "User-Agent: custom_name" \
     -H "Content-Type: application/json" \
     -H "Date: Thu, 27 Jun 2019 18:46:24 GMT" \
     -H "Authorization: BalanceAPIAuth eSKzYGehz5s8R9QJ3:05c8fc86fa0568ec05412caab4327e3a7baf78f288832a53bc54cf168a15d3f8" \
     https://your_custom_subdomain.balancecustody.ca/api/v1/wallets

Note that this should produce the following canonical_string:

GET,application/json,/api/v1/wallets,,1561661184

Helper Libraries

Ruby

There's a helper module packaged together with this doc in hmac_auth_helpers.rb (see below). You can inspect the Ruby code to help you understand how to implement this scheme in your language of choice.

You can also use it to generate a curl request for testing purposes. Here's an example (note that access_id and secret_key in this example are dummy values):

$ irb

irb(main):001:0> require "./hmac_auth_helpers.rb"
=> true

irb(main):002:0> HMACAuthHelpers.print_curl_request(
  url_base: 'https://your_custom_subdomain.balancecustody.ca',
  request_uri: '/api/v1/wallets',
  access_id: '93G9toV9KxgDisd9p',
  secret_key: '2AxHS3cqqUMrCCKDNGmgCU1ovjAYgzVwRoT3QMVW5j6b'
)

curl -XGET \
     -H "User-Agent: test-client" \
     -H "Content-Type: application/json" \
     -H "Date: Fri, 05 Jul 2024 15:52:17 GMT" \
     -H "Authorization: BalanceAPIAuth 93G9toV9KxgDisd9p:b86e3ffdf6b814f180c1d37bad328b2e241d90db747e98f44fd86a24e02b6fed" \
     https://your_custom_subdomain.balancecustody.ca/api/v1/wallets

You can then copy the above curl command and paste it in your shell. This request will be valid for 15 minutes, provided that you specified correct parameters.

Postman

In addition to the Ruby helper, you can use the following JavaScript snippet in Postman to automate HMAC authentication.

Before running requests, make sure your Postman Environment includes the following variables:

  • accessId – your API access ID from Balance

  • secretKey – your API secret key from Balance

  • userAgent – a custom string to help identify your integration (e.g., my-client-prod)

Paste the contents of postman_helper.js into the Pre-request Script tab of your Postman request or collection

Make sure to include the following headers in your request: Content-Type, Authorization, Date, and User-Agent. These should be added to the Headers tab in Postman using the environment variables defined by the pre-request script:

Content-Type: {{contentTypeHeader}}  
Authorization: {{authorizationHeader}}  
Date: {{dateHeader}}  
User-Agent: {{userAgentHeader}}  
PreviousIntroductionNextV1

Last updated 1 month ago

2KB
hmac_auth_helpers.rb
1KB
postman_helpers.js