Skip to main content
selo test is the release gate. It runs a free preflight, shows every price, pays Selo once with a dedicated wallet, waits while Selo pays your endpoint and runs the five release checks, then exits 0 only for a fully evidenced PASS.
A release test makes real payments on Algorand Mainnet. You pay Selo 1.00 USDC. Selo then sends one paid request to your endpoint and one replay of the identical signed payment and body. If the paid route has side effects, test a staging route or a test SKU.

Prerequisites

  • A checkout of the Selo repository, Node 24 and pnpm 10, with pnpm install --frozen-lockfile. See CLI overview.
  • A verified authorization for the exact URL and method. See Authorize your endpoint.
  • A release contract file. See Write a release contract.
  • For POST, the JSON request body file. See Run a preflight.
  • A dedicated payer wallet: an Algorand account opted in to USDC (ASA 31566704) that holds at least 1.00 USDC per run. Keep only what a few tests cost in it.
  • Selo’s payee address, the payTo in Selo’s 402. On the public API it is N37HMJCB4BAITC2ZU7C4XW7PUMCO4T3TUASHQEL6A4EWMLOTTHOB7IOOKY. The CLI prints the payTo it finds before signing and refuses to pay any other address than the one you pass.

What one run does

The CLI signs exactly one payment, the one Selo’s 402 asks for, and sends it once. It never retries a payment on its own.

Run it

1

Provide the payer wallet

The CLI reads the payer’s 25-word mnemonic from SELO_PAYER_MNEMONIC only. It never prints it or writes it to a file.
Terminal
read -rs keeps the words out of your shell history and off the screen.
2

Run the test

Terminal
The paid request is a single long call: Selo answers only after your payment has settled, it has paid your endpoint and the checks have run. The CLI waits up to 5 minutes for each answer.
3

Read the verdict and the exit code

Terminal
0 means ship. Anything else blocks. See Exit codes.

Flags

Relative paths resolve from the directory you ran pnpm selo in. Unknown flags are rejected. Run pnpm selo --help for the built-in usage.

Reading the terminal output

This is the output selo test prints, filled in with the values of the fixed-v2 run against the demo merchant on 26 October 2026, taken from that run’s published summary. Values that run did not publish, and that will be your own, are in angle brackets.
Output
The output comes in four blocks. inbound is the transaction in which you paid Selo. downstream is the transaction in which Selo paid your endpoint. Look either up at https://allo.info/tx/<txId>. For the broken-v1 run, the result lines read:
Output
A proven FAIL decides the verdict even though discovery_contract could not be proven in that run. See Verdicts and the gate.

Exit codes

The CLI does not trust the verdict label. It recomputes the verdict from the report’s checks with the same pure reducer Selo uses. If they disagree, or a PASS lacks a check, evidence or a transaction, it blocks with exit 2. A WARN, such as a route not yet listed in Bazaar, appears as a warning line and does not block a PASS.

Files the run writes

The summary of the fixed-v2 run, as published:
selo-gate.json
Add .selo/ to your .gitignore. See Output files for every field of each file.

The private report

The terminal and the summary redact the report token. The full link is kept only in the run state file, as reportUrl. It opens Selo’s full report: the observed response’s hash and size, every payment with its expected and actual transaction id, and every scenario with its operation id, attempts and duration.
Terminal
Anyone who has the link can read the report. Selo serves it with X-Robots-Tag: noindex, nofollow, Cache-Control: private, no-store and Referrer-Policy: no-referrer. To share a result, share the attestation instead: it holds no secret and anyone can verify it.

Spending and approval

Before it signs, the CLI refuses when:
  • the 402 asks for another network than --network;
  • the 402 does not offer exactly one exact USDC requirement on Algorand;
  • the price is zero, above 5.00 USDC, or above --max-usdc;
  • the payTo differs from --pay-to, or equals your own payer address;
  • the payment is on Mainnet and --approve-mainnet or --pay-to is missing.
Each refusal exits 3 with nothing signed. The paid request carries an Idempotency-Key derived from the preflight and your payer address, so Selo never settles the same request twice.

Testnet

--network testnet exists for a Selo deployment that runs on Algorand Testnet, where USDC is ASA 10458941. Point --api at that deployment; http://localhost is accepted for a local one. The public API at https://api.useselo.xyz runs on Mainnet. Against it, --network testnet is refused before signing:
Output
To run Selo itself, see “Running it yourself” in the repository README.

Troubleshooting

Next

Gate deploys in GitHub Actions

Run the same gate in CI behind a protected environment.

Verify a signed verdict

Check the attestation offline before you promote.