API Reference / Version 1

От первого запроса до выпуска карты.

Выпуск, пополнение и управление виртуальными картами из вашего приложения. Все методы, параметры и примеры ответов — здесь.

Base URL/v1
01

Быстрый старт

  1. Шаг 01

    Создайте аккаунт и API-ключ в личном кабинете.

  2. Шаг 02

    Передайте ключ в заголовке Authorization.

  3. Шаг 03

    Выпустите карту с нужной платёжной сетью.

Первый запрос · аккаунтshell
curl /v1/me \
  -H "Authorization: Bearer cmk_live_YOUR_KEY"

Спецификация для вашего проекта

Импортируйте OpenAPI в ваш API-клиент или передайте ИИ-агенту для генерации интеграции. Используйте переменную окружения вместо реального ключа.

Скачать OpenAPI ↗

Авторизация и правила

Bearer API key

Все запросы требуют заголовок Authorization: Bearer cmk_live_….

Формат JSON

Тело запроса и ответ используют application/json. Результат находится в поле data.

Идемпотентность

Для выпуска и пополнения обязательно передавайте уникальный client_request_id в JSON. Для повтора той же операции используйте прежнее значение. Другой запрос с тем же ID получит 409. При operation_requires_review обратитесь в поддержку; деньги автоматически не возвращаются.

Аккаунт

Проверка ключа и внутреннего баланса клиента.

GET
/me

Текущий аккаунт

Проверяет API-ключ и возвращает владельца аккаунта.

Пример успешного ответаjson
{
  "data": {
    "id": "uuid",
    "username": "demo",
    "role": "user",
    "balance_usd": 125.5,
    "disabled": false
  }
}

Подготовка операции

Посмотрите справочную информацию о карточных продуктах. Конкретный BIN при выпуске не выбирается.

GET
/bins

Доступные BIN

Список доступных карточных продуктов с сетью, страной, валютой и лимитами.

Пример успешного ответаjson
{
  "data": [
    {
      "bin": "424242",
      "network": "visa",
      "country": "US",
      "currency": "USD",
      "min_amount": 20,
      "max_amount": 1000,
      "available": true,
      "apple_pay": false,
      "google_pay": false,
      "stripe": false
    }
  ]
}

Карты

Выпуск, реквизиты и пополнение виртуальной карты.

GET
/cards?limit=50&offset=0

Список карт

Возвращает карты владельца ключа.

Пример успешного ответаjson
{
  "data": [
    {
      "id": "card-uuid",
      "status": "active",
      "network": "visa",
      "last4": "4242",
      "amount_usd": 25,
      "total_loaded_usd": 25,
      "balance_usd": 25,
      "holder_name": "IVAN IVANOV",
      "created_at": 1791378000000
    }
  ],
  "total": 1
}
POST
/cards

Выпустить карту

Создаёт виртуальную карту и списывает рассчитанную стоимость с внутреннего баланса.

Передавайте уникальный client_request_id в JSON, чтобы повтор запроса не создал вторую карту.

Тело запросаjson
{
  "amount_usd": 25,
  "network": "visa",
  "holder_name": "IVAN IVANOV",
  "holder_email": "[email protected]",
  "client_request_id": "order-1001"
}
Пример успешного ответаjson
{
  "data": {
    "id": "card-uuid",
    "status": "active",
    "network": "visa",
    "last4": "4242",
    "amount_usd": 25,
    "total_loaded_usd": 25,
    "balance_usd": 25,
    "holder_name": "IVAN IVANOV",
    "created_at": 1791378000000
  }
}
GET
/cards/{id}

Состояние карты

Возвращает статус, сеть, последние 4 цифры, баланс и лимиты одной карты.

Пример успешного ответаjson
{
  "data": {
    "id": "card-uuid",
    "status": "active",
    "network": "visa",
    "last4": "4242",
    "amount_usd": 25,
    "total_loaded_usd": 25,
    "balance_usd": 25,
    "holder_name": "IVAN IVANOV",
    "created_at": 1791378000000
  }
}
GET
/cards/{id}/details

Реквизиты карты

Возвращает PAN, CVV и срок действия. Используйте только в защищённом интерфейсе.

Ограничение: 20 запросов в минуту.

Пример успешного ответаjson
{
  "data": {
    "id": "uuid",
    "number": "4242…",
    "cvv": "123",
    "expiry": "12/30",
    "holder_name": "IVAN IVANOV"
  }
}
POST
/cards/{id}/topup

Пополнить карту

Добавляет USD на баланс карты и списывает стоимость с внутреннего баланса.

Передавайте client_request_id в JSON. Повтор той же операции не приводит к повторному списанию.

Тело запросаjson
{
  "amount_usd": 50,
  "client_request_id": "topup-1001"
}
Пример успешного ответаjson
{
  "data": {
    "id": "card-uuid",
    "status": "active",
    "network": "visa",
    "last4": "4242",
    "amount_usd": 25,
    "total_loaded_usd": 75,
    "balance_usd": 75,
    "holder_name": "IVAN IVANOV",
    "created_at": 1791378000000
  }
}

Операции и 3DS

История платежей и события карты, включая 3DS.

GET
/cards/{id}/transactions?limit=50&offset=0

Транзакции

Возвращает покупки, пополнения, статусы и причины отклонения.

Пример успешного ответаjson
{
  "data": [
    {
      "id": "transaction-uuid",
      "card_id": "card-uuid",
      "type": "authorization",
      "status": "posted",
      "amount_usd": 12.5,
      "currency": "USD",
      "merchant": "Example Store",
      "created_at": 1791378000000
    }
  ],
  "total": 1
}
GET
/cards/{id}/events?limit=50&offset=0

События

Возвращает технические события карты, включая запросы 3DS.

Пример успешного ответаjson
{
  "data": [
    {
      "id": "event-uuid",
      "card_id": "card-uuid",
      "type": "card.3ds.required",
      "otp_code": "123456",
      "merchant": "Example Store",
      "currency": "USD",
      "created_at": 1791378000000
    }
  ],
  "total": 1
}

Вебхуки

Уведомления отправляются после обработки события в Cardmaker. ID карты и события — наши. Состояние карты отражает момент отправки; при повторной доставке оно может измениться. Уведомления формируются из сохранённых записей Cardmaker. Реквизиты карты не отправляются.

GET
/webhooks

Список вебхуков

Активные URL текущего пользователя. Настройки также доступны в личном кабинете в разделе «Вебхуки».

Пример успешного ответаjson
{
  "data": [
    {
      "id": "webhook-uuid",
      "url": "https://example.com/webhooks/cardmaker",
      "events": [],
      "active": true,
      "created_at": 1791378000000
    }
  ]
}
GET
/webhooks/{id}/deliveries?limit=50&offset=0

Журнал доставок

Статусы pending, delivered, failed, cancelled. Ошибки повторяются до 12 попыток с растущей задержкой от 5 секунд. Срок доставки — 24 часа, журнал хранится 30 дней. Ответ 2xx подтверждает доставку; редиректы не выполняются.

Пример успешного ответаjson
{
  "data": [
    {
      "id": "delivery-uuid",
      "event_id": "event-uuid",
      "event_type": "card.issued",
      "status": "delivered",
      "attempts": 1,
      "status_code": 200,
      "next_attempt_at": 0,
      "delivered_at": 1791378000000,
      "created_at": 1791378000000
    }
  ],
  "total": 1
}
POST
→ ваш URL

Входящее уведомление

События: card.issued, card.frozen, card.unfrozen, card.closed, card.topup.succeeded, card.transaction.posted, card.transaction.declined, card.3ds.required, card.3ds.resolved. Для пополнений data.topup включается при точном совпадении client_request_id. Для 3DS data.event содержит otp_code и expires_at.

Проверяйте X-Cardmaker-Signature по алгоритму из раздела «Подпись вебхука». Заголовки X-Cardmaker-Event-Id, X-Cardmaker-Delivery-Id, X-Cardmaker-Event идентифицируют событие и доставку. Обрабатывайте id идемпотентно: повторы возможны, порядок доставки не гарантируется. Поля времени в JSON — Unix в миллисекундах.

Пример успешного ответаjson
{
  "id": "event-uuid",
  "type": "card.transaction.posted",
  "created_at": 1791378000000,
  "processed_at": 1791378001000,
  "data": {
    "card": {
      "id": "card-uuid",
      "status": "active",
      "amount_usd": 25,
      "total_loaded_usd": 25,
      "balance_usd": 12.5,
      "created_at": 1791378000000
    },
    "event": {
      "id": "event-uuid",
      "card_id": "card-uuid",
      "type": "card.transaction.posted",
      "amount": 12.5,
      "currency": "USD",
      "created_at": 1791378000000
    }
  }
}

Подпись вебхука

Каждый запрос содержит заголовок X-Cardmaker-Signature. Его значение — MD5-хеш в виде 32 шестнадцатеричных символов в нижнем регистре. MD5 не шифрует тело: уведомление передаётся обычным JSON.

  1. Возьмите исходные байты HTTP-тела до разбора JSON. Пробелы, переносы строк и порядок полей имеют значение.
  2. Добавьте в конец байты вашего signing_secret в UTF-8 без разделителя.
  3. Вычислите MD5 и преобразуйте результат в hex в нижнем регистре. Формула: md5(raw_body + signing_secret).
  4. Сравните результат с X-Cardmaker-Signature. Секрет показывается при создании вебхука в личном кабинете.
Проверка подписи · Node.jsjavascript
import { createHash, timingSafeEqual } from "node:crypto";

// rawBody — Buffer с исходными байтами HTTP-тела.
function verifySignature(rawBody, signingSecret, signature) {
  if (typeof signature !== "string" || !/^[0-9a-f]{32}$/.test(signature)) return false;
  const expected = createHash("md5")
    .update(rawBody)
    .update(signingSecret, "utf8")
    .digest();
  return timingSafeEqual(expected, Buffer.from(signature, "hex"));
}

Заголовок содержит только хеш, без timestamp и префиксов. Храните секрет на сервере. Повторные уведомления с тем же id обрабатывайте идемпотентно.

Возможные ошибки

HTTP-статус описывает тип ошибки. Поле error содержит её причину.

400Некорректный JSON, сумма
401Ключ отсутствует, отозван или неверен
403Аккаунт отключён или нет доступа
404Карта или событие не найдено
402insufficient_balance — недостаточно средств
409Конфликт состояния или реквизиты ещё не готовы
429rate_limited — превышен лимит запросов
502service_unavailable — сервис временно недоступен
500Внутренняя ошибка сервиса
Пример ошибки · 402json
{
  "error": "insufficient_balance"
}