Payment links API and API keys
Create an invoice from your backend and receive checkoutUrl immediately. The API supports scoped keys, idempotent retries, independent fee and VAT shares, an order reference and private metadata.
On this page
A server request returns a ready link#
POST /api/v1/payments and /api/v1/payment-links create the same invoice type. The payments route name does not imply a charge: the result is persisted invoice terms and a checkoutUrl for the customer.
Send Authorization: Bearer <key>, Content-Type: application/json and Idempotency-Key. Idempotency keys contain 16–100 letters, digits, hyphens or underscores. Persist one key for each logical order creation.
curl 'https://kevmi.maxeevmax1.chatgpt.site/api/v1/payments' \
-H "Authorization: Bearer $KEVMI_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-1042-create-v1' \
--data '{"title":"Design project · order 1042","description":"One-time payment for the agreed design work","amountMinor":500,"currency":"USD","methods":["card","alipay"],"vatCustomerPercent":100,"feeCustomerPercent":0,"orderId":"order-1042","metadata":{"campaign":"autumn"}}'API key scopes and expiry#
Create a key at /account#keys in your verified merchant account. Its full value appears once; only a hash is stored. Keys last 90 days by default, with a permitted lifetime of 1–365 days and up to ten active keys per account.
Grant only the required scopes. Revocation or expiry stops access. A key does not replace the browser session for account settings, endpoint administration, applications or moderation. Keep it out of widgets, URLs, public repositories and support messages.
The website uses /api/payment-links with its session cookie, exact Origin and X-CSRF-Token. Those routes operate on the same owned invoices.
| Scope | Purpose |
|---|---|
| invoices:read | Read owned invoices and their list |
| invoices:write | Create invoices and change link availability |
| events:read | Read the server event log |
Any and concrete API methods#
Any is an interface selection mode. New invoices accept methods: ["card", "alipay"] or a nonempty subset for USD; ["sbp"] for RUB; ["crypto"] for USDT. The value any is not an API payment method.
For a new invoice in the interface, USD offers cards and Alipay; RUB offers SBP; USDT offers crypto. The API can also save USD + crypto for compatibility, but its live crypto payment is blocked with crypto_requires_usdt. USD and USDT are distinct, with no automatic conversion or assumed 1:1 rate. A crypto payment requires a separate USDT invoice.
For a new live card or Alipay payment, the current gateway supports only feeCustomerPercent=0 and vatCustomerPercent=100: the merchant covers the entire processing fee and VAT is added in full for the customer. Other shares can be saved and calculated on an invoice, but execution is blocked with unsupported_allocation. The server never silently changes saved terms. SBP and USDT crypto payments support every processing-fee share and have no VAT.
Fields and persisted terms#
The invoice saves the merchant name, price, currency, methods, both cost shares and calculated quotes. Metadata is returned to the owner and in server events, but not through public checkout. Do not store payment secrets in it.
If shares are omitted, the merchant covers the fee; VAT inherits vatPayer or the account setting. A partial allocation can return vatPayer=shared. The title, orderId and description are public.
| Field | Rule |
|---|---|
| title / description | 1–120 / 0–500 characters |
| amountMinor | Integer 1–10,000,000,000; 500 means $5.00 in USD |
| currency / methods | USD: card, alipay; RUB: sbp; USDT: crypto. Nonempty unique list. |
| vatCustomerPercent / feeCustomerPercent | Independent integer customer shares from 0 to 100 |
| vatPayer | Legacy customer or merchant; cannot conflict with the VAT share |
| orderId | Optional, up to 100 characters; visible to the customer |
| metadata | Up to ten string entries; key 1–40 letters/digits/_/-; value up to 500 characters; total up to 3000 UTF-8 bytes |
| expiresAt | Future Unix ms within 90 days; seven days by default |
Retry after a network error#
Initial creation returns 201 with replayed=false. The same key and canonical body return 200, the original checkoutUrl and replayed=true. A different request under that key returns 409 IDEMPOTENCY_CONFLICT.
Do not generate another key after a timeout. Repeat the original request with identical fields. Omitted values do not inherit changed settings again. orderId helps correlate an order but does not replace Idempotency-Key and is not required to be unique in storage.
Reading and pagination#
GET /api/v1/payments returns links and nextCursor; GET /api/v1/payments/{id} returns one owned link. invoices:read is required. The default page size is 30; limit accepts 1–100.
GET list and detail responses include link.payment: a summary of the related operation, or null when no operation exists. POST/PATCH responses may omit it; read the invoice again when you need the summary. Link status separately describes whether a new payment may start. Card fields and private keys are never included.
Pass nextCursor unchanged through URLSearchParams. null marks the end; unknown and other merchants’ IDs both return 404.
GET /api/v1/payments?limit=30
Authorization: Bearer <server-side key>Pause, resume and cancel#
PATCH /api/v1/payments/{id} with invoices:write accepts only {"status":"active"}, {"status":"paused"} or {"status":"cancelled"}. Cancellation is final. expired is derived from the expiry time; an expired invoice cannot be extended.
Price, cost shares, description, orderId, metadata and expiry are immutable. Create another invoice for different terms. Changing availability emits invoice.updated, not a successful-payment event.
The customer response#
GET /api/checkout/{token}?method=card returns the public invoice, quote, method availability and existing operation. Owner metadata, secrets and balances are not exposed.
POST /api/checkout/{token}/pay requires the Site Origin and a concrete method. Card data is accepted only as sealed: {intent,jwe}, after the browser obtains /card-intent. Bank codes are encrypted and sent through /code. Crypto uses a saved USDT invoice and an available coin/network pair.
A new payment and card intent require the merchant’s latest website-review application to be approved. Approval alone does not connect the payment gateway. If the review changes after dispatch, the existing operation remains available for status reads, reconciliation and a requested bank code.
A missing live connection returns GATEWAY_NOT_CONNECTED; an incompatible allocation is never replaced with another calculation. Status and reconcile read the original operation without a duplicate charge.
Multiple stores and one USD base price#
Choose All stores for aggregate analytics and operations, or select a store for its own records. Each store has a separate storeId, name, VAT default, invoices, API keys, webhook endpoints, event history and website application. Notifications and support tickets belong to the account. An account can create up to 100 stores. Existing records remain in its first store.
New workspace invoices use pricingMode="universal" and a USD base price. Any includes card, alipay, sbp and crypto; a merchant may select a subset. Cards and Alipay charge USD. SBP charges RUB using the Bank of Russia USD/RUB reference rate. Crypto charges USDT under the explicit invoice rule 1 USD = 1 USDT. This is an invoice conversion rule, not a market USDT quote. The gateway supplies the selected coin’s rate, exact transfer amount and instructions before transfer.
The reference rate and both amounts are frozen on creation. Invoices involving RUB conversion expire within 24 hours. If the reference rate cannot be obtained, creation fails with FX_UNAVAILABLE; no invented or stale fallback rate is used. The owner response amountMinor and quotes use the USD accounting currency. quotes[method].settlement contains the native charge quote. Public checkout exposes the selected charge currency in currency, the original price in baseAmountMinor/baseCurrency, and the reference rate in fx. Once a payment has been dispatched, its method cannot be changed; an invoice has one gateway operation.
Create an API key inside the intended store and send Authorization: Bearer <key> from your server. Its store binding is immutable; X-Kevmi-Store cannot grant it access to another store. Browser sessions select X-Kevmi-Store: <storeId>; omitting it selects the first store. The all value is accepted only by GET /api/account/dashboard and GET /api/payment-links. Mutations require a selected store, Origin and X-CSRF-Token. Account IDs and store IDs are different identifiers.
For compatibility, API requests without pricingMode="universal" retain native pricing and the original currency restrictions. Existing invoices are never recalculated. Confirmed receipts in analytics reflect verified payments less saved invoice expenses; they are not a withdrawable balance. Legacy invoice currencies remain separate and payouts are arranged with support. Fulfil an order only after checking payment.fulfillmentReady=true and payment.status="succeeded" through the server API, event history or a signed webhook.