Skip to main content

API key authentication

Send your developer API key on every authenticated request using either header:
curl https://mcp.echozero.app/api/v1/users/me \
  -H "x-api-key: ez_live_..."
curl https://mcp.echozero.app/api/v1/users/me \
  -H "Authorization: Bearer ez_live_..."
Create and revoke keys in the Dev Portal. Each key has scoped permissions - request only the scopes your integration needs.

Common scopes

ScopeTypical use
read:agents / write:agentsAgent CRUD, webhook provisioning
read:strategies / write:strategiesStrategy configuration
read:wallet / write:walletBalances, virtual mode
read:tradesTrade and signal history
read:earnEarnings and claims

Optional REST HMAC signing

For server-to-server integrations, sign requests with the API secret returned when the key was created. HMAC is opt-in: when x-signature is omitted, verification is skipped.
HeaderDescription
x-api-keyYour API key id (ez_live_...)
x-signatureHMAC-SHA256(secretKey, stringToSign) as lowercase hex
x-timestampEpoch milliseconds; rejected if drift exceeds 5 minutes

String to sign

stringToSign = timestamp + METHOD + path + body
  • METHOD - uppercase HTTP verb (GET, POST, …)
  • path - full request path including query string (e.g. /api/v1/developers/earnings)
  • body - raw JSON string for POST/PUT/PATCH, or empty string when there is no body
REST HMAC uses milliseconds and includes the HTTP method and path. This is different from inbound agent webhook signing, which uses seconds and canonical JSON only.

curl example (GET)

API_KEY="ez_live_..."
SECRET="ezs_..."   # secret shown once at key creation
TS=$(date +%s%3N)
REQ_PATH="/api/v1/users/me"
SIG=$(printf '%s' "${TS}GET${REQ_PATH}" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

curl -sS "https://mcp.echozero.app${REQ_PATH}" \
  -H "x-api-key: $API_KEY" \
  -H "x-timestamp: $TS" \
  -H "x-signature: $SIG"

curl example (POST)

API_KEY="ez_live_..."
SECRET="ezs_..."
TS=$(date +%s%3N)
REQ_PATH="/api/api-keys"
BODY='{"name":"HMAC Test Key"}'
SIG=$(printf '%s' "${TS}POST${REQ_PATH}${BODY}" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

curl -sS -X POST "https://mcp.echozero.app${REQ_PATH}" \
  -H "x-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-timestamp: $TS" \
  -H "x-signature: $SIG" \
  -d "$BODY"

Python (echozero-sdk)

import os
from echozero import EchoZeroClient

client = EchoZeroClient(
    api_key=os.environ["EZ_API_KEY"],
    hmac_secret_key=os.environ["EZ_SECRET_KEY"],
)
me = client.get("/api/v1/users/me", hmac=True)
print(me)
Pass hmac=True on each request to sign it, or omit when HMAC is not needed.

TypeScript (echozero-sdk)

import { EchoZeroClient } from '@echozero/sdk';

const client = new EchoZeroClient({
  apiKey: process.env.EZ_API_KEY!,
  hmacSecretKey: process.env.EZ_SECRET_KEY,
});

const me = await client.get('/api/v1/users/me', { hmac: true });
Or sign manually with signRestRequest:
import { signRestRequest } from '@echozero/sdk';

const headers = await signRestRequest({
  secretKey: process.env.EZ_SECRET_KEY!,
  method: 'GET',
  path: '/api/v1/users/me',
});
// headers['x-timestamp'], headers['x-signature']

HMAC error responses

ConditionHTTPMessage
x-signature present, no x-timestamp401Missing x-timestamp header
Non-numeric timestamp401Invalid x-timestamp value
Timestamp > 5 min drift401Request timestamp expired
Wrong signature401Invalid HMAC signature
Key has no secret401API key does not support HMAC signing

MCP authentication

API keys (with optional HMAC) work on POST https://mcp.echozero.app/mcp the same way as REST. Send x-api-key or Authorization: Bearer on every MCP call, including initialize. See the MCP Server guide.