Authentication
One header, one key, every endpoint
Monocrawl authenticates with a single API key sent on each request. There are no OAuth flows, no per-platform credentials and no tokens to refresh.
The header
Send x-api-key on every request
The key goes in the x-api-key request header. This is the supported form on every route, including POST /v1/batch.
curl "https://www.monocrawl.com/v1/bluesky/profile?handle=bsky.app" \ -H "x-api-key: mn_your_key_here"
A key is a server-side credential. The /v1 API is not configured for cross-origin browser calls. Never ship a key in client code: call it from your server, an edge function or a scheduled job, and keep the key there.
A missing key and an unrecognised key both answer 401 UNAUTHORIZED; the details.reason field separates the two — missing_api_key or invalid_api_key. Neither costs credits. Repeated invalid-key attempts can instead receive 429 with reason invalid_key_attempts.
{
"success": false,
"error": {
"type": "UNAUTHORIZED",
"message": "API key is invalid or has been revoked.",
"status": 401,
"doc_url": "https://www.monocrawl.com/docs/errors#unauthorized",
"details": { "reason": "invalid_api_key" }
},
"credits_used": 0,
"request_id": "req_9c07b1e4da62f8a03d"
}Bearer
Authorization: Bearer, for header-restricted clients
Some clients only expose an Authorization field. The same key works there as a Bearer token on GET /v1, GET /sandbox and /mcp. POST /v1/batch requires x-api-key.
curl "https://www.monocrawl.com/v1/bluesky/profile?handle=bsky.app" \ -H "Authorization: Bearer mn_your_key_here"
Never in the URL
Keys are refused in the query string — URLs land in proxy logs, browser history and referrers, which is exactly where a credential must not live. A request relying only on ?api_key= answers 401 with reason query_string_key_rejected, so the mistake is caught loudly, not silently accepted.
Batch exception
Use x-api-key for POST /v1/batch. Bearer authentication is supported on GET /v1, GET /sandbox and the MCP server, not on batch.
Trying in a browser?
Use the Playground in the console — it runs real requests on your key without the key ever reaching the address bar.
Key format
What a key is made of
mn_4pQ8Zr1nKuT0aWxYb7cLdE3fGh9JmNpQsRtUvWxYz01
| Part | Value | Notes |
|---|---|---|
| Prefix | mn_ | Three fixed characters. Use them to spot a Monocrawl key in a config file or a secret scanner rule. |
| Body | 43 characters | 32 random bytes, base64url-encoded — the part that actually authenticates you. |
| Total length | 46 characters | New keys use this format. If yours differs, check that you copied the complete value. |
| Stored form | Hash + encrypted copy | A SHA-256 hash validates requests. New keys also have an encrypted copy for owner-only recovery; the console normally shows the prefix and last 4. |
Keys are masked by default, for example mn_4pQ8...Yz01. For new active keys, sign in and use Reveal or Copy on the API keys page. Older keys only have a hash and cannot be recovered. If you no longer have one, create a new key and revoke the old one.
Lifecycle
Creating and revoking keys
Your first key is provisioned for you: the first time you open the console overview with no key on the account, one is created server-side and revealed on that render. After that, keys are managed at /dashboard/api/keys — create, rename, revoke, delete (a revoked key stays revoked: create a new one). An account can hold up to five active keys, which is enough to separate production, staging and a laptop.
| Status | Behaviour |
|---|---|
| active | Authenticates. The only status that reaches the pipeline. |
| revoked | No longer authenticates or can be revealed. Revocation is permanent; create a new key instead. |
| deleted | Stops working and disappears from the console. The row is kept rather than erased, so your historic usage and invoices still reference a real key. There is no undo. |
Revocation takes effect on the next request — there is no cache to wait out. Deleting is a soft delete so that your usage history and invoices keep pointing at a real key row.
Per-key limits
Cap what one key can spend
Every key carries an optional credit_limit. When it is set, the pipeline reserves the call's cost against that key before spending your wallet, and refuses the request the moment credits_used + cost would exceed the cap:
402 KEY_LIMIT_EXCEEDED
The response carries credit_limit and credits_used in details, and charges 0 credits. Raise the cap or move the workload to another key.
Reserved atomically
The cap is enforced by a conditional update, so concurrent calls on one key cannot race past it — a burst of 50 requests cannot overshoot the limit.
Null means uncapped
Keys are created without a limit. An uncapped key can spend the whole account balance, which is what you want for a single production key.
Independent of the wallet
The limit is a per-key budget, not a separate balance. Credits still come out of one account-wide wallet.
Request limits follow your plan and apply both per key and across the account. Starter allows 600 requests a minute and 50 in flight per key; higher tiers increase both. Details in endpoint pricing, and the failure mode in errors.
Good practice
Keeping a key safe
01Server-side only
A key in browser JavaScript is a key you have published. Call Monocrawl from your backend and forward only what your users need.
02One key per environment
Separate keys make usage attributable — the console reports requests per key — and let you revoke staging without touching production.
03Environment, not source control
Read the key from an environment variable. The mn_ prefix makes it easy to write a pre-commit rule that catches the mistake.
04Rotate by overlap
Create the replacement, deploy it, confirm traffic has moved on the per-key request counts, then revoke the old key.