Metre Client API

OpenAPI-ready security guide

Metre Client API layers RSA + AES + HMAC on top of standard OpenAPI endpoints. This documentation walks through the integration guide, describes the security protocol, and explains the core workflows implemented in the `examples/cpp-client` code base.

100%

OpenAPI™

Standards compliant

C++ / Go / JS

Client SDKs

Generate instantly

Resilient

Heartbeat

Replay-safe tokens

Overview

The Metre Client API is designed for OpenAPI-first adoption while enforcing an encrypted handshake. Every critical POST request encrypts the payload with RSA-OAEP-SHA256 + AES-256-GCM, signs it with HMAC-SHA256, and bundles the membership information (token/expiresAt) inside a signed response that both client and server verify.

Security Protocol

Required headers

  • Content-Type: application/json
  • Authorization: Bearer <token>
  • X-Metre-Timestamp: UNIX seconds

Encrypted payload

{
  "appId": 1,
  "data": "BASE64_AES_GCM_ENCRYPTED",
  "signature": "HEX_HMAC_SHA256",
  "timestamp": 1708000000
}

Encryption steps

  1. Serialize the business payload to JSON, chunk it into at most 190 byte segments, and encrypt each chunk using RSA-OAEP-SHA256. Join the Base64 segments with colon separators.
  2. Build the string signData = {appId}{plain}{timestamp} and HMAC-SHA256 it with the app secret; send the hex digest as `signature`.
  3. Send both `data` and `signature`. The server decrypts first and then verifies the signature.

Signed response

{
  "code": 0,
  "data": {
    "data": "{"token":"...","expiresAt":...}",
    "signature": "HEX_HMAC"
  }
}

Compare `HMAC-SHA256(data.data, appSecret)` to `data.signature`. Only after the match should you trust the token + expiresAt fields.

Workflows

1. Fetch RSA public key

Call `GET /api/client/apps/{appId}/info` to retrieve the RSA-2048 public key, AES key, and HMAC secret used for all downstream requests.

2. Encrypted login + HMAC

For `POST /api/client/auth/login`, AES-256-GCM encrypt the payload and include an HMAC-SHA256 signature over `appId + plain + timestamp` to prevent tampering. The endpoint supports both account login (`email/password`) and card login (`mode=card` + `key/code` + `deviceId`), and the app-level `security_settings.login_mode` controls which path is enabled.

3. Verify membership signature

The server responds with `data.payload` (containing token/expiresAt/membership). Clients must verify its HMAC signature using the shared app secret before trusting membership data.

SDK Implementation Guide

Refer to examples/cpp-client/main.cpp for real code. Reuse the RSA+AES+HMAC steps and validate the signed membership before calling `challenge`, `heartbeat`, `recharge`, or `announcement`.

def make_client_request(payload, public_key, app_secret, app_id):
    timestamp = int(time.time())
    encrypted = rsa_encrypt(json.dumps(payload), public_key)
    sign_data = f"{app_id}{json.dumps(payload)}{timestamp}"
    signature = hmac.new(app_secret.encode(), sign_data.encode(), hashlib.sha256).hexdigest()
    return {
        "appId": app_id,
        "data": encrypted,
        "signature": signature,
        "timestamp": timestamp,
    }

Additional Details

Challenge & Heartbeat

POST `/api/client/auth/challenge` to receive a program, execute it to compute a result, and submit `heartbeat` with `X-Metre-Challenge-Id` and `X-Metre-Challenge-Result` headers to keep the token alive.

Recharge

POST `/api/client/auth/recharge` consumes a metre card (card key). The request requires a valid token; the server signs the updated membership in the response.

Announcement / Variables

These endpoints deliver notices and runtime variables to clients; calls must include a membership-backed token.

OpenAPI Registry

Document the encrypted payload format alongside OpenAPI specs so SDK generators and teams understand the client handshake.