POST /cards/requestЗаголовок Idempotency-Key обязателен, без него — 400 IDEMPOTENCY_KEY_REQUIRED. Нужно право cards.create.
Тело запроса необязательно. Единственное поле — externalId, ваш идентификатор карты (см. Привязка к своему id).
curl -X POST 'https://b2b.lumowallet.io/cards/request' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000'С привязкой к своему идентификатору:
curl -X POST 'https://b2b.lumowallet.io/cards/request' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
-H 'Content-Type: application/json' \
-d '{"externalId": "user-42-card-1"}'{
"status": "assigned",
"card": {
"id": "8c7f1823-0d43-4618-86ee-fa0c77643cb2",
"externalId": "user-42-card-1",
"status": "assigned",
"maskedPan": "4466********1234",
"expiry": "03/29",
"assignedAt": "2026-04-23T12:00:00.000Z",
"createdAt": "2026-04-23T12:00:00.000Z",
"upayState": null,
"upayStateName": null
}
}Ответ — 201. Состояние у эквайера (upayState, upayStateName) в этом ответе не заполняется — запрашивайте его через GET /cards/{id}.
{
"status": "pending",
"request": {
"id": "2077f4ef-a03d-4001-82e3-1965e44036e8",
"externalId": "user-42-card-1",
"status": "pending",
"cardId": null,
"createdAt": "2026-04-23T12:00:00.000Z"
}
}Когда карта выпустится, вы получите webhook card.assigned с requestId заявки, а у заявки появится cardId и статус fulfilled. Если в очереди несколько ваших заявок, выданная карта закрывает самую раннюю из них. Статус заявки можно и опрашивать:
curl 'https://b2b.lumowallet.io/cards/requests/2077f4ef-a03d-4001-82e3-1965e44036e8' \
-H 'X-API-Key: YOUR_API_KEY'Ответ — объект заявки в том же формате, что request выше (право cards.read).
Вебхук card.assigned приходит и на мгновенную выдачу — с requestId: null: карта к этому моменту у вас уже есть из ответа на запрос. В тестовом режиме вебхук не отправляется.
Idempotency-Key защищает от двойного выпуска: повтор с тем же ключом не создаёт вторую карту и не списывает комиссию ещё раз. Но вернуть результат первого запроса повтор может не всегда:
- первый запрос сразу выдал карту и
externalIdне передавался — вернётся та же карта; - передавали
externalId— повтор отклоняется409 CARD_EXTERNAL_ID_TAKEN, а вdetailsприходитcardIdвыданной карты илиrequestIdзаявки; - первая заявка ушла в очередь, первый запрос ещё выполняется или на балансе не хватает средств на временный резерв — повтор завершится ошибкой.
Поэтому передавайте externalId и ищите результат через details ошибки, GET /cards?externalId=… или вебхук card.assigned. Для каждой новой карты используйте новый ключ.
Исключение — ответ 502: эквайер не ответил, но карту мог выдать. Такая карта придёт вебхуком card.assigned без requestId и без externalId.
externalId — необязательное поле в теле запроса: ваш идентификатор карты (id пользователя, номер заказа, что угодно до 128 печатаемых ASCII-символов без пробелов). Дальше он ездит вместе с картой:
- возвращается в
POST /cards/request,GET /cards,GET /cards/{id}иGET /cards/requests/{requestId}; - приходит в webhook
card.assigned— так отложенный выпуск связывается с вашей сущностью без хранения маппинга на нашей стороне; - по нему можно искать карту:
GET /cards?externalId=user-42-card-1.
Если заявка ушла в очередь, externalId хранится на ней и переезжает на карту в момент выдачи.
Уникальность — в рамках вашей компании. Второй выпуск с тем же значением вернёт 409 CARD_EXTERNAL_ID_TAKEN, а в details придёт cardId (или requestId) того, кто уже занял значение:
{
"statusCode": 409,
"error": "Conflict",
"errorCode": "CARD_EXTERNAL_ID_TAKEN",
"message": "externalId \"user-42-card-1\" уже занят картой 8c7f1823-0d43-4618-86ee-fa0c77643cb2",
"details": {
"externalId": "user-42-card-1",
"cardId": "8c7f1823-0d43-4618-86ee-fa0c77643cb2"
}
}У разных компаний значения не пересекаются — свой user-42-card-1 может быть у каждой. Карты, выпущенные без externalId, приходят с null, и задним числом поле не проставляется.
Пока карта по заявке не выпущена, заявку можно отменить — например, если она надолго зависла в очереди, а деньги под неё нужны на другое.
POST /cards/requests/{requestId}/cancelНужно право cards.create.
curl -X POST 'https://b2b.lumowallet.io/cards/requests/2077f4ef-.../cancel' \
-H 'X-API-Key: YOUR_API_KEY'{
"id": "2077f4ef-a03d-4001-82e3-1965e44036e8",
"externalId": "user-42-card-1",
"status": "cancelled",
"cardId": null,
"createdAt": "2026-04-23T12:00:00.000Z"
}Резерв под заявку возвращается в доступный баланс, а externalId снова освобождается — его можно использовать в новой заявке.
Отменить можно только заявку в статусе pending. Если карта уже выпущена, придёт CARD_REQUEST_NOT_CANCELABLE: выданную карту не отменяют, её закрывают через POST /cards/{id}/retire. Если карта по заявке выдаётся прямо сейчас, отмена может завершиться 422 — тогда карта придёт вебхуком card.assigned.
Повторная отмена не ошибка — вернётся та же заявка, и ничего не изменится. Поэтому запрос безопасно повторять, если ответ не дошёл.
Заявку может отменить и наша сторона — например, если карту по ней выдать не удалось. Тогда придёт webhook card.request_cancelled, а резерв так же вернётся на баланс.
На момент POST /cards/request:
- Проверяется, что
availableBalance >= openingFee + minInitialDeposit, иначе —400сerrorCode: BAD_REQUESTи сообщениемINSUFFICIENT_FUNDS: need N USDT, have M. - Сумма
openingFee + minInitialDepositпереводится вfrozenBalance. - При выдаче карты резерв снимается целиком:
openingFeeсписывается сbalance,minInitialDepositвозвращается в доступный баланс. - Если запрос к эквайеру не прошёл — вся сумма размораживается.
| HTTP | errorCode | Значение |
|---|---|---|
| 400 | IDEMPOTENCY_KEY_REQUIRED | Не передан Idempotency-Key |
| 400 | BAD_REQUEST | Сообщение INSUFFICIENT_FUNDS: … — не хватает availableBalance на резерв |
| 400 | VALIDATION_ERROR | externalId пустой, длиннее 128 символов или с недопустимыми символами |
| 403 | CARDS_NOT_ENABLED | У компании не подключена программа карт |
| 409 | CARD_EXTERNAL_ID_TAKEN | externalId уже занят картой или заявкой компании |
| 422 | UNPROCESSABLE | Эквайер отклонил заявку, причина в message |
| 502 | BAD_GATEWAY | Эквайер не ответил, исход неизвестен. Резерв возвращён; если карта всё же выдана, она придёт вебхуком card.assigned. Повторяйте с тем же Idempotency-Key |
| 400 | CARD_REQUEST_NOT_CANCELABLE | Заявку нельзя отменить: карта уже выпущена |
| 403 | CARD_NOT_OWNED | GET /cards/requests/{id}: заявка принадлежит другой компании |
| 404 | CARD_REQUEST_NOT_FOUND | Заявки с таким id у компании нет |
Одна заявка за раз для заданного Idempotency-Key. Чтобы выпустить 10 карт — сделайте 10 вызовов с разными ключами.