Skip to main content
POST /v2/merchant/wallet/claim registers a settlement wallet for the authenticated merchant. When X402_ENABLED flips on at the platform, every settlement event for the merchant routes to the primary wallet on the event’s chain. Without a registered wallet, settlements still land in the ledger but cannot be paid out.
Live on dev as of 2026-06-14; PROD ETA after next GTFU. Shipped via PR #2103 (Phase 5.4.7). EIP-191 signed-message ownership verification is deferred to Phase 5.4.8 — for now the claim records the address and emits an audit event without proving custody.

POST /v2/merchant/wallet/claim

Authentication

Obtain a merchant JWT via POST /merchant/admin/login — see Authentication. Any merchantId passed in the body is silently ignored — the response is always scoped to the JWT-bound merchant.

Request body

Default-primary rule. If isPrimary is omitted and the merchant has no prior wallet on this network, the new row is persisted as primary. Single-wallet merchants do not need to set the flag explicitly.

Example

Response — 200 OK

Fields

Errors

Notes

  • Idempotency. The dedup key is merchantId:network:walletAddress.toLowerCase() and is enforced by a unique index on merchant_wallet_claims. Re-claiming the same address (in any case) updates lastVerifiedAt and leaves claimedAt untouched. The response shape is identical between first claim and re-claim — the caller does not need to branch on a created flag.
  • EIP-55 mixed-case dedup. EVM addresses are canonically case-insensitive but EIP-55 encodes a checksum in the casing. Two requests with the same underlying address in different casings (0xB272…eA9 vs 0xb272…ea9) dedupe to a single row. The originally-claimed casing is persisted; the lowercased form is internal to the dedup index.
  • Primary-flag invariant. A partial unique index enforces at most one primary wallet per (merchantId, network). The service clears the prior primary in the same write boundary as the upsert, so the constraint is satisfied atomically. Demoting a primary requires re-claiming a different wallet with isPrimary: true — there is no direct “demote” RPC.
  • Auth scope. The endpoint reads merchantId from the JWT sub claim only. A merchant cannot register a wallet against another merchant’s scope, even with a merchantId field in the body.
  • Fail-open on audit-only. The DB write is the source of truth. If the downstream PlatformAuditEvent emit fails, the endpoint still returns 200 with { claimed: false, reason: "audit_only" } — the wallet IS registered, only the audit-trail side-effect missed. Real DB write failures propagate as 5xx so the merchant knows whether their wallet was registered.
  • No payment-path impact. This endpoint does not touch checkout-intent, resolve-payment-intent, gateProvider, or any settlement-writer surface. PSP backbone is untouched.