Skip to content

Getting started

Authentication

API keys, permissions, budgets, expiry, idempotency and request ids.

Every request carries your API key as a bearer token:

header
Authorization: Bearer vmn_live_...

Missing, malformed, revoked or expired keys get a 401 unauthorized, for 0 credits.

API keys#

  • Keys belong to an organisation, not a person. Owners and admins can create, rotate and revoke them in Dashboard → API keys.
  • The full key is shown once at creation. We store only a SHA-256 hash, so we can't show it again. Lose it, rotate it.
  • Rotate issues a replacement key with the same name, permissions, budget and expiry, and revokes the old one, so roll out the new secret first. For a zero-downtime swap, create a second key, deploy it, then revoke the first. Revoke kills a key everywhere within about a minute.
  • Edit renames a key or changes its permissions, budget and expiry. Changes reach the API within about a minute.
  • The SDKs read VERMIN_API_KEY from the environment when you don't pass a key explicitly.

Permissions#

Keys have full access by default, including operations added later. A restricted key only gets the permissions (scopes) you tick:

ScopeAllows
runEvery call that spends credits (scrape, crawl, map, search, extract, brand, …) and cancelling crawls.
readReading crawl jobs: GET /v1/crawl/{id} and its /events stream. Free.

Anything else answers 403 forbidden, with a message naming the missing permission. The OpenAPI spec lists the scope each operation needs under security. A read-only key is handy for a dashboard or agent that watches crawls but must never start one.

Budgets#

Give a key a credit budget per UTC day, week or month (weeks start on Monday). A request that could take the key past its budget answers 402 insufficient_credits with a message saying how much is left, while your other keys keep working. The budget resets at the start of the next period. It's the best guard rail for keys you hand to agents, CI jobs or third parties: a leaked or runaway key can only spend its budget. Your organisation's spend cap still applies on top.

Expiry#

Keys can expire after 7, 30 or 90 days, or a year. An expired key answers 401 unauthorized, shows as expired on the keys page, and can be given a new expiry with Edit.

When an MCP client connects through sign-in, the consent screen lets you set a budget and expiry for its key too.

Playground keys#

The Playground doesn't ask for your real keys. When you open it, the dashboard mints a temporary key for your organisation: valid for one hour, one per person, capped at 20 requests a minute, 2 concurrent requests and 50 credits in total (after that the API answers 402 insufficient_credits for that key; mint a fresh one or use your own key), audited, and hidden from the keys page. It lives only in that browser tab. You can also paste one of your own keys if you want to test your real limits.

Idempotency#

POST /v1/scrape, POST /v1/crawl, POST /v1/search and POST /v1/extract accept an Idempotency-Key header (up to 255 characters). Retrying with the same key within 24 hours returns the original result (with an Idempotent-Replayed: true header) instead of doing, and charging for, the work again. Sending the same key while the first request is still running returns 409. The SDKs generate a key for you and reuse it across their own retries.

bash
curl -X POST https://api.vermin.dev/v1/crawl \
  -H "Authorization: Bearer $VERMIN_API_KEY" \
  -H "Idempotency-Key: nightly-docs-2026-09-28" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://docs.example.com","limit":500}'

Request ids#

Every response, success or failure, includes a request_id in the body and an X-Request-Id header. It's the fastest way to get help: paste it into a support message and we can see exactly what happened.

Base URL#

Production is https://api.vermin.dev. The SDKs accept a base URL option (baseUrl, base_url, :base-url) if you run against a local or self-hosted deployment.