Skip to main content
Selo only calls a route its owner has authorized. You prove control of one origin, route and method by serving a token that Selo gives you at a well-known path on your own domain. Authorization is free and needs no wallet.

What an authorization covers

An authorization covers exactly one target. Selo never infers consent from a neighbouring route or method. An authorization for POST https://api.example.com/v1/orders does not cover GET /v1/orders, POST /v1/orders/ or POST /v1/orders/123. Authorize each route and method you want to test. Selo checks the authorization again when you preflight, when you pay for a release test, when the test starts, and before it replays the payment. See Authorization for the model behind it.

Prerequisites

  • The HTTPS URL of your paid route on a public hostname. IP addresses, localhost, single-label hosts, the suffixes .local, .localhost, .internal, .lan and .home.arpa, and non-default ports are refused.
  • A way to serve a static text file at https://<your origin>/.well-known/selo-verification.txt.
  • A checkout of the Selo repository with pnpm install --frozen-lockfile (Node 24, pnpm 10) to use the CLI, or curl to call the API directly. See CLI overview.

Authorize with the CLI

1

Request a challenge

Terminal
Selo answers with a pending authorization and the exact line to serve:
Output
The token is a random 43-character value. Selo stores only its SHA-256 hash and never returns it again, so copy the line now.
2

Serve the verification line

Publish the line, exactly as printed, at /.well-known/selo-verification.txt on the same origin as your route.
selo-verification.txt
The file may hold several lines, so one file can authorize several routes or keep an older authorization’s line next to a new one:
selo-verification.txt
Check that it is reachable before you verify:
Terminal
3

Verify

Terminal
Output
The command exits 0 when the authorization is VERIFIED. Keep the auth_… id: selo preflight and selo test need it, and in CI it becomes the SELO_AUTHORIZATION_ID variable.
4

Check the status at any time

Terminal
It prints the same three lines. It exits 0 only while the authorization is VERIFIED, and 3 when it is PENDING, EXPIRED or REVOKED.

How Selo fetches the file

When you run verify, Selo makes one GET request to https://<your origin>/.well-known/selo-verification.txt with Accept: text/plain, through the same network guard it uses for every target. The comparison is made on SHA-256 hashes in constant time, so the token you serve is compared with the hash Selo stored when it created the challenge.

Re-authorize

An authorization does not renew itself. Running verify again on a verified authorization returns it unchanged and does not extend its expiry.
  1. When selo auth status reports EXPIRED, run selo auth create again. You get a new auth_… id and a new line.
  2. Add the new line to selo-verification.txt. You can leave older lines in place.
  3. Run selo auth verify with the new id, and update anything that stores the old id, such as the SELO_AUTHORIZATION_ID variable in CI.
Authorize shortly before a release window. A preflight or a paid request with an expired authorization is refused before anything is charged. If the authorization lapses after Selo has accepted your payment but before the test starts, or before the replay, the test stops and the verdict is INCONCLUSIVE with AUTHORIZATION_LAPSED.

The same flow with the API

Every step is a plain HTTP call. None of them is paid.
1

Create the challenge

Terminal
string
required
The https URL of your paid route, at most 2048 characters.
string
required
GET or POST.
string
required
1 to 80 characters after trimming.
string
required
3 to 200 characters after trimming.
Unknown fields are rejected. Selo answers 201:
201 Created
string
The id to verify and to pass to preflight.
string
PENDING until verified.
string
The origin the authorization covers.
string
The exact path the authorization covers.
string
The method the authorization covers.
string
Where Selo will look for the line.
string
The line to serve. It is returned only here.
2

Verify

Terminal
The request needs no body. Selo fetches your file and answers 200 with the authorization:
200 OK
3

Read the status

Terminal
The answer has the same shape. A verified authorization past its expiry is reported, and stored, as EXPIRED.
string
PENDING, VERIFIED, EXPIRED or REVOKED.
string
well_known_file for the flow on this page. manual_owner_consent marks an authorization an operator of a Selo deployment recorded by hand, with a note, after the route’s owner consented explicitly.
string | null
When the authorization was verified, or null while pending.
string
For a pending authorization, when the challenge expires (1 hour after creation). For a verified one, 24 hours after verifiedAt.

Troubleshooting

Errors come back as JSON with an error code and a message. The CLI prints them as HTTP <status> <CODE>: <message> and exits 3 for a 4xx and 2 for a 5xx or when Selo cannot be reached.
Selo follows a redirect only while it stays on the origin it is verifying. Serve /.well-known/selo-verification.txt directly on the exact origin of your paid route, for example with a static rule at the edge.
The preflight URL or method does not match the authorization exactly. Compare the covers line from selo auth status with the URL and method you pass to selo preflight, including any trailing slash. See Run a preflight.
Create two authorizations, one per method, and serve both lines in the same file.

Next

Run a preflight

Check eligibility and every price for free.

selo auth reference

Every flag and exit code of the auth commands.