Skip to main content

Auth Requirements By Endpoint Type

  • GET /external-api/...: Authorization: Bearer <org_api_key>
  • PATCH /external-api/...: Authorization + X-Cora-Timestamp + X-Cora-Signature

API Key Format

Expected bearer token format:
cora_org_<keyId>.<secret>
Use the full value in Authorization. The <secret> portion is used for HMAC signing.

Timestamp Window

  • X-Cora-Timestamp must be within 5 minutes of server time.
  • Seconds or milliseconds are accepted.

PATCH Signature Algorithm

For each PATCH request:
  1. Build rawBody as the exact JSON string sent.
  2. Compute bodyHash = sha256(rawBody) as hex.
  3. Build canonical payload:
<timestamp>.<METHOD_UPPER>.<path_with_query>.<bodyHash>
  1. Compute signature:
HMAC_SHA256_HEX(secret, canonical_payload)
  1. Send it as X-Cora-Signature.
path_with_query must match the actual request path exactly.

Node.js Signing Example

import crypto from "crypto";

function sha256Hex(value: string) {
  return crypto.createHash("sha256").update(value).digest("hex");
}

function hmacHex(secret: string, payload: string) {
  return crypto.createHmac("sha256", secret).update(payload).digest("hex");
}

function parseApiKey(apiKey: string) {
  const token = apiKey.startsWith("cora_org_") ? apiKey.slice("cora_org_".length) : apiKey;
  const dot = token.indexOf(".");
  if (dot < 0) throw new Error("Invalid API key format");
  return {
    keyId: token.slice(0, dot),
    secret: token.slice(dot + 1),
  };
}

function buildPatchHeaders(args: {
  apiKey: string;
  secret: string;
  pathWithQuery: string;
  rawBody: string;
}) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const canonical = `${timestamp}.PATCH.${args.pathWithQuery}.${sha256Hex(args.rawBody)}`;
  const signature = hmacHex(args.secret, canonical);

  return {
    Authorization: `Bearer ${args.apiKey}`,
    "X-Cora-Timestamp": timestamp,
    "X-Cora-Signature": signature,
    "Content-Type": "application/json",
  };
}

Auth Error Codes

  • MISSING_AUTH_HEADER: Missing Authorization on API-key-auth endpoint
  • MISSING_AUTH_HEADERS: Missing one or more required PATCH auth headers
  • INVALID_API_KEY: Key invalid, revoked, or not found
  • REQUEST_TIMESTAMP_OUTSIDE_WINDOW: Timestamp outside allowed skew
  • INVALID_REQUEST_SIGNATURE: Signature does not match request payload
  • API_KEY_ORG_MISMATCH: Key does not belong to :organizationId
  • AUTH_CHECK_FAILED: Internal auth verification failure