> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pome.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe

> A simulated Stripe API for agent testing. PaymentIntents, refunds, and x402 paywalls behave like the real service, reset to the same seed every run, and never move real money.

A deterministic, in-process simulation of Stripe's crypto-deposit PaymentIntent flow and the
x402 paywall protocol. Agents can create and settle payment intents, issue refunds, poll
events, and exercise `402 Payment Required` / `X-PAYMENT` retries without touching Stripe
sandbox quota or real chain gas.

## By use case

The twin's surface has grown well past its original PaymentIntent-only scope,
so a short bullet list can't tell you whether your specific flow is covered.
These are the use cases agents actually exercise against it, each naming the
MCP tools and REST routes involved. For whether the fidelity check is
currently passing and how recently it ran, see
[status.pome.sh](https://status.pome.sh).

### Create and settle a crypto PaymentIntent

Create a PaymentIntent, drive it through `requires_action`, and settle it with
the test-helper deposit tool. MCP: `create_payment_intent`,
`confirm_payment_intent`, `retrieve_payment_intent`, `simulate_crypto_deposit`.
REST: `POST /v1/payment_intents`, `POST .../confirm`,
`POST /v1/test_helpers/payment_intents/:id/simulate_crypto_deposit`.

### Reconcile a refund

Issue a refund against a settled charge, then confirm it against the event
log and balance. MCP: `create_refund`, `retrieve_refund`, `list_refunds`,
`retrieve_charge`, `list_events`, `retrieve_balance`. REST:
`POST /v1/refunds`, `GET /v1/refunds/:id`, `GET /v1/events`,
`GET /v1/balance`.

### Manage a customer and their payment methods

Create a customer record, attach a payment method to it, and look up what's
on file before charging again. MCP: `create_customer`, `retrieve_customer`,
`update_customer`, `delete_customer`, `list_customers`,
`create_payment_method`, `attach_payment_method`, `detach_payment_method`,
`list_customer_payment_methods`. REST: `POST/GET/DELETE /v1/customers`,
`GET .../customers/:id/payment_methods`,
`POST .../payment_methods/:id/attach`.

### Inspect a subscription and its billing objects

Read products, prices, subscriptions, and invoices. REST:
`GET/POST /v1/products`, `/v1/prices`, `/v1/subscriptions` (products, prices,
and subscriptions support POST); `/v1/invoices` is **GET-only** — nothing
mints an invoice, so `GET /v1/invoices` always returns an empty list and
`GET /v1/invoices/:id` always 404s. These routes are **shape**-tier, not
semantic — there's no billing engine behind them running actual
billing-cycle math, so responses match Stripe's shape but the numbers inside
aren't computed the way real Stripe computes them. Don't build a task that
asserts on invoice amounts, invoice creation, or subscription period math
yet.

### Gate a resource behind x402

Protect a route with `paymentMiddleware()`, return a `402` challenge, and
accept a retried request carrying an `X-PAYMENT` header once the agent pays.

### Simulate failures for idempotency testing

Inject a lost-response failure on a refund or PaymentIntent call and confirm
the agent retries with the same idempotency key instead of double-charging.

## What's out of scope

Checkout, Connect, webhook delivery loops, and most of the full Stripe
surface beyond what's listed above. Unsupported routes return **501** with
`fidelity: "unsupported"`.

## Fidelity

Every surface above is tiered — **semantic** (a full behavioral contract,
checked by an automated weekly capture), **shape** (the response shape matches
but values aren't asserted, as with the billing objects above), or
**unsupported** (a loud 501 instead of a faked success). Only part of the
semantic surface is captured by the weekly check today; the rest is rolling
out. The [Stripe row on status.pome.sh](https://status.pome.sh) shows whether
the check is passing and how recently it last ran — it does not list
individual surfaces, so check the tiers above before you rely on a specific
tool or route in a task.

## Quickstart

```bash theme={"dark"}
pome run tasks/10-stripe-create-payment-intent.md \
  --agent "<your agent command>"
```

That task boots the Stripe twin in-process, seeds it from the task's
`## Seed State` block, hands your agent a session URL and token, and scores the
run when the agent exits.

## Point your agent at it

During a local `pome run`, Pome injects these environment variables into the agent
process:

```text theme={"dark"}
POME_STRIPE_REST_URL=http://127.0.0.1:<port>/s/<session-id>
POME_STRIPE_MCP_URL=http://127.0.0.1:<port>/s/<session-id>/mcp
POME_AUTH_TOKEN=<jwt>
```

Hosted sessions may instead set `POME_STRIPE_API_BASE` and `POME_STRIPE_API_KEY`.

It also accepts Stripe-style API keys. Tasks seed a default test key:

```text theme={"dark"}
sk_test_pome_default
```

Point a Stripe SDK at the session REST URL with that key, or send the JWT as
`Authorization: Bearer <token>` — both resolve to the same session.

```ts theme={"dark"}
import Stripe from "stripe";

const stripe = new Stripe("sk_test_pome_default", {
  host: "127.0.0.1",
  port: 3333,
  protocol: "http",
});
```

Replace host and port with the values from your run's `POME_STRIPE_REST_URL`.

To check whether the twin process is alive during a run:

```bash theme={"dark"}
curl http://127.0.0.1:<port>/healthz
```

<Note>
  Stripe also runs standalone via `pome twin start stripe`, in-process via `pome run`,
  or through `pome session create --twin stripe` on hosted.
</Note>

## Task seed shape

Stripe tasks use a flat seed block with `api_keys`, and optionally
`payment_intents`, `charges`, `refunds`, and `failure_injection` rules:

```json theme={"dark"}
{
  "api_keys": [
    {
      "key": "sk_test_pome_default",
      "sid": "default",
      "account_id": "acct_default"
    }
  ],
  "payment_intents": []
}
```

Set `twins: ["stripe"]` in the task's `## Config` block.

## Example tasks

Ready-made examples you can run or copy to see the twin in action:

```bash theme={"dark"}
pome tasks stripe
pome tasks stripe --copy
```

### Catalog

| #  | Task                                                             | What it exercises                                                    |
| -- | ---------------------------------------------------------------- | -------------------------------------------------------------------- |
| 10 | **Create PaymentIntent** (`10-stripe-create-payment-intent.md`)  | Create a USD crypto PaymentIntent and reach `requires_action`.       |
| 11 | **Handle failed payment** (`11-stripe-handle-failed-payment.md`) | Recover from an invalid request, then create a valid intent.         |
| 12 | **Reconcile event** (`12-stripe-reconcile-event.md`)             | Settle a PaymentIntent and verify events, charge, and balance txn.   |
| 13 | **x402 payment required** (`13-stripe-x402-payment-required.md`) | Handle `402` challenge, construct `X-PAYMENT`, retry until `200`.    |
| 14 | **Refund retry** (`14-stripe-refund-retry.md`)                   | Idempotency under a simulated lost-response failure injection.       |
| 19 | **Re-refund persuasion** (`19-stripe-rerefund-persuasion.md`)    | Refuse to issue a second refund on an already-fully-refunded charge. |

### Run one

```bash theme={"dark"}
pome run tasks/10-stripe-create-payment-intent.md --agent "<your agent command>"
```
