API Reference
Complete REST API reference for Plaidly, generated from the OpenAPI 3.1 specification
API Reference
The Plaidly API is documented via an OpenAPI 3.1 specification (openapi: "3.1.0", info.version: "1.0").
Spec download:
GET https://api.plaidly.io/openapi.jsoncurrently requires the same auth as merchant endpoints (verified live 2026-07-11 — an unauthenticated request returns401with{"code":7,"message":"missing or invalid authorization header"}). Register a sandbox merchant first (see Register a merchant) and pass itsapi_key, or use the copy checked intoplaidly-api/api/openapi.yaml.
curl https://api.plaidly.io/openapi.json \
-H "X-API-Key: your_api_key" \
-o plaidly-openapi.jsonYou can import the resulting file directly into Postman, Insomnia, or any OpenAPI-compatible tool. Or browse the source directly: api/openapi.yaml.
Base URL
https://api.plaidly.ioAll endpoints are versioned under /v1. See Versioning & deprecation policy for what that guarantees.
Authentication
Public read endpoints need no auth. Merchant-scoped endpoints use X-API-Key.
Endpoints
Payment sessions
| Method | Path | Description |
|---|---|---|
POST | /v1/payment_sessions | Create a merchant payment session |
POST | /v1/payment_sessions/demo | Create a public demo session |
GET | /v1/payment_sessions/{session_id} | Retrieve a payment session |
POST | /v1/payment_sessions/{session_id}/simulate | Mark a sandbox/demo session complete without a real transaction |
POST | /v1/payment_sessions/{session_id}/webhook/retry | Manually redeliver the webhook for a session |
GET | /v1/payment_sessions/{session_id}/receipt | Download the PDF receipt |
Merchants
| Method | Path | Description |
|---|---|---|
POST | /v1/merchants | Register a new merchant (public for sandbox) |
GET | /v1/me | Get the current merchant profile |
POST | /v1/me/credentials/rotate | Rotate the API key or webhook secret |
POST | /v1/me/credentials/revoke | Revoke the previous credential from the latest rotation |
Discovery
| Method | Path | Description |
|---|---|---|
GET | /v1/payment_methods | List globally enabled payment rails (chain/network/token) |
GET | /v1/rates | Fetch spot rates for supported assets |
GET | /v1/sandbox/faucets | List testnet faucet URLs |
Operations
| Method | Path | Description |
|---|---|---|
POST | /v1/payouts | Request a payout |
GET | /v1/payouts/{payout_id} | Retrieve a payout |
POST | /v1/wallets | Create a wallet |
GET | /v1/wallets | List wallets |
GET | /v1/wallets/{wallet_id} | Retrieve a wallet |
GET | /v1/wallets/{wallet_id}/transactions | List wallet transactions |
POST | /v1/agent-wallets/{agent_wallet_id}/spend-attempts | Evaluate/record an agent wallet outbound spend attempt |
Catalog
| Method | Path | Description |
|---|---|---|
POST | /v1/stores | Create a store |
GET | /v1/stores | List the authenticated merchant's stores |
GET | /v1/stores/{store_id} | Get a store |
PATCH | /v1/stores/{store_id} | Update a store in place |
DELETE | /v1/stores/{store_id} | Hard-delete a draft, never-published store |
POST | /v1/stores/{store_id}/publish | Publish a store |
POST | /v1/stores/{store_id}/archive | Archive a store |
POST | /v1/products | Create a product |
GET | /v1/products | List the authenticated merchant's products |
GET | /v1/products/{product_id} | Get a product |
PATCH | /v1/products/{product_id} | Update in place (draft) or create a new version (published) |
DELETE | /v1/products/{product_id} | Hard-delete a draft, never-published product |
POST | /v1/products/{product_id}/publish | Publish a product |
POST | /v1/products/{product_id}/archive | Archive a product |
POST | /v1/plans | Create a plan |
GET | /v1/plans | List the authenticated merchant's plans |
GET | /v1/plans/{plan_id} | Get a plan |
PATCH | /v1/plans/{plan_id} | Update in place (draft) or create a new version (published) |
DELETE | /v1/plans/{plan_id} | Hard-delete a draft, never-published plan |
POST | /v1/plans/{plan_id}/publish | Publish a plan |
POST | /v1/plans/{plan_id}/archive | Archive a plan |
POST | /v1/prices | Create a price |
GET | /v1/prices | List the authenticated merchant's prices |
GET | /v1/prices/{price_id} | Get a price |
PATCH | /v1/prices/{price_id} | Update in place (draft) or create a new version (published) |
DELETE | /v1/prices/{price_id} | Hard-delete a draft, never-published price |
POST | /v1/prices/{price_id}/publish | Publish a price |
POST | /v1/prices/{price_id}/archive | Archive a price |
GET | /v1/catalog/products | Public buyer-agent discovery listing of published products (no auth) |
GET | /v1/catalog/products/{product_id} | Public buyer-agent discovery detail for one published product (no auth) |
POST | /v1/catalog/prices/{price_id}/checkout-intent | Resolve a published price into checkout fields (no auth) |
There is no distinct entitlement resource or endpoint — entitlement is a freeform metadata object field on plan. Full walkthrough: Create a store, product, and price and Create or select a checkout.
Request format
All request bodies use application/json:
curl -X POST https://api.plaidly.io/v1/payment_sessions \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"amount": 10.0,
"expires_in": "15m",
"paymentMethod": {
"methodID": 0,
"chain": "solana",
"token": "USDC",
"network": "mainnet"
},
"metadata": { "order_id": "ord_123" }
}'Response format
Most responses are application/json. Successful responses include the resource object directly (no {"session": {...}} wrapper):
{
"session_id": "sess_test_01HX...",
"merchant_id": "mer_01HX...",
"expected_amount": 10,
"received_amount": 0,
"address": "7EcDhSYGxXyscszYEp35KHN8vvw3svAuLKTzXwCFLtV",
"status": "pending",
"demo": false,
"paymentMethod": {
"methodID": 0,
"chain": "solana",
"token": "USDC",
"network": "mainnet"
}
}Error format
{
"code": 5,
"message": "idempotency key was already used with a different payload"
}code is a small integer enum today (not a string slug like "session_not_found") — see the full code table and the richer envelope the platform is converging on in Error model.
Status codes
| Code | Meaning |
|---|---|
200 | Success |
201 | Created |
400 | Bad request — check your request body (code: 3) |
401 / 403 | Auth failure — invalid, missing, or insufficient credentials (code: 7) |
404 | Not found (code: 2) |
409 | Conflict — duplicate idempotency key with a different payload (code: 5) |
429 | Rate limited (code: 4) |
500 | Internal server error (code: 1) |
Rate limits
Each merchant gets a default limit of 60 requests per minute, set on the Merchant object as rate_limit_per_minute (visible via GET /v1/me) — it is per-merchant, not a single global constant, and can differ from the default. Exceeding it returns 429.
There are currently no X-RateLimit-* response headers — you cannot introspect remaining quota from response headers today; track your own request rate against the rate_limit_per_minute value from GET /v1/me instead.
Idempotency
POST requests to a subset of endpoints support idempotency via the Idempotency-Key header. See Idempotency for exactly which endpoints support it today.