documentation

API reference

One base URL, bearer keys, JSON problem details, and a surface the build itself publishes. If you are starting from zero, the quickstart is three commands to a verdict, and the sample is one real analysis shown end to end — certificate included, verifiable. This page is the map around both.

Base URL and authentication

auth
curl https://api.hiddencontent.ai/v1/usage \
-H "authorization: Bearer $HCS_KEY"
# Keys are bearer credentials, shown once, stored only as hashes.
# Every key is live; analyses spend prepaid credit at a cent a page.

Everything lives under https://api.hiddencontent.ai/v1 (the JWKS is the one exception). Keys are shown exactly once and stored as hashes — a lost key is replaced from any key you still hold, never recovered. Revocation cascades: revoking a key also revokes every key it minted.

Endpoints

MethodPathAuth
GET/nowhat this deployment offers, including its sign-up routes
GET/v1/healthznoliveness, engine and rule-pack versions, and whether the vision pass is enabled
GET/v1/output-surfacenothe recorded output surface this build ships — every technique, limit, and field, generated from the build. Build your fixtures from this
POST/v1/signupnoemail sign-up: {"email", "name", "source"?} → account + live key. A known address is a 409 and no key
POST/v1/signup/githubnobegin GitHub device-flow sign-up; returns a code and a pollToken
POST/v1/signup/github/pollnopoll it; 202 until authorised, then the account and key. Signing in again later recovers the same account
POST/v1/contactnothe talk-to-a-human form: {"email", "message"?} — answered by a person
POST/v1/analyzeyesthe one that matters. Multipart file upload → verdict, findings, canonical text, certificate. Large scanned documents return 202 + a job
GET/v1/analyze/{jobId}yespoll a 202
GET/v1/documents/{sha256}yesstored reports for a document hash
GET/v1/usageyesbalance, usage this period, and account state — alarm on analysisUnitsRemaining before a 402 does it for you
POST/v1/keysyesmint another live key on your own account — one per environment, separately revocable
GET/v1/keysyesyour keys, metadata only — never a token
POST/v1/keys/{keyId}/revokeyesrevoke it and everything it created, transitively
POST/v1/text/sanitizeyestext you already hold, no file
POST/v1/billing/checkoutyesa Stripe Checkout URL for a credit purchase ($10 minimum, $5,000 maximum)
POST/GET/DELETE/v1/billing/auto-refillyesopt-in below-X-charge-Y; consent required verbatim; one call disables
GET/v1/account/exportyeseverything we hold on your account, as JSON
DELETE/v1/accountyesdelete the account; needs {"confirm": "<customer id>"}
POST/v1/certificates/verifynounauthenticated by design, so an auditor can check a certificate. Gate on attests, not valid
GET/.well-known/jwks.jsonnopublic keys, for verifying certificates offline — with our servers switched off entirely

The health path is /v1/healthz, not /healthz — the first thing every new integration gets wrong.

Errors

problem+json
{
"type": "/v1/errors/quota-exhausted", // open it — every type URL is a docs page
"title": "Quota exhausted",
"status": 402,
"detail": "Analysis balance exhausted: 12 of 12 used. Buy credit with
POST /v1/billing/checkout — one cent is one page. …",
"requestId": "req_…" // quote this when you write to us
}

Every error is an RFC 9457 problem document, and every type URL is a page this service serves — open it in a browser for the full story and the fix. The two worth knowing in advance: a 402 names the exact shortfall before any work is billed (a document you cannot afford is refused whole, never partially analysed and charged), and a 429 carries Retry-After — honour it.

Certificates

A certified analysis returns a signed certificate: this document (by hash), this verdict, this engine version, at this time. It verifies offline against/.well-known/jwks.json with our servers switched off entirely — months or years later. Two rules keep you honest when you build on them: gate onattests, not valid (a correctly signed certificate can still attest nothing), and a certificate attests to process, not safety — it records that an analysis ran and what it found, never that a document is clean.certified: false always names its reason.

The surface that cannot drift

output surface
GET /v1/output-surface

Every technique the running build detects, every limit it enforces, and every field it emits — generated from the build, so it cannot disagree with what you receive. Build your fixtures and your routing against it, and diff it across deploys: theengineVersion inside is the same one pinned into every certificate. Known blind spots are declared per finding (residuals) rather than discovered by your users; we treat narrowing one as a change worth announcing.

The full integration guide

Behind this reference is a much longer integration guide — verified request-by-request against the running service, with a changelog that records every behaviour change, which direction your numbers move, and how far. It comes with every evaluation:ask us.