Desenvolvedores/Integração
Catálogo e pedidos
Este guia mostra o fluxo de compra do começo ao fim: consultar o saldo, encontrar um produto, ver o preço, fazer o pedido e receber os códigos.
Veja também: Autenticação · Convenções · Webhooks
#Conta e saldo
#Conta
GET/api/v1/account mostra os dados da sua empresa e se a API está liberada.
{
"merchant_id": "M00000001",
"name": "Acme Shop",
"legal_name": "Acme Shop Ltd",
"tier": "standard",
"billing_email": "[email protected]",
"status": "active",
"kyb_status": "approved",
"api_access_enabled": true,
"default_currency": "USD"
}default_currencyé a moeda da sua carteira. Todos os preços que você paga estão nessa moeda.api_access_enabledficatruedepois que a CardV aprova a sua empresa.
#Saldo
GET/api/v1/balance mostra quanto você tem para gastar.
{
"currency": "USD",
"balance": "1520.4000",
"reserved_amount": "0.0000",
"available_balance": "1520.4000",
"low_balance_threshold": "200.0000",
"low_balance_notified_at": null,
"is_active": true
}available_balanceé o que você pode gastar agora:balancemenosreserved_amount.- Um pedido maior que o
available_balanceé recusado, e nada é cobrado. low_balance_thresholdé o valor que dispara o e-mail de saldo baixo. Você define esse valor no Portal.- Para adicionar saldo, use o Portal.
#Produtos (SKUs)
Um SKU é um produto que você pode comprar, por exemplo "Steam Wallet 10 USD".
O ID tem este formato: S000456. É pelo SKU que você consulta o preço e faz o pedido.
GET/api/v1/skus lista os SKUs que você pode comprar. Exemplo:
GET /api/v1/skus?search=steam®ion=US&limit=50&offset=0Filtros (todos opcionais):
| Filtro | Exemplo | O que busca |
|---|---|---|
search | steam | ID do SKU, nome ou marca |
brand | Steam | Nome da marca (maiúsculas ou minúsculas) |
region | US | Código ou nome do país |
vertical | gift_card | Linha de produto |
product_type | pin_code | Forma de entrega |
Paginação: envie limit (padrão 100, máximo 500) e offset.
Continue pedindo com um offset maior até offset chegar a count.
{
"count": 7,
"limit": 1,
"results": [
{
"sku_id": "S000456",
"product_id": "P000123",
"name": "Steam Wallet 10 USD",
"product_name": "Steam Wallet US",
"brand": "Steam",
"region": "US",
"vertical": "gift_card",
"product_type": "pin_code",
"denomination_type": "fixed",
"denomination_value": "10.0000",
"face_currency": "USD",
"merchant_price": "9.2500",
"settlement_currency": "USD",
"availability": "available",
"min_quantity": 1,
"max_quantity": 100,
"required_input_schema": [],
"...": "more fields"
}
],
"filter_options": {"brands": [], "regions": [], "verticals": []}
}GET/api/v1/skus/{sku_id} retorna um único SKU, com os mesmos campos.
Os campos mais úteis:
| Campo | Significado |
|---|---|
sku_id | O ID que você usa para ver o preço e fazer o pedido. |
merchant_price | O seu preço por unidade, em settlement_currency. |
availability | available ou unavailable. Só compre SKUs available. |
denomination_type | fixed ou range. Veja valor fixo ou variável. |
face_currency | Moeda impressa no cartão. Pode ser diferente da moeda da sua carteira. |
min_quantity, max_quantity | Quantas unidades cabem em um item do pedido. |
product_type | pin_code (você recebe um código) ou direct_charge (a CardV recarrega uma conta). |
required_input_schema | Dados que você precisa enviar nas recargas diretas. |
brand_logo_url, image_url | Imagens hospedadas pela CardV, ou "". |
description, redemption_instructions, terms | Textos que você pode mostrar aos seus clientes. |
Dicas:
- Você só vê SKUs ativos e liberados para a sua conta. Os outros retornam 404.
- Atualize a lista de SKUs a cada 5–15 minutos. Consulte sempre o preço logo antes de fazer o pedido.
filter_optionsmostra as marcas, regiões e linhas de produto que você pode usar nos filtros.
#Valor fixo ou variável
A maioria dos SKUs tem valor de face fixo (fixed), como 10 USD.
Alguns têm valor variável (range): o seu cliente escolhe o valor, por exemplo de 5 a 500 USD.
| Tipo | Ao consultar o preço | Ao fazer o pedido |
|---|---|---|
fixed | Envie quantity | Não envie amount |
range | Envie quantity e amount | Envie amount |
Em um SKU de valor variável, amount precisa estar entre min_face_value e max_face_value.
O valor é em face_currency.
#Recargas diretas
Alguns produtos recarregam direto a conta do seu cliente, por exemplo uma conta de jogo. Nesses casos, a CardV precisa dos dados da conta. O SKU informa quais são:
"required_input_schema": [
{"key": "player_id", "label": "Player ID", "required": true},
{"key": "server", "label": "Server", "required": false}
]Envie os valores no campo inputs do item do pedido, usando cada key:
"inputs": {"player_id": "123456789", "server": "EU"}- Todo campo é obrigatório, a menos que venha com
"required": false. - Se faltar um valor obrigatório, o pedido é recusado com um erro em
items. - Esses valores são dados pessoais do seu cliente. Proteja-os (veja Segurança).
#Consulta de preço
A consulta de preço (quote) informa o preço atual para uma quantidade.
GET /api/v1/skus/S000456/quote?quantity=2
GET /api/v1/skus/S000789/quote?quantity=1&amount=25.00{
"sku_id": "S000456",
"settlement_currency": "USD",
"merchant_price": "9.2500",
"quantity": 2,
"total_price": "18.5000",
"min_quantity": 1,
"max_quantity": 100,
"availability": "available"
}- A consulta não garante o preço. Os preços podem mudar a qualquer momento.
- Para se proteger, envie o
merchant_pricecomoexpected_unit_priceao fazer o pedido. Se o preço tiver mudado, a CardV recusa o pedido e não cobra nada. - Quantidade ou valor fora do intervalo retorna HTTP 400 com erro em
quantityouamount.
#Fazer um pedido
POST/api/v1/orders compra um ou mais SKUs e paga com a sua carteira.
Esta chamada precisa ser assinada.
{
"external_order_id": "SHOP-20260929-10001",
"items": [
{"sku_id": "S000456", "quantity": 2, "expected_unit_price": "9.2500"},
{"sku_id": "S000789", "amount": "25.00", "expected_unit_price": "23.7500"},
{
"sku_id": "S000900",
"expected_unit_price": "4.9000",
"inputs": {"player_id": "123456789"}
}
]
}| Campo | Obrigatório | Significado |
|---|---|---|
external_order_id | Sim | O seu número de pedido, de 1 a 120 caracteres. Não pode se repetir. |
items | Sim | Um ou mais itens do pedido. |
items[].sku_id | Sim | O SKU que você quer comprar. |
items[].quantity | Não | Quantas unidades. Padrão: 1. |
items[].amount | SKUs de valor variável | O valor de face que você quer comprar. |
items[].expected_unit_price | Recomendado | O merchant_price da consulta. Envie sempre. |
items[].inputs | Recargas diretas | Dados da conta para recargas diretas. |
Quando a CardV aceita o pedido, ela cobra o valor total da sua carteira na hora. A entrega começa em seguida, em segundo plano.
A resposta é HTTP 201:
{
"idempotent_replay": false,
"order": {
"order_id": "O-00001234",
"external_order_id": "SHOP-20260929-10001",
"status": "accepted",
"total_amount": "46.2000",
"...": "more fields"
}
}Guarde o order.order_id. Esta resposta nunca traz os códigos. Você os busca depois (veja Consultar um pedido).
#Pedidos recusados
Um pedido recusado retorna HTTP 400 e não cobra nada. A chave do erro diz o motivo:
| Chave | Motivo | O que fazer |
|---|---|---|
items | Preço mudou, SKU indisponível, valor inválido ou dado faltando | Consulte o preço de novo, corrija e reenvie |
balance | Saldo insuficiente na carteira | Adicione saldo no Portal |
risk | Acima do seu limite por pedido ou do limite diário | Fale com a CardV |
external_order_id | O seu número de pedido já foi usado em outro pedido | Veja Reenviar com segurança |
Exemplo de mudança de preço:
{
"items": "SKU S000456 price changed from 9.2500 to 9.4100 USD; refresh quote and confirm again."
}O plano da sua conta define os limites por pedido, de gasto diário e de quantidade de pedidos por dia. Os limites diários zeram às 00:00 UTC. Pergunte à CardV quais são os seus limites.
#Reenviar com segurança
O seu número de pedido (external_order_id) evita que você compre duas vezes.
Se você reenviar o mesmo pedido com o mesmo número, a CardV não cobra de novo.
Ela devolve o pedido que já existe.
| Você envia | Você recebe |
|---|---|
| Um número de pedido novo | HTTP 201. Um pedido novo. A carteira é cobrada. |
| O mesmo número e o mesmo pedido | HTTP 200 e "idempotent_replay": true. O pedido que já existe. Nenhuma cobrança. |
| O mesmo número, mas um pedido diferente | HTTP 400 em external_order_id. Nada acontece. |
"O mesmo pedido" quer dizer os mesmos itens, na mesma ordem, com o mesmo SKU, quantidade, valor e dados de recarga.
Se você enviar expected_unit_price, ele precisa ser igual ao preço do primeiro pedido.
A CardV reconhece o pedido repetido antes de verificar saldo e preço. Por isso a resposta é sempre o primeiro pedido, mesmo que o preço tenha mudado depois.
#Fluxo de reenvio seguro
Se você não tiver uma resposta clara, basta reenviar o mesmo pedido.
POST /orders com o número de pedido R
├─ 201 ou 200 → guarde o order_id. Pronto.
├─ 400 items / balance / risk → nenhum pedido foi criado.
│ Corrija a causa e reenvie. Você pode usar R de novo.
├─ 400 external_order_id → R pertence a outro pedido. Pare e verifique.
├─ 403 erro de assinatura → assine de novo e envie o mesmo corpo.
├─ 429 → espere o Retry-After, assine de novo e envie o mesmo corpo.
└─ timeout, 5xx ou conexão perdida
→ reenvie o mesmo corpo com o mesmo R.
Você recebe 201 (a primeira tentativa não chegou) ou 200 (chegou).Regras:
- Nunca crie um número de pedido novo só porque uma resposta se perdeu. Se a primeira requisição tiver chegado, um número novo compraria tudo duas vezes.
- Cada reenvio precisa de timestamp, nonce e assinatura novos. O corpo continua igual.
#Consultar um pedido
GET/api/v1/orders/{order_id} retorna o pedido, o status e os códigos.
{
"order_id": "O-00001234",
"external_order_id": "SHOP-20260929-10001",
"status": "succeeded",
"currency": "USD",
"total_amount": "18.5000",
"created_at": "2026-09-29T08:15:30.123456Z",
"updated_at": "2026-09-29T08:15:41.004211Z",
"items": [
{
"sku_id": "S000456",
"product_name": "Steam Wallet US",
"quantity": 2,
"unit_price": "9.2500",
"total_price": "18.5000",
"delivery_count": 2,
"deliveries": [{"...": "see Codes below"}]
}
],
"...": "more fields"
}total_amounté o valor cobrado quando o pedido foi aceito.items[].unit_priceé o preço travado para este pedido.items[].deliveriestraz os códigos completos. Trate a resposta como confidencial.invoice_urledelivery_file_urlsão caminhos para a fatura e para os códigos em CSV. Os dois só funcionam no Portal. Com chave de API, retornam HTTP 403.- A resposta também traz
id(um número antigo, não use),events(histórico só para exibição) e o andamento da entrega de cada item. Você pode ignorar esses campos. - Um número de pedido desconhecido retorna HTTP 404.
#Status do pedido e códigos
#Status
accepted ──► processing ──► succeeded
│
├──► partially_succeeded (alguns itens entregues, outros não)
│
└──► failed ──► refunded (dinheiro devolvido à sua carteira)| Status | Terminou? | O que fazer |
|---|---|---|
accepted | Não | Aguarde. A carteira já foi cobrada e a entrega ainda não começou. |
processing | Não | Aguarde. Não faça o pedido de novo. |
succeeded | Sim | Busque os códigos e entregue ao seu cliente. |
partially_succeeded | Sim | Entregue o que chegou. O restante é reembolsado depois. |
failed | Ainda não | Aguarde o refunded. Falha ainda não é reembolso. |
refunded | Sim | O dinheiro voltou para a sua carteira. |
Se você não usa webhooks, consulte o pedido assim: depois de 5 segundos, depois 10 s, 30 s, 60 s e então a cada 5 minutos. Respeite o limite de requisições. A maioria dos pedidos termina em segundos. Alguns precisam de verificação manual e podem levar horas.
#Códigos
Cada unidade entregue é um objeto em items[].deliveries:
{
"status": "stored",
"delivery_type": "card_pin",
"display_fields": [
{"key": "card_number", "label": "Card number", "value": "X1234", "kind": "secret"},
{"key": "pin_code", "label": "PIN", "value": "9876", "kind": "secret"}
],
"redeem_url": "",
"expiry_date": "2027-09-29",
"instructions": "Redeem at ...",
"is_masked": false
}- Mostre ao seu cliente os
display_fields: cada um tem umlabele umvalue. Mostre tambémredeem_url,expiry_dateeinstructionsquando não estiverem vazios. kindésecretpara códigos e PINs, ereferencepara dados como números de série.delivery_typediz o que você recebeu:code,card_pin,link,code_linkouqr. Podem surgir tipos novos, então monte a exibição sempre a partir dedisplay_fields.- Nas entregas do tipo
link, o próprioredeem_urlé o código. Mantenha-o em sigilo. - Nunca entregue ao cliente uma unidade com
statusigual avoided. - Produtos de recarga direta normalmente não têm entregas.
succeededsignifica que a conta foi recarregada. - Cópias como
card_numberepin_codetambém aparecem como campos separados. Elas podem vir vazias. - Os webhooks nunca trazem códigos. Consulte o pedido depois que o webhook chegar.
Dúvidas sobre a integração? Envie um e-mail para [email protected] com seu Merchant ID e o ID do pedido ou da requisição.