---
title: Gate
description: Gate is the x402 gateway. Put an x402 paywall in front of any API or MCP server and get paid in USDC on Base. Share a gateway URL, charge agents per call, no signup, no card, no session.
---

import { Callout } from "fumadocs-ui/components/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";

# Gate

<Callout title="Sell-side, self-serve" type="info">
**Gate is the x402 gateway.** Put an x402 paywall in front of any API or MCP
server and get paid in USDC on Base. An agent that calls the endpoint pays per
request over [x402](/docs/concepts/facilitator) before the call reaches your
backend.
</Callout>

<Callout title="Which chain a payment settles on" type="warn">
The settlement network is decided by the **key's environment**, never by the
caller:

- A `csk_test_` key always settles on **Base Sepolia**. No flag, env var or
  request field can move a test-mode payment to mainnet.
- A live key settles on **Base mainnet**, but only where the deployment sets
  `X402_MAINNET_ENABLED`. Without it a live USDC settlement is refused with
  `501 x402_mainnet_not_enabled` — it is never silently downgraded to testnet,
  which would move fake money under a live mandate and mint a misleading
  receipt.
- On mainnet a hard per-payment ceiling (`X402_MAINNET_MAX_USDC`, default
  **20 USDC**) applies on top of the mandate cap. A broken or missing value
  falls back to that default, never to "unbounded".

On CodeSpar's hosted production the flag is on, so live keys settle real USDC
on Base today, under that ceiling. Self-hosters start with it off.
</Callout>

<Callout type="info">
Gate was previously documented as the "Monetize Gateway". The product is the
same and no endpoint paths changed; only the name did.
</Callout>

A **paywall** is a thin x402 seller in front of one of your endpoints. You
declare a price and where the money should land; CodeSpar issues an
`HTTP 402` challenge on every unpaid call, verifies the agent's signed payment,
settles it on-chain, seals a receipt, and only then proxies the request to your
upstream. Private headers stay private; there is no order, no session, and no
account for the caller to create.

## The flow

```
agent ──GET──▶ gw.codespar.dev/<slug> ──▶ 402 (price, payTo, network)
      ◀────────────────────────────────────┘
agent ──GET + X-PAYMENT──▶ gw.codespar.dev/<slug>
                            │ verify signature
                            │ settle USDC on Base  ──▶ your payTo
                            │ seal receipt
                            └──▶ proxy to your upstream ──▶ 200 + data
```

Every paid call settles USDC to the address you chose and closes with a
hash-chained [receipt](/docs/concepts/audit-chain). A caller that does not pay
gets the 402 back; nothing reaches your upstream until the payment verifies.

## Create a paywall

Admin auth required. See [Authentication](/docs/concepts/authentication).

<Tabs items={["curl"]}>
<Tab value="curl">
```bash
curl -X POST https://api.codespar.dev/v1/paywalls \
  -H "authorization: Bearer $CODESPAR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "slug": "market-data",
    "name": "Market data API",
    "upstream_url": "https://api.yourservice.com/quote",
    "price": "0.01",
    "payto": { "kind": "provisioned" },
    "consumer_id": "your-consumer"
  }'
```
</Tab>
</Tabs>

The response carries the **gateway URL** you share with agents:

```json
{
  "id": "pw_...",
  "slug": "market-data",
  "price": "0.01",
  "currency": "USDC",
  "gateway_url": "https://gw.codespar.dev/market-data",
  "payto_kind": "provisioned",
  "active": true
}
```

### Who gets paid: `payto`

<Callout type="info">
The USDC lands directly at the destination you name, never in a CodeSpar
pooled account. That is not the same as non-custodial: a `provisioned` payTo
resolves to a CDP account created under the CDP credentials connected for your
org, falling back to CodeSpar's own, and whoever holds that CDP wallet secret
is who can sign its transfers. A `byo` address is one CodeSpar has no key for.
</Callout>

| `payto.kind` | Money lands in | When to use |
|---|---|---|
| `provisioned` | The CodeSpar-derived wallet of the `consumer_id` you pass | You want a governed wallet you can also spend from, with receipts on both sides |
| `byo` | The `payto.address` you pass (a `0x` EVM address) | You already have a wallet and want the funds there directly |

### Pricing

`price` is a decimal string of USDC per call, minimum **`"0.01"`**. Endpoint-level
pricing: one paywall, one price. Charge different prices by creating more
paywalls in front of different upstream paths.

Gate's flat, tiered, and dynamic pricing models are live. If a call's cost
depends on how much work it actually did, [Meter](/docs/concepts/meter) prices
it after the fact and refunds the difference on-chain. Meter is the one model
still in beta, while its own mainnet validation completes; flat, tiered and
dynamic are not.

## Path passthrough

`gw.codespar.dev/<slug>` and `gw.codespar.dev/<slug>/<path>` both dispatch to the
paywall; the trailing path is forwarded to your `upstream_url`. So a single
paywall can front a whole API surface, charging the same price per call.

## Earnings

Read what a paywall has earned, an aggregate over its settled payments:

```bash
curl https://api.codespar.dev/v1/paywalls/pw_.../stats \
  -H "authorization: Bearer $CODESPAR_API_KEY"
```

```json
{ "settled_count": 128, "gross": "1.28", "last_settled_at": "2026-07-10T21:04:11Z" }
```

The dashboard's **Machine payments** page shows the same figure inline on each
paywall.

## Manage

- `GET /v1/paywalls`: list your project's paywalls.
- `PATCH /v1/paywalls/:id`: change `name`, `upstream_url`, `price`, or `active` (pause/resume).
- `DELETE /v1/paywalls/:id`: remove it.

Full field and error reference: [Paywalls API](/docs/api/paywalls).

## Monetized MCP servers

A paywall fronts one endpoint at one price. A monetized **MCP server** is the
same runtime applied to a whole MCP surface: wrap an MCP server you already
run, price each tool individually, and point clients at the gateway URL:

```
https://gw.codespar.dev/mcp/<slug>
```

Any MCP client connects to that URL instead of your upstream. The gateway only
charges a `tools/call` for a tool you priced: `initialize`, `tools/list`,
pings, notifications, and calls to unpriced tools proxy through free, so a
client can connect and browse the tool catalog without paying. The gateway
covers request/response JSON-RPC; a GET SSE stream proxies through, with full
streaming fidelity still being completed.

A priced call can be paid two ways at the same interception point:

- **Any x402 agent** pays exactly as on a paywall. An unpaid priced call gets
  a 402 with the challenge in the `PAYMENT-REQUIRED` header; the signed
  payment goes back in `PAYMENT-SIGNATURE` (or `X-PAYMENT`), and the
  settlement result returns in `PAYMENT-RESPONSE`.
- **A CodeSpar-native agent** sends a signed [wallet](/docs/concepts/wallets)
  mandate in the `X-CODESPAR-PAYMENT` header: base64-encoded JSON
  `{"mandate": ..., "signature": "...", "agent_id": "..."}` (`agent_id`
  optional). The charge verifies against the mandate's cap and allowlist,
  debits the paying agent's governed wallet, and seals a receipt; the receipt
  id returns in the `x-codespar-receipt` response header.

Either way, settlement lands in the provisioned wallet of the `consumer_id`
you named at create time; BYO addresses are not offered for MCP servers. The
`Idempotency-Key` header from the [gateway protocol](/docs/api/paywalls#gateway-protocol)
works on paid tool calls too, scoped per tool.

### Manage MCP servers

Admin auth required, on `/v1/mcp-servers`:

- `POST /v1/mcp-servers/validate`: connect to an `upstream_url` (optionally
  with one auth header) and get back the tools it advertises
  (`{ valid, count, tools }`), so you can price them before creating anything.
- `POST /v1/mcp-servers`: create with `slug`, `name`, `upstream_url`,
  `consumer_id`, and `tools: [{ "tool_name": "...", "price": "0.05" }]`
  (at least one). Returns `201` with the object, including `gateway_url`.
- `GET /v1/mcp-servers` and `GET /v1/mcp-servers/:id`: list, and read one with
  its priced tools.
- `PATCH /v1/mcp-servers/:id`: update listing metadata (`name`, `description`,
  `category`) or `active`.
- `PATCH /v1/mcp-servers/:id/tools/:tool`: change one tool's `price` or
  `active` without touching the rest.
- `DELETE /v1/mcp-servers/:id`: remove the server and its tools.

Tool prices are USDC decimal strings with up to 6 decimals. Slugs are global,
one namespace across all MCP servers. If your upstream needs an auth header,
pass `upstream_auth: { "header": "...", "value": "..." }` on create; it is
stored encrypted and never returned by the API.

## Getting discovered

Every project has a public, machine-readable manifest of its active paywalls:

```
GET https://gw.codespar.dev/.well-known/x402?project=<projectId>&env=live
```

No auth; it is meant to be crawled. x402 indexes and buying agents read it to
find and price your resources without a single 402 round-trip. `env` is `live`
or `test` (default `test`).

```json
{
  "x402Version": 2,
  "resources": [
    {
      "url": "https://gw.codespar.dev/market-data",
      "description": "Market data API",
      "pricing_model": "flat",
      "accepts": [
        {
          "scheme": "exact",
          "network": "eip155:8453",
          "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "amount": "10000",
          "payTo": "0x...",
          "maxTimeoutSeconds": 120,
          "extra": { "name": "USD Coin", "version": "2" }
        }
      ]
    }
  ]
}
```

Each entry mirrors the live 402 challenge of its gateway URL, so what a
crawler reads here equals what the endpoint actually charges. A tiered paywall
advertises its current tier. A dynamic or metered paywall carries
`"variable_price": true` because the advertised `amount` is not the exact
charge: the fallback price for dynamic, the ceiling for metered.

Only active paywalls appear. Pause one and it leaves the manifest; there is
nothing to submit or refresh. To preview your own manifest, call
`GET https://api.codespar.dev/v1/discovery/manifest` with your API key: it
returns `{ "manifest": ..., "project_id": ..., "environment": ... }` scoped to
your authenticated project and environment.

## Need Pix too?

Paywalls settle in USDC. When the payer might be a person in Brazil rather
than an agent, use a [Collect payment link](/docs/api/payment-links): the same
gateway serves one shareable URL where an agent pays over x402/USDC and a
person pays via Pix, under the same receipt model. Early access.

## Related

- [Meter](/docs/concepts/meter): post-paid metered pricing on a Gate paywall (beta).
- [Pay to Agent](/docs/concepts/pay-to-agent): the other direction: an agent pays another agent by Agent ID.
- [Facilitator](/docs/concepts/facilitator): how x402 verification and settlement work.
- [Audit chain](/docs/concepts/audit-chain): the receipt every settlement seals.
