---
name: payments-ai
version: 1.0.0
description: Create merchants, products, and branded checkout links on Payments AI through its authenticated MCP server.
homepage: 'https://doc.mor.payments.ai'
---

# Payments AI

Payments AI is the Merchant of Record for AI-built apps. Agents provision a merchant, create products and plans, and hand back a hosted checkout URL. Payments AI collects payment, tax, and subscription renewal.

If you are an AI agent or coding assistant reading this file, save it as a local skill or persistent reference. Then connect the MCP server before calling tools.

## Discovery

| Resource              | URL                                                       |
| --------------------- | --------------------------------------------------------- |
| This skill            | https://doc.mor.payments.ai/SKILL.md                                |
| Agent auth            | https://doc.mor.payments.ai/auth.md                                 |
| Concise agent index   | https://doc.mor.payments.ai/llms.txt                                |
| Full agent index      | https://doc.mor.payments.ai/llms-full.txt                           |
| MCP setup (humans)    | https://doc.mor.payments.ai/mcp                                     |
| Agent Skills index    | https://doc.mor.payments.ai/.well-known/agent-skills/index.json     |
| MCP Server Card       | https://mor.payments.ai/.well-known/mcp/server-card.json |
| MCP endpoint          | https://mor.payments.ai/api/mcp                                          |
| OpenAPI (public)      | https://doc.mor.payments.ai/openapi-public.json                     |
| Skills + plugins repo | https://github.com/paymentsai/Payments-AI-skills          |

Install a local copy:

```bash
mkdir -p "$HOME/.payments-ai" && curl --fail --show-error --location \
  --output "$HOME/.payments-ai/SKILL.md" \
  "https://doc.mor.payments.ai/SKILL.md"
```

Host plugins (Claude Code, Cursor, Codex, Gemini, Grok, Antigravity, Copilot) still install from GitHub:

```bash
npx skills add paymentsai/Payments-AI-skills
```

## Connect MCP

OAuth is the default. Do not ask the developer to paste a token unless OAuth is unavailable.

```json
{
  "mcpServers": {
    "payments-ai": {
      "url": "https://mor.payments.ai/api/mcp"
    }
  }
}
```

First tool call opens a browser for sign-in and consent. Scopes are listed in [auth.md](https://doc.mor.payments.ai/auth.md).

Bearer fallback (User MCP Key from https://mor.payments.ai/settings/developer-tools). A token works only with the MCP URL of the dashboard tab it was generated on: Sandbox tokens with `https://sandbox.mor.payments.ai/api/mcp`, Live tokens with `https://mor.payments.ai/api/mcp`. A 401 carries a `code` and `docUrl`; the codes and their recovery are listed in [auth.md](https://doc.mor.payments.ai/auth.md).

```json
{
  "mcpServers": {
    "payments-ai": {
      "url": "https://mor.payments.ai/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}
```

## Before you mutate anything

1. Call `get_my_merchant`. If it fails, paste the MCP config above and stop.
2. Prefer sandbox. Product and checkout mutations target sandbox until `go_live`. `go_live` does not copy them: the live side starts with an empty catalog, so re-create products/plans and re-apply checkout branding with `update_checkout_customization` after promoting. `set_checkout_logo` writes to sandbox only; set the live logo in https://mor.payments.ai/checkout-builder with Live selected.
3. Never expose API keys, MCP tokens, or OAuth codes in chat logs you cannot redact.
4. Do not call payout, refund, revoke, or delete tools — they are not on this server.
5. Sandbox needs no KYC/KYB. Live can process up to $5,000 in card transactions before identity verification is required, but payouts always require completed KYC/KYB regardless of that threshold.

## Workflow A — first sandbox checkout

Complete each step. Wait for missing human input.

### A1. Merchant

Call `get_my_merchant` first. If it returns a merchant, reuse that `merchantId` — creating a
second one splits products and checkout links across two accounts that never merge. An empty
list means there is none yet.

Ask for business **name**, **email**, and **phone** in E.164 (`+14155552671`). Call `create_merchant_account`. Show `merchantId`.

### A2. Product

Ask what they sell in plain English. Call `create_product` with:

- `name` (max 80 chars)
- `merchantId`
- `plans[]` with `name`, `currency` (`usd` unless stated), `amount` as a decimal dollar (`29.00`, not cents), `type` (`recurring` \| `one-time` \| `free-access`), `billingPeriod`, `periodLength` (default `1`), optional `freeTrial` days (recurring plans only)

Show `id` (product) and every `planIds[n]`. Read each `plans[n].price` back to the user and check it matches what they asked for. If `warnings` is present, relay it; if they meant the smaller price, fix it with `update_plan` before sharing the link.

### A3. Checkout URL

Sandbox testing:

`https://mor.payments.ai/payment/{planId}?isSandbox=true`

Live (only after `go_live` **and** re-running `create_product` there — `go_live` does not create the plan on live, so this URL 404s until you do):

`https://mor.payments.ai/payment/{planId}`

`list_products` also returns `checkoutUrl` per plan. A sandbox checkout link never becomes this URL on its own; it keeps `?isSandbox=true` forever.

## Workflow B — checkout branding

Requires `checkout:read` / `checkout:write` and a `merchantId`.

1. `get_checkout_customization`
2. `update_checkout_customization` — merge-only; omit fields you are not changing
3. `set_checkout_logo` — `mint` then HTTP PUT bytes to `uploadUrl`, then `confirm` with the returned `path`

Colors are 6-digit hex. `fontFamily` is `Inter` or `Roboto`. `themeMode` is `light` or `dark`. `inputStyle` is `rounded` or `square`.

## Tools

| Tool                             | Use                                              |
| -------------------------------- | ------------------------------------------------ |
| `search_payments_ai_docs`        | Search developer docs                            |
| `get_my_merchant`                | Merchants this connection owns                   |
| `create_merchant_account`        | Dual-provision live + sandbox merchant           |
| `get_merchant_activation_status` | Activation status (see below)                    |
| `go_live`                        | Promote to live; a repeat returns current status |
| `create_product`                 | Product + plans (sandbox until go-live)          |
| `create_order`                   | Multi-item or caller-priced checkout             |
| `list_products`                  | List products, plans, checkout URLs              |
| `get_product_image_upload_url`   | Presigned POST for product image                 |
| `confirm_product_image`          | Attach uploaded product image                    |
| `get_checkout_customization`     | Read hosted checkout branding                    |
| `update_checkout_customization`  | Merge-update branding                            |
| `set_checkout_logo`              | Mint → PUT → confirm checkout logo               |

### Activation status

`get_merchant_activation_status` (and every `go_live` response, as `activationStatus`) returns one of:

- `pending` — not promoted to live yet. The only status where `go_live` is the next step.
- `verification_pending` — promoted to live; identity verification (KYC) is not complete. Do not call `go_live` again.
- `active` — live and identity verified.
- `not_provisioned` — no live merchant record; re-run `create_merchant_account` with the same `merchantId`.

`identityVerification` carries the KYC state (`not_started`, `pending`, `in_review`, `verified`, `rejected`). Before verification completes, a live merchant can process up to $5,000 in card transactions; payouts (adding a payout method and withdrawing funds) require completed identity verification.

After `go_live` the live catalog starts empty: create the products and plans again with `create_product` and share the new live checkout URLs. `go_live` is idempotent — a repeat call changes nothing and returns `alreadyLive: true` with the current status.

## REST (no MCP)

Sandbox API: `https://sandbox.mor.payments.ai/api`

Merchant Public API: `/v1/public-api/merchants/{merchantId}/…` with Bearer `pai_test_*` (sandbox) or `pai_live_*` (live). Partners create sub-merchants with `POST /v1/public-api/merchants` using their own Merchant API Key; the parent is derived from the key. After create, `POST /v1/public-api/merchants/{merchantId}/members` assigns an active member of the key's own team onto a managed sub-merchant (`ownerAttached: false` at create is incomplete until the seller claims the returned `joinUrl`, an assign, or Support). Read `ownerAttached` and `activation` back with `GET /v1/public-api/merchants/{merchantId}`, or subscribe to the `merchant.owner_attached` webhook; never remint the join link to check for a claim, because remint invalidates the delivered link. Sub-merchant API keys: `GET`/`POST`/`DELETE` `/v1/public-api/merchants/{merchantId}/api-keys`. Guide: https://doc.mor.payments.ai/partner-onboarding. Single-merchant flows can also create via dashboard or MCP (`create_merchant_account`).

Buyer checkout (no key): `/v1/checkout/plans/{planId}/…`

Full HTTP reference: https://doc.mor.payments.ai/llms-full.txt
