Skip to content

HMAC Request Signing ​

Protected APIs require X-API-KEY, X-TIMESTAMP, X-NONCE, and X-SIGNATURE. The signature is Base64-encoded HMAC-SHA256 using the issued HMAC key.

text
METHOD\n\nPATH_WITH_QUERY\n\nTIMESTAMP\n\nNONCE\n\nBODY_JSON

Node.js example ​

js
import { createHmac, randomUUID } from 'node:crypto'

const hmacKey = process.env.WALLET_HMAC_KEY
if (!hmacKey) throw new Error('WALLET_HMAC_KEY is required')

const method = 'GET'
const pathQuery = '/networks?is_active=true&page=1&page_size=20'
const timestamp = String(Date.now())
const nonce = randomUUID()
const bodyJson = ''
const stringToSign = [method, pathQuery, timestamp, nonce, bodyJson].join('\n\n')
const signature = createHmac('sha256', hmacKey)
  .update(stringToSign)
  .digest('base64')

Sign the exact outgoing path, query order, encoding, timestamp, nonce, and serialized body. Generate new authentication values for every retry.

For GET and DELETE requests with an empty body, the \n\n separator between the nonce and the empty body remains part of the signature. Shell command substitution ($(...)) removes trailing newlines, so pipe printf output directly into the HMAC calculation instead of storing the canonical string in an intermediate variable. Serialize JSON without formatting whitespace using JSON.stringify or jq -c, then sign and send that string.

ErrorCorrective action
MISSING_AUTH_HEADERAdd the reported header
INVALID_API_KEYReplace or verify the environment key
INVALID_TIMESTAMPSynchronize system time
NONCE_REPLAYEDGenerate a new nonce
INVALID_SIGNATURERebuild the canonical string and signature

Never log the HMAC key or the complete authentication context.

POST body example ​

js
const bodyJson = JSON.stringify({
  uid: 'user-001', account_type: 'USER', metadata: { source: 'onboarding' }
})
const canonical = ['POST', '/accounts', timestamp, nonce, bodyJson].join('\n\n')

Pass bodyJson itself to the HTTP client. Do not let the client serialize the object a second time.

Test GET without body, GET with ordered query parameters, POST with nested JSON, Unicode metadata, an empty object, and a retry with new authentication fields. Use deterministic fixture keys only in tests and never copy production key material into a signing test.

OOLIN is a digital asset operations infrastructure product by BPMG.