Разработчикам/Начало работы

Общие правила

Правила, которые действуют для всех семи методов.

См. также: Аутентификация · Каталог и заказы · README

#Запросы

  • Базовый URL: https://b2b.cardv.net/api/v1 (Live) или https://sandbox.cardv.net/api/v1 (Sandbox).
  • Пути пишутся без косой черты в конце: /api/v1/orders, а не /api/v1/orders/.
  • Тело в JSON отправляйте в кодировке UTF-8 с заголовком Content-Type: application/json.
  • Суммы передавайте строками, например "9.2500". Так не будет ошибок округления.
  • Указывайте понятный User-Agent, например AcmeShop-CardV/1.4.

#Деньги и время

  • Сумма — это строка с 4 знаками после точки, например "merchant_price": "9.2500".
  • Читайте суммы в десятичный тип, а не в число с плавающей точкой.
  • Вы платите в валюте кошелька (default_currency в GET/account, сейчас это USD).
  • face_currency — валюта, указанная на самой карте. Она может отличаться от валюты кошелька.
  • Для расчёта затрат всегда берите merchant_price. Поля вроде price_label нужны только для показа.
  • Всё время указано в UTC в формате ISO 8601, например 2026-09-29T08:15:30.123456Z.
  • Разбирайте время полноценным парсером ISO 8601: число знаков в долях секунды бывает разным.
  • X-Timestamp для подписи — время Unix в секундах.

#Идентификаторы

ЧтоПримерПояснение
Merchant IDM00000001Никогда не меняется.
ID товара (SKU)S000456Нужен, чтобы узнать цену и заказать.
ID продуктаP000123Продукт, к которому относится SKU.
Номер заказа CardVO-00001234По нему читают заказ.
Ваш номер заказаSHOP-10001external_order_id, от 1 до 120 символов, уникальный.
  • Храните ID как строки и не разбирайте их на части. Со временем они могут стать длиннее.
  • У заказов есть ещё числовое поле id. Не используйте его — берите order_id.
  • В своём номере заказа используйте только A–Z a–z 0–9 - _ ..

#Постраничная выдача

Постранично отдаёт данные только GET/skus. Передавайте limit и offset:

HTTP
GET /api/v1/skus?limit=100&offset=200
JSON
{"count": 1234, "limit": 100, "results": ["..."], "filter_options": {}}
  • По умолчанию limit равен 100, максимум — 500. Большие значения уменьшаются до 500.
  • count — общее число найденных записей. Запрашивайте дальше, пока offset не дойдёт до count.
  • Отрицательный или нечисловой limit или offset вернёт HTTP 400.
  • Неизвестное значение фильтра вернёт пустой список, а не ошибку.

#Лимит запросов

  • По умолчанию — 60 запросов в минуту на весь аккаунт. Этот лимит общий для всех ваших ключей и пользователей кабинета. Для вашего тарифа число может быть другим.

  • Минута отсчитывается от :00 по часам. Отклонённые запросы тоже учитываются.

  • При превышении вы получите HTTP 429 и заголовок Retry-After (сколько секунд ждать):

    JSON
    {"detail": "Merchant API rate limit exceeded. Expected available in 23 seconds."}
  • Чтобы не упираться в лимит, кешируйте список товаров, используйте вебхуки вместо частых опросов и после каждого ответа 429 выжидайте чуть дольше.

#Ошибки

Сначала всегда смотрите на HTTP-статус, потом читайте тело JSON. Что пошло не так, подсказывает ключ в теле ответа. Не опирайтесь на текст сообщения.

Ошибки аутентификации, прав доступа, «не найдено» и превышения лимита приходят в поле detail:

JSON
{"detail": "Order not found."}

Ошибки заказа и запроса цены называют поле, в котором проблема:

JSON
{"balance": "Insufficient available balance."}

Если строка заказа составлена неправильно, ошибка приходит для каждой строки — в том же порядке, что и ваши items:

JSON
{"items": [{}, {"quantity": ["Ensure this value is greater than or equal to 1."]}]}
КлючГдеЧто делать
detailВездеСмотрите таблицу кодов статуса ниже.
itemsPOST/ordersИсправьте строку. Если изменилась цена, запросите её заново.
balancePOST/ordersПополните кошелёк в кабинете.
riskPOST/ordersВы упёрлись в лимит заказов. Свяжитесь с CardV.
external_order_idPOST/ordersНомера заказа нет, он слишком длинный или уже занят другим заказом.
walletPOST/ordersНет активного кошелька. Свяжитесь с CardV.
quantity, amountЗапрос ценыЗначение вне допустимого диапазона или не число.
limit, offsetGET/skusНедопустимое число.

Некоторые ошибки приходят не в JSON:

  • HTTP 403 с простым текстом вроде error code: 1010 возвращает сетевой периметр CardV. До самого CardV запрос не дошёл. Сообщите CardV IP своего сервера и User-Agent.
  • Неизвестный путь (404) или ошибка прокси (5xx) могут вернуть HTML.

Когда пишете ошибки в лог, никогда не записывайте API-ключи, подписи и коды.

#Коды статуса HTTP

СтатусЧто значитПовторять?
200Успех. Для POST/orders — такой заказ уже был.Не нужно
201Создан новый заказ.Не нужно
400Запрос отклонён. Деньги не списаны.После исправления
403Учётные данные, подпись, IP или метод только для кабинета.После исправления
404Не найдено или недоступно вашему аккаунту.Нет
405Для этого пути нужен другой HTTP-метод.Нет
429Слишком много запросов.После Retry-After
5xx или тайм-аутПроблема на сервере или в сети. Заказ мог создаться.Да, см. ниже

POST/orders повторяйте только с тем же телом и тем же номером заказа. См. безопасный повтор.

#Ответы

  • brand_logo_url и image_url — полные URL картинок на серверах CardV или "". Они публичные, их можно кешировать.
  • Поля заказа invoice_url и delivery_file_url — это пути вида /orders/O-00001234/invoice или "", если данных ещё нет. Они работают только в кабинете: с API-ключом вернут HTTP 403. Счета и CSV-файлы с кодами открывайте в кабинете.

#Совместимость

  • Незнакомые поля пропускайте. CardV добавляет поля без выпуска новой версии API.
  • Могут появиться новые статусы. Если статус вам незнаком, считайте, что заказ ещё не завершён.
  • Не рассчитывайте на порядок ключей в JSON и на формулировки сообщений.

Вопросы по интеграции? Напишите на [email protected], указав ваш Merchant ID и ID заказа или запроса.