Документация API
Платёжный микросервис: CRM создаёт заказ, получает ссылку на оплату, принимает server-callback после успеха. Деньги и статусы хранит Pay.
Authentication
Все методы (кроме webhook банка) требуют заголовки:
| Header | Description |
|---|---|
X-Service
|
Имя вызывающего сервиса, например
crm
|
X-Secret
|
Секрет Pay (SECRET) |
X-Owner
|
Публичный
owner_id
|
X-Owner-Secret
|
Пароль владельца |
owner_id
в JSON тела не передаётся — берётся из
X-Owner.Payment flow
callback_url
Server → CRM. JSON об успешной оплате. Не редирект браузера.
success_url / fail_url
Браузер пользователя после формы Точки. У каждой CRM — свои URL.
Create Order + Payment
Создаёт заказ и сразу платёж. В ответе —
order, опционально
subscription, и
payment
со ссылкой
url.
Суммы в
копейках
(1 ₽ =
100).
Required body fields
| Field | Type | Description |
|---|---|---|
product_ids
|
string[] | ID версий продуктов |
price
|
int | Сумма до скидок (коп.) |
amount
|
int | Итог к оплате (коп.) |
client_id
|
string | ID клиента в CRM |
client_email
|
string | Email клиента |
success_url
|
string | Redirect после успеха (обязателен для Tochka) |
fail_url
|
string | Redirect после ошибки (обязателен для Tochka) |
Optional
| Field | Default | Description |
|---|---|---|
currency
|
RUB
|
Валюта |
provider
|
Tochka
|
Tochka
|
Robo
|
callback_url
|
— | Куда Pay шлёт результат оплаты |
client_name
/
phone
/
address
/
comment
|
— | Данные клиента |
utm,
manager_id,
parent_id,
meta
|
— | Метаданные CRM |
is_recurring
|
false
|
Подписка |
subscription
|
— | Обязателен при
is_recurring=true
|
subscription
| Field | Description |
|---|---|
uuid
|
ID подписки/сделки в CRM (уникален в рамках owner) |
period
|
1
day |
2
week |
3
month |
4
quart |
5
year |
amount
|
Сумма регулярного списания (коп.) |
next
|
Дата следующего списания, RFC3339 |
subscription.uuid
уже есть →
subscription already exists, заказ не создаётся.Example request
curl -s -X POST 'https://pay.potap.io/api/order/create' \
-H 'Content-Type: application/json' \
-H 'X-Service: crm' \
-H 'X-Secret: YOUR_PAY_SECRET' \
-H 'X-Owner: your_owner_id' \
-H 'X-Owner-Secret: your_owner_secret' \
-d '{
"product_ids": ["prod_ver_1"],
"price": 100,
"amount": 100,
"currency": "RUB",
"client_id": "42",
"client_email": "user@example.com",
"callback_url": "https://crm.example.com/hooks/pay",
"success_url": "https://crm.example.com/pay/success",
"fail_url": "https://crm.example.com/pay/fail",
"provider": "Tochka"
}'
Example response
{
"order": {
"id": 15,
"uuid": "ord_abc123",
"owner_id": "your_owner_id",
"client_id": "42",
"amount": 100,
"status": 1,
"is_recurring": false
},
"payment": {
"id": 3,
"provider": "Tochka",
"url": "https://merch.tochka.com/order/?uuid=...",
"order_uuid": "ord_abc123",
"amount": 100,
"operation_id": "op_example_uuid",
"status": 1
}
}
CRM редиректит пользователя на
payment.url.
Order status
| status | Meaning |
|---|---|
1
|
создан |
5
|
частично оплачен |
7
|
оплачен |
8
|
отменён |
9
|
возврат |
Callback
После успешной оплаты Pay делает
POST
на
callback_url. До 5 попыток с backoff. Ошибка callback не откатывает оплату. CRM отвечает HTTP
2xx.
{
"event": "payment.succeeded",
"owner_id": "your_owner_id",
"order_uuid": "ord_abc123",
"payment_uuid": "op_example_uuid",
"client_id": "42",
"amount": 100,
"currency": "RUB",
"provider": "Tochka",
"is_recurring": true,
"status": 7
}
Browser redirects
| Field | When |
|---|---|
success_url
|
Успешная оплата на стороне Точки |
fail_url
|
Ошибка / отмена |
Передаются в CreateOrder каждой CRM отдельно. Pay прокидывает их в Точку как
redirectUrl
/
failRedirectUrl.
List Orders
| Query | Default | Description |
|---|---|---|
limit
|
50 (max 100) | Размер страницы |
offset
|
0 | Сдвиг |
curl -s 'https://pay.potap.io/api/orders?limit=20&offset=0' \ -H 'X-Service: crm' \ -H 'X-Secret: YOUR_PAY_SECRET' \ -H 'X-Owner: your_owner_id' \ -H 'X-Owner-Secret: your_owner_secret'
Get Order + Payments
curl -s 'https://pay.potap.io/api/order?uuid=ord_abc123' \ -H 'X-Service: crm' \ -H 'X-Secret: YOUR_PAY_SECRET' \ -H 'X-Owner: your_owner_id' \ -H 'X-Owner-Secret: your_owner_secret'
Ответ:
{ "order": {...}, "payments": [...] }
Client Orders
curl -s 'https://pay.potap.io/api/orders/client?client_id=42' \ -H 'X-Service: crm' \ -H 'X-Secret: YOUR_PAY_SECRET' \ -H 'X-Owner: your_owner_id' \ -H 'X-Owner-Secret: your_owner_secret'
Go client
Единый
CallAPI
+ отдельные структуры запросов и ответов.
func CallAPI(method, path string, req any, dest any) error {
var body io.Reader
if req != nil {
b, err := json.Marshal(req)
if err != nil { return err }
body = bytes.NewReader(b)
}
httpReq, err := http.NewRequest(method, "https://pay.potap.io"+path, body)
if err != nil { return err }
if req != nil { httpReq.Header.Set("Content-Type", "application/json") }
httpReq.Header.Set("X-Service", "crm")
httpReq.Header.Set("X-Secret", paySecret)
httpReq.Header.Set("X-Owner", ownerID)
httpReq.Header.Set("X-Owner-Secret", ownerSecret)
resp, err := (&http.Client{Timeout: 15 * time.Second}).Do(httpReq)
if err != nil { return err }
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("pay status %d: %s", resp.StatusCode, raw)
}
if dest == nil || len(raw) == 0 { return nil }
return json.Unmarshal(raw, dest)
}
type CreateOrderReq struct {
ProductIDs []string `json:"product_ids"`
Price int64 `json:"price"`
Amount int64 `json:"amount"`
ClientID string `json:"client_id"`
ClientEmail string `json:"client_email"`
CallbackURL string `json:"callback_url"`
SuccessURL string `json:"success_url"`
FailURL string `json:"fail_url"`
Provider string `json:"provider"`
}
type CreateOrderResp struct {
Order Order `json:"order"`
Payment PaymentInfo `json:"payment"`
}
func CreateOrder(req CreateOrderReq) (*CreateOrderResp, error) {
var resp CreateOrderResp
if err := CallAPI(http.MethodPost, "/api/order/create", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
Полные структуры и CRM-методы — в
readme/API.md.