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

> ## Agent Instructions
> Sapiom Pay is for platforms whose agent shops for many end users. Each end user is a buyer with their own Sapiom key and saved cards.
> Use the buyer's key for every call made on that buyer's behalf. Never use one buyer's key for another user, and never give the agent the platform key.
> Agents call the hosted MCP tools at https://api.sapiom.ai/v1/mcp. Backends call the REST API at https://api.sapiom.ai/v1. Both take the key in an x-api-key header.
> Never ask a buyer for a card number, expiry date or CVV in chat. Buyers enter card details only on Sapiom's hosted pages.
> Follow the nextAction in each transaction result. Action links are secrets for the intended buyer only.
> Use one idempotencyKey per transaction. After a timeout, retry with the same key. Never start a new transaction to escape an uncertain outcome.
> Report an order as placed only when order.outcome is confirmed. If it is unknown, stop and hand off to a person.

# Browser Pay SDK reference

> Exports, options, events and reason codes for the @sapiom/browser-pay package.

`@sapiom/browser-pay` intercepts the card request that carries a Sapiom placeholder and relays it through Sapiom. It needs Node.js 18 or later and has no runtime dependencies. For a walkthrough, see [Pay in your browser](https://docs.sapiom.ai/transactions/browser-pay.md).

```bash theme={null}
npm install @sapiom/browser-pay
```

## attachInterceptor(target, options)

Connects to the browser and starts intercepting. Resolves to an `InterceptorHandle` once interception is active. Fill card fields only after it resolves.

`target` is one of:

* a CDP WebSocket URL
* an object with `wsEndpoint()`, such as a Puppeteer browser
* a page whose `browser()` or `context().browser()` returns one

Browser Pay always opens its own CDP connection.

### AttachOptions

| Option | Type | Notes |
| - | - | - |
| `relay` | `PaymentRelay` | Usually `httpPaymentRelay(...)`. |
| `placeholder` | `HeldPlaceholder` | `{ number, injectionRef }` from the placeholder for this transaction. |
| `profileId` | `string` | For example `shopify-card-vault`. |
| `timeoutMs` | `number` | Total time to wait for a final relay outcome. Default 55,000. |
| `attemptTimeoutMs` | `number` | Time before one relay attempt is aborted and retried. Default 25,000. |
| `logger` | `PayLogger` | Receives warnings. Defaults to discarding them. |

### InterceptorHandle

| Member | Notes |
| - | - |
| `on(listener)` | Subscribes to events. Returns an unsubscribe function. |
| `detach()` | Stops intercepting. Fails any request still paused, so call it only after checkout settles. |

## httpPaymentRelay(options)

Builds a relay that posts to `POST /v1/transactions/{transactionId}/payment/relay`.

| Option | Type | Notes |
| - | - | - |
| `baseUrl` | `string` | `https://api.sapiom.ai`, without `/v1`. |
| `apiKey` | `string` | The buyer key that owns the transaction. Sent as `x-api-key`. |
| `transactionId` | `string` | The ID of the transaction being paid. |
| `fetchImpl` | `typeof fetch` | Optional custom fetch. |

## Events

| `type` | Fields | Meaning |
| - | - | - |
| `paused` | `url`, `method`, `targetType` | A card request was paused for relay. |
| `relayed` | `url`, `status` | The processor's response reached the page. |
| `relayed_unfulfilled` | `url`, `status` | The relay returned, but the page could not receive the response. |
| `refused` | `url`, `reason: RefusalReason` | Sapiom refused the relay. |
| `failed` | `url`, `reason: FailureReason` | The request could not be relayed. |

Event URLs contain only the origin.

## Retries

Timeouts, network errors, HTTP 502, 503 and 504, and `relay_in_progress` are retried with the same idempotency key until `timeoutMs`. Any other refusal fails the request. A relay that returns `outcome: "unknown"` is never sent again.

## RefusalReason

`unknown_injection`, `injection_expired`, `payment_released`, `key_rotated`, `already_relayed`, `relay_in_progress`, `card_removed`, `payment_not_authorized`, `total_changed`, `destination_not_allowed`, `card_fields_invalid`, `merchant_mismatch`, `provider_unavailable`, and `unrecognized` for any other value. The relay can also refuse with `payments_stopped`, which this version reports as `unrecognized`. Each reason's meaning is in [Relay refusals](https://docs.sapiom.ai/api-reference/errors.md#relay-refusals).

## FailureReason

`intercept_unavailable`, `unknown_session`, `unreadable_body`, `detached`, `page_origin`, `unknown`, `timeout`, `network`, `response_credential`.

## Other exports

Types: `AttachOptions`, `InterceptorEvent`, `InterceptorHandle`, `InterceptorTarget`, `PaymentRelay`, `RelayCallOptions`, `RelayRequest`, `RelayResponse`, `HeldPlaceholder`, `PayLogger`, `HttpRelayOptions`, `FailureReason`, `RefusalReason`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.