INVALID_REQUEST
The request body was malformed, or a required field was missing or the wrong type.
Read `error.param` — it names the exact field. The message says what was expected.
An OpenAI-shaped HTTP API over an uncensored model and 1.3 million declassified documents. One model, no routing, no fallback chain. The status and type shown for every error are read from the same table the API answers with.
Base URL https://evilasf.com/api/v1. Authenticate with a bearer key from Settings → API. Keys look like inf_sk_live_… and are 51 characters.
curl https://evilasf.com/api/v1/models \ -H "Authorization: Bearer inf_sk_live_..."
A chat completion is one POST. The Idempotency-Key makes your retries safe on a metered endpoint; end_user is your own opaque id for the person behind the request.
curl https://evilasf.com/api/v1/chat/completions \
-H "Authorization: Bearer inf_sk_live_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"model": "infinet-uncensored",
"end_user": "customer-8f2c1a",
"stream": false,
"messages": [{"role": "user", "content": "Hello"}]
}'Send the key in the header and nowhere else. A key in a query string is refused outright — query strings are written to access logs, proxy logs and the Referer header, so a key that appears in one has to be treated as leaked.
Real requests against the live service. /status needs no key, so you can see a real response before you have an account.
Health, corpus version and document count. No key required.
Note — your key stays in this tab. It is not saved and it is sent only to evilasf.com, as an Authorization header. Do not paste a live key into anybody else’s playground.
curl https://evilasf.com/api/v1/status
What is serving today. Every endpoint on this list answers right now; nothing here is planned.
POST /chat/completionsMetered chat over the uncensored model. OpenAI-shaped: stream true or false, temperature, top_p, stop honored; everything else refused rather than ignored. Requires an Idempotency-Key header and an end_user field, and bills in credits by prompt-size band — the bands are in GET /models.GET /searchFree ranked retrieval over the archive. q, repeatable corpus, limit (1–20), highlight, signed cursor pagination. Three outcomes, never two: matched, no-match with a qualification that absence is not evidence, or a real error — an outage is never dressed as an empty page.GET /modelsThe one model this API serves, with the price bands and the assembled-prompt ceiling. Returns a single-element list, which is the honest description of a service with no picker and no routing.GET /keyYour limits, what you have used against them today, and the counts behind the two controls that can act on a key. Exists because otherwise “am I about to be rate limited?” is only answerable by getting rate limited.GET /usageLine items you can reconcile a bill against, including refunded, aborted and refused calls with their real credit values. ?from=, ?to=, ?granularity=day|request.GET /creditsBalance and the grant buckets behind it, each with its expiry — so a balance that drops overnight has an explanation that is not a support ticket.GET /statusUnauthenticated, on purpose: a notice about an outage is least useful when the outage is stopping people from authenticating.Rate-limit headers use OpenAI’s names so an existing client reads them with no shim. Ours carry an x-infinet- prefix.
x-ratelimit-remaining-requestsRequests left in the current window.x-ratelimit-scopekey or user. Worth reading: a user-scope 429 means another key on your account used the shared allowance, which is why your own count looked fine.x-infinet-request-idOn every response. Quote it in a support ticket.retry-afterInteger seconds, never an HTTP date. Present only where waiting actually helps.Errors are OpenAI-shaped, so an existing SDK parses error.type and error.message without a shim. Branch on error.code — the message is prose and will be reworded.
{
"request_id": "3f2a…",
"error": {
"type": "invalid_request_error",
"code": "UNSUPPORTED_PARAMETER",
"message": "n is not supported…",
"param": "n",
"doc": "https://evilasf.com/docs/api#unsupported_parameter"
}
}Retrieval errors additionally carry is_evidence_of_absence: false. That flag exists so your handler can assert that an outage is not a finding: an empty result and a failed query are different things, and on this archive the difference matters.
The request could not be understood. Retrying it unchanged will fail the same way.
INVALID_REQUESTThe request body was malformed, or a required field was missing or the wrong type.
Read `error.param` — it names the exact field. The message says what was expected.
MISSING_IDEMPOTENCY_KEYA billed request arrived without an Idempotency-Key header.
Send `Idempotency-Key: <uuid>`, generated once per logical request and reused on retries. Without it a network timeout can charge you twice.
UNKNOWN_MODELThe `model` field named a model this API does not serve.
Use `infinet-uncensored`. There is one model and no routing — `error.allowed` lists it.
UNKNOWN_CORPUSA corpus id in your request does not exist in the index.
Call GET /api/v1/corpora for the current list. Corpus ids change only when a corpus is added.
CURSOR_EXPIREDThe pagination cursor is older than 15 minutes, or the index changed underneath it.
Restart the search from the first page. Cursors are short-lived so a page 2 cannot silently answer from a different index than page 1.
CURSOR_INVALIDThe cursor failed its signature check, or it belongs to a different query.
Pass the `next_cursor` value back exactly as received. Do not construct, decode or edit one.
RESULT_DEPTH_EXCEEDEDYou paged past the maximum search depth.
Narrow the query. Beyond this depth relevance ranking stops being meaningful, and a corpus scan is a bulk-access conversation rather than a search.
QUERY_TOO_BROADThe query matched too much of the archive to rank inside the time budget.
This is not an outage — the archive is up. Add corpus= filters or more specific terms; a query matching most of a million documents has no meaningful ranking anyway.
Authentication. Every one of these carries a WWW-Authenticate header, except the control plane’s, which uses a session cookie.
MISSING_CREDENTIALSNo Authorization header was sent.
Send `Authorization: Bearer inf_sk_live_...`.
UNSUPPORTED_SCHEMEAn Authorization header was sent, but not as a Bearer token.
Use the Bearer scheme. Basic auth and a bare key are both refused.
CREDENTIALS_IN_QUERYA key was found in the query string. It is refused even alongside a valid header.
Treat that key as leaked — query strings are written to access logs, proxy logs and the Referer header. Rotate it, then send the replacement in the Authorization header.
MALFORMED_KEYThe key is not a well-formed Evil ASF key. Its checksum did not match.
Almost always a truncated paste. Check the key is the full 51 characters before rotating it — the key itself is probably fine.
INVALID_API_KEYThe key is well-formed but is not one of ours.
Check you are not sending a test key to live, or a key from another account.
KEY_REVOKEDSomebody revoked this key.
Check your dashboard for who and when. If it was not you, an operator revoked it and will have been in touch.
KEY_EXPIREDThe key passed its expiry, or its rotation grace window closed.
Deploy the replacement key from the rotation. Distinct from KEY_REVOKED because nobody took an action — a date passed.
SESSION_REQUIREDA key-management endpoint was called without a signed-in session.
The control plane at /api/account/keys uses your browser session, not an API key. API keys deliberately cannot mint API keys.
Money. Terminal, never transient — retrying does not clear a 402, only a purchase or a reset does. This is why they are not 429.
INSUFFICIENT_CREDITSYour balance cannot cover this request. Nothing was charged and nothing was consumed.
Buy credits. This is 402 and not 429 on purpose — retrying will not clear it, only a purchase will.
DAILY_CAP_EXHAUSTEDThis key hit its daily credit cap. Your balance is untouched.
Wait for UTC midnight, or raise the cap on the key. The cap is per key, so another key on the account still works.
BALANCE_FROZENYour credit balance is frozen, usually because a payment is disputed.
The credits are held, not forfeited. Resolving the dispute unfreezes them — reply to the notification you were sent.
The key is valid; the permission is not.
INSUFFICIENT_SCOPEThe key is valid but does not carry the scope this endpoint needs.
`error.required_scope` names it and `error.granted_scopes` lists what you have. Scopes are set at key creation.
SCOPE_UNAVAILABLEThe scope you asked for cannot be granted yet.
Create the key with the scopes that are available; adding the missing one later needs no new key.
SUBSCRIPTION_REQUIREDThe account behind this key has no active subscription.
Restore the card on file. Purchased API credits keep working — this gate is about the plan, not the balance.
ACCOUNT_SUSPENDEDThe account is suspended.
Suspension is reversible and your balance is frozen rather than forfeited. Reply to the notification.
CONTENT_REFUSEDThe request asked for one of the only two things this API refuses: sexual content involving a minor, or sexual content depicting a real identifiable person.
The published floor is at /api-terms#the-floor. This call was billed — screening it did the work. Three refusals on one key in 24 hours suspends the key.
END_USER_FROZENThe end_user this request is attributed to has been frozen for abuse.
Your account and your other end users are unaffected — stop routing this one. You were notified with the evidence and have 72 hours to contest; reply to that notification.
BULK_ACCESS_REQUIREDYou crossed the monthly distinct-document ceiling for your tier.
That volume is a mirroring arrangement rather than a bigger plan. Get in touch and we will talk about a contract.
The route does not exist, or the resource is not yours. Those are deliberately the same answer.
NOT_FOUNDThe route does not exist, or the resource is not yours.
On the control plane these are deliberately the same answer — telling you a key id exists but belongs to somebody else would confirm it exists. A missing document is a 200 with a status, never this.
A conflict with something already in flight or already recorded.
REQUEST_IN_FLIGHTThis Idempotency-Key is currently being served by another request.
Wait and retry with the same key. You will get the original result rather than a second charge.
IDEMPOTENCY_KEY_EXPIREDThe key is known but its stored result has aged out.
Use a new Idempotency-Key. The bill is permanent; the stored response body is not.
GROUNDING_UNAVAILABLEour sideRetrieval was requested but the archive could not answer.
Retry shortly. Nothing was charged, and this is explicitly NOT evidence that no records exist.
CORPORA_VERSION_UNAVAILABLEYou pinned a corpus version that is no longer served.
Drop the pin or move to the current version from GET /api/v1/status.
KEY_LIMIT_REACHEDThe account is at its live-key ceiling for its tier.
Revoke a key you are not using. Rotation also needs one spare slot, since both halves are live during the grace window.
KEY_ALREADY_CREATEDA key was already created with this Idempotency-Key, and its secret cannot be shown again.
Delete that key using the `delete_path` in the response, then retry with a fresh Idempotency-Key. The plaintext is unrecoverable by construction, so no retry can return it.
Too large to serve at any price.
REQUEST_TOO_LARGEThe assembled prompt is over the ceiling the price list rests on.
Refused rather than truncated — a silent truncation is an answer to a question you did not ask. Shorten the prompt or retrieve fewer documents.
Understood, and refused rather than partially honoured.
IDEMPOTENCY_KEY_REUSEDThis Idempotency-Key was used before with a different request body.
Generate one key per logical request. Reusing one across different bodies is how a retry returns somebody else’s answer.
UNSUPPORTED_PARAMETERYou sent a parameter this API does not implement. It is refused rather than ignored.
`error.param` names it. Ignoring it would change your cost or remove a control without telling you — `n` would make your cost model wrong, `seed` would make you cache on output that is not reproducible.
Genuinely transient. Both carry retry-after, and waiting really does clear them.
RATE_LIMIT_EXCEEDEDYou exceeded a requests-per-minute limit.
Back off for `retry-after` seconds. Check `x-ratelimit-scope` — a `user` scope means another key on your account used the shared allowance, which is why your own count looked fine.
CONCURRENCY_LIMITEvery concurrent stream slot for this key is in use.
Wait for one to finish, or raise concurrency by moving up a tier. GET /api/v1/key reports how many are held.
Ours.
SERVER_ERRORour sideSomething broke on our side.
Retry. Quote `request_id` if it keeps happening — it is how we find the exact call.
CORPUS_PROFILE_MISSINGour sideA corpus in scope has no provenance profile, so we cannot describe what its absence means.
Ours to fix, and deliberately loud: answering without it would let a gap in our index read as a fact about the record.
Ours, upstream.
UPSTREAM_ERRORour sideThe inference provider returned an error.
Retry. Your credits were refunded if nothing was generated.
Ours, capacity. You were inside your published limit.
ARCHIVE_UNAVAILABLEour sideThe document index is not answering.
Retry after `retry-after`. This is NOT evidence of absence — an empty result and a failed query are different things and this says which one happened.
UPSTREAM_UNAVAILABLEour sideWe are at capacity, or the provider is.
Back off for `retry-after`. This is 503 rather than 429 on purpose: you were inside your published limit and we ran out of supply. Nothing is wrong with your integration.
SERVICE_UNCONFIGUREDour sideThe API is missing configuration it needs to serve requests safely.
Ours, and it refuses rather than falling back to a weaker path. Retry shortly.
CHAT_DISABLEDour sideThe chat endpoint is not currently serving.
GET /api/v1/status reports whether chat is ready. Retrieval endpoints are unaffected.
Ours, upstream timeout.
UPSTREAM_TIMEOUTour sideThe inference provider did not respond in time.
Retry. If you were streaming, anything already delivered was billed and the rest refunded.