# AI Context File

Copy the markdown below into a `CLAUDE.md`, `.cursorrules`, or similar AI context file in your project. This gives your AI coding assistant the knowledge it needs to work with the Tesser API without re-reading the full documentation each session.

## Usage

1. Copy the content below
2. Save it as `CLAUDE.md` (for Claude Code), `.cursorrules` (for Cursor), or any context file your tool supports
3. Place it in your project root

## Context File

````markdown
# Tesser Payments API

## Overview

Tesser is a payments platform for stablecoin and fiat transfers. The API handles payment creation, wallet management, counterparty onboarding, compliance screening, and treasury operations.

## API Access

- **Base URL**: `https://sandbox.tesserx.co/v1`
- **Auth**: OAuth 2.0 client credentials → Bearer token
- **Docs**: https://docs.tesser.xyz
- **LLM docs**: https://docs.tesser.xyz/llms-full.txt
- **OpenAPI Schema**: https://docs.tesser.xyz/api/v1/schema.json

### Authentication

```bash
curl --request POST \
  --url https://dev-awqy75wdabpsnsvu.us.auth0.com/oauth/token \
  --header 'content-type: application/json' \
  --data '{
    "client_id": "'$TESSER_API_KEY'",
    "client_secret": "'$TESSER_API_SECRET'",
    "audience": "https://sandbox.tesserx.co",
    "grant_type": "client_credentials"
  }'
```

### Environment Variables

```
TESSER_API_KEY=your-api-key
TESSER_API_SECRET=your-api-secret
```

## MCP Server

All API operations are available as MCP tools at `https://sandbox.tesserx.co/v1/mcp`.

## Key Endpoints

| Method | Path | Description |
| --- | --- | --- |
| POST | `/v1/payments` | Create a payment (payout, deposit) |
| GET | `/v1/payments/{id}` | Get payment by ID |
| PATCH | `/v1/payments/{id}` | Update payment with account info |
| POST | `/v1/payments/{id}/review` | Submit risk review decision |
| GET | `/v1/accounts` | List accounts (wallets, ledgers, bank accounts) |
| POST | `/v1/accounts/wallets` | Create a wallet account |
| POST | `/v1/accounts/ledgers` | Create a ledger account |
| POST | `/v1/accounts/banks` | Create a bank account |
| GET | `/v1/entities/counterparties` | List counterparties |
| POST | `/v1/entities/counterparties` | Create a counterparty |
| GET | `/v1/currencies` | List supported currencies |
| GET | `/v1/networks` | List supported blockchain networks |

## API Conventions

- All request/response fields use **snake_case**
- Amounts are strings (e.g. `"1000.50"`)
- IDs are UUIDs
- Timestamps are ISO 8601 (e.g. `"2025-12-01T09:00:00.000Z"`)
- Webhook events follow the pattern `resource.action` (e.g. `payment.balance_updated`, `step.confirmed`)

## Domain Glossary

Language that is easy to confuse. This is a glossary, not a spec.

### Funds Movement

- **Payment** — A funds-movement resource with a `direction` (`inbound`, `outbound`, `rebalance`) and a `payment_type` (`deposit`, `withdrawal`, `transfer`). Carries `desired` / `estimated` / `actual` overlays and one or more steps.
- **Inbound Payment** — A payment with `direction = "inbound"` recording funds sent on-chain from an external wallet to one of your **Managed Wallets**. Detected by monitoring the chain, not initiated through the API. Distinct from a **Deposit**.
- **Deposit** — A customer-initiated inbound funds movement (`POST /v1/treasury/deposits`) that routes fiat or stablecoin through a provider to a destination account. Not the same as an **Inbound Payment**.
- **Step** — One leg of a payment's execution (`transfer`, `swap`). Has a lifecycle status and `estimated` / `actual` overlays.

### Inbound Lifecycle

- **Confirmed** — Step state when the on-chain transaction is included in a block. Fires `payment.created`. Funds are visible but **not yet final** — the block can still be reorganized.
- **Completed** — Step state when the block has finalized. Fires `step.completed` + `payment.updated`. Funds are safe to spend.

Avoid using "confirmed" and "completed" interchangeably — for inbound they are two distinct moments.

### Outbound Lifecycle (wallet source)

- **Signature Requested** — The unsigned transaction is prepared and Tesser is waiting for the customer to sign. Fires `step.signature_requested`.
- **Signed** — The signature was accepted and the source balance is reserved. The step already carries `transaction_hash`: it is derived from the signed payload, so it is known before broadcast. A hash at this stage is a correlation key, not evidence that the transaction reached the network. A nonce-queued step stays here until its turn to broadcast. Fires `step.signed` followed by `payment.balance_updated` (`reserved`).
- **Submitted** — Event-only marker that broadcast is beginning.
- **Confirmed (outbound)** — The broadcast was accepted by the network (mempool). Carries the transaction hash. **Not final.** Unlike inbound, this means broadcast acceptance, not block inclusion.
- **Completed (outbound)** — The transfer reached finality. `step.completed` fires, followed by the terminal `payment.updated`. That ordering is contractual: detect terminal state from the pair.

### Balances

- **Total Balance** — All funds credited to an account asset, including inbound funds that have arrived but not yet finalized. For an inbound payment, credited at **Confirmed**.
- **Available Balance** — Funds free to spend (total minus reserved). For an inbound payment, credited once the step is **Completed** (block finality). Inbound risk screening does not gate it. Invariant: available ≤ total.

### Risk & Screening

- **Risk Screening** — Evaluation of a payment's external counterparty wallet against the workspace's risk policy. For an inbound payment the screened party is the **sender** (the Unmanaged Account); for an outbound payment it is the recipient. The outcome is a `risk_status` and drives the `payment.risk_updated` webhook. **Advisory for inbound** (does not gate Available Balance — funds are already custodied), **gating for outbound** (fail-closed).
- **Risk Decision** — A manual approval/rejection submitted when screening returns `awaiting_decision`. Recorded as `manually_approved` / `manually_rejected` with reviewer and timestamp.

### Accounts & Counterparties

- **Managed Wallet** (a.k.a. Managed Account, `is_managed: true`) — A wallet Tesser custodies and can sign for. Inbound funds are credited to one.
- **Unmanaged Account** (`is_managed: false`) — An external wallet Tesser does not control. Auto-created to represent the **sender** of an inbound payment, keyed by its on-chain address.
- **Placeholder Counterparty** — The single shared counterparty that all inbound senders are attached to, because the owner of a sending wallet cannot be identified. One per tenant.

### Relationships

- An inbound payment has exactly one step (type `transfer`), born **Confirmed**, transitioning to **Completed** at finality.
- An inbound payment's sender is an **Unmanaged Account** attached to the **Placeholder Counterparty**; its recipient is a **Managed Wallet**.
- **Confirmed** credits **Total Balance**; **Completed** (finality) credits **Available Balance**. Inbound risk screening is advisory and does not gate this credit.
````
