Skip to main content

Authentication errors

401 Unauthorized

Cause: Missing or invalid API key.
{ "error": "Unauthorized" }
Fix:
  • Check your key is set: zam config show
  • Verify the key works: zam api-keys list
  • If expired, create a new one: zam api-keys create
  • If you lost all keys, recover your account: zam wallet recover

403 Forbidden — insufficient scope

Cause: Your API key doesn’t have the scope required for this operation.
{ "error": "Forbidden", "message": "API key lacks required scope: order:create" }
Fix: Create a new key with the right scopes:
OperationRequired scope
Activate a listingorder:create
View ordersorder:read
Create a providerprovider:create
Manage listingslisting:create, listing:update, etc.
Manage API keysapi_key:create, api_key:read, etc.
zam api-keys create
# Select the scopes you need from the checklist

Order errors

400 — input validation failed

Cause: Your requestBody doesn’t match the listing’s inputSchema.
{ "error": "Bad Request", "message": "Validation failed: city is required" }
Fix: Check the listing’s input schema before activating:
zam search --show-schema
# Find the listing and check its inputSchema

422 — no run contract

Cause: The listing exists but has no endpoint configured. Fix: This listing can’t be activated. Choose a different listing, or contact the seller.

429 — rate limit exceeded

Cause: The seller has set invocation limits on their provider and the limit has been reached. Fix: Wait and try again later. The seller controls these limits.

Provider creation errors

Review rejection — endpoint unreachable

Endpoint unreachable (HTTP 404)
Cause: ZAM couldn’t reach your /run endpoint during review. ZAM sends a HEAD request (falling back to GET) to verify reachability. Fix: Your /run endpoint must respond to HEAD and GET with a 200 status:
if (url.pathname === "/run") {
  if (request.method === "HEAD" || request.method === "GET") {
    return new Response(null, { status: 200 });
  }
  // ... handle POST
}

Review rejection — HTTPS required

Cause: Your endpoint URL uses http:// instead of https://. Fix: Deploy to a platform that provides HTTPS (Cloudflare Workers, Vercel, etc.), or add an SSL certificate.

Review rejection — content flagged

Cause: Automated content screening flagged your provider’s title or description. Fix: Check reviewRejectionReason for details:
zam providers get <provider-id>
Update the provider and it will go through review again.

Invalid contract format

Invalid contract response: listing.price.currency: Invalid input
Cause: Your /contract endpoint returns the wrong price format. Fix: Use the correct format:
{
  "provider": {
    "price": { "currency": "USD", "amountCents": 100, "unit": "call" }
  }
}
Common mistakes:
  • {"amount": 100, "unit": "cents"} — wrong fields
  • Missing currency: "USD" — required

Signing secret errors

Missing ZAM headers (401)

Cause: A request reached your service without X-ZAM-Signature and X-ZAM-Payload headers. Possible reasons:
  • Someone is calling your endpoint directly (not through ZAM)
  • The provider doesn’t have a signing secret yet
Fix: Generate a signing secret if you haven’t:
zam listings get-secret <provider-id>

Invalid signature (401)

Cause: The HMAC signature doesn’t match. Possible reasons:
  • Wrong signing secret in your environment
  • Secret was rotated but your service still has the old one
Fix:
# Check which secret ZAM expects
zam listings get-secret <provider-id>

# Update your service's secret
npx wrangler secret put ZAM_SIGNING_SECRET

Request timestamp expired

Cause: The request is older than 5 minutes (default maxAgeSeconds in zam-verify). Possible reasons: Your server’s clock is significantly out of sync, or a request was replayed. Fix: Sync your server’s clock. If you need a longer window, configure maxAgeSeconds:
verifyZamRequest({
  ...opts,
  maxAgeSeconds: 600, // 10 minutes
});

CLI errors

”No API key configured”

Fix:
# Create a new account
zam wallet create

# Or set an existing key
zam config set-key zam_your_key_here

“Challenge not found or already used”

Cause: The proof-of-work challenge expired (60-second TTL) or was already used. Fix: Run zam wallet create again — it fetches a fresh challenge.

Activation timeout

Cause: The seller’s service took longer than the CLI timeout (default 10 seconds). Fix: Use a longer timeout or check the order manually:
# Longer timeout
zam activate LISTING_ID --timeout 60

# Check existing order
zam orders get ORDER_ID