Developer documentation

API workspace
https://api.rentron.xyz/v1
OpenAPI schema

Authentication

// DOC

Production API

HMAC authentication

Exact headers, canonical payload, and stable HMAC-SHA256 test vectors.

On this page

Every endpoint except GET /v1/time requires HMAC-SHA256. The API secret is never transmitted; it signs a canonical request payload.

Required headers

Authorization: HMAC-SHA256 {api_key}:{base64_signature}
X-Request-Timestamp: {unix_seconds}

Requests with a body also require Content-Type: application/json.

Canonical payload

{timestamp}\n{METHOD}\n{path}\n{query}\n{bodyHash}

Rules:

  • uppercase METHOD;
  • path contains only the request path, such as /v1/energy/orders;
  • query is the exact transmitted query string including its leading ?, or empty;
  • bodyHash is the lowercase hex SHA-256 of the exact UTF-8 body bytes — and the empty string when the request has no body;
  • never reserialize JSON after signing it.

A request without a body signs an empty last segment. Do not hash the empty string: SHA-256("") is a fixed non-empty digest (e3b0c442…), so the server builds a different canonical payload than you did and rejects the signature. This applies to every GET and DELETE, and to a POST sent without a body.

So GET /v1/balance signs exactly this — five segments, the last one empty, and the string ends with a newline:

1784376000\nGET\n/v1/balance\n\n

The signature is base64(HMAC-SHA256(api_secret, canonical_payload)).

Node.js implementation

import crypto from 'node:crypto';

export function sign(secret, timestamp, method, path, query = '', body = '') {
  const bodyHash = body
    ? crypto.createHash('sha256').update(Buffer.from(body, 'utf8')).digest('hex')
    : '';
  const canonical = `${timestamp}\n${method.toUpperCase()}\n${path}\n${query}\n${bodyHash}`;
  return crypto.createHmac('sha256', secret).update(canonical, 'utf8').digest('base64');
}

Stable test vectors

Use timestamp 1784376000 and secret rtn_sk_live_0123456789abcdefghijklmnopqrstuvwxyzABCDEFG.

Request Expected signature
GET /v1/balance MAcY78Aad0bL9LGIJGMHR4plQ9jZH3TPUrYEJIMnSFY=
POST /v1/energy/orders with the body below 4+nngnu7C6PVGfCs3zPJ34PWylIZdkdNSw8wmoywnTk=
{"client_request_id":"order-1042","address":"TJRabPrwbZy45sbavfcjinPJC18kjpRTv8","energy":65000,"duration_minutes":60,"expected_total_trx":"3.200000"}

If a vector does not match, fix serialization, query handling, or newlines before sending production traffic.

Authentication failures

An invalid scheme, key, signature, timestamp, or IP allowlist returns 401 as Problem Details. Repeated failures can return 429; respect Retry-After.