API reference
Every endpoint on the hosted verifier at ochk.io. The public endpoints are CORS-enabled and usable from any language or runtime without an API key. The /api/auth/* family is site-internal (same-origin, cookie-based) and backs /signin + /dashboard.
Base URL
https://ochk.io
Conventions
- Protocol — HTTPS, JSON bodies, UTF-8.
- Timestamps — RFC-3339 UTC with
Zsuffix. - Auth — none on the free tier. Paid tier uses bearer tokens (not yet public).
- CORS —
Access-Control-Allow-Origin: *on every endpoint.
Endpoint map
Public (CORS-enabled, no cookie)
| Endpoint | Method | Purpose |
|---|---|---|
/api/check | GET | Sybil-gate decision. Load-bearing. |
/api/verify | POST | Verify a raw (addr, msg, sig) tuple. |
/api/challenge | GET / POST | Signed-challenge auth primitive. |
/api/discover | GET | List attestations for a subject. |
/api/stats | GET | Aggregate network stats. |
/api/og/check | GET | Dynamic OG image for social previews. |
Site-internal (same-origin, cookie-based)
Back /signin and /dashboard. See /api/auth/* for the full reference.
| Endpoint | Method | Purpose |
|---|---|---|
/api/auth/signin | POST | Exchange a signed challenge for a session cookie. |
/api/auth/me | GET | Read the signed-in account + cached attestations. |
/api/auth/logout | POST | Revoke the session and clear the cookie. |
/api/auth/account | PATCH | Update profile fields. |
Rate limits (free tier)
| Endpoint | Limit |
|---|---|
/api/check | 60 req/min/IP |
/api/discover | 60 req/min/IP |
/api/stats | 30 req/min/IP |
/api/challenge | 30 req/min/IP |
/api/verify | 10 req/min/IP |
/api/auth/signin | 20 req/min/IP |
Beyond these, requests return 429 with { "error": "rate_limited" }. Higher limits, webhook delivery, and SLAs are part of the paid tier.
Cache headers
/api/check,/api/discover,/api/stats,/api/og/check—Cache-Control: public, max-age=60(or 300 for OG)./api/verify,/api/challenge,/api/health—Cache-Control: no-store.
Status codes
| Code | Meaning |
|---|---|
200 | Success. Response body carries the decision or data. |
400 | bad_request — missing or malformed parameters. |
401 | Signed-challenge verify only: signature / nonce / audience mismatch. |
404 | not_found — no attestation matches the subject. |
405 | method_not_allowed. |
429 | rate_limited. |
500 | server_error. |
Error shape
{
"error": "<code>",
"issues": [ /* optional, populated on validation failure */ ]
}
Self-host
Every endpoint lives in src/pages/api/* in the open-source oc-web repo. You can run your own verifier — it reads from public Bitcoin explorers and Nostr relays of your choice.
Start with /api/check. It's the whole product.