---
name: agentpay
description: Discover and call AgentPay-protected APIs. Use when given an AgentPay URL, an agent-proxy.alchemy.com URL, an AgentPay OpenAPI document, x-payment-info metadata, HTTP 402 Payment Required from AgentPay, x402 payment requirements, or an MPP Payment challenge. Covers x402/x402-testnet payments with PAYMENT-SIGNATURE and MPP Tempo/Stripe payments with Authorization credentials.
---

# AgentPay Client Skill

AgentPay is a payment proxy for APIs. Call the AgentPay URL, satisfy the payment challenge returned by HTTP 402, then retry the exact same request. Do not call the provider's backend URL directly.

## Start with discovery

If you know the project ID, fetch the OpenAPI document before choosing a route:

```text
https://agent-proxy.alchemy.com/v1/{projectId}/openapi.json
https://agent-proxy.alchemy.com/openapi.json?projectId={projectId}
```

Use the OpenAPI paths, operation descriptions, request/response schemas, parameters, and `x-payment-info` metadata to pick an endpoint and estimate price. The unpaid 402 response is still the source of truth for exact payment requirements.

## URL shape

```text
https://agent-proxy.alchemy.com/v1/{protocol}/{projectId}/{endpointSlug}/{path}
```

- `{protocol}` is one of `x402`, `x402-testnet`, `mpp-tempo`, `mpp-tempo-testnet`, or `mpp-stripe`.
- `{projectId}` is the dashboard-generated project ID.
- `{endpointSlug}` is the configured operation slug, usually the OpenAPI `operationId`.
- `{path}` is optional extra path appended to the configured backend URL. Query parameters are preserved.

## Protocols

| Protocol | Header on paid retry | Typical client |
| --- | --- | --- |
| `x402` | `PAYMENT-SIGNATURE` | x402 v2 client with production wallet funds |
| `x402-testnet` | `PAYMENT-SIGNATURE` | x402 v2 client with testnet wallet funds |
| `mpp-tempo` | `Authorization` | MPP client with Tempo mainnet payment support |
| `mpp-tempo-testnet` | `Authorization` | MPP client with Tempo testnet support |
| `mpp-stripe` | `Authorization` | MPP client with Stripe/card-backed payment support |

## Universal request flow

1. Confirm the user has approved the protocol, network, credential, and spend limit.
2. Send the intended request without a payment credential.
3. If the response is not `402`, handle it as a normal API response.
4. If the response is `402`, parse the challenge and select only a payment option you can satisfy within budget.
5. Retry the same URL, method, body, and query string with the protocol-specific payment credential.
6. On success, return the backend response. When present, decode `PAYMENT-RESPONSE` for payment settlement metadata.

`PAYMENT-RESPONSE` is base64-encoded JSON:

```json
{
  "success": true,
  "transaction": "0x...",
  "network": "eip155:8453",
  "payer": "0x..."
}
```

## x402 requests

AgentPay's x402 channels use x402 v2 HTTP headers:

- Missing payment response: HTTP `402` with JSON body and `PAYMENT-REQUIRED` header.
- Paid retry header: `PAYMENT-SIGNATURE`.
- Do not use legacy `X-PAYMENT` or `X-PAYMENT-RESPONSE`.

Unpaid x402 response:

```json
{
  "x402Version": 2,
  "error": "PAYMENT-SIGNATURE header is required",
  "resource": {
    "url": "https://agent-proxy.alchemy.com/v1/x402-testnet/project/chat/messages",
    "description": "API access payment required",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "amount": "10000",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0x...",
      "maxTimeoutSeconds": 300,
      "extra": { "name": "USDC", "version": "2" }
    }
  ]
}
```

Important x402 rules:

- Sign for the exact `resource.url`. It must match the retried URL, including query string.
- Copy the selected `accepts[]` entry into the payment payload as `accepted`.
- Keep `x402Version` as number `2`, not string `"2"`.
- Match `network`, `asset`, `amount`, and `payTo` exactly.
- For EVM USDC, use `accepted.extra.name` and `accepted.extra.version` as the EIP-712 domain name/version.
- AgentPay can add Circle Gateway batching options for EVM USDC. Use those only if your client supports Circle Gateway batching; otherwise choose the standard `exact` option for the same network.

Supported x402 network IDs currently returned by AgentPay:

| AgentPay channel | Network key | Requirement `network` | Asset |
| --- | --- | --- | --- |
| `x402` | `base` | `eip155:8453` | USDC `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` or ETH zero address |
| `x402-testnet` | `base-sepolia` | `eip155:84532` | USDC `0x036CbD53842c5426634e7929541eC2318f3dCF7e` or ETH zero address |
| `x402` | `solana` | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | USDC `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
| `x402-testnet` | `solana-devnet` | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | USDC `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU` |

### x402 JavaScript pattern

Prefer the official x402 client packages when available:

```ts
import { x402Client } from '@x402/core/client';
import { x402HTTPClient } from '@x402/core/http';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { toClientEvmSigner } from '@x402/evm';
import { privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const core = registerExactEvmScheme(new x402Client(), {
  signer: toClientEvmSigner(account),
  policies: [
    (_version, requirements) =>
      requirements.filter((req) => BigInt(req.amount) <= 1000000n),
  ],
});
const client = new x402HTTPClient(core);

async function agentpayX402Fetch(url: string, init: RequestInit = {}) {
  const unpaid = await fetch(url, init);
  if (unpaid.status !== 402) return unpaid;

  const paymentRequired = client.getPaymentRequiredResponse(
    (name) => unpaid.headers.get(name),
    await unpaid.json(),
  );
  const paymentPayload = await client.createPaymentPayload(paymentRequired);

  return fetch(url, {
    ...init,
    headers: {
      ...Object.fromEntries(new Headers(init.headers).entries()),
      ...client.encodePaymentSignatureHeader(paymentPayload),
    },
  });
}
```

If you build the header manually, base64-encode a JSON `PaymentPayload` containing:

```json
{
  "x402Version": 2,
  "resource": { "url": "same URL from the 402 response" },
  "accepted": { "copy": "one entry from accepts[]" },
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0x...",
      "to": "accepted.payTo",
      "value": "accepted.amount",
      "validAfter": "0",
      "validBefore": "unix timestamp before timeout",
      "nonce": "0x bytes32"
    }
  }
}
```

Then retry with:

```text
PAYMENT-SIGNATURE: <base64 JSON payment payload>
```

## MPP requests

MPP channels use the HTTP `Authorization` header with the `Payment` authentication scheme. AgentPay verifies and charges the credential before forwarding the request.

- Missing payment response: HTTP `402` with an MPP challenge, usually in `WWW-Authenticate`.
- Paid retry header: `Authorization: Payment ...`.
- `mpp-tempo` charges Tempo mainnet.
- `mpp-tempo-testnet` charges Tempo Moderato/testnet.
- `mpp-stripe` charges through a Stripe/card-backed MPP method.

Use an MPP-capable client whenever possible. For Tempo in JavaScript:

```ts
import { Mppx, tempo } from 'mppx/client';
import { privateKeyToAccount } from 'viem/accounts';

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const mppx = Mppx.create({
  methods: [tempo({ account })],
  polyfill: false,
});

const response = await mppx.fetch(
  'https://agent-proxy.alchemy.com/v1/mpp-tempo-testnet/{projectId}/{endpointSlug}/{path}',
  { method: 'POST', body: JSON.stringify({ query: 'hello' }) },
);
```

If you are handling MPP manually, parse the returned payment challenge, create a compatible credential for the advertised method and intent, then retry the same request with the serialized credential in `Authorization`.

## Errors and guardrails

- `400` usually means malformed URL or unknown protocol.
- `403` usually means the endpoint is disabled or the selected payment channel is not configured for the project.
- `404` means the project or endpoint slug was not found.
- `402` with an error body means payment is missing, malformed, expired, over budget, for the wrong resource URL, or for an unaccepted network/asset/recipient/amount.
- `429` means the provider's AgentPay team exceeded its usage limit.
- Never sign or send payment if the price, recipient, network, asset, or resource URL differs from what the user approved.
