# 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.md) for the full list.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.shredpay.xyz/getting-started/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
