Celon

API Reference

API reference

Every endpoint the gateway actually serves. The base URL is https://api.celon.ai (http://localhost:8787 for local dev), and authentication uses the Authorization: Bearer <key> or x-api-key header. GET /v1/models and GET /v1/endpoints are open without a key; the self-serve console (/v1/me) authenticates with a Supabase session token, and admin endpoints with CELON_MASTER_KEY.

Error format

Every error is returned in an OpenAI-compatible envelope. If an upstream error occurs mid-stream, the same error object shape is delivered as SSE data.

error.json
{
  "error": {
    "message": "Monthly budget exceeded",
    "type": "insufficient_quota",
    "code": "budget_exceeded"
  }
}
StatuscodeMeaning
400The body is not JSON, or a required field is missing
400guardrail_violationBlocked by a guardrail — a block-mode violation or a banned word (action: block) was detected
401invalid_api_keyKey missing, invalid, or disabled
402budget_exceededMonthly budget exceeded (organization, team, or key reject policy)
403model_blockedRequested a model blocked by the organization or key model policy
403master_key_requiredCalled an admin endpoint with a regular key
404model_not_foundA model id not in the catalog
502upstream_unavailableEvery candidate in the fallback chain failed

POST /v1/chat/completions

OpenAI-compatible chat completions. OpenAI parameters not listed in the table below are passed through the adapter unchanged, without validation.

FieldTypeDescription
modelstring · requiredcelon/auto · celon/code · celon/quality · celon/nitro · celon/floor · a catalog id (vendor/model)
messagesMessage[] · requiredOpenAI chat format. Supports text and image_url content parts
temperaturenumberPassed through to the upstream. Must be ≤ 0.3 to be cacheable (see Caching)
top_p · stop · presence_penalty · frequency_penalty · seed · userpassthroughPassed through to the upstream
max_tokens / max_completion_tokensnumberOutput token cap
streambooleanSSE streaming (see the format below)
tools · tool_choiceobjectFunction calling — excludes the request from caching, and signals structured output to the classifier
response_formattext | json_object | json_schemaStructured output — factored into the classifier score
celonobjectRouting/cache options — dial, anchor, session_id, context_compression, tier, no_cache, no_pii_mask, fallbacks (see Smart routing)
terminal
curl https://api.celon.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-celon-…" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "celon/auto",
    "messages": [{ "role": "user", "content": "Hello!" }],
    "temperature": 0.2,
    "stream": false
  }'

The response carries a celon metadata field and x-celon-* headers (x-celon-model · x-celon-tier · x-celon-cache · x-celon-dial · x-celon-sticky · x-celon-guardrail-findings, and more) — for the full header table and field definitions, see Response metadata.

SSE streaming format

With stream: true, OpenAI-compatible chunks are delivered as text/event-stream. The final data chunk has an empty choices array and carries the usage and celon metadata, followed by data: [DONE] to terminate.

event-stream
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1750000000,"model":"meta-llama/llama-4-maverick","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1750000000,"model":"meta-llama/llama-4-maverick","choices":[{"index":0,"delta":{"content":"Hi there"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1750000000,"model":"meta-llama/llama-4-maverick","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","created":1750000000,"model":"meta-llama/llama-4-maverick","choices":[],"usage":{"prompt_tokens":21,"completion_tokens":96,"total_tokens":117},"celon":{"model":"meta-llama/llama-4-maverick","provider":"deepinfra","tier":2,"classifier_score":0.41,"cache_hit":null,"cost_usd":0.000122,"saved_usd":0.003886,"latency_ms":842,"pii_masked":0,"attempts":[],"dial":"balanced","sticky":false,"guardrails":{"mode":"mask","findings":0,"blocked":false}}}

data: [DONE]

POST /v1/embeddings

OpenAI-compatible embeddings. model defaults to openai/text-embedding-3-small when omitted, and accepts both catalog ids and raw OpenAI names (text-embedding-3-large). input is a string or string[]. The response's celon field carries provider · cache_hit · cost_usd · latency_ms.

terminal
curl https://api.celon.ai/v1/embeddings \
  -H "Authorization: Bearer sk-celon-…" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/text-embedding-3-small",
    "input": ["first sentence", "second sentence"]
  }'

POST /v1/images/generations

OpenAI-compatible image generation. model defaults to openai/dall-e-3 when omitted, and accepts prompt (required), n (≤ 10), size, quality, style, and response_format. The prompt goes through the same guardrail input checks as chat, and a block-mode violation is rejected with 400 guardrail_violation. Billing is per call, not per token — perCallUsd × n. The response's celon metadata carries model · provider · cost_usd · latency_ms.

terminal
curl https://api.celon.ai/v1/images/generations \
  -H "Authorization: Bearer sk-celon-…" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/dall-e-3",
    "prompt": "Seoul at night, minimalist illustration",
    "n": 1,
    "size": "1024x1024"
  }'
response.json
{
  "created": 1750000000,
  "data": [{ "url": "https://…/img.png" }],
  "celon": {
    "model": "openai/dall-e-3",
    "provider": "openai",
    "cost_usd": 0.04,
    "latency_ms": 4120
  }
}

POST /v1/audio/transcriptions

OpenAI-compatible audio transcription (multipart/form-data). The form fields are file (required, the audio part), model (defaults to openai/whisper-1 when omitted), and language. Billing is by duration — the playback length is parsed directly from the audio container, rounded up to whole minutes (with a 1-minute floor), and multiplied by perCallUsd. If parsing fails, the request is not failed; it falls back to a bytes/32k estimate. The response's celon metadata carries the actual billed minutes (billed_minutes) and how the duration was determined (duration_source: "parsed" | "estimated").

terminal
curl https://api.celon.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer sk-celon-…" \
  -F file=@meeting.mp3 \
  -F model=openai/whisper-1 \
  -F language=ko
response.json
{
  "text": "Full meeting transcript…",
  "celon": {
    "model": "openai/whisper-1",
    "provider": "openai",
    "cost_usd": 0.012,
    "latency_ms": 1830,
    "billed_minutes": 2,
    "duration_source": "parsed"
  }
}

GET /v1/models

Returns the virtual models (celon/auto, celon/code, celon/quality, celon/nitro, celon/floor) and the full catalog. Each entry's celon metadata reports the tier, $/1M pricing, context window, modality, and whether it can currently be served (available — whether that provider's key is configured). This endpoint is public — it can be called without an API key, so the web catalog reads it directly from the browser.

terminal
# Public endpoint — no key required
curl https://api.celon.ai/v1/models
response.json (excerpt)
{
  "object": "list",
  "data": [
    /* celon/* package labels are served in Korean */
    { "id": "celon/auto",   "object": "model", "owned_by": "celon",
      "celon": { "tier": null, "pricing": null, "modality": "text", "available": true } },
    { "id": "celon/quality", "object": "model", "owned_by": "celon",
      "celon": { "virtual": true, "package": { "label": "최고 품질", "strategy": "frontier", "dial": "strict-quality" } } },
    { "id": "celon/nitro", "object": "model", "owned_by": "celon",
      "celon": { "virtual": true, "package": { "label": "최고 속도", "strategy": "nitro", "dial": "low-latency" } } },
    { "id": "celon/floor", "object": "model", "owned_by": "celon",
      "celon": { "virtual": true, "package": { "label": "최저가", "strategy": "floor", "dial": "max-savings" } } },
    { "id": "anthropic/claude-fable-5", "object": "model", "owned_by": "anthropic",
      "celon": { "tier": 1, "pricing": { "inputPerM": 10, "outputPerM": 50 },
                 "context_window": 500000, "modality": "text", "available": true } }
  ]
}

GET /v1/endpoints

Per-model provider endpoint statistics — returns the provider, $/1M pricing and its source (pricingSource), measured latency/throughput/uptime and their sources, and the sample count. It's a public endpoint, so the web catalog reads it directly from the browser. The response has the shape { modelId: EndpointStat[] }, and GET /v1/endpoints/:vendor/:model queries a single model and returns that model's EndpointStat[] (an unregistered model returns 404).

terminal
# Public endpoint — no key required
curl https://api.celon.ai/v1/endpoints
# A single model only: /v1/endpoints/deepseek/deepseek-v3.2
response.json (excerpt)
{
  "deepseek/deepseek-v3.2": [
    {
      "modelId": "deepseek/deepseek-v3.2",
      "provider": "deepinfra",
      "inputPerM": 0.27,
      "outputPerM": 0.40,
      "pricingSource": "openrouter-endpoints",
      "latencyMs": 640,
      "latencySource": "measured",
      "throughputTps": 78.2,
      "uptimePct": 0.998,
      "uptimeSource": "measured",
      "samples": 128
    }
  ]
}

Self-serve console — /v1/me

GET /v1/me returns the logged-in user and their organization (org: null if no organization exists yet). POST /v1/me/provision idempotently bootstraps the organization and issues a default key once (the plaintext key is shown only in this response). From there, GET · POST /v1/me/keys list and issue keys, and DELETE /v1/me/keys/:id revokes one (soft delete — ledger attribution is preserved). GET /v1/me/dashboard?days=, GET /v1/me/billing/balance, and POST /v1/me/billing/checkout each serve the same data as /v1/dashboard and /v1/billing/* below, scoped to the organization resolved from the JWT.

terminal
# Every /v1/me call authenticates with a Supabase session token (JWT)
curl https://api.celon.ai/v1/me \
  -H "Authorization: Bearer <supabase-access-token>"
# → { "userId": "…", "email": "dev@acme.co.kr", "org": null | {…} }
POST /v1/me/provision → 201
{
  "org": { "id": "org_abc123", "name": "acme", "plan": "prepaid", "billingMode": "prepaid" },
  "created": true,
  "defaultKey": {
    "id": "key_7f3d",
    "name": "default",
    "prefix": "sk-celon-…1a2b",
    "monthlyBudgetUsd": null,
    "overBudgetBehavior": "reject",
    "disabled": false,
    "createdAt": "2026-07-16T02:00:00.000Z",
    "key": "sk-celon-<48 hex — shown only in this response>"
  }
}
terminal
# Issue a key (the plaintext key is shown only in this response)
curl -X POST https://api.celon.ai/v1/me/keys \
  -H "Authorization: Bearer <supabase-access-token>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "prod-backend", "monthlyBudgetUsd": 1000 }'

# List (masked view — hash and BYOK keys are never returned)
curl https://api.celon.ai/v1/me/keys \
  -H "Authorization: Bearer <supabase-access-token>"

# Revoke (soft delete — ledger attribution is preserved)
curl -X DELETE https://api.celon.ai/v1/me/keys/key_7f3d \
  -H "Authorization: Bearer <supabase-access-token>"

GET /v1/dashboard

The organization dashboard read model — returns spend, savings, and baseline; cache hit rate; request count; per-tier aggregates; per-key and per-team budget gauges; daily trends; recent usage (metadata only); and a Korean briefing. Prepaid organizations also get the credit balance (balanceUsd), billing mode (billingMode), and the platform fee rate (platformFeePct, default 5). Query days (1–365, default 30). A regular key sees only its own organization; a master key can view any organization via ?orgId=.

terminal
curl "https://api.celon.ai/v1/dashboard?days=30" \
  -H "Authorization: Bearer sk-celon-…"
response.json (excerpt)
{
  "orgId": "org_abc123",
  "windowDays": 30,
  "spendUsd": 12.4,
  "savedUsd": 63.1,
  "baselineUsd": 75.5,
  "cacheHitRate": 0.23,
  "requests": 1284,
  "balanceUsd": 42.5,
  "billingMode": "prepaid",
  "platformFeePct": 5,
  "byTier": { "1": 96, "2": 512, "3": 676 },
  "keys": [ { "name": "prod-backend", "prefix": "sk-celon-…1a2b",
             "spentUsd": 8.2, "budgetUsd": 1000, "overBudgetBehavior": "downgrade" } ],
  "teams": [ { "id": "team_9a2b", "name": "Marketing", "spentUsd": 5.1,
             "budgetUsd": 500, "overBudgetBehavior": "reject", "keys": 3 } ],
  "daily": [ { "date": "2026-07-15", "spendUsd": 0.62, "savedUsd": 3.1, "baselineUsd": 3.72 } ],
  "recent": [ /* metadata only — no bodies (ZDR) */ ],
  /* briefing text is generated by the gateway in Korean */
  "briefing": { "summary": "지난 30일 동안 1284건 요청, …", "highlights": ["캐시 적중률 23.0% …"] }
}

Billing and balance

Billing is based on prepaid credits. The 5% platform fee is charged once, at top-up — top up $100 and you pay $105, leaving a $100 balance. The ledger records the gross payment (toss/polar) and the fee (fee) as separate rows, so the charge explains itself.

Requests then draw the model's raw cost (a usage row), and a request served from cache — which made no upstream call — draws nothing. Postpaid organizations never top up, so their fee accrues per request as a fee row instead and lands on the monthly invoice.

GET /v1/billing/balance

Returns the current prepaid balance along with the plan, billing mode, and fee rate.

terminal
curl https://api.celon.ai/v1/billing/balance \
  -H "Authorization: Bearer sk-celon-…"
# → { "balanceUsd": 42.5, "plan": "prepaid", "billingMode": "prepaid", "platformFeePct": 5 }

POST /v1/billing/checkout

Creates a hosted top-up session — amountUsd (required), provider (polar | toss), successUrl. Polar uses a redirect checkout; Toss links to our /billing/topup widget page. Redirect to the url in the response. On a gateway with no payment provider configured (no TOSS_CLIENT_KEY/TOSS_SECRET_KEY or Polar keys), 400 checkout_unavailable is returned.

terminal
curl -X POST https://api.celon.ai/v1/billing/checkout \
  -H "Authorization: Bearer sk-celon-…" \
  -H "Content-Type: application/json" \
  -d '{ "amountUsd": 50, "provider": "toss",
        "successUrl": "https://celon.ai/billing/topup" }'
response.json
{
  "url": "https://celon.ai/billing/topup?orderId=ord_…",
  "provider": "toss",
  "ref": "ord_…"
}

POST /v1/billing/toss/confirm

Confirms a Toss widget payment server-side and grants credit — pass paymentKey, orderId, and amount (the KRW integer Toss returned to the success URL). The grant is idempotent — reconfirming the same payment returns alreadyApplied: true and does not double-grant.

terminal
curl -X POST https://api.celon.ai/v1/billing/toss/confirm \
  -H "Authorization: Bearer sk-celon-…" \
  -H "Content-Type: application/json" \
  -d '{ "paymentKey": "…", "orderId": "ord_…", "amount": 65000 }'
# → { "granted": 48.5, "alreadyApplied": false, "balanceUsd": 91.0 }

Payment providers also reflect top-ups through a signature-verified webhook (POST /v1/billing/webhook/:provider, public and always 200).

Admin API

POST /admin/orgs · GET /admin/orgs · PATCH /admin/orgs/:id

Create, read, and update organizations. Set zdr (the no-body-storage policy), monthlyBudgetUsd (a hard cap, null = unlimited), and plan (byok | prepaid | enterprise), along with the organization's default governance policy (governance — custom PII patterns, banned words, model policy; see the governance docs). GET /admin/orgs returns the full organization list, and GET /admin/orgs/:id returns a single organization.

Changing billingMode to "postpaid" via PATCH /admin/orgs/:id switches to month-end postpaid settlement — requests are not blocked even at a zero balance, and usage accrues as a negative balance (debt). It's a contact-based, master-only switch and is not exposed to self-serve.

terminal
curl -X POST https://api.celon.ai/admin/orgs \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "acme", "zdr": true, "monthlyBudgetUsd": 5000 }'
governance config
curl -X PATCH https://api.celon.ai/admin/orgs/org_abc123 \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "governance": {
      "guardrails": {
        "mode": "mask",
        "pii": {
          "entities": { "EMAIL": false },
          "custom": [{ "name": "EMPLOYEE_ID", "pattern": "EMP-\\d{6}" }]
        },
        "bannedWords": [
          { "word": "Project Falcon", "action": "block" },
          { "word": "Internal codename" }
        ]
      },
      "models": {
        "blockedModels": ["xai/*"],
        "allowedModels": []
      }
    }
  }'
postpaid switch
# Switch to postpaid settlement (contact-based, master only) — no blocking
# even at zero balance; debt accrues as a negative balance and is settled at month-end close.
curl -X PATCH https://api.celon.ai/admin/orgs/org_abc123 \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "billingMode": "postpaid" }'

POST /admin/teams · GET /admin/teams · PATCH·DELETE /admin/teams/:id

Manage departments (teams). A team is the budget unit between the organization and the key — set a per-team monthly budget (monthlyBudgetUsd) and an over-budget policy (overBudgetBehavior: reject = deny with 402 / downgrade = switch to Tier 3). Keys join via teamId, and GET /admin/teams?orgId= returns each team's spend this month (spentUsd) and key count. Deleting a team moves its keys to no team, and past spend attribution is unchanged.

terminal
# Create a team (budget $500, rejects with 402 when exceeded)
curl -X POST https://api.celon.ai/admin/teams \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "orgId": "org_abc123", "name": "Marketing",
        "monthlyBudgetUsd": 500, "overBudgetBehavior": "reject" }'

# List (includes this month's spend + key count)
curl "https://api.celon.ai/admin/teams?orgId=org_abc123" \
  -H "Authorization: Bearer $CELON_MASTER_KEY"

# Assign a key to a team
curl -X PATCH https://api.celon.ai/admin/keys/key_7f3d \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "teamId": "team_9a2b" }'

POST /admin/keys

Issue a virtual key (sk-celon- + 48 hex). Configure, per key: the budget (monthlyBudgetUsd, overBudgetBehavior), team membership (teamId), PII masking, ZDR, the routing policy (routing — the default intent dial and the anchorModel ceiling), the guardrail policy (guardrailsmode block | mask | shadow, per-detector detectors, custom pii and bannedWords, output inspection streamOutput), the model policy (modelPolicy blockedModels/allowedModels), and BYOK upstream keys (byokKeys). Key policy takes precedence over the organization's governance, and celon.dial / celon.anchor in the request body take precedence over key policy.

terminal
curl -X POST https://api.celon.ai/admin/keys \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "orgId": "org_abc123",
    "name": "prod-backend",
    "monthlyBudgetUsd": 1000,
    "overBudgetBehavior": "downgrade",
    "piiMasking": true,
    "zdr": true,
    "routing": {
      "dial": "strict-quality",
      "anchorModel": "anthropic/claude-fable-5"
    },
    "guardrails": {
      "mode": "mask",
      "detectors": { "pii": true, "secrets": true, "injection": true, "presidio": false },
      "streamOutput": true
    },
    "byokKeys": {}
  }'
# The plaintext key (sk-celon-…) is shown only in this response

POST /admin/credits · GET /admin/credits

Manually grant or adjust prepaid credit and read the ledger history. POST adds a ledger entry with amountUsd (positive = top-up, negative = deduction) and source (admin-grant · promo · adjustment · polar · toss), and GET ?orgId= returns the current balance (balanceUsd) and credit history (credits). Polar/Toss top-ups and usage deductions are recorded in the same ledger.

terminal
# Manual credit grant/adjustment (positive = top-up, negative = deduction)
curl -X POST https://api.celon.ai/admin/credits \
  -H "Authorization: Bearer $CELON_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "orgId": "org_abc123", "amountUsd": 100, "source": "admin-grant" }'

# Ledger history + current balance
curl "https://api.celon.ai/admin/credits?orgId=org_abc123" \
  -H "Authorization: Bearer $CELON_MASTER_KEY"
# → { "balanceUsd": 142.5, "credits": [ { "id": "…", "ts": "…",
#      "orgId": "org_abc123", "amountUsd": 100, "source": "admin-grant" } ] }

GET /admin/audit

Returns the immutable, append-only audit log of guardrail decisions as an events array, newest first. Each event carries only id, ts, orgId, keyId, endpoint, model, dial, the outcome decision (allowed · blocked · masked · shadow · error), the detection count guardrailFindings, the per-category tally findingsByCategory (pii · secret · injection · presidio · banned), and the response status — no prompt or response bodies (ZDR). Query parameters: orgId (required), limit (1–1000). For the policy and mode descriptions, see Governance — Audit Trail.

terminal
curl "https://api.celon.ai/admin/audit?orgId=org_abc123&limit=50" \
  -H "Authorization: Bearer $CELON_MASTER_KEY"
response.json
{
  "events": [
    {
      "id": "audit_9f2a",
      "ts": 1750000000000,
      "orgId": "org_abc123",
      "keyId": "key_7f3d",
      "endpoint": "chat",
      "model": "meta-llama/llama-4-maverick",
      "dial": "balanced",
      "decision": "masked",
      "guardrailFindings": 2,
      "findingsByCategory": { "pii": 1, "secret": 1 },
      "status": 200
    }
  ]
}

GET /admin/usage/summary

An organization-level usage summary — returns the request count, total cost, total savings, cache hit rate, and per-tier and per-model aggregates.

terminal
curl "https://api.celon.ai/admin/usage/summary?orgId=org_abc123" \
  -H "Authorization: Bearer $CELON_MASTER_KEY"
response.json
{
  "requests": 1284,
  "totalCostUsd": 12.4,
  "totalSavedUsd": 63.1,
  "cacheHitRate": 0.23,
  "byTier": { "1": 96, "2": 512, "3": 676 },
  "byModel": {
    "google/gemini-3-flash": { "requests": 512, "costUsd": 4.2 }
  }
}

GET /admin/health

An operational status snapshot — exposes the active health-probe configuration, the last run time, and the real state of fail-open integrations. Optional guardrails (presidio, promptGuard) show whether they're configured (configured) and, when configured but failing open (passing through), the failure count and last error (failures, lastError) — without this, “configured but dead and simply passing through” would be indistinguishable from “nothing detected.” It also carries the cache backend (upstash | memory), whether the semantic cache is enabled, and whether the mock provider is enabled.

terminal
curl https://api.celon.ai/admin/health \
  -H "Authorization: Bearer $CELON_MASTER_KEY"
response.json
{
  "enabled": true,
  "intervalMinutes": 15,
  "lastRun": "2026-07-16T02:00:00.000Z",
  "guardrails": {
    "presidio": { "configured": false },
    "promptGuard": { "configured": true }
  },
  "cache": {
    "backend": "upstash",
    "semantic": { "enabled": true }
  },
  "mock": { "enabled": false }
}

POST /admin/health/probe · POST /admin/endpoints/refresh

POST /admin/health/probe runs the active health probe once immediately and returns a per-provider success/failure and latency report. POST /admin/endpoints/refresh re-fetches the endpoint stats feed (OpenRouter) and returns a refresh summary (model/row counts, how many were priced from the feed, how many have measured stats).

terminal
# Run one active health probe immediately (per-provider ok/failed/latency)
curl -X POST https://api.celon.ai/admin/health/probe \
  -H "Authorization: Bearer $CELON_MASTER_KEY"

# Re-fetch the endpoint stats feed (OpenRouter)
curl -X POST https://api.celon.ai/admin/endpoints/refresh \
  -H "Authorization: Bearer $CELON_MASTER_KEY"
# → { "refreshedAt": "…", "models": 41, "rows": 128, "feedPriced": 96, "measured": 54 }

GET /healthz

A liveness check. Used by the health probe in deployment environments.

terminal
curl https://api.celon.ai/healthz
# → { "status": "ok" }

GET /metrics

An in-process metrics snapshot (JSON) — total requests, requests per minute, per-endpoint and per-tier counts, cache hit rate, and p50/p95 latency (over the most recent 1,000 samples).

terminal
curl https://api.celon.ai/metrics
response.json
{
  "uptimeSeconds": 3600,
  "requests": { "total": 1284, "ok": 1279, "error": 5, "perMinute": 21 },
  "byEndpoint": { "chat": 1201, "embeddings": 83 },
  "byTier": { "1": 96, "2": 512, "3": 676 },
  "cache": { "exactHits": 214, "semanticHits": 81, "hitRate": 0.23 },
  "latencyMs": { "p50": 640, "p95": 2210, "avg": 812, "samples": 1000 }
}