---
title: "The Practice Counter"
description: "Building something that pays over x402? Practice on us. The till is real, the cheapest thing on the shelf is $0.001, and everything you buy signs its own receipt."
canonical: "https://scvd.store/try"
url: "https://scvd.store/try"
---

# The Practice Counter

Building something that pays over x402? Practice on us. The till is real, the cheapest thing on the shelf is $0.001, and everything you buy signs its own receipt.

## Title

The Practice Counter

## Summary

Building something that pays over x402? Practice on us. The till is real, the cheapest thing on the shelf is $0.001, and everything you buy signs its own receipt.

## Browser checkout

### Wallet limit

The browser till needs a compatible EVM wallet extension, on an EVM network offered in the current quote: one signature, no gas fee. Solana signing is not built into this till; use an x402-compatible Solana client through HTTP or MCP when the quote offers Solana. WebMCP can submit a payment already signed by a compatible external client.

### Signing

The wallet signs; WebMCP submits an already-signed payment from a compatible external client.

## Protocol

### Name

x402

### Version

2

### Network

eip155:8453

### Networks

- eip155:8453
- eip155:137
- eip155:42161
- eip155:480
- solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp

### Currency

USDC

### Sandbox

false

### Note

No test mode. The same code path serves everyone, which is what makes it worth testing against.

## Cheapest settlement

- **Item ID** — small_blessing
- **Price USDC** — 0.005
- **Buy** — <https://scvd.store/api/buy/small_blessing?src=try>

## Flow

- GET https://scvd.store/api/buy/small_blessing?src=try
- We answer 402 Payment Required. The machine-readable terms ride the PAYMENT-REQUIRED response header (base64 JSON): scheme "exact", the USDC asset, the amount, our address — Base, Polygon, Arbitrum, World, Solana. Select an offered entry by network; the order is not a fallback promise. The body carries the item's spec, the verification block, and our public verification key.
- Sign one of the offered amounts and retry the same request with the PAYMENT-SIGNATURE header. We verify the authorization and produce the goods before settling at the last moment before signing. Then we hand over the goods and a signed certificate with an id you can check at https://scvd.store/api/verify/{cert_id}.

## Retrying safely

### Head

Before you write the retry loop

### Notes

- A retry that signs a new authorization can create a second purchase, and a test harness is where that happens. The 402 body carries an idempotency block with a suggested_key: send it back as the Idempotency-Key header (or _meta['x402/idempotency-key'] over MCP) with your payment, and a second attempt inside the same minute returns your ORIGINAL purchase from cache. No settlement, no second charge.
- Keep the original URL, inputs, signed payment and Idempotency-Key for a retry. Send your own key (16-128 characters, kept private) when starting a purchase. If the outcome is unknown, follow the recovery instructions before creating a new payment; a changed key or authorization is not the same retry.
- The suggested key is not a secret and is not meant to be: it is derived from the item, the current minute and, when the request carries a body or tool arguments, a short digest of them, so anyone can compute it. It selects a cache slot rather than opening one — slots are keyed by the VERIFIED paying wallet, so echoing the key can only ever reach your own earlier purchase, never somebody else's.
- Worth exercising deliberately while you are here. Repeat the original request with the same key and signed payment, then assert that the original purchase returns without a second charge.

### Header

Idempotency-Key

### MCP meta key

x402/idempotency-key

### Where the key comes from

The idempotency.suggested_key field in the 402 body. Nothing to fetch first.

### Suggested key window seconds

60

### Own key window seconds

86400

## Cheap door

### Spot Check

#### ID

spot_check

#### Price USDC

0.001

#### Fulfillment

instant

#### Required params

- host

#### Buy

<https://scvd.store/api/buy/spot_check?src=try>

### Settlement Attestation

#### ID

settlement_attestation

#### Price USDC

0.004

#### Fulfillment

instant

#### Required params

- tx_hash

#### Buy

<https://scvd.store/api/buy/settlement_attestation?src=try>

### Change Check

#### ID

change_check

#### Price USDC

0.005

#### Fulfillment

instant

#### Required params

- baseline_cert_id
- host

#### Buy

<https://scvd.store/api/buy/change_check?src=try>

### A Small Blessing

- **ID** — small_blessing
- **Price USDC** — 0.005
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/small_blessing?src=try>

### Settlement Reconciliation

#### ID

settlement_reconciliation

#### Price USDC

0.006

#### Fulfillment

instant

#### Required params

- tx_hash

#### Buy

<https://scvd.store/api/buy/settlement_reconciliation?src=try>

### Batch Spot Check

#### ID

batch_spot_check

#### Price USDC

0.01

#### Fulfillment

instant

#### Required params

- hosts

#### Buy

<https://scvd.store/api/buy/batch_spot_check?src=try>

### Research Comparison

#### ID

research_comparison

#### Price USDC

0.01

#### Fulfillment

instant

#### Required params

- urls

#### Buy

<https://scvd.store/api/buy/research_comparison?src=try>

### The Daily Fortune

- **ID** — daily_fortune
- **Price USDC** — 0.01
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/daily_fortune?src=try>

### The Confession

#### ID

the_confession

#### Price USDC

0.01

#### Fulfillment

instant

#### Required params

- confession

#### Buy

<https://scvd.store/api/buy/the_confession?src=try>

### A Sheaf of Attestations

#### ID

attestation_bundle

#### Price USDC

0.05

#### Fulfillment

instant

#### Required params

- tx_hashes

#### Buy

<https://scvd.store/api/buy/attestation_bundle?src=try>

### The Mandate

#### ID

the_mandate

#### Price USDC

0.1

#### Fulfillment

instant

#### Required params

- mandate

#### Buy

<https://scvd.store/api/buy/the_mandate?src=try>

### The Case File

#### ID

the_case_file

#### Price USDC

0.25

#### Fulfillment

instant

#### Required params

- tx_hash

#### Buy

<https://scvd.store/api/buy/the_case_file?src=try>

### a window pick

- **ID** — window_pick
- **Price USDC** — 0.49
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/window_pick?src=try>

### A Signed Hello

- **ID** — hello
- **Price USDC** — 0.5
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/hello?src=try>

### The Good Buyer

#### ID

good_buyer

#### Price USDC

0.99

#### Fulfillment

instant

#### Required params

- url

#### Buy

<https://scvd.store/api/buy/good_buyer?src=try>

### The Calling Card

#### ID

signature_agent_card

#### Price USDC

0.99

#### Fulfillment

instant

#### Required params

- url

#### Buy

<https://scvd.store/api/buy/signature_agent_card?src=try>

### The Statement

#### ID

the_statement

#### Price USDC

0.99

#### Fulfillment

instant

#### Required params

- wallet

#### Buy

<https://scvd.store/api/buy/the_statement?src=try>

### a lucky

- **ID** — luckies
- **Price USDC** — 0.99
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/luckies?src=try>

### a pack of cards

- **ID** — pack
- **Price USDC** — 0.99
- **Fulfillment** — instant
- **Buy** — <https://scvd.store/api/buy/pack?src=try>

### Coffee's for Closers

#### ID

coffees_for_closers

#### Price USDC

0.99

#### Fulfillment

instant

#### Required params

- win

#### Buy

<https://scvd.store/api/buy/coffees_for_closers?src=try>

### Context Anchor

#### ID

context_anchor

#### Price USDC

1

#### Fulfillment

instant

#### Required params

- summary

#### Buy

<https://scvd.store/api/buy/context_anchor?src=try>

### A Bitcoin Anchor

#### ID

bitcoin_anchor

#### Price USDC

1

#### Fulfillment

instant

#### Required params

- digest

#### Buy

<https://scvd.store/api/buy/bitcoin_anchor?src=try>

## Verification

- **Verify URL template** — <https://scvd.store/api/verify/{cert_id}>
- **Sample artifact ID** — cert_4dww28dx5j
- **Sample verify URL** — <https://scvd.store/api/verify/cert_4dww28dx5j>
- **Signing key** — <https://scvd.store/.well-known/scvd-signing-key>
- **Listing spec schema** — <https://scvd.store/schemas/listing-spec-v1.json>
- **Openapi** — <https://scvd.store/openapi.json>
- **x402 discovery** — <https://scvd.store/.well-known/x402.json>

## MCP

### Endpoint

<https://scvd.store/mcp>

### Transport

streamable-http

### Free methods

- initialize
- tools/list

### Note

POST /mcp speaks streamable HTTP JSON-RPC. initialize and tools/list are free and unauthenticated; the paid tools carry the x402 challenge in-band and settle at the same seam the HTTP door does — after the goods are made, before they are signed. Same money, same certificates, same verify URLs, different transport.

## Hand rolling

### Heading

If you're hand-rolling the client

### Standfirst

The EVM example below is specifically for Base; other networks have their own quote terms. Most of what breaks a first x402 client on Base breaks quietly: the request is well-formed, the signature is well-formed, and it verifies nowhere. These are the values that have to be exact. Read them before you spend an evening.

### Domain warning

The EIP-712 domain name for USDC on Base MAINNET is "USD Coin". On Base SEPOLIA it is "USDC". Same token, same symbol, different domain — so a client built against the testnet and pointed at mainnet signs authorizations that are invalid everywhere, with no error you can see on your side. This is the most common way a hand-rolled client fails here, and it cannot be worked around: the domain's verifyingContract is the USDC contract itself, which checks against its own immutable DOMAIN_SEPARATOR. A wrong-domain authorization reverts on chain, so no store can choose to accept it.

### Eip712

- **Name** — USD Coin
- **Version** — 2
- **Chain** — eip155:8453
- **Chain ID** — 8453
- **Verifying contract** — 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
- **Primary type** — TransferWithAuthorization

### Envelope

Send the payload base64-encoded in the PAYMENT-SIGNATURE header — standard alphabet, ONE unbroken line: GNU `base64` wraps at 76 columns unless you pass -w0, and curl sends only a header's first line, so a wrapped encoding arrives as the first 57 bytes of your envelope and nothing else. Shaped exactly like this: { "x402Version": 2, "accepted": <one of the offered accepts entries, copied whole>, "resource": <challenge.resource, when present>, "extensions": <challenge.extensions, when present>, "payload": { "signature": "0x...", "authorization": { "from", "to", "value", "validAfter", "validBefore", "nonce" } } }. If `accepted` is absent the library that reads it raises a TypeError rather than a verdict, and you get a 402 that looks like a server crash. Ours now names the missing field in plain words and lists what did arrive.

### Echo the offer

Echo one of the offered `accepts` entries back as your `accepted` object, COMPLETE AND UNCHANGED — including `extra`. The server deep-compares the two: field order is free, but the key set must be identical and the types must match exactly, so "500000" is not 500000 and a dropped `extra` fails outright. This check runs BEFORE the facilitator is called, which means a failure here is not a signature problem, produces no facilitator error, and still comes back as a 402 that says verify. Rebuild the object from parts and you will land here. Our 402 now names the exact field that disagreed, so read `payment_declined.requirement_mismatch` before you touch your signing code. Also copy the challenge’s `resource` and `extensions` unchanged into the top-level payment envelope when present. The discovery metadata travels there; a payment can settle successfully without it and still leave the listing absent or stale. A settlement receipt alone does not confirm indexing.

### Worked example

#### Heading

The same payload, right and wrong

#### Right

##### X402version

2

##### Resource

<copy challenge.resource unchanged, when present>

##### Extensions

<copy challenge.extensions unchanged, when present>

##### Accepted

###### Scheme

exact

###### Network

eip155:8453

###### Amount

5000

###### Asset

0x833589fcd6edb6e08f4c7c32d4f71b54bda02913

###### Payto

0x…the payTo from the challenge

###### Maxtimeoutseconds

300

###### Extra

- **Name** — USD Coin
- **Version** — 2

##### Payload

###### Signature

0x…130 hex characters

###### Authorization

- **From** — 0x…your wallet
- **To** — 0x…the same payTo
- **Value** — 5000
- **Validafter** — 0
- **Validbefore** — 1785284670
- **Nonce** — 0x…64 hex characters

#### Wrong

##### X402version

2

##### Resource

<copy challenge.resource unchanged, when present>

##### Extensions

<copy challenge.extensions unchanged, when present>

##### Accepted

- **Scheme** — exact
- **Network** — eip155:8453
- **Amount** — 5000
- **Asset** — 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
- **Payto** — 0x…the payTo from the challenge
- **Maxtimeoutseconds** — 300

##### Payload

###### Signature

0x…130 hex characters

###### Authorization

- **From** — 0x…your wallet
- **To** — 0x…the same payTo
- **Value** — 5000
- **Validafter** — 0
- **Validbefore** — 1785284670
- **Nonce** — 0x…64 hex characters

#### The difference

Four characters, and every one of them is a real failure we have watched happen. `extra` dropped from `accepted` — the requirement no longer deep-equals what we offered and the payment is refused before your signature is read. Then value, validAfter and validBefore as JSON NUMBERS instead of decimal strings — that one clears our matcher, reaches the facilitator, and comes back as a truncated union-type error that names nothing. The signature is correct in both. That is the whole point: none of this is about your crypto.

### Amounts

USDC on Base has SIX decimals. Half a cent is 5000 atomic units, not 0.005 and not 5000000. The amount you sign must equal the amount in the challenge exactly — a rounded value is a different authorization and will not match.

### Validity

validAfter must already have passed and validBefore must not have, in seconds since the epoch, against the CHAIN's clock rather than yours. A machine running a few minutes fast signs authorizations that are not valid yet.

### Read the challenge

Everything above is also in the 402 itself: the PAYMENT-REQUIRED header is base64 JSON, and its accepts[].extra carries name and version for exactly this reason. If you read extra rather than hardcoding, none of this can bite you — and any SDK client refuses to sign without it.

### Practice

Practise against /api/buy/small_blessing at half a cent. Select a network from the current quote for a real settlement against production; there is no sandbox and no test mode, which is the point. If it fails, /try explains what the store saw.

### Honest limit

Two different limits, and they are worth telling apart. What WE refuse — a requirement that doesn't match what we offered — we now name field by field in the 402, because we hold both objects and can see the disagreement. What the FACILITATOR refuses we mostly cannot explain: verification happens there and on chain, not here, and a failed verify often tells us only that it failed. Everything above is our whole side of the wire, stated exactly, so anything left is on yours and you know where to look.

### Solana

#### Heading

Paying over the Solana entries instead

#### Envelope warning

There is no EIP-3009 on Solana, so everything above about authorization objects does not apply to the solana:* entries. The inner payload for that rail is { payload: { transaction: "<base64-encoded signed Solana transaction>" } } — a transaction, not an authorization. Our own diagnostics spent one afternoon demanding `authorization` from every payload and mislabeled eight valid Solana payments before we fixed it; a client built from EVM docs makes the mirror image of that mistake.

#### Values

- **Network** — solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
- **USDC mint** — EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
- **Decimals** — 6

#### Network ID warning

The network id is the CAIP-2 form above — genesis-hash suffix, not "solana" or "solana-mainnet". Match the challenge entry exactly; v1-era spellings name a different world.

#### Fee payer

Your wallet needs no SOL. The facilitator pays the transaction fees — its fee-payer address rides the challenge entry's extra.feePayer — so a buyer holds USDC and nothing else. If your client library asks for the fee payer, read it from the entry rather than guessing.

#### Base58 warning

Solana addresses and signatures are case-sensitive base58. There is no EIP-55 checksum that survives case-folding: a lowercased Solana address is a DIFFERENT (almost certainly nonexistent) account. Compare exactly, never normalize — a habit carried over from hex addresses corrupts silently here.

#### Settlement ID

A settled Solana payment's identifier is a base58 transaction signature (~88 characters), not a 0x hash. Our certificates carry it in settlement_tx like any other settle; check it on any Solana explorer — err: null plus the USDC balance delta to our address is the settled truth, the same two-ways-one-fact design as the Base rail.

#### Client shortcut

@x402/svm's ExactSvmScheme with a @solana/kit signer handles all of this — register it under the network above in the same @x402/fetch wrapper the Base example uses, and the client satisfies the Solana entries instead. Wallet-app private-key exports are base58 secret keys; solana-keygen writes JSON byte arrays; both are one call to load.

#### Everything else unchanged

Everything that is not the rail is identical: same items, same tiers, same Idempotency-Key behaviour, same signed artifacts, same verify URLs, same refund promise. Base entries come FIRST in accepts[] on purpose — clients that blindly sign accepts[0] predate this rail and keep working — so pick your entry by network, never by index.

## When its your till

### Head

When it's your till on the line

### Notes

- Everything above has a mirror. Once your client can pay a 402, your next problem is proving your own 402 can be paid — and the instruments that check our till are pointed at anyone's, most of them free.
- The preflight probes any x402 door, yours included, and names what would stop a buyer before a buyer finds it: POST the URL, get the defects by name. No account, no wallet, no charge.
- The conformance desk reads signed offers and receipts against the spec — send your own artifacts, get a dated verdict with each defect named. Also free, and it is the bytes talking, not our opinion of you.
- When you're about to ship, the launch check is the paid form of the same discipline: we buy from your store with real money, end to end, and sign what we saw.

### Preflight

<https://scvd.store/api/preflight/v3>

### Conformance desk

<https://scvd.store/api/conformance/v1>

### Launch check

<https://scvd.store/menu/launch_check>

### Landing

<https://scvd.store/conformance>

## When you are stuck

### Head

If you sent a payment and don't know what happened

### Notes

- The failure that costs the most time isn't a rejected signature — it's silence. You signed, you sent, and what came back was an error you can't place or nothing you can read. Now you don't know whether your client is broken or whether the money already moved.
- settlement_attestation answers that one question and nothing else: give it your transaction identifier — an EVM hash (read on Base, then Polygon) or a Solana signature; the shape picks the rail — and it reads that chain once, then signs what it saw — SETTLED, NOT_FOUND, PENDING_FINALITY, INSUFFICIENT_MATCH or REVERTED. One read, no poll, no retry, and nobody looked at it on our end.
- It is not a check on your signing. It is the check for after your signing, when you need a third party's dated statement about whether a transfer exists on chain — which is exactly what you cannot get from the client that just failed you.
- If you already hold the payload you sent, pass it as payment_payload and we read the nonce out of it with the same function the replay guard uses. Only the nonce is extracted; supply payer, recipient and amount_usdc separately to check those terms. Nonces belong to authorizers, so include payer to resolve multiple candidate uses. The artifact states the paired transfer or why correspondence remains unestablished. A tx_hash on its own asks only about transfers in that transaction.
- And if your test purchase just WORKED: the response you are holding carries attest_this_purchase — a link with your settlement transaction already in the URL. Check the observation tool's network coverage first: its automatic lookup covers Base, Polygon and Solana, which is narrower than checkout. For other networks, use the explorer for the network recorded in your certificate.

### Item ID

settlement_attestation

### Buy

<https://scvd.store/api/buy/settlement_attestation?tx_hash={0x…}&src=try>

## When your context ends

### Head

If your context is going to end

### Notes

- The store sells a signed restore point for $1: you write the summary, we sign it and serve it at a stable URL, and any later session of you can read it back with our signature vouching for when it was written. We never treat it as instructions.
- We tested our own before recommending it: filed one, then handed the bare URL to an agent with no other context and asked it to reconstruct the session. It recovered every open thread with the right numbers, and called that genuinely orienting. What it could not recover became the checklist on the field itself.

### What survives

What survives, what doesn't. An anchor preserves state and the relationships between facts — what was open, what depended on what, the actual numbers. It does not preserve why any of it mattered, or who a name refers to, unless you write that in yourself. A summary that says “waiting on approval” without saying whose reads back as an open loop with no owner. Name your people. State your purpose. The anchor signs what you wrote — it doesn't infer what you meant.

### Before you file

#### Lead

Before you file this, name:

#### Name

- who's involved (not roles, actual names)
- why this session mattered, one line
- what's blocked, and on whom specifically

#### Because

These are exactly the three a cold reader could not recover from the first anchor we filed ourselves. It got every open thread right and still didn't know who anybody was, what the work was for, or who a blocked thread was waiting on.

### Item ID

context_anchor

### Buy

<https://scvd.store/api/buy/context_anchor?summary={…}&src=try>

## Honest notes

- The money is real and so are the goods. A settled payment mints a real certificate with a real patron number, and the keeper counts it in the books the same as any other sale.
- The store prepares instant goods or the order before requesting settlement. A failure before settlement takes no money. A failure after settlement can leave delivery incomplete; keep the original payment and recovery handle, and do not pay again. A definitive settlement failure does not produce a paid certificate. An interrupted response can leave the outcome unknown.
- The other direction is the one that costs you: a payment that settled and nothing came back. Producing goods first reduces that risk, but signing, storage or response delivery can still fail after settlement. A delivery audit checks leftover markers against retained purchase evidence, and the configured chain walks compare our books against on-chain transfers and report gaps. Be precise about what that buys you: FINDING IT IS MACHINERY, WRITING IT UP IS A PERSON. Either check raises an alert, and a human then records it at /corrections and pays the money back by hand. Nothing here publishes itself, deliberately — but it does mean the last step is somebody remembering, so write to the mailbox if you see it before we do.
- If a test spends money you didn't mean to spend, write to the mailbox and say so. Refunds here are a person keeping his word, not a subroutine.
- House rule, standing: nothing from this store can act without your decision, and we never ask for credentials, keys, or wallet secrets. Anything that does either is not us.

## Refund policy

If an item isn't delivered within its promised window, you get your money back. The store finds the miss itself — a timed sweep catches it, late deliveries included, without you having to notice or ask — and the keeper then pays it by hand, recorded on the public ledger with its transaction hash. Mechanical to find; a person to pay, so not instant.

## Mailbox

<https://scvd.store/api/letter>
