# The Trade Counter

Round the back, for marketplaces. Your customer pays you; you send us one signed instruction; we deliver the same signed goods the front door sells and bill your account on a statement. Your customer never touches x402.

A trade account on this store's shelf: any platform that resells to agents — a marketplace, an aggregator, a payments layer that hides x402 from its own users — lists our instruments under its roof, collects its customer's money itself, and orders from us by signed webhook. One door, one JSON body, one signed instruction per sale, delivery in seconds, a certificate the end customer can verify against our public key without trusting either of us.

Trade price is retail plus 20% net of your share, rounded up to the cent, billed per delivery and never for a delivery that did not happen.

## Try it now, no account
The sandbox account signs with a published secret: `scvd-trade-sandbox-secret-anyone-may-use` (provider key `scvd-trade-sandbox-key`, dialect `canonical`). Real signatures checked, real goods delivered and marked test, a certificate that verifies at /api/verify, and nothing booked to anyone. The check desk on this account prints the signature we expected, since the secret is public anyway. 50 deliveries a day. Start at the check desk: `POST https://scvd.store/api/trade/sandbox/check` with the headers and body you would send to `https://scvd.store/api/trade/sandbox/{item_id}`.

## Why a marketplace would
- **Your customer gets a receipt that is not your word or ours.** Every item mints an ed25519-signed certificate that verifies against a published key, offline, forever. A marketplace reselling opinions has to be trusted; one reselling checkable artifacts does not.
- **No x402 in your customer's path, and none required of you.** One signed POST. No wallet, no facilitator, no chain, no gas. You already know how to sign a webhook; that is the whole integration.
- **The prices are a rule, not a negotiation.** Trade price is retail plus a published uplift, divided by one minus your share, rounded up to the cent. Printed per item at /api/trade/contract. What you charge above it is your business.
- **Delivery first, always.** The goods are produced before anything is booked. A failed delivery leaves no line on your statement, so you never owe for something your customer did not get.
- **You can be integrated before you have talked to anyone.** A sandbox account with a published secret, a check desk that names which of the four signature checks failed, and a catalog feed with every item's copy, specimen and price at your share. Write to the keeper already working.
- **Everything you would want to audit is already public.** Your account's terms, the shelf you may order from, your receivable, the refusal codes by name, the reference signer, and every correction this store has ever had to make.

## How it works
0. **The sandbox, first.** Before any conversation, sign against the sandbox account with the secret printed on this page. Real signatures, real goods, marked test, booked nowhere. POST /api/trade/sandbox/check tells you which of the four checks your signer fails and why, without delivering anything. _Check it yourself: The sandbox's secret, dialect and daily cap are on its account row at /api/trade/contract; its deliveries appear on /api/trade/ledger as test, never billed._
1. **The account.** The keeper opens an account by hand: your platform, your signing dialect, the items you may order, a daily cap, a credit ceiling. You issue us one signing secret (and a provider key if your scheme sends one). We hold them as Worker secrets; nothing of ours is ever asked of you. _Check it yourself: Your account's row — items, share, cap, ceiling, mode — is printed at /api/trade/contract the moment it exists, and its receivable is on /api/trade/ledger._
2. **The sale, on your side.** Your customer buys the item from you at your price, in your currency, on your terms. We are not in that transaction and never see it. _Check it yourself: Nothing to check with us — which is the point. Our trade price per item is public; what you charge above it is yours._
3. **The instruction.** Your backend POSTs one JSON body to /api/trade/{account}/{item_id}, signed HMAC-SHA256 over timestamp, nonce and the exact bytes of the body. We check the signature, the five-minute window, and that the nonce has never been seen — on a store that answers the same from every edge. _Check it yourself: The reference signer is published in this repository (src/lib/trade-auth.ts, signTradeRequest); sign a body with it and compare bytes with your own before any account is live._
4. **The delivery.** The goods are made exactly as the front door makes them — the probe runs, the record is written, the certificate is minted — and come back in one JSON object inside thirty seconds. A delivery that fails books nothing: no statement line, no receivable. _Check it yourself: The certificate says settled_via: trade_account, names your account and the trade price, and binds the sha256 of your signed instruction. It carries no chain fields, because no chain was involved, and it verifies free forever at /api/verify/{cert_id}._
5. **The statement.** Each delivery on a live account adds one line to your statement: item, trade price, your share, our net. Outstanding net is the receivable, published per account. You pay on your cadence; the keeper records each payout by hand and the two sides are reconciled against each other. _Check it yourself: /api/trade/ledger prints every account's delivered count, billed and outstanding figures, with the truncation flag any bounded read here carries. Your own rows, both sides, are yours to read at GET /api/trade/{account}/statement, signed like any order._

## The shelf at the counter
Prices at a 5% partner share; your account's row at https://scvd.store/api/trade/contract prints them at yours. List by machine from https://scvd.store/api/trade/catalog.

| Item | Retail | Trade price | Store nets | Fields |
|---|---|---|---|---|
| Certificate of Patronage | $20 | $25.27 | $24.00 | order_ref, agent_name, purpose |
| Context Anchor | $1 | $1.27 | $1.20 | summary, order_ref, agent_name, purpose |
| A Bitcoin Anchor | $1 | $1.27 | $1.20 | digest, label, order_ref, agent_name, purpose |
| The Calling Card | $0.99 | $1.26 | $1.19 | url, order_ref, agent_name, purpose |
| The Shop Window | $3 | $3.79 | $3.60 | url, order_ref, agent_name, purpose |
| The Once-Over | $5 | $6.32 | $6.00 | url, order_ref, agent_name, purpose |
| The Refresh | $1 | $1.27 | $1.20 | url, order_ref, agent_name, purpose |
| The Good Buyer | $0.99 | $1.26 | $1.19 | url, max_usd, no_spend_controls, order_ref, agent_name, purpose |
| The Company an Address Keeps | $5 | $6.32 | $6.00 | address, order_ref, agent_name, purpose |

## The call
`POST https://scvd.store/api/trade/{account}/{item_id}` with one JSON object. Sign HMAC-SHA256 over `timestamp + "." + nonce + "." + exact_raw_body` with the secret you issued us; send it as `X-Trade-Signature: sha256=<hex>` beside `X-Trade-Timestamp` (unix seconds) and `X-Trade-Nonce` (32 hex, fresh each call). Timestamps outside five minutes and nonces seen before are refused. Send `order_ref` on every call. Your own statement: `GET https://scvd.store/api/trade/{account}/statement`, signed over the empty body. Reference signer: https://github.com/seancrecord/scvd-general-store-repo/blob/main/src/lib/trade-auth.ts

### Every refusal, by name
- `404 unknown_account` — No trade account by that name. Check the path segment against your account row at /api/trade/contract.
- `503 counter_closed` — The counter cannot take orders right now: the account is not provisioned on this side, or the replay store is unreachable. Do not retry in a loop; the condition is ours to fix and the keeper is paged. Retry after a minute.
- `413 body_too_large` — The body is over one mebibyte. Send only the item's fields; the terms document lists them.
- `401 missing_headers` — A required signing header is absent. Send every header your dialect names, on every call.
- `401 bad_provider_key` — The provider key does not match the one on the account. Check which key you issued us; a rotated key needs the keeper's hand on this side.
- `401 bad_timestamp` — The timestamp is not an integer in the unit your dialect states. Unix seconds or milliseconds as your account row says, digits only.
- `401 stale_timestamp` — The timestamp is outside the window, past or future. Sign at send time with a synchronised clock; do not reuse a signed request.
- `401 bad_nonce` — The nonce is not the shape your dialect requires. Thirty-two hex characters, fresh per request.
- `401 bad_signature` — The HMAC does not verify against the secret in service or the previous one. Sign the exact bytes you send, in the order timestamp.nonce.body, and compare with the reference signer before assuming the secret is wrong.
- `409 replayed` — This nonce (or this exact instruction) has already been presented. Nothing was delivered on this call. If you are retrying a timed-out order, send order_ref and a FRESH nonce: the same order_ref returns the original delivery.
- `404 not_at_the_counter` — The item is not on your account, or not traded at the counter at all. Order from the items on your account row; ask the keeper to add one.
- `400 bad_request` — The body is not a JSON object, or the item's required field is missing or malformed. The terms document names each item's fields; the error names the one at fault.
- `400 target_refused` — The URL is not one we will probe: private, loopback, non-https, or our own hostname. Send a public https door. We do not sell audits of ourselves.
- `429 credit_ceiling_reached` — Your live account's unpaid net has reached its credit ceiling. Settle the statement; the ceiling is printed on your account row and the outstanding figure on /api/trade/ledger. The keeper can raise it.
- `429 cap_reached` — Your account has ordered its daily cap. The cap is the blast-radius bound on a leaked secret, not a rate limit; it resets at UTC midnight and the keeper can raise it.

## Questions people ask
**What does the certificate say about payment?**

That the sale settled on a trade account, which account, at what trade price, and the digest of the instruction you signed. It does not say USDC, Base, Solana or Polygon, because none of them were involved, and it does not name a payer wallet, because there was none. A receipt that claimed otherwise would be the kind of false claim this store files against other people.

**Do you verify that my customer actually paid me?**

No, and we say so on the artifact. What we verify is that YOU instructed the delivery. What we check afterwards is your statement against your payouts. A marketplace's word about its own customers is the one thing this door has to take on trust, and the daily cap, the receivable ceiling and the test mode are the shape of that trust.

**Why is the trade price above the front door's?**

Because an account is credit. The uplift covers the receivable, the reconciliation and your share, by a formula printed beside every price. If your customers would rather pay less and sign an x402 authorization, the front door is open and always will be.

**My call timed out. Did you deliver?**

Possibly. Send order_ref on every call: a retry carrying the same order_ref within a day returns the original delivery, unbilled a second time. Without an order_ref, a retry with a fresh nonce is a fresh sale.

**Can I rotate my secret without downtime?**

Yes. Tell the keeper the new secret; for the handover window both verify and the response says which one signed. Then the old one is unset.

**My signature is rejected and I cannot see why.**

POST the same headers and body to /api/trade/{account}/check. It runs the four checks and reports each — headers present, provider key, clock skew in seconds, nonce shape, and whether the HMAC verified under the secret in service, the previous one, or neither — and prints the sha256 of the signing string we computed so you can compare it with yours. It delivers nothing and consumes no nonce. On the sandbox it also prints the signature we expected.

**Who handles refunds for my customer?**

You do. You collected the payment; this store took none and cannot return any. A refund on your side does not reverse a statement line here — the goods were delivered — unless the keeper agrees one by hand.

**How do I open an account?**

Prove your signer on the sandbox first, then write to the store — POST /api/letter — with your platform, the dialect you sign in (or that you will use ours), the items you want, and expected daily volume. A human reads it. Accounts open in test mode, so you can run real calls against real goods before anyone owes anyone anything.

## What this is not
Not a payment rail: no money moves through this door, and the store does not verify that any moved through yours. Not a discount channel: trade prices sit above the front door's, by a published rule, because an account is credit. Not an escrow, a guarantor, or a dispute court between you and your customer. And not a way to buy the keeper's hands: the human-queue shelf is not at this counter.

**Honest limits.** The store sees no payment on this door and signs none. A trade certificate proves the store delivered on a signed instruction from a named account; it does not prove the account's customer paid, was refunded, or existed. The receivable is derived from delivery rows on a capped read that says when it was cut short; the daily cap is counted on eventually consistent storage and can overshoot by a unit under a race. Nothing here is a rail, and the payout side of a statement is recorded by a person.

The contract: https://scvd.store/api/trade/contract · the ledger: https://scvd.store/api/trade/ledger · this room as JSON: https://scvd.store/trade.json · corrections: https://scvd.store/corrections
