faucet
Request access
Reference

Endpoints

Every endpoint Faucet serves, which credential authenticates it, and what it answers with.

Everything below is reachable at https://api.intfaucet.com. Two endpoints are public; the rest take a key in Authorization: Bearer.

Inference

EndpointNotes
POST /v1/chat/completionsStreaming and non-streaming, every chat provider. See Chat
POST /v1/messagesAnthropic's native format. anthropic/* chat models only
POST /v1/messages/count_tokensAnthropic's native token count. Admitted and metered at zero — the one deliberately free operation
POST /v1/embeddingsNever streamed. See Embeddings
POST /v1/images/generationsNever streamed. See Images
POST /v1/images/editsJSON or multipart/form-data
POST /v1/audio/transcriptionsmultipart/form-data only. See Transcription

A model answers on one endpoint. Sending it to another is a 400 naming the endpoint that would have worked — not a 404, because the slug is fine. See Choosing a model.

Catalog

EndpointNotes
GET /v1/modelsYour catalog, filtered to what this key can reach. Exactly OpenAI-shaped
GET /v1/models/{id}Accepts a slug or an alias and echoes the canonical slug, plus a faucet capability block

GET /v1/models is narrower than the Models reference: it applies the key's allowlist and skips providers holding no usable credential, so it never advertises a model that would 403 or 503 on use.

The detail route answers 404 when the model is not carried, is outside your key's allowlist, or has no usable credential — one answer for all three, because distinguishing them would confirm which model ids exist. What the faucet block contains is on Model capabilities.

Money and credentials

EndpointCredentialNotes
GET /v1/creditsinference keyThe organization's live credit. available is what the next request is judged against
GET /v1/keyinference keyWhat the presenting key is allowed, and its own spend this month
DELETE /v1/keyinference keyRevoke the presenting key. Names no id; idempotent
POST /v1/management/keysmanagement keyMint an inference key
GET /v1/management/keysmanagement keyThis organization's keys
GET /v1/management/keys/{id}management keyIts limits, plus spend_this_month_micros
PATCH /v1/management/keys/{id}management keyChange a plan
DELETE /v1/management/keys/{id}management keyRevoke

Neither credential works where the other does

A management key (fct_mgmt_…) is refused at every inference endpoint, and an inference key is refused on /v1/management/*. A key that leaks from a subscriber's machine can spend its budget and cannot mint more. See Management keys.

/v1/credits and /v1/key are not rate-limited or metered. A key with nothing left must still be able to ask what it is allowed — admitting there would refuse the one request whose purpose is explaining a refusal.

The two routes answer different questions, and the difference matters under a reseller: /v1/credits reports the organization's balance, which under a reseller holds every subscriber and is the reseller's commercial information. /v1/key reports only the presenting key's own budget and spend, which is what a subscriber may see. Both are scoped to the key that calls them, so the worst a stolen key learns is the allowance of the credential the thief already has.

Public, unauthenticated

EndpointNotes
GET /healthThat this process is alive. A constant; touches no database
GET /statusWhether the gateway is working, per provider

These are not interchangeable. /health is what liveness probes watch — a liveness check that read the database would turn a database blip into a restart loop. /status reads recent traffic, so it can be slow or fail without anything being restarted.

/status is the only endpoint that answers cross-origin, and deliberately: its payload is public, identical for every caller, and sent with no credentials. Nothing under /v1 is callable from a browser, because a Faucet key is a server-side credential.

{
  "status": "ok",                  // or "degraded"
  "windowMinutes": 30,
  "providers": [
    {
      "slug": "anthropic",
      "status": "ok",              // ok · degraded · unknown
      "sample": "normal",          // none · low · normal
      "reportedStatus": "operational",
      "statusPage": "https://status.anthropic.com"
    }
  ]
}
FieldMeaning
statusok or degraded, across every provider
windowMinutesHow far back the observed verdict looks
providers[].statusok, degraded or unknown for one provider
providers[].samplenone, low or normal — how much traffic the verdict rests on
providers[].reportedStatusThe provider's own published report, or null
providers[].statusPageWhere to read that report yourself, or null

Three things about that payload:

  • It never reports request counts or model slugs. sample buckets how much traffic a verdict rests on without saying how much; low is what stops you trusting a degraded off a handful of requests.
  • Observed health wins. A provider's own report changes the aggregate only when the observed sample is empty. A failed or unreadable provider feed is null, never a degradation.
  • unknown alone is not degraded. The top-level status is degraded when a provider is observed degraded, or is unknown and independently reports a problem.

Errors

Errors follow the dialect of the endpoint: Anthropic's envelope on /v1/messages and its token-counting route, OpenAI's { "error": { "message", "type", "param", "code" } } everywhere else — transcription included. Status meanings, the three 402 scopes and your allowance are on Errors and limits.