Skip to main content
Private alpha. The x402 payment-link surface is ecosystem-partner access only and not yet stable. Endpoint shapes, error codes, and chain support will change before general availability — coordinate with your account manager before any production integration.
A payment link is part of Atomic Money — Sumvin’s payments, ramps, cards, and settlement layer. It is a shareable URL that carries a signed PurchaseIntent: the user’s Stamped Mandate authorising the payment, delivered on the wire as a PINT. A person opens it in a browser and is bounced to the canonical payer-facing resource. A machine hits the same URL with Accept: application/json and receives a 402 Payment Required challenge over x402. Both paths converge on the same signature. One URL, two audiences, one PINT underneath.
This guide is for partners in the x402 private alpha. If you have not yet read the Payment Links and x402 concept page, start there — it frames the mental model this quickstart assumes.
01 / PREREQUISITES

Before you start.

Three things have to be in place before the first call lands. Each is a one-time setup step for the owner account.
  • A Platform API credential. Every owner-facing route (POST /v0/payment-links, list, detail) requires a user-status gate — the authenticated account must be onboarded to at least pending. See authentication for the JWT flow.
  • A signer wallet. The PurchaseIntent carried by the link is an EIP-712 payload signed by the owner’s wallet. The signature is the cryptographic anchor — the link’s slug is literally the signature bytes, base64url-encoded. See PINTs for the mint flow, scope catalogue, and the canonical EIP-712 domain.
  • A payer-side wallet that speaks x402. Any EIP-3009-capable wallet on a supported chain can settle the link. Browser payers land on the hosted pay view; agents negotiate the 402 handshake directly.
The x402 surface is in private alpha for ecosystem partners. Access is staged — the contract below is the shape partners build against today, not a GA promise.
02 / CREATE A LINK

Sign once, share forever.

A payment link is created with a single POST. The owner signs the inner PurchaseIntent with their wallet, submits that payload alongside the hex ECDSA signature, and the API returns a PaymentLinkResponse whose slug is deterministically derived from the signature bytes. Re-signing the same intent produces the same slug — this is intentional and guards against duplicate issuance.
1

Sign the PurchaseIntent payload

The inner payload is an EIP-712 PurchaseIntent struct. See PINTs for the domain separator, type definitions, and a signing walkthrough. The output is a 130-hex-character ECDSA signature (0x + r + s + v).
2

POST to /v0/payment-links

Submit the payload, signature, accepted chains, and an expiry. The API verifies the signature against the payload, mints the underlying PINT, derives the slug, persists the link, and returns the full response with navigation.
3

Share the slug or the pay URL

The owner keeps two artifacts: the slug (the canonical ID) and _links.pay.href (the public URL to share with a payer).

Request

See POST /v0/payment-links for the full parameter and response schema reference.

Request fields

The link’s expires_at is epoch milliseconds. The inner pint.expires_at is epoch seconds — the EIP-712 convention the signed payload carries. The API normalises both to milliseconds on the server, and the effective expiry is the stricter of the two. See section 05.

Response — 201 Created

Key response fields

The slug is the signature. Two links cannot exist for the same intent.
03 / SHARE AND INSPECT

Three surfaces, one truth.

A payment link speaks through three surfaces: the shareable pay URL, the public payer view, and the owner-scoped inspection endpoints. They are three windows onto the same persisted object — nothing about the link changes based on which surface reads it.

The shareable pay URL — /pay/{slug}

See GET /pay/{slug}. This is the URL you hand to a payer. It is protocol-agnostic: a browser gets an HTML page that meta-refreshes to the public view; an agent sets Accept: application/json and begins the x402 handshake. See section 04 for the agent path.
The pay URL is unauthenticated and rate-limited at 60 requests per minute per IP.

The public payer view — GET /v0/payment-links/public/{slug}

See GET /v0/payment-links/public/{slug}. A payer-facing JSON projection safe to render without authentication. It omits what the owner should not share publicly and includes the full signed EIP-712 mandate so a wallet or agent can verify the signature locally before settling.
This endpoint has its own rate limits and returns 410 Gone with PAYMENT_LINK_EXPIRED once the effective expiry has passed.

Owner inspection — authenticated

The owner can fetch a single link or list their links with filters. Both endpoints require the same JWT used for creation. Get one link:
Full schema: GET /v0/payment-links/{slug}. Returns the same PaymentLinkResponse shape as POST. If the slug does not exist — or exists but belongs to another user — the response is 404 PAYMENT_LINK_NOT_FOUND. Ownership is not disclosed. List with filters:
Full schema: GET /v0/payment-links. The response carries HAL pagination with all filters preserved across pages:
The pay URL is for payers. The inspection endpoints are for owners. Same object, different audiences.
04 / THE x402 HANDSHAKE

Two round trips. One signature.

An agent that resolves /pay/{slug} sets Accept: application/json and receives a 402 Payment Required response carrying an x402 v2 challenge. The agent signs the challenge with its payer wallet, base64-encodes the signed envelope, and retries the same URL with the envelope in the PAYMENT-SIGNATURE header. The server validates the envelope, dispatches to the x402 facilitator, and returns a settlement receipt.

The 402 challenge shape

On the first hit (Accept: application/json, no PAYMENT-SIGNATURE), the response is 402 X402PaymentRequired:
One accepts entry is returned per chain in the owner’s accepted_chains, in the order the owner provided. Only the exact scheme is supported today; an envelope carrying a different scheme is rejected with 400 PAYMENT_LINK_X402_UNSUPPORTED_SCHEME.

The retry

The agent constructs an x402 signed-payload envelope, base64-encodes it (standard base64, not base64url), and retries:
The envelope itself is validated at the route layer — x402Version, scheme, and network are checked against the link’s accepted set. The inner payload is scheme-specific (EIP-3009 fields for exact on EVM) and is carried opaquely to the facilitator. A successful retry returns 200 X402SettlementResponse:
A retry against a link that has already been settled returns 409 PAYMENT_LINK_ALREADY_SETTLED regardless of envelope validity — the check sits above the signature branch. The signature does not reopen a closed link.
05 / LIFECYCLE AND EXPIRY

Pending. Settled. Expired.

A payment link has three lifecycle states. settled and expired are terminal. Effective expiry is the stricter of payment_link.expires_at and the underlying pint.expires_at. Both are persisted as epoch milliseconds — the API normalises the PINT’s seconds-valued EIP-712 input on the server. Whichever deadline comes first closes the window for both the public view and the agent pay route. Once a link is settled, further retries return 409 PAYMENT_LINK_ALREADY_SETTLED. The public view continues to render — settled_at, tx_hash, and payer_addr are now populated and serve as a permanent receipt. A settled link is a permanent record, not a deleted one.
06 / ERRORS

RFC 7807, everywhere.

Every error is returned as RFC 7807 Problem Details with a stable error_code. The ones a partner will encounter most: The instance field on each error points to the route that emitted it; the trace_id field ties it to your Logfire span for support. One format, one code space — read the code and act.
07 / SEE ALSO

Payment Links and x402

The concept page — why the URL and the 402 carry the same signature, and what the verifier checks.

Purchase Intents (PINTs)

The signed primitive underneath every payment link. Mint flow, scopes, and EIP-712 shape.

Accept a PINT at checkout

The verifier-side flow — what a merchant does when a payer presents a PINT JWT.

Error handling

Full RFC 7807 reference and the stable error-code catalogue.

Reference

Supported chains

At private-alpha launch, Sei is the settlement network. Base, Optimism, and Tempo follow shortly after. The accepted_chains field stays enum-typed across the roster — code against the enum and new networks surface without an API change.

Lifecycle statuses

x402 schemes

Questions.

The link accepts settlements until its effective expiry. Most integrations want max_uses: 1 — it is the safer default for invoice-style flows.
The owner view mirrors the create response — it is the authoritative object, including pint_uri and usage_count useful for reconciliation. The public view adds the full EIP-712 message, signature, and nonce so a payer wallet can verify locally before settling. Neither view exposes anything that would compromise the link.
Sei at launch. Base, Optimism, and Tempo follow shortly after. The Sei testnet (1328) is available for integration testing. The accepted_chains field stays enum-typed across the roster — code against the enum and new networks surface without an API change.