An open standard for delegated crypto withdrawal authorization on centralized exchanges — named after HTTP 428 Precondition Required, the status code used for step-up 2FA.
+-----------+
| Resource |
| Owner |
+-----+-----+
| consent
v
+------------------+ +-----+-----+ +------------------+
| Client App | OAuth | Exchange | chain | Blockchain |
| (wallet, bot, +------->+ (Coinbase,+------->+ (Ethereum, |
| aggregator) | tokens | Kraken…) | tx | Bitcoin…) |
+------------------+ +-----------+ +------------------+
// 1. OAuth — get scoped withdrawal permissions
const { access_token } = await exchange.token({
grant_type: "authorization_code",
code, redirect_uri, code_verifier, client_id, client_secret,
});
// 2. Discover assets
const { data: assets } = await exchange.get("/assets", {
headers: { Authorization: `Bearer ${access_token}` },
});
// 3. Withdraw — may return 428 if step-up 2FA is required
const res = await exchange.post("/withdrawals", {
headers: {
Authorization: `Bearer ${access_token}`,
"Idempotency-Key": crypto.randomUUID(),
},
body: { asset: "ETH", network: "ethereum", amount: "1.5", address: "0x…" },
});
if (res.status === 428) {
// Complete step-up challenge, then retry with proof token
const { challengeId, methods } = await res.json();
const proof = await completeChallenge(challengeId, methods);
// retry with challengeProof in body
}Development setup
pnpm install
pnpm run generate # OpenAPI spec, JSON Schemas, LaTeX tables
pnpm run typecheck # verify TypeScript compiles
pnpm run build:pdf # generate + compile LaTeX spec PDF- Open standard — vendor-neutral, implementable by any exchange
- OAuth 2.0 + PKCE — no custom auth; builds on proven standards (RFC 6749, RFC 7636)
- Security-first — step-up 2FA via HTTP 428, scoped permissions, idempotent submissions
- Compliance-ready — FATF Travel Rule data as a first-class field
- Developer-friendly — single source of truth in Zod schemas; generates OpenAPI, JSON Schema, and LaTeX
| Term | Definition |
|---|---|
| Exchange | Centralized crypto exchange implementing the x428 protocol |
| Client Application | Third-party app requesting delegated withdrawal access |
| Resource Owner | End-user who owns the exchange account and grants consent |
| Step-Up Challenge | 2FA prompt triggered when a withdrawal requires elevated assurance |
| Proof Token | Short-lived token issued after step-up, attached to the withdrawal retry |
| Idempotency Key | Client-generated ID preventing duplicate withdrawals on retry |
The full protocol spec lives in spec/ and covers:
- OAuth 2.0 profile — authorization code + PKCE, scoped tokens, refresh
- Asset discovery —
GET /assetswith network/fee metadata - Withdrawal submission —
POST /withdrawalswith idempotency - Step-up 2FA — HTTP 428 challenge/verify flow
- Withdrawal lifecycle — async status tracking with cursor-based pagination
- Error handling — standardized error envelope with typed error codes
- Coinbase compatibility — mapping to Coinbase Advanced Trade API
x428 suggests major six second-factor methods:
| Method | Type | Description |
|---|---|---|
totp |
Synchronous | TOTP code from authenticator app |
webauthn |
Synchronous | FIDO2/WebAuthn assertion |
push |
Asynchronous | Approve via push notification in exchange app |
sms |
Asynchronous | Code delivered via SMS |
email |
Asynchronous | Code delivered via email |
face |
Asynchronous | Biometric face recognition in exchange app |
Exchanges may require one method (policy: "any") or multiple (policy: "all").
src/schemas/ Zod 4 schemas (single source of truth)
src/document.ts OpenAPI 3.1 document via zod-openapi
scripts/ Generation and PDF build scripts
openapi/ Generated OpenAPI spec (JSON + YAML)
generated/ Generated JSON Schemas and LaTeX tables
spec/ LaTeX protocol specification
examples/ Request/response examples
- Specification text: CC-BY-4.0
- Code and schemas: Apache-2.0
- Patents: OWFa 1.0