Authentication
Cloven supports two distinct authentication paths. They cover every deployment shape we have seen: humans clicking through a console, server-side agents pulling fresh context, and fully autonomous agents that no human ever logs into.
Mode 1 — Bearer API keys (credit-balance path)
A user-issued API key tied to a Supabase account and a prepaid credit balance. Use this when there is a human owner, when you want a dashboard with usage charts and key rotation, and when you want predictable cost from bulk credit packs.
Issuance
Open /console, claim your anonymous session with magic link or wallet, and click "New key". The key is shown exactly once, prefixed with cv_, then hashed with SHA-256 server-side. Cloven stores only the hash. If you lose the key, you must revoke and re-issue.
cv_<32 bytes of base62>The first 16 characters form the public keyId — safe to log. The rest is the secret. Cloven never displays the full key again after issuance.
Sending the key
All REST and HTTP MCP endpoints accept a standard Bearer header:
GET /v1/fresh?pack=crypto HTTP/1.1
Host: api.cloven.cloud
Authorization: Bearer cv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxFor stdio MCP (Claude Desktop, Cursor), put the key in the env block of your claude_desktop_config.json:
{
"mcpServers": {
"cloven": {
"command": "npx",
"args": ["-y", "@cloven/mcp"],
"env": { "CLOVEN_API_KEY": "cv_xxx" }
}
}
}The SDK reads the same env var by default, or accepts apiKey as a constructor argument.
Validation flow
On every authenticated request the middleware:
- Extracts the Bearer token, hashes it with SHA-256.
- Looks up the hash in the
api_keystable (RLS-bypassing service-role read). - Checks
revoked_atis null. - Returns an
ApiKeyContextwithkeyId,userId,tier,creditBalance, and the list of pack ids the key is subscribed to. - Hands off to the rate-limiter (free-tier: 100 calls/day sliding window in Redis) then to the credit debit gate (paid calls: decrements
credit_balancevia thedebit_creditsPostgres fn).
Invalid bearer → 401 invalid_token. Revoked key → 401 key_revoked. Quota exhausted → 429 quota_exhausted with Retry-After header. Insufficient credits → 402 insufficient_credits.
Mode 2 — x402 anonymous (agent-to-agent path)
Use this when an autonomous agent needs context and no human is in the loop to provision a key. The agent signs a USDC transfer on Base for the per-call price; Cloven verifies the transaction and serves the response. No account, no dashboard, no monthly bill.
Flow at a glance
- Agent calls
GET /v1/fresh?pack=cryptowith no auth header. - Cloven responds
402 Payment RequiredwithPaymentRequirements(recipient, amount, validUntil, nonce). - Agent signs a USDC
transferon Base for the quoted amount. - Agent retries the call with
x-payment: <base64-encoded payment proof>. - Cloven verifies the tx on-chain, caches the tx hash for 24h idempotency, and returns the
MindResponse.
Full wire format and verification rules: x402 protocol guide.
The SDK handles this dance automatically when constructed with a viem WalletClient instead of an API key — see the SDK x402 mode page.
Mode 3 — SSE token (subscription-only)
The EventSource browser API cannot set custom request headers. SSE subscriptions therefore accept the API key as a token query parameter:
GET /v1/subscribe?pack=crypto&token=cv_xxxThe token is validated identically to a Bearer header (same hash, same RLS, same rate-limit consume). Use the same value you would pass as Authorization: Bearer …. Treat the URL as secret; SSE tokens leak through server logs and HTTP proxies if not handled carefully.
x402 is not currently supported on SSE because we cannot prompt mid-stream for a fresh payment.
Credit deposits via USDC on Base
To fund a key's credit balance, open /console/credits in the console and select a pack (Starter / Hobby / Pro / Team). The UI creates a deposit intent and presents:
- The exact USDC amount to send and the Cloven treasury address on Base.
- A QR code encoding the EIP-681 payment URI for wallet-app scanning.
- An expires-in countdown (30-minute window).
Send the USDC transfer from any Base-compatible wallet. Once you have a tx hash, paste it into the "Submit tx hash" field for an immediate fast-path verify — or wait up to 60 seconds for the background cron to pick it up automatically.
On verification the deposits row flips to status = verified and your api_keys.credit_balance is incremented atomically. Credits are shared across all your non-revoked keys.
Deposits that receive no matching on-chain transfer within 30 minutes flip to status = expired. No charge applies. Re-open /console/credits to start a new deposit.
Tier-gated pack access
A key's packIds array determines which packs it can call. Free tier is restricted to ["crypto"]. Keys with a credit balance unlock every registered pack. Calling ?pack=ai from a free-tier key with no credit balance returns:
{
"error": {
"code": "pack_access_denied",
"message": "your key does not have access to pack 'ai'; buy a credit pack to unlock all packs",
"requestId": "req_abc123"
}
}Pack access is gated on credit balance, not a separate subscription toggle.
Credit balance and revocation
Revoking a key does not destroy its remaining credits — the credits stay on the row. If you re-issue a replacement key, transfer the balance manually via ops@cloven.cloud or buy a new pack on the replacement key.
Rotation + revocation
Revoke a key from /console. Revoked keys are rejected instantly (Redis cache invalidates within 60 seconds; Postgres lookup catches the rest). Issue a replacement before revoking if you care about uptime. Keys cannot be edited or "rotated" — the only safe rotation pattern is issue-new, deploy, revoke-old.