live · mainnetoc · docs
specs · api · guides
docs / http api

OC Me · HTTP API

The hosted me.ochk.io substrate exposes the contracts the SDK calls into. The SDK is the canonical integration path; this page is the raw HTTP surface for clients that aren't TypeScript or that want to bypass the SDK.

Every endpoint is at https://me.ochk.io/api/... unless noted. Auth is by cross-subdomain oc_session cookie (Domain=.ochk.io, HttpOnly, SameSite=None, Secure) issued by the auth host at https://ochk.io, OR by an Authorization: Bearer <jwt> header (cross-domain integrators that captured the session token from the popup-signin postMessage). Mutating endpoints are rate-limited per IP per bucket; limits are returned in X-RateLimit-* headers.

Sign-in endpoints (auth host · https://ochk.io)

The session cookie is issued by the family auth host, not by me.ochk.io directly. me.ochk.io's /signin page calls these endpoints cross-origin with credentials — they are CORS-allowed for any *.ochk.io browser origin.

MethodPathPurpose
POST/api/auth/email-otp/startissue a stateless OTP token + email a 6-digit code (rate-limited 5/hr)
POST/api/auth/email-otp/verifyverify {email, code, token}, upsert account, set oc_session cookie
GET/api/challengeissue a fresh BIP-322 challenge to sign
POST/api/auth/signinverify a signed BIP-322 challenge, upsert account, set oc_session
POST/api/auth/logoutclear the oc_session cookie
GET/api/auth/mecrypto-only identity lookup; 401 otherwise

See oc-me-web/src/pages/signin.tsx for the canonical client implementation against these endpoints.

Public endpoints

MethodPathPurpose
GET/api/healthliveness probe
GET/api/health/deepdependency probe
GET/api/envelope/[id]canonical envelope JSON for a billable event
GET/api/payment/[id]canonical envelope for a payment
GET/api/checkout/lightning/[hash]invoice status by payment_hash
GET/api/platform-fee-policypublished PLATFORM_FEE_POLICY
GET/api/abuse-limitspublished per-class abuse rate limits
GET/api/integrator-config?project_key=…sample IntegratorPriceConfig lookup
GET/api/stats/earnedaggregate sat-earnings (last 7d, by class)
POST/api/integrator-configvalidate an IntegratorPriceConfig (echoes on success)
POST/api/checkout/lightninggenerate a BOLT-11 invoice (rate-limited 60/min)
POST/api/checkout/stripegenerate a Stripe checkout URL
POST/api/contactcontact form submission (Resend-backed)
POST/api/integrator/eventfire a billable event under a project_key (live mode requires domain verification)

Authenticated endpoints (oc_session required)

MethodPathPurpose
GET/api/auth/mecrypto-only identity lookup; 401 otherwise
GET/api/me/profileprofile + onboarding state
GET/api/me/balancesat balance + last-7d aggregate + by-class breakdown
GET/api/me/siteslist of sites the identity has signed in to
GET/api/me/sites/[domain]per-site activity + IntegratorPriceConfig
GET/api/me/notificationsnotifications feed
POST/api/me/notificationsmark read/unread ({ id, read } or { all: true, read: true })
GET/api/me/exportGDPR-style account dump · downloadable JSON

Authenticated · session lifecycle (Class C)

MethodPathPurpose
POST/api/session/createopen a Class C session — billable atom
POST/api/session/refreshrefresh inside the policy window — free
POST/api/session/invalidatetear down — free, telemetry-only

Authenticated · payment authorization (Class B)

MethodPathPurpose
POST/api/payment/authorizeauthorize a payment, rate-limited 30/min · Class B billable

Authenticated · integrator project lifecycle

MethodPathPurpose
GET/api/me/projectslist every project owned by your identity
POST/api/me/projectscreate a project, rate-limited 5/min
GET/api/me/projects/[id]per-project state · owner-gated
POST/api/me/projects/[id]update IntegratorPriceConfig · owner-gated, validates
DELETE/api/me/projects/[id]delete project · owner-gated
POST/api/me/projects/[id]/verifyrun a domain-ownership check (DNS TXT, falls back to meta tag) · owner-gated, rate-limited 5/min
DELETE/api/me/projects/[id]/verifyreissue the verification token (rotate / retry from scratch) · owner-gated
POST/api/me/projects/[id]/test-firefire a real envelope under this project_key (same pipeline as production) · owner-gated · for the smoke-test sandbox
GET/api/me/projects/[id]/eventslive event stream for this project · owner-gated
GET/api/me/projects/[id]/webhookslist registered webhooks · owner-gated
POST/api/me/projects/[id]/webhooksregister a webhook URL · owner-gated
POST/api/developer/webhook-testtest-fire a synthetic envelope at a registered webhook

Response shapes

All authenticated 401s are { ok: false } with Cache-Control: no-store, private and Vary: Cookie. All 422 validation failures return { error: string, details?: [{ subtype?: string, message: string }] }. All 429 rate-limit responses include a Retry-After header in seconds.

Rate limits per bucket

BucketLimitWindow
integrator.event12060s
payment.authorize3060s
wallet.send3060s
checkout.lightning6060s
me.attest-tier560s
webhooks.register1060s
projects.test-fire2060s
developer.projects.create560s
verify-domain:<addr>560s

Limits are per IP, per bucket (except verify-domain which is per-account so DNS retries don't get throttled by a noisy neighbor). Headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Window are emitted on every rate-limited response. v1 buckets reset on cold start (per-instance in-memory); production fronts every endpoint with an edge-level limiter.