---
title: "Quickstart: get paid"
description: Put an x402 paywall in front of your API and take the first paid call in five minutes.
---

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

# Quickstart: get paid

You have an endpoint. Agents want to call it. This guide puts [Gate](/docs/concepts/gate), the x402 gateway, in front of it: an unpaid call gets an HTTP 402, a paid call settles USDC to a wallet you choose and is proxied to your backend with a sealed receipt. The caller creates no account, holds no card, opens no session. Gate is live on Base mainnet.

Four steps: create a paywall, read the 402 with your own eyes, pay it, read the earnings.

## Prerequisites

- A CodeSpar API key with the **admin** role. Mint one at [Dashboard → API Keys](https://codespar.dev/dashboard/api-keys). A `csk_test_` key creates paywalls that settle on Base Sepolia; a `csk_live_` key settles real USDC on Base mainnet.
- A public `https` endpoint to charge for. The gateway fetches it server-side on every paid call, so localhost and private hosts are rejected at create time.
- For step 3, something that can pay: the CodeSpar CLI (shown below) or any x402 v2 client such as `@x402/fetch` or an agent on the CDP Bazaar.

<Callout type="info">
No endpoint handy? `curl -i https://gw.codespar.dev/e2e-live` hits a permanent live paywall priced at $0.01. Every step below works against it, except that the money lands with us.
</Callout>

<Steps>

<Step>
### Create a paywall

One `POST /v1/paywalls` names your upstream, sets the price, and says where the money lands ([full reference](/docs/api/paywalls)). Prefer clicking? The dashboard's [Machine payments](https://codespar.dev/dashboard/paywalls) page has a create drawer with the same fields.

```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": "you"
  }'
```

`payto` decides who gets paid, and settlement is non-custodial either way. `provisioned` settles into the CodeSpar-derived wallet of the `consumer_id` you pass, a governed wallet your own agent can later spend from. `{ "kind": "byo", "address": "0x..." }` settles straight to an EVM address you already hold.

The `201` response carries the URL you share with the world:

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

Flat pricing is the default. Tiered price curves and dynamic per-request pricing are live too; post-paid metered pricing is in beta, see [Meter](/docs/concepts/meter). Slugs are a global namespace, and `gw.codespar.dev/market-data/<path>` forwards the trailing path to your upstream, so one paywall can front a whole API surface.
</Step>

<Step>
### Curl it and read the 402

```bash
curl -i https://gw.codespar.dev/market-data
```

```
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJwYXltZW50IHJlcXVpcmVkIi...
```

The challenge arrives base64-encoded in the `PAYMENT-REQUIRED` response header; the JSON body of the 402 is only a human-readable hint. Decode the header and you get an x402 version 2 challenge:

```bash
curl -sD - -o /dev/null https://gw.codespar.dev/market-data \
  | awk 'tolower($1)=="payment-required:" {print $2}' | base64 -d
```

```json
{
  "x402Version": 2,
  "error": "payment required",
  "resource": {
    "url": "https://gw.codespar.dev/market-data",
    "mimeType": "application/json",
    "description": "Market data API"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amount": "10000",
      "payTo": "0x15cA...9E41",
      "maxTimeoutSeconds": 120,
      "extra": { "name": "USD Coin", "version": "2" }
    }
  ]
}
```

`amount` is atomic USDC (6 decimals), so `10000` is your $0.01. `network` follows the paywall's environment: `eip155:8453` (Base mainnet) on live, `eip155:84532` (Base Sepolia) on test. Nothing has reached your upstream yet, and nothing will until a payment verifies.
</Step>

<Step>
### Pay it

An x402-capable client reads the header, signs the payment, and retries the call.

<Tabs items={["CodeSpar CLI", "Any x402 client"]}>
<Tab value="CodeSpar CLI">
The CLI pays under a signed mandate, so the spend is capped and receipted on the buyer side too. It uses the same `CODESPAR_API_KEY` (run `codespar login` once, or export the key):

```bash
npx @codespar/cli mandate create \
  --consumer you --agent smoke-test \
  --purpose "first paid call on my own paywall" \
  --payee https://gw.codespar.dev/market-data \
  --cap 10 --per-tx-cap 1

codespar spend --mandate cm_xxx --agent smoke-test \
  --payee https://gw.codespar.dev/market-data --amount 1
```

CLI amounts are minor units (cents): `--amount 1` pays the $0.01 challenge. The response is your upstream's `200` body; the settlement result rides back in the `PAYMENT-RESPONSE` header.
</Tab>
<Tab value="Any x402 client">
Any client that speaks x402 version 2 works: decode `PAYMENT-REQUIRED`, sign an EIP-3009 USDC authorization for `amount` to `payTo` on the advertised network, and retry with the signed payment in the `PAYMENT-SIGNATURE` request header (`X-PAYMENT` is accepted for v1 compatibility). `@x402/fetch` wraps this into a drop-in `fetch`; agents on the CDP Bazaar discover and pay 402 endpoints on their own.
</Tab>
</Tabs>

Either way, the gateway verifies the signature, settles the exact amount on-chain to your `payTo`, seals a hash-chained receipt, and only then proxies the request to your upstream.
</Step>

<Step>
### Read the receipt and the earnings

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

```json
{
  "paywall_id": "pw_9f81c2",
  "slug": "market-data",
  "currency": "USDC",
  "settled_count": 1,
  "gross_atomic": "10000",
  "gross": "0.01",
  "refunded_atomic": "0",
  "refunded": "0",
  "net_atomic": "10000",
  "net": "0.01",
  "last_settled_at": "2026-08-06T18:22:41Z"
}
```

`net` is what landed and stayed. On flat, tiered, and dynamic paywalls `gross` equals `net`; on a metered paywall the gap is the on-chain refund of unused ceiling, which is the feature working, not revenue lost ([Meter](/docs/concepts/meter)). The same figures show inline on each paywall in [Machine payments](https://codespar.dev/dashboard/paywalls), and every settlement seals a receipt in the [audit chain](/docs/concepts/audit-chain).
</Step>

</Steps>

## Drive it from your coding agent

The wallet a `provisioned` paywall settles into is a governed wallet your own agent can hold. Add the CodeSpar MCP server to the coding agent you already use:

```bash
claude mcp add codespar --env CODESPAR_API_KEY=csk_live_your_key -- npx -y @codespar/mcp serve
```

Then ask it "what's my wallet balance?" and watch the earnings arrive (`codespar_wallet`), or send them onward under a mandate (`codespar_pay`). Earning and spending are two halves of the same loop; the other half is the [buyer quickstart](/docs/quickstart-buyer).

## Where to go next

<NextStepsGrid items={[
  { label: "CONCEPT", title: "Gate", description: "The x402 gateway in depth: payTo, pricing models, path passthrough, and the Pix lane.", href: "/docs/concepts/gate" },
  { label: "BETA", title: "Meter", description: "Post-paid pricing: the buyer signs a ceiling, your upstream reports the actual work, the difference refunds on-chain.", href: "/docs/concepts/meter" },
  { label: "REFERENCE", title: "Paywalls API", description: "Every field, pricing model, and error code, plus the gateway protocol details.", href: "/docs/api/paywalls" },
  { label: "EARLY ACCESS", title: "Collect payment links", description: "One shareable link: an agent pays over x402/USDC, a person pays via Pix.", href: "/docs/api/payment-links" },
  { label: "FREE TOOL", title: "Check", description: "Scan your site with the Agent-Ready checker before you send agents its way.", href: "/docs/check" },
]} />
