OC Me · Integrations
OC sits as a peer next to your existing OAuth providers. A first-time user picking OC has a federation-custodied bitcoin wallet provisioned silently — no seed phrase, no key handling, no "what is a sat" conversation. Sat-earning starts on first session.
See it live first
Before you read another paragraph,
me-demo.ochk.io is a real OC integration we built
ourselves — a fictional newsletter site (Lumen Notes), styled deliberately
not-orangecheck. The signin button there opens the OC popup. Sign in once and
you'll see the whole loop end-to-end. Source at
github.com/orangecheck/oc-me-demo-web.
~280 lines of meaningful integration code, including the /api/auth/me wrapper
and the popup-signin handler.
OAuth-peer pattern
import { signInWithOc } from '@orangecheck/me-client/popup';
import { signIn } from 'next-auth/react';
import { useState } from 'react';
export function SignInOptions() {
const [busy, setBusy] = useState(false);
async function onOc() {
setBusy(true);
const result = await signInWithOc();
setBusy(false);
if (result) {
localStorage.setItem('oc-token', result.token);
location.assign('/dashboard');
}
}
return (
<div className="auth-options">
<button onClick={() => signIn('google')}>
continue with google
</button>
<button onClick={() => signIn('apple')}>continue with apple</button>
<button onClick={() => signIn('email')}>email magic link</button>
<button onClick={onOc} disabled={busy}>
{busy ? 'opening…' : 'sign in with oc'}
</button>
</div>
);
}
| What your user sees | What your user does NOT see |
|---|---|
| a button next to google / apple | a seed phrase |
| one redirect to me.ochk.io | a wallet creation flow |
| signed in on your site | a "buy bitcoin" CTA |
| (eventually) a growing sat balance | any crypto vocabulary at all |
When do they find out? When they want to. me.ochk.io/me shows their balance, me.ochk.io/me/wallet shows receive/send/withdraw, me.ochk.io/me/graduate offers self-custody. None of this is in the OAuth path. None of it surfaces unless the user explicitly visits.
Sample integrator archetypes
The configurator at me.ochk.io/integrate ships with six representative sample configurations. Different unit economics produce different choices — there's no "right" config OC sets, just the math.
| Archetype | Domain | Account creation | Session | Payment | User share |
|---|---|---|---|---|---|
| Lightning fintech | breez.example | 2,100 sats | 80 sats | 0.50% | 70% |
| Cashback-heavy | fold.example | 1,600 sats | 60 sats | 0.95% | 78% |
| Lightning-native social | damus.example | — | 40 sats | — | 50% |
| Merchant SaaS · KYC-required | zaprite.example | 5,300 sats | 75 sats | 0.85% | 55–65% |
| Community federation | fedi.example | 850 sats | 50 sats | — | 78% |
| Creator platform | creator.example | 1,100 sats | 35 sats | 0.65% | 60–70% |
The config schema is open and self-served — see /me/sdk for the full shape and /developer/config for the inline editor.
Cross-product flows · me + fleet
A consumer using me.ochk.io may sign into a SaaS that runs on fleet.ochk.io for managed agent infrastructure. The envelopes are the same primitive (oc-attest, oc-stamp, oc-agent) — the two products are two integration surfaces over identical contracts.
| Flow | Surface |
|---|---|
| User signs into a SaaS using OC button | me.ochk.io issues the session · fleet.ochk.io receives it via the family cookie / JWT |
| Agent takes a stamped action | fleet.ochk.io publishes the envelope · me.ochk.io credits sats per the SaaS's pricing |
| User revokes a delegation | fleet.ochk.io publishes oc-agent-rev:[id] · the verifier drops further envelopes |
Agent delegation lifecycle (issuance, revocation, list, audit) lives on fleet.ochk.io — that's the enterprise managed Agent product. me.ochk.io handles the wallet, identity, and billing substrate underneath. See fleet.ochk.io integrations docs for the operator-side view.
Errors and edge cases
| Error | Meaning | Fix |
|---|---|---|
IntegratorPriceConfig invalid (422) | Validation failed server-side. | Run oc.config.validate(cfg) locally first; the response includes details: [{ subtype, message }]. |
signature does not match from oc.webhook.verify | Either you parsed the body before verifying, or you're verifying against a stale JWK. | Use raw body bytes; re-fetch JWKS via oc.webhook.fetchJwks(). |
rate_limit_exceeded (429) | You exceeded a per-IP bucket. | Honor Retry-After; back off exponentially. |
domain not verified (403) | Your project_key fired in live mode but verification.state !== 'verified'. | Run domain verification at me.ochk.io/me/projects/<key> (DNS TXT or meta tag), then retry. |
Self-host considerations
me.ochk.io is one implementation of the canonical OC primitives. Anyone can run their own me-equivalent against the same envelope contracts — that's the product strategy. If you're considering self-hosting, the contracts to honor are at:
oc-attest-protocol/SPEC.md(identity)oc-attest-protocol/FEDERATION-CUSTODY.md(v1.2-draft-1 federation custody)oc-stamp-protocol/SPEC.md(anchored receipts)oc-agent-protocol/SPEC.md+FEDERATION.md(delegations)oc-lock-protocol/SPEC.md(encrypted DMs)
The hosted me.ochk.io substrate is a convenience, not a moat. Charter commitment 04 keeps every reference site free and self-hostable forever.