# Choose a service using your rules

Find candidates, check their current offers, and select an eligible endpoint in one check.

Canonical: https://402signal.com/developers/choose-service

## Find and check a service in one request

Use this path when your app knows the task but has not chosen an endpoint. 402Signal finds candidates, checks their current offers, applies your requirements, and returns a qualifying selection with its decision record.

### One check, one checking fee

Discovery, live checks and selection are part of the same `POST /route` request. A qualifying check costs $0.003 USDC. A normal completed no-match check costs nothing. Verifying the returned evidence locally does not require a second paid check. Seller payment is separate.

### 1. Describe the task and your rules

This request looks for web search on Base at no more than $0.25 per call, requires enough input information to construct the call, and prefers the lowest comparable price among eligible candidates.

```
{
  "need": "web search",
  "networks": ["base"],
  "max_price_usd": 0.25,
  "require_invocable": true,
  "objective": "cheapest",
  "require_route_binding": true
}
```

`need` starts candidate discovery. If you supply `url`, that exact endpoint is checked instead; including both does not start a wider search.

Already know the endpoint?

```
{
  "url": "https://seller.example/search",
  "networks": ["base"],
  "max_price_usd": 0.25,
  "require_route_binding": true
}
```

For this path, use the [x402 client hook](/developers/check-offer) to obtain the check and verify it before seller signing.

Choose requirements and ranking

 | Your requirement | Request field

 | Allowed seller networks | `networks`

 | Maximum seller price | `max_price_usd` or `max_amount_atomic`

 | Enough input information to construct a call | `require_invocable`

 | Observation history | `min_observations`, `min_observed_success`

 | Maximum HTTP probe time | `max_probe_latency_ms`

 | Seller price plus known seller-side fees | `max_total_cost_usd`, excluding the separate checking fee

Required bounds exclude a candidate when the needed measurement is missing. `prefer_network` only changes preference; use `networks` for a requirement.

Set `objective` to `cheapest`, `fastest`, `most_reliable` or `best`. `fastest` uses this check's HTTP probe time, not the paid service's completion time. Reliability uses recorded observations, not a guarantee of output quality. `lowest_total_cost` and `fastest_settlement` use available cost and settlement/finality data.

Selection covers the eligible candidates actually probed within server limits. `search_depth: "thorough"` or `max_candidates_to_probe` can increase the search budget within those limits; neither searches the entire market. See [all request fields](/openapi.json).

### 2. Submit one paid check

Send the request to `POST /route` through your payment-capable client. Its initial HTTP 402 supplies the checking-fee requirements. Your wallet validates and authorizes that fee, then resubmits the same request. The completed response includes the selected endpoint and offer, compared candidates, and signed evidence when a qualifying bound selection is available.

Retain the exact request JSON and raw response text. Inspect the offer and billing outcome together: HTTP 200 alone does not authorize a seller payment. For durable attempt storage and lost responses, use [RouteClient and recovery](/developers/recover-routing-attempt).

Browse for free before submitting

[The API catalog](/catalog) and `GET /preview?need=web%20search` return catalog candidates without live probes or payment. Use them to explore. The paid `/route` check performs current probing, applies your requirements and selects an eligible offer.

### 3. Verify the selected offer before your wallet signs

Reuse the response from step 2. Check the selected URL against your application's destination policy, then read that seller's current unpaid challenge using the same URL, method and body, with redirects disabled. Immediately before authorization, pass the original check request, raw response and current seller challenge to `withVerifiedRoute`.

Reuse the receipt in your existing signing flow

Install `@402signal/route-guard@0.7.7` and pin the log key independently. This excerpt begins after your app has obtained the check response and the seller's current raw challenge. The callback is where your existing wallet integration validates and executes the payment.

```
import { withVerifiedRoute } from '@402signal/route-guard';

await withVerifiedRoute({
  routeRequestJson,  // Exact need-based request from step 1.
  routeResponseJson, // Raw response from the same check.
  trustedLogVkey,
  request: { url, method: 'GET', body: new Uint8Array() },
  challenge: { status: 402, bodyText, paymentRequired, xPaymentRequired },
}, async verified => {
  // Validate transaction effects against verified.accepted and buyer policy.
  // Reserve your durable budget; invoke your existing wallet once.
});
```

The verifier checks the receipt and current offer locally. It makes no network calls or payments. A mismatch or expired observation throws before the callback runs. The wallet still validates the actual transaction and prevents duplicate payment.

The `signalGuard` hook in the endpoint quickstart obtains a fresh check each time; it does not accept an existing selection response. For this receipt-reuse path, use `withVerifiedRoute` at the signing boundary instead of adding that hook to the same purchase.

[SDK integration boundary](https://github.com/402signalhq/402signal/blob/main/sdk/route-guard/README.md) · [HTTP lifecycle and guarded execution example](https://github.com/402signalhq/402signal/blob/main/sdk/route-guard/examples/search.ts)

### 4. Keep the selection and its rationale

Save the original request, response, receipt and private reveal alongside your approved policy and seller-payment record. The response's `compared[]` summary records selection and exclusion reasons for up to five candidates. The verifiable record describes 402Signal's decision, not the agent's private reasoning or proof that the seller delivered.

Start with a [supported x402 request and payment profile](/developers/supported-profiles). Generic MPP observation alone does not provide the signed offer binding used here; supported native MPP integrations have their own guide.

[Next: save and verify the record](/developers/evidence) · [Native MPP guide](/developers/native-mpp) · [Explore the catalog](/catalog)

Copy a brief for your coding agent

```
Add criteria-based service selection using https://402signal.com/developers/choose-service. Send one need-based /route request with explicit network, price cap, ranking objective and require_route_binding. Retain the exact request and raw response. Discovery, live probing and selection share one qualifying checking fee. Validate the selected destination, read its current unpaid challenge, and reuse the same receipt with withVerifiedRoute immediately before the existing wallet authorizes payment. Do not add signalGuard to that same purchase expecting it to reuse the receipt: that hook obtains a new check. Preserve trusted key pins, transaction validation, durable budgets and original-attempt recovery. Test refusals before funding.
```

Copy integration brief
