Skip to main content
This guide takes you from a fresh checkout to a signed verdict on your own x402 endpoint. You pay Selo 1.00 USDC once, Selo pays your endpoint as a real x402 client, and the selo CLI exits with a code your pipeline can trust.
A release test makes a real payment to your endpoint. Selo sends one paid request and one replay of the identical signed payment and body. If your paid route has side effects (an order, a message, a charge), point Selo at a staging route or a test SKU.

Prerequisites

  • An x402 endpoint you own on Algorand Mainnet. It must answer an unpaid request with an x402 v2 402 that offers an exact USDC payment (ASA 31566704), and it must be served over public HTTPS on the default port. Selo tests GET and POST routes priced at up to 0.50 USDC.
  • A way to publish a file at your origin. You serve one line at https://<your origin>/.well-known/selo-verification.txt to prove you own the route.
  • A Mainnet payer wallet. An Algorand account opted in to USDC (ASA 31566704) that holds at least 1.00 USDC per release test, plus enough ALGO for the account’s minimum balance and the opt-in transaction. Use a dedicated wallet that holds only what a few release tests cost.
  • Node 24 and pnpm 10.
Authorization and preflight are free. You pay only for the release test itself: 1.00 USDC to Selo. Selo pays your endpoint’s price from its own wallet. See Pricing and limits.

Run it

1

Clone and install

The CLI runs from a checkout of the Selo repository.
Terminal
pnpm selo … works from anywhere inside the checkout. Relative file paths resolve from the directory you run it in.Set two variables for the rest of this guide. Replace the URL with your own paid route:
Terminal
2

Authorize your endpoint

Ask Selo for a verification challenge for the exact URL and method:
Terminal
The CLI prints the authorization id (auth_…, status PENDING), the URL to serve, the line to serve, and the verify command to run next. The line looks like selo-verification= followed by a random token.Serve that line at https://<your origin>/.well-known/selo-verification.txt. The file may hold several lines, must answer with a 2xx status and must be at most 4,096 bytes. Then verify:
Terminal
On success the CLI prints authorization auth_…: VERIFIED, the method and route it covers, and when it expires, and exits 0. An authorization is valid for 24 hours after verification. You have 1 hour to verify a new challenge before it expires.
Check the status at any time with pnpm selo auth status --api $API --authorization auth_…. More detail in Authorize your endpoint.
3

Run a free preflight

A preflight makes one unpaid request to your endpoint, reads its 402, and tells you what the test will cost before anyone pays.
Terminal
--body is a JSON file with the request body to send. It is allowed only with --method POST; omit it for GET.An eligible preflight prints:If the target is not eligible, the CLI prints ineligible (<reason>) with a message and exits 3. Nothing is paid. The reasons are listed in Run a preflight.
You do not have to keep this preflight id. selo test runs its own fresh preflight on every run.
4

Write your release contract

Declare what a paid response must look like. Write contract.json with the status, content type and JSON Schema that your paid route actually returns:
contract.json
All three fields are optional. The schema is compiled in strict mode before anything is paid: every name in required must also appear under properties, or the CLI exits 3. See Write a release contract.
5

Run the paid release test

Export the payer wallet’s 25-word mnemonic in SELO_PAYER_MNEMONIC and run the test. The CLI never prints the mnemonic or writes it to disk.
Terminal
The Mainnet flags are required and deliberate:Before signing, the CLI prints the terms: your release, the target, the preflight, the target fee, Selo’s cap, what you pay and on which network, your approved budget and the payer address. It then prints the price, network, payTo and tag read from Selo’s live 402. It pays once and never retries a payment on its own. Every flag is documented in selo test.
6

Read the result

After the report comes back, the terminal shows:
  • verdict: PASS, FAIL or INCONCLUSIVE.
  • One check line per release check, with its status and code, for example response_contract FAIL SCHEMA_MISMATCH.
  • Any warning lines.
  • job: the job id (job_…).
  • inbound: the transaction where you paid Selo.
  • downstream: the transaction where Selo paid your endpoint.
  • report: the private report link, redacted. The full link is kept only in .selo/runs/<release>.json.
  • gate: ALLOW or BLOCK, the exit code and the reason, for example gate ALLOW (exit 0): PASS on every release check or gate BLOCK (exit 1): FAIL: response_contract.
Check the exit code:
Terminal
Look both transactions up on an Algorand explorer at https://allo.info/tx/<txId>. The inbound one always comes first.

Files the run leaves behind

Here is the summary from a real Mainnet run against the demo merchant:
selo-gate.json
Never upload or commit the .selo/ directory. It holds the private report link.

Verify the signed verdict

Anyone can check the attestation offline against Selo’s published keys. selo verify exits with the attested verdict and refuses an attestation for any other release, URL or method:
Terminal
For CI, download the key set once, review it and commit it, then pass the file to --keys instead of the URL. See Verify a signed verdict.

Troubleshooting

Interrupted runs are covered in detail in Recover an interrupted run.

Next steps

Gate deploys in GitHub Actions

Run the free preflight on every build and promote only a signed PASS.

How Selo works

The two payment legs, the order they happen in, and how the verdict is decided.

The five release checks

What each check proves and every code it can return.

Try the demo merchant

See a healthy endpoint fail its contract, then pass after the fix.