> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grantex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 Architecture

> Official x402 v2 payment messages backed by principal-controlled Grantex prepaid-wallet reservations.

Grantex uses x402 as the payment-message transport and the prepaid-wallet service
as the authorization and accounting authority. Payment requirements alone do
not prove that an AI agent has delegated authority or available principal-owned
value; the server-issued reservation connects those facts.

## Components

| Component | Responsibility |
| - | - |
| Principal | Funds wallets, sets policies, approves reloads, and blocks use |
| OAuth authorization server | Issues DPoP-bound agent access tokens for the wallet resource |
| Wallet policy service | Atomically evaluates assignments, limits, allowlists, and balance |
| `@grantex/x402` client | Converts official `PAYMENT-REQUIRED` into a reservation-backed `PAYMENT-SIGNATURE` retry |
| Resource server | Defines amount, asset, recipient, resource, scope, and timeout |
| Facilitator endpoints | Verify and settle the exact signed authorization |
| PostgreSQL | Serializes spend, stores reservations, and records the wallet ledger |

## Protocol flow

```text theme={null}
Agent              Resource server       Grantex wallet/facilitator       Principal
  | GET /resource         |                          |                         |
  |---------------------->|                          |                         |
  | 402 PAYMENT-REQUIRED  |                          |                         |
  |<----------------------|                          |                         |
  | DPoP authorize(amount, recipient, resource, scope, idempotency key)       |
  |------------------------------------------------->|                         |
  |                         lock wallet -> check policy -> reserve             |
  | signed one-time authorization                    |                         |
  |<-------------------------------------------------|                         |
  | retry PAYMENT-SIGNATURE                          |                         |
  |---------------------->| POST /v1/x402/verify     |                         |
  |                       |------------------------->|                         |
  |                       | valid                    |                         |
  |                       |<-------------------------|                         |
  |                       | POST /v1/x402/settle     |                         |
  |                       |------------------------->|                         |
  |                       | settled + transaction ID |                         |
  | 200 PAYMENT-RESPONSE  |<-------------------------|                         |
  |<----------------------|                          |                         |
```

## Exact binding

The authorization JWT and database reservation bind:

* authorization and reservation identifiers;
* developer, principal, agent, grant, wallet, and assignment;
* amount in atomic units, asset, and network;
* recipient and exact resource URL;
* delegated action scope;
* canonical request hash and expiry.

The authorization lifetime is at most 300 seconds. The accepted x402
requirements must exactly equal the requirements supplied to the facilitator.
The facilitator rejects malformed envelopes, unsupported versions/schemes,
expired signatures, released reservations, and any binding mismatch.
Verification is provisional. A resource server must settle successfully before
starting irreversible protected work or returning the paid result; treating
verification alone as payment would reintroduce a verify/use race.
Remote resource URLs must use HTTPS so `PAYMENT-SIGNATURE` cannot disclose the
one-time authorization over plaintext. HTTP is accepted only for explicit
loopback development addresses.

## Idempotency and replay

The agent supplies a high-entropy idempotency key when reserving. Its hash is
unique across the developer, principal, and agent, not merely within one wallet.
This is important for automatic wallet selection: a lost response can be
retried, but the retry cannot select a different wallet or change its terms.

Settlement is idempotent and returns the original transaction identifier.
Calling authorization again with a key whose reservation settled returns
`PAYMENT_ALREADY_SETTLED`. Verification accepts only a currently reserved
authorization; a settled authorization cannot verify again and therefore
cannot re-run protected work. Released and expired reservations cannot be
revived.

The fetch adapter accepts a caller-provided `idempotencyKey`. Callers should
derive it from a durable logical order/request identifier and reuse it after a
timeout or a lost wallet-authorization response. The generated default protects
a single fetch flow, but cannot correlate two independently restarted caller
invocations.

That option is deliberately not an HTTP header and cannot recover merchant work
after settlement. A side-effecting merchant must also accept a normal
`Idempotency-Key` request header, atomically persist its business result under
that key, and return the cached result on a caller retry. Without that merchant
record, a response lost after settlement fails closed with
`PAYMENT_ALREADY_SETTLED`; Grantex does not replay protected work.

## Blocking semantics

For `grantex:prepaid`, applying an assignment, wallet, or all-wallet agent block happens in the same
database transaction that releases affected outstanding reservations. New
authorizations fail, old authorizations stop verifying, and reserved value
returns to available value. Historical settlements remain immutable.

For opt-in Base USDC, blocks prevent new signatures but cannot recall signatures
already issued. These EVM reservations remain held until finalized settlement
or confirmed unused expiry. Manual release, local timeout, policy mutation and
RPC failure do not return that exposure to the available balance.

## Legacy GDT boundary

The package still includes standalone GDT issuance and verification for signed
authorization context. That path is not the managed wallet protocol. A GDT is
stateless unless the host supplies durable state, so its `spendLimit` claim must
not be described as an atomically enforced cumulative balance. New prepaid x402
integrations should use `PrepaidWalletAgentClient.x402Authorizer`.

## External payment rails

`grantex:prepaid` identifies the repository's managed prepaid settlement
scheme. It does not claim an on-chain transfer. The opt-in
[Base USDC adapter](/guides/base-usdc-custody) uses standard x402 v2 `exact` on
`eip155:8453`, a policy-gated EIP-3009 signer and the merchant's EVM facilitator.
Grantex checks finalized USDC funding and reconciles on-chain nonce/transfer
evidence independently of the merchant's HTTP response. It does not send an
internal Grantex JWT to an EVM merchant. Other rails require separate adapters.

Base `agent.fetch` binds the original request URL, sends the stable logical
request key as HTTP `Idempotency-Key`, rejects redirects and reuses the stored
signature after response loss. Merchant-side result persistence is still
required. Unconfigured custody, stale RPC or ambiguous evidence fails closed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.