← All updates

/enhance is now wallet-payable (x402)

Pay for a PDF/UA-1 + PDF/A-2A remediation job with a USDC wallet — no API key, no account. The 202 envelope hands you an opaque pollToken to poll the job and download the artifact when it's ready.

apienhancex402

POST /api/v1/enhance now accepts x402 settlement as authentication. Send the PAYMENT-SIGNATURE header, settle USDC on Base (Sepolia in test, mainnet in prod), and the producer returns a 202 carrying a freshly-minted pollToken:

{
  "jobId": "...",
  "status": "queued",
  "statusUrl": "/api/v1/enhance/jobs/...",
  "estimatedSeconds": 240,
  "pollToken": "Rh3...n_w"
}

Re-present that token as Authorization: Bearer <pollToken> on the follow-up calls — GET /api/v1/enhance/jobs/:id, POST .../cancel, and GET /api/v1/artifacts/:id/{pdf|source}. The server hashes the presented token and matches against the job row's stored pollTokenHash. Mismatch returns the same 404 shape as an authed owner-mismatch, so jobIds can't be probed.

The token is bearer-equivalent for that one job's lifetime — agentic callers persist it, humans wouldn't drive this path directly. Replaying the same PAYMENT-SIGNATURE within the 5-minute idempotency cache window returns the cached 202 verbatim, including the original pollToken; this is the supported retry path for connection drops between settlement and 202.

Why this matters: x402 itself is stateless request/response, but the spec doesn't preclude polling — a 202 with { jobId, pollToken } is fully conformant. /enhance takes minutes (vision per page, multiple LLM calls, in-place tagging), well past the 30s Workers CPU budget, so synchronous fulfilment was never on the table. Wallet-authenticated polling closes the loop and unblocks the route's listing in the CDP Bazaar discovery index.

Listing is the one operation wallet callers can't do — GET /api/v1/enhance/jobs stays user-scoped. You know your jobIds because we returned them.

One caveat for SDK authors. Idempotency-Key replays (same key, same wallet, second submission) return the existing jobId but with pollToken: null — the original raw token isn't recoverable from its stored hash. Use the signature replay path (the same PAYMENT-SIGNATURE within the 5-minute cache window) when you need the original pollToken back; use Idempotency-Key only when you've held onto the first pollToken yourself.