Skip to content

Authentication

Get a key

In studio → API keys, pick a hub and generate a key. You receive:

  • clientId — public, e.g. 0xb_live_ab12…. Goes in the x-api-key header.
  • secret — shown once. Store it server-side. Used only to sign writes.

Warning

The secret is displayed a single time and never again. If you lose it, revoke the key and mint a new one. Never expose the secret in browser code.

Reads — public key only

Send the clientId in x-api-key:

curl https://vectorlabz.io/api/v1/hub/aevon/leaderboard?limit=10 \
  -H "x-api-key: 0xb_live_ab12..."

This is safe to call from a browser (CORS is enabled).

Writes — HMAC signature

Write requests (POST /hub/{slug}/bits/earn) additionally require a signature that proves you hold the secret without sending it.

Signing key = sha256(secret) (hex). This is also what the server stores, so it can verify without ever seeing the raw secret.

Payload to sign:

{timestamp}.{METHOD}.{path}.{rawBody}

Headers to send alongside x-api-key:

Header Value
x-api-timestamp Unix seconds. Must be within ±300s of server time.
x-api-signature HMAC-SHA256(key = sha256(secret), payload), hex.

Reference implementation (Node)

import { createHash, createHmac } from "node:crypto";

function signedHeaders({ clientId, secret, method, path, body }) {
  const ts = String(Math.floor(Date.now() / 1000));
  const signingKey = createHash("sha256").update(secret).digest("hex");
  const payload = `${ts}.${method.toUpperCase()}.${path}.${body}`;
  const sig = createHmac("sha256", signingKey).update(payload).digest("hex");
  return {
    "x-api-key": clientId,
    "x-api-timestamp": ts,
    "x-api-signature": sig,
    "content-type": "application/json",
  };
}

const path = "/api/v1/hub/aevon/bits/earn";
const body = JSON.stringify({ wallet: "So1...", kind: "engage:post", ref: "post-123" });

await fetch("https://vectorlabz.io" + path, {
  method: "POST",
  headers: signedHeaders({ clientId, secret, method: "POST", path, body }),
  body,
});

Note

The ref field makes an award idempotent — replay the same signed request (or pass the same ref) and the points are awarded only once. Use it for end-to-end safety across retries.

Replay & timestamp window

A signed request is valid for ±300 seconds. Sign right before you send. If you batch or queue writes, sign each one at send time, not enqueue time.