# Welcome

The source for the ShredPay developer portal at [developers.shredpay.xyz](https://developers.shredpay.xyz).

ShredPay is a crypto payment and DeFi investment platform. These docs cover everything developers need to integrate with ShredPay — most prominently the **Agent Wallet API**, which lets AI agents securely operate on-chain assets through REST and MCP interfaces.

## What's in this repo

| Section            | Contents                                                                       |
| ------------------ | ------------------------------------------------------------------------------ |
| `introduction.md`  | Platform overview                                                              |
| `getting-started/` | Authentication, environments, first request                                    |
| `agent-wallet/`    | Agent Wallet product — quickstarts, concepts, guides, API reference, MCP tools |
| `webhooks/`        | Event delivery, signature verification                                         |
| `sdks/`            | Official SDK index                                                             |
| `reference/`       | Errors, rate limits, glossary                                                  |

## License

Documentation © ShredPay. See repository for terms.


# Introduction

**ShredPay** is a crypto payment and DeFi investment platform. We provide the on-chain plumbing — wallets, payments, swaps, yield — so you can ship products without building blockchain infrastructure from scratch.

## What you can build

| Product                    | Description                                                                                                                                                                                       |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Agent Wallet**           | Give AI agents a secure on-chain wallet they can use through REST or [MCP](https://modelcontextprotocol.io/). Per-key spend limits, address screening, and sponsored gas for swap and DeFi flows. |
| **Payments** *(coming)*    | Accept stablecoin payments with automatic settlement to your treasury.                                                                                                                            |
| **DeFi Vaults** *(coming)* | Programmatic access to curated yield vaults across multiple chains.                                                                                                                               |

Today these docs focus on **Agent Wallet** — our first generally available developer product.

## How ShredPay is structured

ShredPay runs as a set of microservices behind a single API gateway. As a developer you only ever interact with the public surface, but it helps to know the boundaries:

* **Wallet Service** — custodial wallet infrastructure (built on Privy 2/2 key quorum).
* **Agent Service** — the API and MCP server that exposes Agent Wallet capabilities.
* **Screening Service** — runs OFAC and risk checks on every counterparty.
* **DeFi Service** — quotes, markets, position tracking.
* **Router contracts** — on-chain entry point that batches approve + swap + deposit and lets ShredPay sponsor gas.

## Who these docs are for

Developers integrating ShredPay into their own product — whether that's an autonomous agent, a wallet UX, a trading bot, or a backend service that needs to move funds on-chain.

If you are looking for the consumer ShredPay app, see [shredpay.xyz](https://shredpay.xyz).

## Next steps

* **New here?** Start with [Getting Started → Overview](/getting-started/overview).
* **Building an agent?** Jump straight to [Agent Wallet → Introduction](/agent-wallet/introduction).
* **Want a working request in 60 seconds?** Try the [Direct API quickstart](/agent-wallet/quickstart/direct-api).


# Overview

A high-level look at how ShredPay is wired together and where your code fits in.

## Architecture at a glance

```
┌────────────────────┐        ┌────────────────────┐
│   Your app /       │        │   AI agent (MCP)   │
│   backend service  │        │   Claude, OpenClaw │
└─────────┬──────────┘        └─────────┬──────────┘
          │                             │
          │  REST  X-Api-Key            │  MCP  X-Api-Key
          │  https://agent-api...       │  /mcp endpoint
          ▼                             ▼
┌──────────────────────────────────────────────────┐
│             Agent Service (public)                │
│   API key auth · spend limits · screening         │
│   tx orchestration · MCP transport                │
└────────┬─────────────┬───────────────┬────────────┘
         │             │               │
         ▼             ▼               ▼
   Wallet Service  Screening     Router contracts
   (sub-wallets,   Service       (on-chain swap +
    P-256 quorum)  (OFAC, risk)   DeFi, gas sponsor)
```

## Request lifecycle (write path)

When an agent calls `POST /api/tx/send`:

1. **Authenticate** — Agent Service resolves the `X-Api-Key` to a sub-wallet and checks the key's permissions and `allowed_chains`.
2. **Limit check** — Daily and monthly USD spend is rolled up against the key's caps.
3. **Screen** — The `to` address (and any beneficiaries decoded from calldata) are screened.
4. **Co-sign** — Agent Service co-signs with its P-256 key; Privy signs with the user-side key (2/2 quorum).
5. **Broadcast** — The transaction is submitted to the configured RPC for the chain.
6. **Webhook** — When the tx confirms (or fails), Agent Service emits an event to your registered webhook URL.

Read-only requests (`get_balance`, `get_positions`, etc.) skip steps 2–5.

## Two ways to integrate

| Path                | When to use                                                                         | Auth               |
| ------------------- | ----------------------------------------------------------------------------------- | ------------------ |
| **REST** (`/api/*`) | Backends, traditional apps, deterministic flows.                                    | `X-Api-Key` header |
| **MCP** (`/mcp`)    | LLM agents that should pick the right tool autonomously (Claude, OpenClaw, custom). | `X-Api-Key` header |

The two surfaces are equivalent — every MCP tool maps 1:1 to a REST endpoint.

## What you need before building

1. A ShredPay account — sign up at [shredpay.xyz](https://shredpay.xyz).
2. Open the **Agent Console** at [console.shredpay.xyz](https://console.shredpay.xyz) and create a sub-wallet.
3. Issue an API key with the limits and chains you want to allow.
4. Fund the sub-wallet (USDC + a small ETH balance, or use the gas swap flow).

You're ready. Continue to [Authentication](/getting-started/authentication).


# Authentication

ShredPay uses two auth schemes depending on who is calling.

| Caller                  | Scheme                      | Header                    |
| ----------------------- | --------------------------- | ------------------------- |
| AI agent / your backend | **API Key**                 | `X-Api-Key: sk_live_…`    |
| Agent Console (browser) | **Privy JWT** (via Gateway) | `Authorization: Bearer …` |

This page covers API keys — the only scheme you need for programmatic access. JWT-authenticated routes are reserved for the Agent Console UI.

## API keys

API keys are issued from the [Agent Console](https://console.shredpay.xyz). Each key is bound to exactly one **sub-wallet** and carries:

* **Permissions** — `read` or `trade`.
* **Spend limits** — daily and monthly USD caps.
* **Allowed chains** — a whitelist of chain IDs the key can transact on.

```http
GET /api/wallet/address HTTP/1.1
Host: agent-api.shredpay.xyz
X-Api-Key: sk_live_e9f3...c104
```

### Key format

```
sk_live_<32-character-secret>     production
sk_test_<32-character-secret>     test environment
```

The full secret is shown **once** at creation time. Store it securely — ShredPay only keeps a hash on disk, so we cannot recover a lost key. Use the rotate endpoint if a key is compromised; the previous key keeps working for 24 hours to give you a grace window.

### Permissions

| Permission | What it allows                                                                                         |
| ---------- | ------------------------------------------------------------------------------------------------------ |
| `read`     | All `GET /api/*` endpoints; MCP read-only tools (`get_balance`, `get_positions`, …).                   |
| `trade`    | Everything in `read` **plus** write endpoints (`send_transaction`, `execute_swap`, `defi_deposit`, …). |

Issue separate keys for read-only dashboards and trading bots. It limits blast radius if one is leaked.

### Spend limits

Limits are enforced **per key**, not per sub-wallet. A request that would exceed either the daily or monthly USD cap is rejected with `403 LIMIT_EXCEEDED` before any signing happens.

Check current usage anytime:

```http
GET /api/limits
```

```json
{
  "daily_limit_usd": "1000",
  "daily_used_usd": "247.50",
  "monthly_limit_usd": "10000",
  "monthly_used_usd": "1820.00",
  "resets_at": "2026-04-26T00:00:00Z"
}
```

### Rotating a key

```http
POST /api/v1/agent/keys/{key_id}/rotate
Authorization: Bearer <console JWT>
```

The response contains a brand-new `sk_live_…` value. The previous key continues to authenticate for 24 hours, then is permanently revoked.

## Storing keys safely

* Treat API keys like passwords — never commit them, never log them, never paste them into chat tools.
* Inject via environment variable or a secret manager (AWS Secrets Manager, Doppler, 1Password).
* Use **separate keys per environment** so a leaked test key cannot move production funds.
* Rotate on a schedule (quarterly is a good default) and immediately on suspected compromise.

## Errors

| Code                    | Meaning                                                                |
| ----------------------- | ---------------------------------------------------------------------- |
| `401 UNAUTHENTICATED`   | Missing or malformed `X-Api-Key` header.                               |
| `401 INVALID_KEY`       | Key does not exist or has been revoked.                                |
| `403 PERMISSION_DENIED` | Key lacks the required permission (e.g. `read` key calling `tx/send`). |
| `403 CHAIN_NOT_ALLOWED` | Target `chain_id` is not in the key's `allowed_chains`.                |
| `403 LIMIT_EXCEEDED`    | Daily or monthly USD cap hit.                                          |

See [reference/error-codes.md](/reference/error-codes) for the full list.


# Environments

ShredPay provides production endpoints for external developers. Credentials are environment-specific and not portable.

| Environment | Purpose                             | API base                         | MCP endpoint                         | Console                        |
| ----------- | ----------------------------------- | -------------------------------- | ------------------------------------ | ------------------------------ |
| **Prod**    | Production. Real funds. SLA-backed. | `https://agent-api.shredpay.xyz` | `https://agent-api.shredpay.xyz/mcp` | `https://console.shredpay.xyz` |

## Chain availability

Prod operates on the following mainnet chains: Ethereum, Base, Arbitrum, Polygon, Optimism, BNB Chain. There is currently no testnet support.

Always query `GET /api/wallet/chains` for the authoritative list — chains may be added without a documentation update.

## Status and uptime

Subscribe to the status page at [status.shredpay.xyz](https://status.shredpay.xyz) for incident notifications.

## Per-environment configuration

When deploying your integration:

1. Create a sub-wallet in the [Console](https://console.shredpay.xyz).
2. Issue an API key bound to that sub-wallet.
3. Register your webhook endpoint and store the signing secret.
4. Update your application config.

API keys are scoped to a single sub-wallet group and cannot be reused across wallets.


# Support

How to get help when you're stuck.

## Channels

| Channel                                                                            | When to use                                                                           |
| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Email — `developers@shredpay.xyz`                                                  | Integration questions, account issues, anything non-urgent.                           |
| GitHub issues — [`ShredPay/dev-docs`](https://github.com/ShredPay/dev-docs/issues) | Documentation bugs, typos, missing examples.                                          |
| Status page — [status.shredpay.xyz](https://status.shredpay.xyz)                   | Live incident updates.                                                                |
| Security disclosures — `security@shredpay.xyz`                                     | Vulnerabilities (please use [responsible disclosure](https://shredpay.xyz/security)). |

## Before you reach out

A short reproduction goes a long way. Please include:

* Environment (`dev` / `test` / `prod`).
* The HTTP method, path, and request body (with the API key redacted).
* The response status, headers, and body.
* A timestamp (UTC) and the `x-request-id` header from the response if available.

## SLA

Response targets for production accounts:

| Severity                                    | First response |
| ------------------------------------------- | -------------- |
| Critical (production outage, funds at risk) | 1 hour         |
| High (degraded production)                  | 4 hours        |
| Normal                                      | 1 business day |

Dev and Test environments are best-effort.


# Introduction

A custodial wallet purpose-built for AI agents. Agent Wallet lets your agent hold assets, sign transactions, swap tokens, and deposit into DeFi vaults — across six EVM chains — through a single REST or [MCP](https://modelcontextprotocol.io/) interface.

## Why a separate wallet for agents

Giving an LLM-powered agent direct access to a user's main wallet is reckless. Agent Wallet exists to make agent autonomy safe:

* **Isolated funds** — Each agent gets its own sub-wallet, scoped per user. Compromise stays contained.
* **Hard spend caps** — Per-key daily and monthly USD limits enforced server-side, before any signing.
* **Address screening** — Every counterparty is checked against OFAC and risk lists on every write call.
* **Quorum signing** — Two-of-two signatures (Privy + ShredPay co-signer) on every transaction. Neither party alone can move funds.
* **Per-chain whitelisting** — Restrict a key to specific chains so a swap on Mainnet can't be triggered with a key meant for Base.
* **Killable** — Revoke or rotate a key from the console without touching the wallet itself.

## What it can do

| Capability                       | REST                                          | MCP                                                                                           |
| -------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------- |
| Read addresses, balances, limits | `GET /api/wallet/*`                           | `get_wallet_address`, `get_balance`, `get_native_balance`, `get_token_balances`, `get_limits` |
| Send arbitrary transactions      | `POST /api/tx/send`                           | `send_transaction`                                                                            |
| Simulate transactions            | `POST /api/tx/simulate`                       | `simulate_transaction`                                                                        |
| Quote and execute swaps          | `POST /api/swap/quote`, `/execute`            | `get_swap_quote`, `execute_swap`                                                              |
| DeFi vault deposit / withdraw    | `POST /api/defi/deposit`, `/withdraw`         | `defi_deposit`, `defi_withdraw`                                                               |
| Position and market discovery    | `GET /api/defi/markets`, `/positions`         | `get_defi_markets`, `get_positions`                                                           |
| Gas management (USDC → ETH)      | `POST /api/gas/swap`, `GET /api/gas/estimate` | `gas_swap`, `gas_estimate`                                                                    |
| Status lookup                    | `GET /api/tx/{tx_id}`                         | `get_transaction_status`                                                                      |
| Chain discovery                  | `GET /api/wallet/chains`                      | `get_supported_chains`                                                                        |

That's the full surface — 17 MCP tools, all also available as REST endpoints.

## Supported chains

Ethereum, Optimism, BNB Chain, Polygon, Base, Arbitrum. Always check `GET /api/wallet/chains` for the live list and to see which chains have ShredPay's **Router** contract deployed (Router-enabled chains support sponsored gas for swap and DeFi flows).

## Pick a starting point

| If you...                                | Go to                                                                |
| ---------------------------------------- | -------------------------------------------------------------------- |
| ...want a working REST request right now | [Direct API quickstart](/agent-wallet/quickstart/direct-api)         |
| ...are wiring up Claude Desktop          | [Claude Desktop quickstart](/agent-wallet/quickstart/claude-desktop) |
| ...are building on the OpenClaw platform | [OpenClaw quickstart](/agent-wallet/quickstart/openclaw)             |
| ...want to understand the model first    | [Sub-wallets](/agent-wallet/concepts/sub-wallets)                    |


# Quickstart


# Claude Desktop

Wire ShredPay Agent Wallet into Claude Desktop in about three minutes. Claude will then be able to use all 17 wallet tools directly from any conversation.

## Prerequisites

* [Claude Desktop](https://claude.ai/download) installed (macOS or Windows).
* A ShredPay API key. If you don't have one, follow steps 1–2 of the [Direct API quickstart](/agent-wallet/quickstart/direct-api).

## 1. Locate your Claude Desktop config

| OS      | Path                                                              |
| ------- | ----------------------------------------------------------------- |
| macOS   | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json`                     |

If the file doesn't exist, create it.

## 2. Add the ShredPay MCP server

```json
{
  "mcpServers": {
    "shredpay-wallet": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-fetch",
        "https://agent-api.shredpay.xyz/mcp"
      ],
      "env": {
        "X_API_KEY": "sk_live_..."
      }
    }
  }
}
```

Replace `sk_live_…` with your real key from the [Console](https://console.shredpay.xyz).

> The `@modelcontextprotocol/server-fetch` package is the simplest way to point Claude Desktop at a remote streamable-HTTP MCP server. If you maintain your own MCP client transport, point it directly at the `/mcp` endpoint with `X-Api-Key` set on every request.

## 3. Restart Claude Desktop

Fully quit and relaunch. After restart, click the tools icon at the bottom of the chat — you should see **shredpay-wallet** with 17 tools listed.

## 4. Ask Claude to use it

```
What's my USDC balance on Base?
```

Claude will call `get_wallet_address` and `get_balance` and answer with a number. Try follow-ups:

```
Show me my open DeFi positions.
Quote a swap of 50 USDC to ETH on Base.
What's my remaining daily spend limit?
```

Trade-permission tools (`send_transaction`, `execute_swap`, `defi_deposit`, `defi_withdraw`) only work if your key has `trade` enabled.

## Troubleshooting

| Symptom                                 | Fix                                                                                             |
| --------------------------------------- | ----------------------------------------------------------------------------------------------- |
| Tools don't appear after restart        | Check the log at `~/Library/Logs/Claude/mcp*.log` (macOS) for JSON parse errors in your config. |
| `401 INVALID_KEY` in tool output        | Key was revoked or you copied a typo. Issue a new one in the console.                           |
| `403 PERMISSION_DENIED` on a write tool | Your key is `read` only. Create a `trade` key.                                                  |

## Next steps

* [MCP Tools reference](/agent-wallet/mcp-tools) — every tool and its parameters.
* [Gas Model](/agent-wallet/concepts/gas-model) — when ShredPay sponsors gas vs. when you pay.


# OpenClaw

Use the official ShredPay Skill on the [OpenClaw](https://openclaw.ai) agent platform.

## What you'll build

A connected ShredPay Skill in your OpenClaw workspace. Once installed, every agent in the workspace can call any of the 17 wallet tools.

## Steps

This page is a placeholder while we finalize the OpenClaw Skill submission flow. The outline:

1. **Get a ShredPay API key** — same as the [Direct API quickstart](/agent-wallet/quickstart/direct-api), steps 1–2.
2. **Open the OpenClaw Skill marketplace** — search for *ShredPay Wallet*.
3. **Install** — click *Install* and paste your API key when prompted.
4. **Test in any agent** — ask the agent for your wallet balance.

## Skill manifest

The Skill is defined by [`shredpay-wallet.skill.yaml`](https://github.com/ShredPay/openclaw-skill) in the public OpenClaw repo. Version `2.2.0` exposes all 17 tools and supports six EVM chains.

## Coming soon

* Full screenshots of the install flow.
* A worked example with a yield-farming agent.
* Notes on per-workspace key rotation.

In the meantime, the [Direct API quickstart](/agent-wallet/quickstart/direct-api) and [MCP Tools reference](/agent-wallet/mcp-tools) cover everything the Skill exposes.


# Direct API

Make your first authenticated request in under a minute.

## 1. Create an API key

1. Sign in to the [Agent Console](https://console.shredpay.xyz).
2. Create a sub-wallet if you don't have one yet.
3. Open **API Keys → New key**. Pick:
   * **Name** — something memorable, e.g. `quickstart-laptop`.
   * **Permissions** — `read` is enough for this quickstart.
   * **Allowed chains** — leave the default (all supported) or restrict.
   * **Daily / monthly limits** — any value; reads don't consume them.
4. Copy the `sk_live_…` value. **It is shown only once.**

```bash
export SHREDPAY_API_KEY="sk_live_..."
export SHREDPAY_BASE_URL="https://agent-api.shredpay.xyz"
```

## 2. Fetch your wallet addresses

```bash
curl "$SHREDPAY_BASE_URL/api/wallet/address" \
  -H "X-Api-Key: $SHREDPAY_API_KEY"
```

```json
{
  "addresses": {
    "evm": "0xA1b2C3d4e5F60718293A4B5c6d7E8f9012345678"
  },
  "sub_wallet_id": "sw_01HRZK..."
}
```

The same EVM address is used across every chain.

## 3. Check a balance

```bash
# USDC on Base
curl "$SHREDPAY_BASE_URL/api/wallet/balance?chain_id=8453&token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" \
  -H "X-Api-Key: $SHREDPAY_API_KEY"
```

```json
{
  "chain_id": 8453,
  "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "balance": "1500000",
  "decimals": 6,
  "symbol": "USDC"
}
```

`balance` is always in the smallest unit (here, 1.5 USDC = 1,500,000).

## 4. Send a transaction

> Requires a key with `trade` permission and a funded sub-wallet (USDC + a small amount of native gas, or use [`gas_swap`](/agent-wallet/guides/gas-management) on Base).

The example below transfers 0.10 USDC to another address on Base.

```bash
# ERC20 transfer(address,uint256) calldata for 100000 (= 0.10 USDC)
TO_TOKEN=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
RECIPIENT=0x000000000000000000000000abc123...           # 32-byte right-padded
AMOUNT=00000000000000000000000000000000000000000000000000000000000186a0
DATA="0xa9059cbb${RECIPIENT}${AMOUNT}"

curl "$SHREDPAY_BASE_URL/api/tx/send" \
  -H "X-Api-Key: $SHREDPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"chain_id\": 8453,
    \"to\": \"$TO_TOKEN\",
    \"data\": \"$DATA\",
    \"value\": \"0\"
  }"
```

```json
{
  "tx_id": "tx_01HRZL...",
  "tx_hash": "0xa3b4...",
  "status": "broadcast"
}
```

Poll status with `GET /api/tx/{tx_id}` or — better — register a [webhook](/agent-wallet/guides/webhooks) and let ShredPay push the confirmation.

## What just happened

1. Your `X-Api-Key` resolved to a sub-wallet.
2. Spend limits were checked (here, the value is denominated and counted).
3. The recipient address was screened.
4. ShredPay co-signed alongside Privy (2/2 quorum).
5. The signed tx was broadcast on Base and an ID was returned.

## Next steps

* [Send a Transaction guide](/agent-wallet/guides/send-transaction) — full request/response with error handling.
* [Swap Tokens guide](/agent-wallet/guides/swap) — sponsored swaps via Router.
* [API Reference](/agent-wallet/api-reference) — every endpoint and field.


# Concepts


# Sub-wallets

Every agent gets its own wallet — distinct from the user's main ShredPay wallet, isolated from other agents, and disposable.

## Mental model

```
ShredPay user
    │
    ├── main wallet           (user controls — receives deposits, settles payments)
    │
    └── agent sub-wallets     (one per agent / use case)
            │
            ├── sub_wallet_1   ← API key A  ← agent #1 (e.g. trading bot)
            ├── sub_wallet_2   ← API key B  ← agent #2 (e.g. yield manager)
            └── sub_wallet_3   ← API key C  ← agent #3 (e.g. read-only dashboard)
```

A sub-wallet is a real on-chain address. It has its own balances and signs its own transactions.

## Properties

| Property    | Notes                                                                                                                                |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Address** | One EVM address used across all six supported chains. Returned by `GET /api/wallet/address`.                                         |
| **Owner**   | The ShredPay user that created it. Visible only to that user in the console.                                                         |
| **Group**   | Sub-wallets are organized under a `group_id`. Today every key maps to exactly one sub-wallet.                                        |
| **Signing** | 2/2 quorum: ShredPay co-signer (P-256) + Privy. Neither party alone can move funds.                                                  |
| **Funding** | Deposit from main wallet via the console. The main → sub transfer goes through the Router contract — full amount lands, no fee skim. |

## Sub-wallet vs. API key

A common point of confusion. They are **separate** concepts:

* A **sub-wallet** is the asset container — the on-chain address.
* An **API key** is the credential that grants access to a sub-wallet.

A sub-wallet can have multiple API keys attached (e.g. one read-only key for a dashboard, one trade key for a bot — both pointing at the same funds). Spend limits live on the **key**, not the wallet.

## Lifecycle

1. **Create** in the Agent Console. Pick a name and (optionally) a group.
2. **Fund** by depositing USDC from your main wallet. You can also send any ERC-20 to the address from outside ShredPay.
3. **Issue API keys** with the permissions you want.
4. **Use** via REST or MCP.
5. **Drain** when done — withdraw funds back to your main wallet from the console.
6. **Archive** — once empty, the sub-wallet can be archived. Archived wallets stop accepting new transactions.

## What sub-wallets do **not** do

* They do not gate which DeFi protocol or which token an agent can interact with. That's the agent's choice. Use **screening** and **per-key limits** for those controls.
* They do not enforce any business policy beyond key-level limits and chain whitelists.

## Related

* [API Keys](/agent-wallet/concepts/api-keys) — auth and limits
* [Multi-chain](/agent-wallet/concepts/multi-chain) — how one address spans six chains
* [Address Screening](/agent-wallet/concepts/address-screening) — automatic OFAC checks on every counterparty


# API Keys

API keys are how AI agents and your backend services authenticate to Agent Wallet. Each key wraps a set of policies — permissions, chains, and spend limits — that ShredPay enforces on every request.

## Anatomy of a key

| Field                        | Description                                                              |
| ---------------------------- | ------------------------------------------------------------------------ |
| `key_id`                     | Stable identifier (e.g. `key_01HRZK…`). Safe to log.                     |
| `secret`                     | The `sk_live_…` or `sk_test_…` value. Sensitive. Shown once at creation. |
| `name`                       | Human label set by the creator.                                          |
| `sub_wallet_id`              | Which sub-wallet the key controls. One-to-one binding.                   |
| `permissions`                | `read` or `trade`.                                                       |
| `allowed_chains`             | List of chain IDs (e.g. `[8453, 42161]`). Empty list = all supported.    |
| `daily_limit_usd`            | USD spend cap per UTC day.                                               |
| `monthly_limit_usd`          | USD spend cap per UTC month.                                             |
| `status`                     | `active`, `revoked`, or `rotating`.                                      |
| `created_at`, `last_used_at` | Audit fields.                                                            |

## Permissions

Two levels — keep them as small as you can get away with.

| `read`  | All `GET /api/*` endpoints. MCP read tools. No signing.                    |
| ------- | -------------------------------------------------------------------------- |
| `trade` | Everything `read` does **plus** `POST /api/tx/send`, swap, DeFi, gas swap. |

## Spend limits

Spend is measured in USD using the price oracle at the time of execution. Native gas paid by ShredPay (sponsored flows) does **not** count against the key's limit. The `value` of swaps and DeFi deposits **does**.

```http
GET /api/limits
```

```json
{
  "daily_limit_usd": "1000",
  "daily_used_usd": "247.50",
  "monthly_limit_usd": "10000",
  "monthly_used_usd": "1820.00",
  "resets_at": "2026-04-26T00:00:00Z"
}
```

When a request would push usage over either cap, ShredPay returns `403 LIMIT_EXCEEDED` **before** any signing. Funds stay safe.

## Allowed chains

`allowed_chains` is an explicit whitelist. A request whose `chain_id` isn't on the list is rejected with `403 CHAIN_NOT_ALLOWED`. Use it to:

* Restrict an experimental key to a low-fee testnet-equivalent like Base.
* Stop a swap bot from accidentally moving on Mainnet.
* Implement per-chain risk budgets at the IAM layer.

## Rotating

```http
POST /api/v1/agent/keys/{key_id}/rotate
```

The response contains a fresh `secret`. The previous secret continues to authenticate for **24 hours** then is permanently retired. Use this window to deploy the new value across your fleet without downtime.

## Revoking

```http
DELETE /api/v1/agent/keys/{key_id}
```

Immediate. There is no grace period — use rotation if you need one.

## Best practices

* **One key per environment.** Test keys never authenticate against Prod and vice versa.
* **One key per agent / use case.** Easier to attribute spend, easier to revoke.
* **Read keys for dashboards, trade keys for bots.** Don't grant `trade` to anything that doesn't need to write.
* **Bind to chains.** Even if a bot only ever runs on Base, set `allowed_chains: [8453]`.
* **Set tight limits.** Start small. You can raise limits without re-issuing.
* **Rotate on a schedule.** Quarterly is a reasonable default.
* **Monitor `last_used_at`.** A key that hasn't been used in 30 days is a candidate for retirement.

## Related

* [Authentication](/getting-started/authentication) — how to send the key
* [Sub-wallets](/agent-wallet/concepts/sub-wallets) — what the key controls
* [Address Screening](/agent-wallet/concepts/address-screening) — the other server-side guardrail


# Gas Model

Two ways to pay for gas. Knowing which applies to which call is the difference between "this transaction worked" and "out of funds."

| Mode                  | Who pays                                                  | When it applies                                                                                                  | Service fee                                         |
| --------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| **Agent pays**        | The sub-wallet's own native balance (ETH, BNB, MATIC, …). | `send_transaction` and any direct call you make through `POST /api/tx/send`.                                     | None.                                               |
| **ShredPay sponsors** | ShredPay's gas wallet on the target chain.                | `execute_swap`, `defi_deposit`, `defi_withdraw`, `gas_swap` — all flows that go through the **Router** contract. | A small fee on the input amount, in the same token. |

## Why two modes

Agents need to be able to call arbitrary contracts (paying their own gas keeps the model simple and uncensorable). But the most common operations — swaps, deposits, withdrawals — go through ShredPay's Router contract, which can batch token approvals and the actual call into a single sponsored transaction. That's faster, cheaper, and avoids the "agent has USDC but no ETH for gas" footgun.

## When you must hold native gas

Any time you call `send_transaction`. Typical examples:

* ERC-20 transfers to addresses outside the Router.
* Direct calls to a third-party protocol that ShredPay does not have a Router pathway for.
* Any custom calldata.

If your sub-wallet runs out of native gas mid-flow, use [`gas_swap`](/agent-wallet/guides/gas-management) — it converts USDC to ETH through the Router with **ShredPay** paying gas, so the agent doesn't need ETH to obtain ETH. This is how an agent funded only in USDC bootstraps itself.

> **Today `gas_swap` is supported on Base only.** Plan accordingly if your agent operates on other chains — pre-fund native gas or hold the agent on Base.

## When ShredPay sponsors

Any time you call:

* `execute_swap` — swap one token for another.
* `defi_deposit` / `defi_withdraw` — vault interactions in the curated DeFi catalog.
* `gas_swap` — bootstrap native gas from USDC.

These calls only succeed on chains where the **Router** contract is deployed. Check `has_router` in `GET /api/wallet/chains`:

```json
{
  "chains": [
    { "id": 1,     "name": "Ethereum", "has_router": false },
    { "id": 8453,  "name": "Base",     "has_router": true  },
    { "id": 42161, "name": "Arbitrum", "has_router": false }
  ]
}
```

A sponsored call on a chain without Router returns `400 ROUTER_NOT_AVAILABLE`.

## Service fees

Sponsored flows charge a small fee (basis points on the input amount, taken in the same token). Fees are returned in every quote — they are never a surprise:

```json
{
  "amount_in": "100000000",
  "amount_out": "0.0473...",
  "fee_amount": "100000",
  "fee_token": "USDC",
  "gas_sponsored": true
}
```

For exact current fee schedules, check the response body of `POST /api/swap/quote` — they are sourced live, not from documentation.

## Gas estimation

```http
GET /api/gas/estimate?chain_id=8453
```

```json
{
  "chain_id": 8453,
  "gas_price_wei": "1000000",
  "recommended_eth_for_5_txs": "0.0005",
  "native_balance_wei": "120000000000000"
}
```

Use this to decide whether the wallet has enough headroom for the next few transactions, or whether to swap up first.

## Related

* [Manage Gas guide](/agent-wallet/guides/gas-management) — how to keep the wallet topped up
* [Multi-chain](/agent-wallet/concepts/multi-chain) — which chains have Router


# Multi-chain

One sub-wallet, one address, six chains. This page explains what that means in practice and where the asymmetries are.

## Supported chains

| Chain     |    ID | Native gas | Router |
| --------- | ----: | ---------- | :----: |
| Ethereum  |     1 | ETH        |    —   |
| Optimism  |    10 | ETH        |    —   |
| BNB Chain |    56 | BNB        |    —   |
| Polygon   |   137 | POL        |    —   |
| Base      |  8453 | ETH        |   Yes  |
| Arbitrum  | 42161 | ETH        |    —   |

The authoritative list is dynamic — query `GET /api/wallet/chains`. Any chain returned there is supported; the documentation above may lag.

## One address, many chains

EVM addresses are deterministic: the same private key produces the same address on every EVM chain. Your sub-wallet has one address that is valid everywhere. There is no per-chain provisioning step.

```http
GET /api/wallet/address
```

```json
{
  "addresses": {
    "evm": "0xA1b2C3d4e5F60718293A4B5c6d7E8f9012345678"
  },
  "sub_wallet_id": "sw_01HRZK..."
}
```

Funds on different chains are independent — sending USDC to your address on Ethereum does not make it appear on Base. Each balance is queried per chain.

## `has_router` matters

The Router contract powers ShredPay's sponsored-gas flows. **Sponsored operations only work on chains with `has_router: true`.** Today that's **Base** only; more chains are in the pipeline.

| Operation                        | Mainnet | Base | Arbitrum | Polygon | Optimism | BNB |
| -------------------------------- | :-----: | :--: | :------: | :-----: | :------: | :-: |
| `send_transaction`               |   yes   |  yes |    yes   |   yes   |    yes   | yes |
| `simulate_transaction`           |   yes   |  yes |    yes   |   yes   |    yes   | yes |
| `execute_swap`                   |    —    |  yes |     —    |    —    |     —    |  —  |
| `defi_deposit` / `defi_withdraw` |    —    |  yes |     —    |    —    |     —    |  —  |
| `gas_swap`                       |    —    |  yes |     —    |    —    |     —    |  —  |
| Read tools (`get_balance`, …)    |   yes   |  yes |    yes   |   yes   |    yes   | yes |

A sponsored call on a non-Router chain returns `400 ROUTER_NOT_AVAILABLE`. Either move the operation to Base, or use `send_transaction` and pay gas yourself.

## Per-chain key whitelisting

The `allowed_chains` array on an API key is checked first. If your bot only operates on Base, set `allowed_chains: [8453]` — every other chain returns `403 CHAIN_NOT_ALLOWED`, no matter what the agent tries. This is the cheapest defense against a confused agent moving funds on the wrong chain.

## Native gas per chain

If you intend to use `send_transaction` (the Agent-pays path), the sub-wallet needs the **right native token** on the **right chain**:

* Ethereum, Optimism, Base, Arbitrum → ETH
* BNB Chain → BNB
* Polygon → POL (formerly MATIC)

Use `GET /api/gas/estimate?chain_id=…` to see how much native gas a chain has. On Base you can self-fund through `POST /api/gas/swap`. On other chains you need to send native tokens to the address from outside.

## Practical advice

* **Default to Base.** Lowest fees, full Router support, sponsored gas. Build there first.
* **Use chain whitelists aggressively.** They cost nothing and prevent footguns.
* **Don't assume cross-chain liquidity.** If your strategy needs USDC on both Mainnet and Arbitrum, plan the bridge yourself — Agent Wallet does not auto-bridge.
* **Read `GET /api/wallet/chains` at startup.** Cache for a session, but re-poll occasionally so new chains light up automatically.


# Address Screening

Every write call has its counterparties screened against OFAC and risk lists before signing. This page explains what's checked, when, and how to interpret the result.

## What gets screened

Outline:

* The `to` address on every `send_transaction`.
* Beneficiaries decoded from calldata for known function selectors (e.g. ERC-20 `transfer`, swap router recipients).
* Counterparties on `execute_swap`, `defi_deposit`, `defi_withdraw`.

## When it happens

* Before any signature is produced.
* Both for `send_transaction` and `simulate_transaction` — simulate is a safe way to pre-flight a screening check.

## Failure modes and codes

* `403 ADDRESS_BLOCKED` — counterparty is on a blocked list. The transaction is refused; funds remain in the sub-wallet.
* `403 SUB_WALLET_FROZEN` — the sub-wallet itself was frozen following a screening alert on an inbound transfer. Reach out to support to begin manual review.

## What to do on a hit

Outline:

* Read the response body for the offending address and category.
* Surface the message back to the agent / end-user — agents should treat blocks as terminal.
* Contact `support@shredpay.xyz` if you believe the block is a false positive.

## Inbound transfers

Outline:

* Funds arriving from a flagged source freeze only the receiving sub-wallet, not the user's main account.
* Resolution is manual.

This page will be expanded with concrete examples once the public screening response schema is finalized.


# Guides


# Send a Transaction

Outline for the full guide:

* Building the request — `chain_id`, `to`, `data`, `value`, optional `gas_limit`.
* The Agent-pays gas model and how to top up.
* Reading the response — `tx_id`, `tx_hash`, status semantics.
* Polling vs. webhook for confirmation.
* Common errors: `LIMIT_EXCEEDED`, `ADDRESS_BLOCKED`, `INSUFFICIENT_GAS`.
* Worked example: ERC-20 transfer.
* Worked example: arbitrary contract call (e.g. NFT mint).

For now see the [Direct API quickstart](/agent-wallet/quickstart/direct-api) for a runnable example.


# Swap Tokens

Outline:

* Quote first with `POST /api/swap/quote` — slippage, fee preview, expected out.
* Execute with `POST /api/swap/execute` — runs through Router, ShredPay sponsors gas.
* Worked example: 100 USDC → ETH on Base.
* Handling slippage failures and re-quoting.
* Why this is Base-only today (Router availability).

See [Gas Model](/agent-wallet/concepts/gas-model) for the sponsorship rules.


# Deposit into DeFi

Outline:

* Discover markets with `GET /api/defi/markets`.
* Deposit with `POST /api/defi/deposit` — `chain_id`, `market_id`, `amount`.
* Track shares and USD value with `GET /api/defi/positions`.
* Withdraw with `POST /api/defi/withdraw` — pass `shares` from the position.
* Worked example: deposit USDC into a curated yield vault on Base.
* Fees, gas sponsorship, and APY semantics.

See [MCP Tools](/agent-wallet/mcp-tools) for the equivalent `defi_deposit` / `defi_withdraw` tools.


# Manage Gas

Outline:

* `GET /api/gas/estimate?chain_id=…` — current gas price and a recommendation.
* `POST /api/gas/swap` — convert USDC to ETH on Base, sponsored by ShredPay.
* Pre-flight check pattern: estimate → swap if low → send.
* What to do on chains without `gas_swap` (manual native-token funding).
* Monitoring native balances across chains.


# Webhooks

Outline:

* Register a webhook URL in the Agent Console.
* Events emitted: `transaction.broadcast`, `transaction.confirmed`, `transaction.failed`, `funds.deposited`, `screening.alert`.
* Payload shape (one example per event).
* Verifying signatures — see [Webhooks → Signature Verification](/webhooks/signature-verification).
* Retries and idempotency keys.


# API Reference

Full machine-readable reference for every Agent Wallet REST endpoint.

## Live OpenAPI / Swagger UI

The authoritative spec is served by the Agent Service itself:

* **Swagger UI**: <https://agent-api.shredpay.xyz/api/docs>
* **OpenAPI JSON**: <https://agent-api.shredpay.xyz/api/docs-json>

## Endpoint summary

| Method | Path                         | Permission | Description                                       |
| ------ | ---------------------------- | ---------- | ------------------------------------------------- |
| GET    | `/api/wallet/chains`         | read       | Supported chains and `has_router` flag            |
| GET    | `/api/wallet/address`        | read       | Sub-wallet addresses                              |
| GET    | `/api/wallet/balance`        | read       | ERC-20 balance for one token on one chain         |
| GET    | `/api/wallet/balances`       | read       | All known-token balances on one chain             |
| GET    | `/api/wallet/native-balance` | read       | Native token balance                              |
| GET    | `/api/wallet/token-balances` | read       | All ERC-20 balances on a chain (Alchemy)          |
| GET    | `/api/limits`                | read       | Daily / monthly USD limits and usage              |
| GET    | `/api/gas/estimate`          | read       | Gas price and recommended ETH amount              |
| GET    | `/api/tx/{tx_id}`            | read       | Transaction status                                |
| GET    | `/api/defi/markets`          | read       | Available DeFi vaults                             |
| GET    | `/api/defi/positions`        | read       | Sub-wallet's open positions                       |
| POST   | `/api/swap/quote`            | read       | Swap quote via Li.Fi                              |
| POST   | `/api/tx/simulate`           | trade      | Simulate a transaction (validation + screening)   |
| POST   | `/api/tx/send`               | trade      | Sign and broadcast a transaction (Agent pays gas) |
| POST   | `/api/swap/execute`          | trade      | Execute a swap via Router (sponsored)             |
| POST   | `/api/defi/deposit`          | trade      | Deposit into a DeFi vault (sponsored)             |
| POST   | `/api/defi/withdraw`         | trade      | Withdraw from a DeFi vault (sponsored)            |
| POST   | `/api/gas/swap`              | trade      | Convert USDC to ETH for gas (sponsored, Base)     |

This page is intentionally a thin index — the Swagger UI is always up to date with the deployed code.


# MCP Tools

ShredPay Agent Wallet exposes 17 tools over the [Model Context Protocol](https://modelcontextprotocol.io/). Every tool maps 1:1 to a REST endpoint — pick whichever surface fits your client.

## Endpoint

```
https://agent-api.shredpay.xyz/mcp
```

Transport: **streamable-http**. Auth: `X-Api-Key` header on every request.

## Read tools (no `trade` permission required)

### `get_supported_chains`

List supported blockchain networks and whether each has the Router contract deployed.

| Param | Type | Required |
| ----- | ---- | -------- |
| —     |      |          |

### `get_wallet_address`

Get the agent's wallet addresses (one EVM address shared across all chains).

| Param | Type | Required |
| ----- | ---- | -------- |
| —     |      |          |

### `get_balance`

Query an ERC-20 token balance on a specific chain.

| Param      | Type   | Required | Description                     |
| ---------- | ------ | :------: | ------------------------------- |
| `chain_id` | number |    yes   | Chain ID (e.g. `8453` for Base) |
| `token`    | string |    yes   | Token contract address          |

### `get_native_balance`

Query the native token balance (ETH / BNB / POL).

| Param      | Type   | Required | Description |
| ---------- | ------ | :------: | ----------- |
| `chain_id` | number |    yes   | Chain ID    |

### `get_token_balances`

List all ERC-20 balances and the native balance on a chain (powered by Alchemy).

| Param      | Type   | Required | Description |
| ---------- | ------ | :------: | ----------- |
| `chain_id` | number |    yes   | Chain ID    |

### `get_limits`

Query daily and monthly spend limits and current usage.

| Param | Type | Required |
| ----- | ---- | -------- |
| —     |      |          |

### `get_transaction_status`

Look up the status of a previously submitted transaction.

| Param   | Type   | Required | Description                                   |
| ------- | ------ | :------: | --------------------------------------------- |
| `tx_id` | string |    yes   | Transaction ID returned by `send_transaction` |

### `gas_estimate`

Estimate current gas price and recommended ETH amount for a chain.

| Param      | Type   | Required | Description |
| ---------- | ------ | :------: | ----------- |
| `chain_id` | number |    yes   | Chain ID    |

### `get_defi_markets`

Get the catalog of available DeFi vaults.

| Param | Type | Required |
| ----- | ---- | -------- |
| —     |      |          |

### `get_positions`

Get the wallet's open DeFi positions (shares, USD value, market info, APY).

| Param | Type | Required |
| ----- | ---- | -------- |
| —     |      |          |

### `get_swap_quote`

Get a swap quote via the Li.Fi aggregator. Useful for previewing a price before calling `execute_swap`.

| Param        | Type   | Required | Description               |
| ------------ | ------ | :------: | ------------------------- |
| `chain_id`   | number |    yes   | Chain ID                  |
| `from_token` | string |    yes   | Source token address      |
| `to_token`   | string |    yes   | Destination token address |
| `amount`     | string |    yes   | Amount in smallest unit   |

## Trade tools (require `trade` permission)

### `send_transaction`

Sign and broadcast an arbitrary on-chain transaction. **Agent pays gas** — sub-wallet must hold native token.

| Param       | Type   | Required | Description                                    |
| ----------- | ------ | :------: | ---------------------------------------------- |
| `chain_id`  | number |    yes   | Target chain ID                                |
| `to`        | string |    yes   | Destination address                            |
| `data`      | string |    yes   | Transaction calldata (hex)                     |
| `value`     | string |    no    | Value in wei (hex or decimal). Defaults to `0` |
| `gas_limit` | string |    no    | Override gas limit                             |

### `simulate_transaction`

Simulate a transaction without broadcasting. Runs validation and address screening — useful for pre-flighting an expensive call.

| Param      | Type   | Required | Description                |
| ---------- | ------ | :------: | -------------------------- |
| `chain_id` | number |    yes   | Target chain ID            |
| `to`       | string |    yes   | Destination address        |
| `data`     | string |    yes   | Transaction calldata (hex) |
| `value`    | string |    no    | Value in wei               |

### `gas_swap`

Swap USDC to ETH for gas. **Sponsored** by ShredPay (you don't need ETH to obtain ETH). Base only today.

| Param         | Type   | Required | Description                               |
| ------------- | ------ | :------: | ----------------------------------------- |
| `amount_usdc` | string |    yes   | USDC amount in smallest unit (6 decimals) |
| `chain_id`    | number |    yes   | Chain ID (currently must be `8453`)       |

### `execute_swap`

Execute a token swap via the Router contract. **Sponsored** — ShredPay pays gas, collects a small fee.

| Param        | Type   | Required | Description                             |
| ------------ | ------ | :------: | --------------------------------------- |
| `chain_id`   | number |    yes   | Chain ID (must have `has_router: true`) |
| `from_token` | string |    yes   | Source token address                    |
| `to_token`   | string |    yes   | Destination token address               |
| `amount`     | string |    yes   | Amount in smallest unit                 |
| `slippage`   | string |    no    | Slippage tolerance (default `0.5%`)     |

### `defi_deposit`

Deposit into a curated DeFi vault via Router. **Sponsored**.

| Param       | Type   | Required | Description                                      |
| ----------- | ------ | :------: | ------------------------------------------------ |
| `chain_id`  | number |    yes   | Chain ID                                         |
| `market_id` | string |    yes   | Market ID from `get_defi_markets`                |
| `amount`    | string |    yes   | Amount in smallest unit (e.g. USDC = 6 decimals) |

### `defi_withdraw`

Withdraw from a DeFi vault via Router. **Sponsored**.

| Param       | Type   | Required | Description                                  |
| ----------- | ------ | :------: | -------------------------------------------- |
| `chain_id`  | number |    yes   | Chain ID                                     |
| `market_id` | string |    yes   | Market ID from `get_defi_markets`            |
| `shares`    | string |    yes   | Shares to redeem (read from `get_positions`) |

## Permission summary

| Permission | Tools                                                                                                                                                                                                                  |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `read`     | `get_supported_chains`, `get_wallet_address`, `get_balance`, `get_native_balance`, `get_token_balances`, `get_limits`, `get_transaction_status`, `gas_estimate`, `get_defi_markets`, `get_positions`, `get_swap_quote` |
| `trade`    | All `read` tools **plus** `send_transaction`, `simulate_transaction`, `gas_swap`, `execute_swap`, `defi_deposit`, `defi_withdraw`                                                                                      |

## Source of truth

The Skill manifest used by OpenClaw and other agent platforms lives at [`ShredPay/openclaw-skill`](https://github.com/ShredPay/openclaw-skill) — `shredpay-wallet.skill.yaml`. If that file disagrees with this page, the YAML wins.


# Changelog

Notable changes to the Agent Wallet API and MCP Skill.

## v2.2.0

* 17 MCP tools across read and trade tiers.
* Multi-chain support: Ethereum, Optimism, BNB Chain, Polygon, Base, Arbitrum.
* Swap and DeFi flows route through the Router contract on Base with sponsored gas.

## Earlier versions

Earlier internal versions are not documented publicly.

## Versioning policy

* Tools and endpoints are added without a version bump.
* Breaking changes (renaming a parameter, changing a return shape, removing a tool) bump the **major** version and ship behind an opt-in flag for at least one minor cycle.


# Overview

Outline:

* Why webhooks (push vs. poll for transaction state).
* How to register a URL in the Agent Console.
* Delivery semantics: at-least-once, ordered per-resource, retried with exponential backoff.
* Required HTTP response (`2xx` within 5 seconds).
* Best practices: respond fast, queue work, dedupe by `event_id`.

See [Signature Verification](/webhooks/signature-verification) for security and [Events](/webhooks/events) for the catalog.


# Signature Verification

Outline:

* Header carrying the signature (e.g. `X-ShredPay-Signature`).
* Algorithm: HMAC-SHA256 over `<timestamp>.<raw body>`.
* Per-endpoint signing secret (different from the API key).
* Pseudocode for verification.
* Replay protection: reject if `timestamp` is older than 5 minutes.
* Sample implementations in Node, Python, Go.


# Events

Outline of events emitted by Agent Wallet:

| Event                   | When                                                                      |
| ----------------------- | ------------------------------------------------------------------------- |
| `transaction.broadcast` | A signed tx has been submitted to the chain.                              |
| `transaction.confirmed` | The tx reached the configured confirmation depth.                         |
| `transaction.failed`    | The tx reverted or was dropped.                                           |
| `funds.deposited`       | An inbound transfer was credited to the sub-wallet.                       |
| `screening.alert`       | An inbound transfer triggered a screening hit; the sub-wallet was frozen. |

Each event will be documented with a sample payload and field reference. For now, follow the patterns in [Webhooks Overview](/webhooks/overview) and verify signatures per [Signature Verification](/webhooks/signature-verification).


# Overview

ShredPay does not yet ship official language SDKs. The REST API is small enough that a generated client from the OpenAPI spec works well in the meantime — see [API Reference](/agent-wallet/api-reference) for the live spec URL.

## Planned

* **TypeScript / Node** — first official SDK, targeting backend agents and Next.js apps.
* **Python** — for ML / data engineering use cases.
* **Go** — for high-throughput backends.

## Community

If you build a client and want it listed here, open a PR against this page.


# Error Codes

Every error response carries a stable `code` field. Use it for programmatic handling — the human `message` may change.

```json
{
  "error": {
    "code": "LIMIT_EXCEEDED",
    "message": "Daily USD limit reached",
    "request_id": "req_01HRZK..."
  }
}
```

Outline of codes (full reference to come):

| HTTP | Code                   | Meaning                                          |
| ---- | ---------------------- | ------------------------------------------------ |
| 400  | `BAD_REQUEST`          | Malformed body or missing required field.        |
| 400  | `INVALID_CHAIN`        | Unknown `chain_id`.                              |
| 400  | `ROUTER_NOT_AVAILABLE` | Sponsored op called on a chain without Router.   |
| 401  | `UNAUTHENTICATED`      | Missing `X-Api-Key`.                             |
| 401  | `INVALID_KEY`          | Key not found or revoked.                        |
| 403  | `PERMISSION_DENIED`    | Key lacks `trade` permission.                    |
| 403  | `CHAIN_NOT_ALLOWED`    | `chain_id` not in key's `allowed_chains`.        |
| 403  | `LIMIT_EXCEEDED`       | Daily or monthly USD cap hit.                    |
| 403  | `ADDRESS_BLOCKED`      | Counterparty failed screening.                   |
| 403  | `SUB_WALLET_FROZEN`    | Wallet under manual review.                      |
| 404  | `NOT_FOUND`            | Unknown `tx_id`, `market_id`, etc.               |
| 429  | `RATE_LIMITED`         | Too many requests; back off.                     |
| 500  | `INTERNAL_ERROR`       | Server-side failure; safe to retry with backoff. |
| 502  | `UPSTREAM_ERROR`       | Chain RPC or Privy unreachable; retry.           |


# Rate Limits

Outline:

* Per-key request budgets (separate for read and write).
* Headers returned on every response (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`).
* Behavior on overflow (`429 RATE_LIMITED`).
* Recommended retry strategy: exponential backoff with jitter.
* Bursts vs. sustained throughput.

Specific limits will be published once the production rollout is complete.


# Glossary

| Term                 | Definition                                                                                                                 |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Agent Wallet**     | ShredPay's product giving AI agents a sandboxed on-chain wallet.                                                           |
| **Sub-wallet**       | A user-owned wallet dedicated to a single agent / use case. Distinct from the user's main ShredPay wallet.                 |
| **API key**          | The credential that grants access to one sub-wallet, with permissions and spend limits attached.                           |
| **Co-signer**        | ShredPay's P-256 key that participates in the 2/2 quorum signing scheme.                                                   |
| **Privy**            | The wallet infrastructure provider that holds the other half of the 2/2 quorum.                                            |
| **Router**           | ShredPay's on-chain contract that batches approve + swap + deposit and lets ShredPay sponsor gas.                          |
| **MCP**              | [Model Context Protocol](https://modelcontextprotocol.io/) — the open standard ShredPay uses to expose tools to AI agents. |
| **OpenClaw**         | An agent platform that ships ShredPay as a one-click installable Skill.                                                    |
| **Skill (OpenClaw)** | A bundled set of tools and metadata an agent can install. ShredPay's Skill is `shredpay-wallet`.                           |
| **Sponsored gas**    | Gas paid by ShredPay (in exchange for a small service fee). Available for swap, DeFi, and `gas_swap`.                      |
| **Allowed chains**   | The whitelist on an API key — only listed chain IDs may be used.                                                           |
| **Group ID**         | An optional grouping of sub-wallets under a user. Reserved for future multi-wallet workflows.                              |
| **Quorum**           | A signing scheme that requires multiple signatures. ShredPay uses 2/2 (Privy + ShredPay co-signer).                        |
| **Smallest unit**    | The integer representation of a token amount (e.g. 1 USDC = `1000000` because USDC has 6 decimals).                        |


