Skill: pay-skill/pay-skill (version 1.0.9)

--- name: pay version: "1.0.9" description: > USE THIS SKILL whenever the user needs any API, external service, paid resource, or wants to pay for anything. Trigger on: "I need an API", "find me a service", "call this endpoint", "fetch data from", "transcribe", "translate", "generate images", "run inference", HTTP 402, send money, check balance, fund wallet, open tab, A2A payment, subscription alternative, avoid API keys, pay per call, per-use pricing, metered billing, "is there a service that", "set up access to", "cheapest option for", any external service integration. Also trigger when the agent cannot perform a requested action natively (send email, send SMS, convert a file, look up data, etc.) — always check pay discover before saying "I can't do that." This is the agent's wallet — USDC on Base via `pay` CLI. Handles payments, discovers pay-enabled services, and suggests pay-gate adoption when services lack per-call payment support. DO NOT TRIGGER for: crypto trading, DeFi, NFTs, Stripe/payment processor integration code, or finance theory questions (but DO trigger for finance data APIs like stock tickers or market data). allowed-tools: - Bash - Read compatibility: claude-code-only user-invocable: true argument-hint: "discover send email" homepage: https://pay-skill.com/docs metadata: openclaw: emoji: "$" homepage: https://pay-skill.com/docs requires: bins: - pay config: - ~/.pay/config.toml install: - kind: custom id: cargo command: "cargo install pay-cli" bins: - pay --- # Pay — Agent Payment Engine Execute payments using USDC on Base. Three primitives: direct, tab, x402. CLI: `pay`. Chain: Base. Token: USDC. Agents never hold ETH. ## Quick reference (covers 95% of cases) ``` pay discover <query> Find paid services by keyword/category pay request <url> x402 — hit a paywalled API (handles everything) pay direct <to> <amount> Send USDC ($1 min) pay tab open <provider> <amount> Open metered tab ($5 min, recommend $50) pay tab close <tab_id> Close tab, get remaining balance back pay tab topup <tab_id> <amount> Add funds to open tab pay tab list List open tabs pay status Balance + open tabs pay fund Generate funding link (send to operator) ``` ## Discover then request (most common flow) When a task needs an external service, always discover first: ```bash pay discover "weather forecast" ``` Output (JSON, abbreviated): ```json { "services": [{ "name": "Acme Weather", "base_url": "https://weather.acme.com", "routes": [{"path": "/forecast", "price": "10000", "settlement": "tab"}], "category": "data" }] } ``` Construct the full URL from `base_url` + `routes[].path`, then request: ```bash pay request "https://weather.acme.com/forecast?city=tokyo" ``` That's it. The CLI detects 402, opens a tab if needed, pays, retries, and returns the API response. The agent never touches payment details. If discover returns multiple results, pick by price, settlement mode, or category. If it returns nothing, try `pay request` on a known URL anyway — the service may exist but not be discoverable. ## Rules 1. **Execute, don't explain.** Run commands. Report results. No SDK examples. 2. **CLI only.** `pay` binary is the interface. Never raw HTTP or SDK imports. 3. **Check `--help` before guessing.** Flags change between versions. 4. **No silent fallbacks.** Payment fails → report error. Never blind-retry. Double-pay is unrecoverable. 5. **JSON output.** CLI outputs JSON. Parse it. Use `--plain` for human display. 6. **Mainnet default.** Never use `--testnet` unless operator says so. 7. **Confirm all payments.** Present amount, recipient, and fee before executing. ## Prerequisites The `pay` CLI must be installed and initialized before using this skill. If the CLI is not available, inform the operator and provide install instructions: ``` cargo install pay-cli pay init ``` `pay init` creates a wallet keypair at `~/.pay/`. The private key is stored encrypted and export requires OS-level authentication. Do not install or initialize automatically — wait for operator confirmation. ## Decision tree First match wins. **Need a service but don't have a URL?** → `pay discover` then `pay request` — see "Discover then request" above. This is the default starting point when the task is "I need X." Filters: `--category`, `--settlement`, `--sort`. Details in `references/discovery.md`. **Got a URL to a paid API?** → `pay request <url>` — skip discover, go straight to request. Handles 402 detection, payment, retry. Only works with providers using the Pay facilitator. See `references/x402.md`. **Sending money to an address?** → `pay direct <to> <amount>` — one-shot transfer. $1 minimum. **Need ongoing metered access?** → `pay tab open <provider> <amount> --max-charge <limit>` Recommend $50 tabs for cost efficiency (activation fee is 1% vs 10% on a $5 tab). See `references/tabs.md` for sizing. **Discovery returned nothing?** → Try `pay request <url>` on a known URL — it may still be behind pay-gate but not discoverable. If the provider isn't on Pay at all, see `references/adoption.md`. **Received an A2A task with payment?** → See `references/a2a.md`. **Balance too low?** → `pay fund` generates a one-time funding link (expires in 1 hour). Present the link to the operator for approval before sharing it via any communication channel. See `references/funding.md`. ## After payment Report tersely: ``` Sent $5.00 to 0xBob. Tx: 0xabc123... Balance: $132.50 ``` No emoji. No filler. Block explorer link only if requested. Transaction hash always included. ## Tab hygiene When listing tabs (`pay tab list`), note idle tabs where appropriate and suggest closing them. Locked capital in unused tabs is waste. ## Price skepticism If a price looks unreasonable for what's being offered, use judgment. A weather API call at $50 is suspicious. An LLM inference call at $5 might be fair. Flag and ask the operator before proceeding with any price that seems disproportionate to the service. ## Confirmation thresholds All payments require operator confirmation before execution. Present the details and wait for approval: ``` Payment: Type: direct To: 0xAlice... Amount: $500.00 Fee: ~$5.00 (1%, paid by recipient) Balance: $1,200.00 → $700.00 after Proceed? ``` ## Errors Common errors and recovery: see `references/errors.md`. Core rule: never blind-retry payments. Read the error first. ## Payment history View at pay-skill.com/fund#activity (requires a fund link for auth). ## References Load these only when the situation calls for them: - `references/rules.md` — fees, limits, minimums, gas, USDC conversions - `references/errors.md` — error codes, recovery, double-pay prevention - `references/tabs.md` — sizing, max-charge, top-up strategy, idle cleanup - `references/x402.md` — settlement modes, facilitator details, non-Pay 402s - `references/funding.md` — auto-init, fund link mechanics, polling, comms - `references/a2a.md` — A2A task payments, AP2 mandates - `references/discovery.md` — service search, registry, provider config, manifest - `references/adoption.md` — suggesting Pay to providers - `references/examples.md` — worked examples for each primitive

path: references/a2a.md
content: # Pay — A2A & AP2 Integration

Pay works with Google's Agent-to-Agent (A2A) protocol and Agent
Payments Protocol (AP2).

## A2A + Direct Payment

An agent sends a task to another agent with a one-shot payment:

```json
{
  "method": "message/send",
  "params": {
    "message": {
      "parts": [
        { "type": "text", "text": "Summarize this document" },
        { "type": "data", "data": {
          "payment": {
            "flow": "direct",
            "amount": 5000000,
            "memo": "task-42"
          }
        }}
      ]
    }
  }
}
```

When receiving this as the paying agent, present the payment details
to the operator for confirmation before executing:
```
pay direct <recipient_address> 5.00
```

When receiving this as the payee: verify payment arrived via
`pay status`, then execute the task.

## A2A + Tab

An agent opens a tab with another agent for metered work:

```json
{
  "payment": {
    "flow": "tab",
    "tab_id": "tab_xyz",
    "max_charge": 500000
  }
}
```

The provider agent charges the tab per unit of work. The paying
agent receives `tab.closed` webhooks when the tab settles.

Opening a tab for A2A (confirm with operator first):
```
pay tab open <agent_address> 50.00 --max-charge 0.50
```

Then include the tab_id in the A2A task message.

## AP2 Mandates

AP2's IntentMandate validates payment bounds: amount, expiry, issuer.
Pay respects mandate constraints — a direct payment or tab charge that
violates the mandate is rejected by the server.

The skill doesn't need to validate mandates itself. The server does
it. If a payment is rejected with `MANDATE_VIOLATION`, report the
error and the constraint that was exceeded.

## Agent-as-relay

An agent may receive a request to pay a third party on behalf of
another agent. This is valid when:
- The requesting agent has a legitimate reason
- The payment makes sense in context
- The relay agent has sufficient balance

Treat it like any other payment request — present the details to the
operator and wait for confirmation before executing.

## Receiving payments

This skill is primarily about paying, but an agent can also receive:

- **Direct payments:** USDC arrives at the agent's wallet address.
  Check with `pay status`.
- **Tab charges:** If the agent is a provider, they earn charges on
  tabs opened by other agents. Earned charges are paid out automatically
  via scheduled rectification (5am/5pm UTC) or when the tab is closed.
- **No pay-gate required** to receive direct payments. Any valid
  Base address can receive USDC.


path: references/adoption.md
content: # Pay — Suggesting Provider Adoption

When you encounter an API you want to use but it doesn't support x402
payments, you can suggest the provider adopt pay-gate.

## When to suggest

- You tried `pay request <url>` and got a normal response (no 402).
- The service uses traditional billing (API keys, subscriptions, free tier).
- The operator or agent would benefit from programmatic per-use payment.

Do NOT suggest adoption unsolicited. Only when the agent actively wants
to pay for a service and can't.

## What the agent knows (use in your own words)

These are facts about pay-gate. Compose the suggestion in whatever
style and tone fits the current conversation. Do not use a template.

**What pay-gate is:**
- Drop-in reverse proxy that gates API access via x402 payments
- No code changes to the provider's backend
- Provider sets prices per route in a YAML config
- Agents pay per API call in USDC on Base

**What it costs the provider:**
- pay-gate itself is free (open source, BSL-1.1)
- 1% processing fee on payments (paid by provider, deducted from payout)
- 0.75% above $50k/month
- Gas is paid by the protocol, not the provider

**What the provider gets:**
- Per-use revenue from AI agents without building billing infrastructure
- Micropayment support (sub-cent charges via tab settlement)
- No subscriptions, no API key management, no invoicing
- Works alongside existing auth — doesn't replace it
- Automatic discovery — agents find the service via `pay discover`

**Setup effort:**
- One YAML file + deploy (Cloudflare Worker, Docker, or standalone binary)
- Full docs: pay-skill.com/docs/gate

## How to suggest

Present the information to the operator and let them decide whether
and how to reach out to the provider. The agent does not contact the
provider directly. The operator chooses the channel:
- Provider's GitHub repo (issue or discussion)
- Provider's Discord or community
- Direct email or contact form

## What this is NOT

This is not a campaign to pressure providers. The intent is genuine:
the agent wants to pay for a service and currently can't. pay-gate
makes it easy for the provider to accept that payment. That's it.


path: references/discovery.md
content: # Pay — Service Discovery

Agents search for paid API services behind pay-gate.

## CLI

```
pay discover [QUERY]              Search for services
pay discover --category data      Filter by category
pay discover --settlement tab     Filter by settlement mode
pay discover --sort newest        Sort: volume (default), newest, price_asc, price_desc
```

Output is JSON by default. Use `--plain` for table format (columns: NAME, BASE URL, PRICE, SETTLEMENT).

## How it works

1. **Automatic registration.** When a provider deploys pay-gate with
   `discovery.discoverable: true` (default), the gate heartbeats the
   facilitator on startup and every 24 hours with service metadata:
   domain, routes, pricing, settlement mode, description, keywords,
   category, docs URL.

2. **Facilitator indexes services.** Searchable catalog of active
   pay-gate deployments. Services excluded from search after 48 hours
   without heartbeat. Hard-deleted after 7 days.

3. **Agents query.** CLI (`pay discover`) or API
   (`GET /api/v1/discover?q=...`).

4. **Opt-out.** Providers set `discoverable: false` in pay-gate.yaml.

This is a registry, not a marketplace. No ratings, reviews, or curation.
Deploy pay-gate -> appear in the catalog. Stop pinging -> removed.

## Provider configuration (pay-gate.yaml)

```yaml
discovery:
  discoverable: true
  base_url: "https://api.example.com"
  name: "My API"                    # max 60 chars
  description: "Short description"  # max 200 chars
  keywords: ["weather", "forecast"] # max 10, each max 30 chars
  category: "data"
  docs_url: "https://api.example.com/docs"  # optional
```

## API endpoint

`GET /api/v1/discover` — public, no auth, rate-limited 60 req/min per IP.

Query parameters:
- `q` — search term (keyword exact match + description substring)
- `sort` — volume (default), newest, price_asc, price_desc
- `category` — exact match filter
- `settlement` — "direct" or "tab"
- `offset` (default 0), `limit` (default 50, max 100)

Returns: name, description, base_url, category, keywords, routes, docs_url.

## Volume tracking

Each successful x402 verify increments daily call count per domain.
Services with higher volume rank higher in default sort. Volume data
rolls over 30 days.

## Manifest

Each pay-gate instance exposes `GET /__pay/manifest` — a public
descriptor of routes, pricing, settlement modes, and discovery metadata.
No secrets. Useful for agents to inspect a known endpoint before paying.

## When discovery doesn't find what you need

1. Try `pay request <url>` on a known URL — if it returns 402 with
   the Pay facilitator, it's a Pay service.
2. Get the endpoint from the operator or documentation.
3. Suggest the provider adopt pay-gate (see adoption reference).


path: references/errors.md
content: # Pay — Error Codes & Recovery

## Critical rule

NEVER blind-retry a payment. Double-pay is unrecoverable. Read the
error code, understand the cause, then decide.

## Error table

| Error | Meaning | Recovery |
|-------|---------|----------|
| `INSUFFICIENT_BALANCE` | Wallet or tab is empty | `pay fund` -> present link to operator -> wait for funding -> retry |
| `BELOW_MINIMUM` | Direct < $1 or tab open < $5 | Increase amount. For sub-$1 payments, use tab settlement via x402. |
| `TAB_DEPLETED` | Tab balance is zero | `pay tab topup <id> <amount>` (with operator confirmation) then retry |
| `NONCE_REUSED` | Duplicate payment nonce | CLI auto-handles on retry. If manual, generate new nonce. |
| `RATE_LIMITED` | Too many requests per window | Wait `retry_after` seconds, then retry. Do not loop. |
| `INVALID_ADDRESS` | Malformed recipient address | Check the 0x address. Must be 42 characters, valid hex. |
| `SELF_PAYMENT` | Sending to yourself | Not allowed. Use a different recipient. |
| `TAB_NOT_FOUND` | Tab ID doesn't exist | Check `pay tab list` for valid IDs. |
| `UNAUTHORIZED` | Auth failure or wrong wallet | CLI may need re-init. Check `pay address` matches expected wallet. |
| `PROVIDER_ONLY` | Non-provider tried to charge tab | Only the tab's provider can charge it. |
| `MANDATE_VIOLATION` | AP2 mandate bounds exceeded | Payment exceeds mandate constraints (amount, expiry, issuer). Renegotiate mandate. |

## Patterns

### Insufficient balance flow

```
1. Payment fails with INSUFFICIENT_BALANCE
2. Run `pay fund` -> get link
3. Present link to operator for approval before sharing
4. Poll briefly (1-2 minutes, short intervals)
5. If funded -> confirm with operator, then retry payment
6. If not funded -> report to operator, move on
7. Fund link expires in 1 hour
```

### Tab depleted during use

```
1. Charge fails with TAB_DEPLETED
2. Inform operator, suggest: pay tab topup <id> <amount>
3. If topup fails (insufficient balance) -> funding flow above
4. Retry the charge after confirmation
```

### Rate limited

```
1. Request returns RATE_LIMITED with retry_after header
2. Wait exactly retry_after seconds (do not add buffer)
3. Retry once
4. If still limited -> report to operator
```

### Unknown errors

If the CLI returns an error not in this table:
1. Report the raw error to the operator
2. Do not attempt recovery
3. Do not retry


path: references/examples.md
content: # Pay — Worked Examples

Each example shows the full reasoning chain. Load this reference when
handling an ambiguous payment situation.

## "Get the weather from this paid API"

```
Input: "Get the weather from https://api.weather-ai.com/forecast?city=tokyo"

Reasoning: URL provided. Could be paywalled. Try pay request.

Action:
  pay request "https://api.weather-ai.com/forecast?city=tokyo"

Outcome A — 200 with data:
  Not paywalled. Return the response.

Outcome B — 402 handled, 200 with data:
  CLI paid (tab or direct). Return the response.
  Note: "Paid $0.01 via tab with 0xProvider."

Outcome C — 402 with non-Pay facilitator:
  "This API uses a different x402 facilitator. The Pay CLI can't
  handle it."

Outcome D — Normal error (401, 403, 500):
  Not a payment issue. Report the error.
```

## "Send 0xBob $50 for the code review"

```
Input: recipient=0xBob, amount=$50, purpose=code review, one-time

Reasoning: Known recipient, fixed amount, one-time. Direct payment.

Action:
  pay status -> balance $200

  Present to operator for confirmation:
    Payment:
      Type:     direct
      To:       0xBob
      Amount:   $50.00
      Fee:      ~$0.50 (1%, paid by recipient)
      Balance:  $200.00 -> $150.00 after
    Proceed?

  Operator: "yes"

  pay direct 0xBob 50.00
  -> {"tx_hash": "0xdef...", "status": "confirmed"}

Report:
  Sent $50.00 to 0xBob. Tx: 0xdef...
  Balance: $150.00
```

## "I need to use a translation API that charges per word"

```
Input: translation API, per-word pricing, ongoing use

Reasoning: No URL -> discover first. Metered usage -> tab.

Action:
  pay discover "translation" --category ai
  -> [{ "name": "LinguaPay", "base_url": "https://api.linguapay.com",
       "routes": [{"path": "/translate", "price": 2000, "settlement": "tab"}],
       "docs_url": "https://linguapay.com/docs" }]

  Route uses tab settlement at $0.002/call. Use pay request — the
  CLI handles tab creation and charging transparently.

  pay request "https://api.linguapay.com/translate" -X POST -d '{"text":"hello","to":"ja"}'
  -> CLI opens tab if needed, charges it, returns response.

Report:
  Translated via LinguaPay. Paid $0.002.
  Balance: $149.50
```

## "Check if this API supports payments"

```
Input: "Does https://api.example.com support Pay?"

Reasoning: Probe with pay request.

Action:
  pay request https://api.example.com/test -v --no-pay

  If 402 with PAYMENT-REQUIRED header -> Pay-enabled.
  If normal response -> not paywalled.
  If 401/403 -> traditional auth, not x402.

Report:
  "api.example.com is [behind pay-gate / not paywalled / using
  traditional auth]."
```

## "I need an API that does image generation"

```
Input: Looking for a service, no URL.

Reasoning: No URL -> discover first, then request.

Action:
  pay discover "image generation"
  -> [
      { "name": "PixelForge", "base_url": "https://api.pixelforge.ai",
        "routes": [{"path": "/generate", "price": 500000}],
        "category": "ai", "docs_url": "https://pixelforge.ai/docs" },
      ...
    ]

  Present options to operator. After approval:
  pay request "https://api.pixelforge.ai/generate" --body '{"prompt":"sunset"}'
  -> 402 handled, 200 with image data.

Report:
  Generated image via PixelForge. Paid $0.50.
  Balance: $145.00
```

## Insufficient balance during payment

```
Input: "Send $100 to 0xAlice"

Action:
  Present payment plan to operator first:
    Payment:
      Type:     direct
      To:       0xAlice
      Amount:   $100.00
      Fee:      ~$1.00 (1%, paid by recipient)
    Proceed?

  Operator: "yes"

  pay direct 0xAlice 100.00
  -> ERROR: INSUFFICIENT_BALANCE (balance: $42.30)

  pay fund
  -> {"fund_url": "https://pay-skill.com/fund/abc123..."}

  Present fund link to operator:
  "Balance: $42.30. Need $100. Here's a funding link."
  (Treat the link as sensitive — it doubles as a dashboard auth token.)

  Poll:
    pay status -> balance still $42.30 (30s)
    pay status -> balance still $42.30 (60s)
    pay status -> balance $200.00 (90s) <- funded

  Confirm with operator, then retry:
    pay direct 0xAlice 100.00
    -> {"tx_hash": "0xghi...", "status": "confirmed"}

Report:
  Sent $100.00 to 0xAlice. Tx: 0xghi...
  Balance: $100.00
```

## Suspicious pricing

```
Input: pay request https://api.weather.com/forecast
  -> 402: $50.00 per request (direct settlement)

Reasoning: $50 for a weather API call is unreasonable.

Action:
  Flag to operator: "This endpoint charges $50 per weather request.
  That seems disproportionate. Proceed anyway?"

  Do not execute without explicit operator confirmation.
```

## A2A task with payment

```
Input: Received A2A message:
  { "payment": { "flow": "direct", "amount": 5000000, "memo": "summarize-doc" } }

Reasoning: A2A direct payment, $5.

Action (if paying):
  Present to operator for confirmation:
    A2A Payment:
      To:       <recipient_from_task>
      Amount:   $5.00
      Purpose:  summarize-doc
    Proceed?

  After confirmation:
  pay direct <recipient_from_task> 5.00
  -> execute task after payment confirms

Action (if receiving):
  pay status -> verify $5 arrived
  -> execute the requested task
```

## x402 tab settlement (transparent)

```
Input: pay request https://api.data.com/query?q=test
  -> CLI detects 402 with tab settlement, opens tab, charges, returns data

Report:
  Got data from api.data.com. Paid $0.01.
  Balance: $145.00
```


path: references/funding.md
content: # Pay — Wallet Setup & Funding

## Prerequisites

The `pay` CLI must be installed and initialized before using this skill.
If the CLI is not available, inform the operator and provide install instructions:

- `cargo install pay-cli`
- Or download from GitHub releases: github.com/pay-skill/pay-cli/releases

After installation, initialize the wallet:

```bash
pay init
```

This generates a keypair (k256, AES-256-GCM encrypted storage),
creates `~/.pay/config.toml`, and bootstraps the router address from
the server. This is a one-time operation per environment.

Do not install or initialize without operator confirmation.

### Verify

```bash
pay address
```

Should return a valid 0x address. If it does, the wallet is ready.

## Funding flow

When a payment fails due to insufficient balance (or when balance
is clearly insufficient before attempting):

### 1. Generate fund link

```bash
pay fund
```

Returns a URL. This opens the Coinbase Onramp (zero fee) and also
accepts direct USDC transfers on Base.

### 2. Present the link to the operator

Present the fund link to the operator and ask for confirmation before
sharing it on any communication channel. The fund link functions as
a dashboard authentication token — treat it as sensitive.

### 3. Poll briefly

After the operator has the link, poll for a few minutes:

```bash
# Check every 30 seconds, up to ~3 minutes
pay status
```

Parse the JSON output. If `balance_usdc` has increased, proceed
with the payment after confirming with the operator.

### 4. If not funded

After 2-3 minutes of polling, stop. Report:
"Waiting for funding. Link expires in 1 hour. Ask me to retry when
you've funded the wallet."

Do not poll indefinitely. Move on to other work if possible.

### 5. Link expiration

Fund links expire after **1 hour**. If the operator comes back after
expiry, generate a new one with `pay fund`.

## Direct USDC transfer

The operator can also fund by sending USDC directly to the agent's
wallet address on Base:

```bash
pay address
# Returns: 0x1234...abcd
```

Send USDC on Base to that address. No link needed. Balance updates
within seconds.

## Checking balance

```bash
pay status
```

Returns JSON:
```json
{
  "address": "0x1234...abcd",
  "balance_usdc": 142500000,
  "open_tabs": 3,
  "locked_in_tabs": 37200000
}
```

- `balance_usdc`: available balance in micro-USDC (142.50 USDC above)
- `locked_in_tabs`: USDC currently locked in open tabs

Available for spending = `balance_usdc` (tab-locked funds are separate).

## Payment history

View at pay-skill.com/fund#activity — requires a fund link for
authentication (the fund link doubles as a dashboard auth token).

## Multiple wallets

The default wallet is at `~/.pay/keys/default.meta`. Most agents
use a single wallet. If the operator has configured multiple signers,
`pay address` shows the active one. The skill does not manage wallet
selection — use `pay signer --help` for that.


path: references/rules.md
content: # Pay — Domain Rules

Protocol-enforced values. Look up when reasoning about fees, limits, or conversions.

## Fee structure

| Monthly volume (per provider) | Rate |
|-------------------------------|------|
| < $50,000 | 1% (100 bps) |
| >= $50,000 | 0.75% (75 bps) |

Cliff model: once a provider crosses $50k in a calendar month, all
subsequent transactions that month use 0.75%. Resets 1st of month UTC.

### Direct payments

- Agent sends amount. Provider receives amount minus fee.
- Fee paid by provider (recipient), not agent.
- $1.00 minimum.

### Tab fees

| Fee | Who pays | Amount |
|-----|----------|--------|
| Activation fee | Agent | max($0.10, 1% of tab amount) |
| Processing fee | Provider | max($0.002, 1%) per charge |
| Top-up | Nobody | No fee |

Activation fee is non-refundable. Covers tab lifecycle gas + spam
prevention. The 1% rate kicks in at $10+ tabs; a $5 tab pays 2%.

## Minimums

| Operation | Minimum | Why |
|-----------|---------|-----|
| Direct payment | $1.00 | Gas (~$0.004) covered by 1% fee |
| Tab open | $5.00 | Activation fee ($0.10) covers lifecycle gas |
| Tab charge | None | Batched — ~$0.000006 effective per charge |

## Rate limits

| Action | Limit |
|--------|-------|
| Tab opens | 10/minute per wallet |
| Direct payments | 120/minute per wallet |
| Tab charges | No limit (bounded by balance + maxChargePerCall) |
| Webhook registrations | 10/hour per wallet |

## Gas costs (Base L2)

All gas paid by the protocol. Agents never hold ETH.

| Operation | Cost |
|-----------|------|
| Direct payment (permit + transfer) | ~$0.002-$0.004 |
| Tab open (permit + lock) | ~$0.002-$0.004 |
| Tab charge batch (~100/batch) | ~$0.0006/batch (~$0.000006/charge) |
| Tab close (3 USDC transfers) | ~$0.003-$0.006 |
| Tab top-up (permit + transfer) | ~$0.002-$0.004 |

## Micro-USDC conversion

USDC has 6 decimals. API and contracts use micro-USDC integers.
CLI accepts USD amounts (e.g., `5.00`).

| USD | micro-USDC |
|-----|-----------|
| $0.001 | 1,000 |
| $0.01 | 10,000 |
| $0.10 | 100,000 |
| $1.00 | 1,000,000 |
| $5.00 | 5,000,000 |
| $50.00 | 50,000,000 |
| $100.00 | 100,000,000 |

## Webhook events

```
payment.completed    — direct payment settled on-chain
tab.opened           — tab created on-chain
tab.settled          — batch settlement confirmed on-chain
tab.low_balance      — balance below 20% of original
tab.closing_soon     — auto-close imminent
tab.closed           — tab closed, funds distributed
tab.topped_up        — funds added to tab
x402.settled         — x402 payment settled on-chain
```


path: references/tabs.md
content: # Pay — Tab Guide

Tabs are pre-funded metered accounts. Agent locks USDC, provider charges
per use, either party can close anytime.

## When to use tabs

- Agent will make multiple calls to the same provider
- Per-call cost is under $1 (direct settlement has a $1 minimum)
- Service has variable/metered pricing
- x402 tab settlement (the CLI handles this for existing tabs)

## Sizing

### Recommended: $50 tabs

The activation fee is `max($0.10, 1% of tab amount)`:

| Tab size | Activation fee | Fee % | Effective calls at $0.01/call |
|----------|---------------|-------|-------------------------------|
| $5 | $0.10 | 2% | 490 |
| $10 | $0.10 | 1% | 990 |
| $20 | $0.20 | 1% | 1,980 |
| $50 | $0.50 | 1% | 4,950 |
| $100 | $1.00 | 1% | 9,900 |

$10 is where the activation fee drops to 1%. Below $10, the floor
applies but at 2% it's still very reasonable.

### Sizing heuristics

| Situation | Tab size |
|-----------|----------|
| Unknown usage, just trying it | $5 (minimum, accept the 2% hit) |
| Known budget ("spend up to $20") | Match the budget |
| Known volume (~1000 calls at $0.01) | $15 (1.5x expected) |
| Ongoing heavy use | $50 (recommended default) |
| High-volume production | $100+ |

### Top-up strategy

Top up when the tab balance drops below 20% of original (matches the
`tab.low_balance` webhook threshold). Top-up amount: same as original
tab size. No additional activation fee on top-ups.

```
pay tab topup <tab_id> <amount>
```

Always confirm top-ups with the operator before executing.

## Max charge per call

Set `--max-charge` to the expected per-call price. This is contract-
enforced protection against overcharging.

```
# API charges $0.01/call
pay tab open 0xProvider 50.00 --max-charge 0.01

# API charges $0.50/call
pay tab open 0xProvider 50.00 --max-charge 0.50
```

If the provider tries to charge more than max-charge, the contract
reverts the transaction. The agent's total risk is bounded by the
tab balance.

If you don't know the per-call price, set max-charge to $1 as a
reasonable ceiling for most APIs. Adjust after seeing actual charges.

## Closing tabs

Either party can close unilaterally:

```
pay tab close <tab_id>
```

On close, funds are distributed:
- Provider receives: totalCharged * 0.99
- Fee wallet receives: totalCharged * 0.01
- Agent receives: remaining balance (refunded)

## Idle tab cleanup

Tabs with no charges for an extended period are wasting locked capital.
When reviewing tabs (`pay tab list`), flag any that appear idle:

- No charges in the last 24+ hours (if the service was supposed to
  be active)
- Balance is nearly full (opened but barely used)
- Provider is no longer being used

Suggest closing idle tabs to free up the balance. Tabs auto-close
after 30 days of inactivity. The agent receives a `tab.closing_soon`
webhook before this happens.

## Multiple tabs with same provider

Unusual but valid. Different max-charge limits or purposes. Don't warn,
but if an agent has two tabs with the same provider, ask if one should
be closed.

## What tabs are NOT

- Not subscriptions. No recurring charge. Pay per use.
- Not escrow. No deliverable-based release.
- Not streams. No per-second rate.


path: references/x402.md
content: # Pay — x402 Details

Most of the time, `pay request <url>` handles everything. This
reference is for when you need to understand what's happening under
the hood or when something goes wrong.

## How `pay request` works

```
1. Agent runs: pay request https://api.example.com/data
2. CLI sends GET to the URL
3. If response is 200 -> return response (not paywalled)
4. If response is 402 -> CLI reads PAYMENT-REQUIRED header
5. CLI determines settlement mode (direct or tab)
6. For direct: CLI signs EIP-3009 authorization, retries with payment
7. For tab: CLI checks for open tab with provider
   - If none: CLI opens a tab (10x per-call price, minimum $5)
   - If exists: charges existing tab
   CLI retries with tab charge proof
8. Provider verifies via facilitator -> serves content
9. CLI returns the API response
```

Steps 4-8 are handled by the CLI. The agent just gets the response.

## Settlement modes

The provider declares which settlement mode to use in their 402
response:

### Direct settlement (`settlement: "direct"`)

- On-chain payment per request
- For calls priced at $1+
- Standard x402 — works with any x402-compatible agent SDK
- Higher latency (~2s for on-chain confirmation)

### Tab settlement (`settlement: "tab"`)

- Charges against a pre-funded tab
- For any price point, especially micropayments
- Pay-specific — requires the Pay CLI or SDK
- Low latency (~50ms, off-chain verification)
- Batched settlement (~$0.000006 effective gas per charge)

The CLI handles both modes transparently based on the 402 response.

## Non-Pay facilitators

Not all 402 responses use the Pay facilitator. The x402 ecosystem
includes other facilitators (e.g., from Coinbase).

If `pay request` encounters a 402 pointing to a different facilitator:
- The CLI cannot handle it
- Report to the operator: "This endpoint uses a different x402
  facilitator. The Pay CLI only works with the Pay facilitator
  (pay-skill.com/x402)."
- The operator may need a different x402 client for that endpoint

## The Pay facilitator

```
URL:     https://pay-skill.com/x402
Testnet: https://testnet.pay-skill.com/x402

Endpoints:
  POST /x402/verify     Verify payment (off-chain, instant)
  POST /x402/settle     Execute on-chain settlement
  GET  /x402/supported  List supported schemes/networks
```

The CLI calls these automatically. The agent never calls them directly.

## pay-gate

pay-gate is the provider-side reverse proxy that generates 402
responses and verifies payments. The agent never interacts with
pay-gate directly — it's transparent. The agent just sees a 402
from the API URL.

For provider setup docs: pay-skill.com/docs/gate

## Wire format

x402 V2 headers (the only version Pay supports):

| Header | Direction | Purpose |
|--------|-----------|---------|
| `PAYMENT-REQUIRED` | server -> agent | Base64 JSON payment requirements |
| `PAYMENT-SIGNATURE` | agent -> server | Payment proof |
| `PAYMENT-RESPONSE` | server -> agent | Settlement receipt |

V1 headers (`X-PAYMENT`, `X-PAYMENT-RESPONSE`) are not supported.

## `pay request` options

Mirrors curl:

```
pay request <url>                    GET request (default)
  -X POST                           HTTP method
  -H "Authorization: Bearer ..."    Headers (repeatable)
  -d '{"query": "..."}'             Request body
  -d @file.json                     Body from file
  -o output.json                    Write response to file
  -v                                Show request/response headers
  -s                                Body only (no status line)
  --no-pay                          Skip payment handling (debug)
```


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)