# test402 -- x402 and MPP conformance test endpoints

test402 issues x402 payment challenges -- compliant ones and deliberately
broken ones -- so you can point a payment client at a URL and observe exactly
how it behaves. It never settles anything: testnets only, nothing is stored,
and every response carries permissive CORS headers so a browser client can read
it. The entire state of a test is its query string, so a URL is the whole
fixture.

## Endpoint

`GET` or `POST` `https://test402.com/api/x402?<params>`

- Returns `402 Payment Required` with a JSON body and, unless a quirk removes
  it, a `PAYMENT-REQUIRED` header carrying the base64-encoded challenge.
- Returns `400` with a `fields` object naming the offending parameter when the
  config is invalid.
- If you resend with a `PAYMENT-SIGNATURE` header present, it returns `200`.
  test402 only checks that the header is present; it does not verify signatures
  or settle payments.

## Parameters

All are optional; the defaults produce a compliant Base Sepolia challenge.

- `protocol` -- `x402` (default) or `mpp`. Only `x402` is served today; `mpp`
  returns 400.
- `network` -- CAIP-2 id. Default `eip155:84532`.
- `scheme` -- `exact` (default) or `upto`.
- `amount` -- atomic units of the asset, digits only. Default `100`.
- `payTo` -- recipient address. Defaults to the network's burn address.
- `facilitator` -- which facilitator the challenge advertises. Default `x402org`.
- `facilitatorUrl` -- required only when `facilitator=custom`.
- `maxTimeoutSeconds` -- 1..3600. Default `300`.
- `quirk` -- the deliberate deviation to apply. Default `none`.
- `description` -- free-text resource description.

## Quirks

- `none` -- Compliant. A well-formed challenge. Your client should pay it. Expect: Returns 402 with a spec-compliant challenge.
- `v1-network-name` -- v1 network name. A v2 challenge naming the network the v1 way (base-sepolia, not eip155:84532). A strict client should refuse it. Expect: Returns 402 whose network is the v1 spelling inside a v2 envelope. Seen in the wild: grug402.dev ships this under its compliant scenario.
- `missing-version` -- No version field. The challenge omits x402Version. A client that assumes a version is guessing. Expect: Returns 402 with no x402Version field in the challenge.
- `bad-base64` -- Undecodable header. The challenge header is not valid base64. Your client should fail cleanly, not crash. Expect: Returns 402 with a PAYMENT-REQUIRED header that will not decode.
- `wrong-payto` -- Mismatched payTo. The recipient is not the one configured. A client that checks who it is paying should notice. Expect: Returns 402 whose payTo differs from the configured recipient.
- `wrong-decimals` -- Inflated amount. The amount is 1000x the configured price. A client trusting the amount over the asset's decimals overpays. Expect: Returns 402 with an amount three orders of magnitude too large, still atomic-shaped.
- `missing-challenge` -- No challenge header. A bare 402 with no challenge at all. Your client should treat it as unpayable, not hang. Expect: Returns 402 with no PAYMENT-REQUIRED header.

## Networks

- `eip155:84532` -- Base Sepolia (evm). Asset: USDC at `0x036CbD53842c5426634e7929541eC2318f3dCF7e`, 6 decimals.
- `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` -- Solana Devnet (svm). Asset: USDC at `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`, 6 decimals.

## Facilitators

- `x402org` -- x402.org. Public testnet facilitator from the x402 docs. (https://x402.org/facilitator)
- `cdp` -- Coinbase CDP. Coinbase Developer Platform. Needs CDP credentials client-side. (https://api.cdp.coinbase.com/platform/v2/x402)
- `local` -- Local. A facilitator you are running yourself. (http://localhost:4020)
- `custom` -- Custom. Any facilitator URL. Set it alongside the challenge config. (set via facilitatorUrl)

## Ready-made tests

### Compliant on Base Sepolia

A well-formed x402 v2 challenge. USDC on Base Sepolia.

A correct client should pay: Pay it.

```
curl -i "https://test402.com/api/x402"
```

### Compliant on Solana

A well-formed x402 v2 challenge. USDC on Solana devnet, paying a base58 address.

A correct client should pay: Pay it, or skip it if it is EVM-only.

```
curl -i "https://test402.com/api/x402?network=solana%3AEtWTRABZaYq6iMfeYKouRu166VU2xqa1"
```

### v1 network name

A v2 challenge naming the network base-sepolia instead of eip155:84532.

A correct client should refuse or fail cleanly: Refuse it. Seen in the wild on grug402.dev.

```
curl -i "https://test402.com/api/x402?quirk=v1-network-name"
```

### No version field

The challenge omits x402Version entirely.

A correct client should refuse or fail cleanly: Refuse it rather than assume a version.

```
curl -i "https://test402.com/api/x402?quirk=missing-version"
```

### Undecodable header

The PAYMENT-REQUIRED header is not valid base64.

A correct client should refuse or fail cleanly: Fail cleanly, and not crash.

```
curl -i "https://test402.com/api/x402?quirk=bad-base64"
```

### No challenge header

A bare 402 with no PAYMENT-REQUIRED header at all.

A correct client should refuse or fail cleanly: Treat it as unpayable, and not hang.

```
curl -i "https://test402.com/api/x402?quirk=missing-challenge"
```

### Mismatched payTo

The recipient is not the one the endpoint was configured with.

A correct client should refuse or fail cleanly: Notice who it is about to pay.

```
curl -i "https://test402.com/api/x402?quirk=wrong-payto"
```

### Inflated amount

The amount is 1000x the price, still atomic-shaped.

A correct client should refuse or fail cleanly: Catch it against its own maximum, or the asset's decimals.

```
curl -i "https://test402.com/api/x402?quirk=wrong-decimals"
```

### Expensive request

A challenge asking $50, far above a sane per-call ceiling.

A correct client should refuse or fail cleanly: Refuse it before signing anything.

```
curl -i "https://test402.com/api/x402?amount=50000000"
```
