Criar um cartão
Cadastre um cartão de crédito ou débito de um cliente e receba de volta um token seguro (card…) que você usa em cobranças futuras sem nunca mais tocar nos dados sensíveis do cartão. Use este endpoint
Cadastre um cartão de crédito ou débito de um cliente e receba de volta um token seguro (card_…) que você usa em cobranças futuras sem nunca mais tocar nos dados sensíveis do cartão. Use este endpoint quando o titular autoriza salvar o cartão — por exemplo, no checkout, no onboarding do app ou para preparar uma assinatura recorrente.
POST /v1/cards
Como funciona
Quando você envia o número do cartão (PAN), a validade, o CVV e o nome do titular, a Selectwin faz três coisas em uma única chamada síncrona:
- Valida os dados — confere o número pelo algoritmo de Luhn, identifica a bandeira (
brand) e verifica se a validade não está vencida. - Tokeniza — armazena o cartão de forma segura e gera um identificador opaco (
card_…). O número completo (PAN) e o CVV não ficam acessíveis depois disso: a resposta só devolve o BIN (firstDigits, 6 dígitos) e os 4 últimos dígitos (lastDigits). - Associa o token ao cliente informado em
customerId.
Tokenizar = trocar os dados crus do cartão por uma referência segura (o token). Você guarda o token, não o cartão — o que reduz drasticamente o seu escopo de conformidade PCI DSS.
A partir daí, o token é o que você passa para os outros recursos (transações, assinaturas). O cartão criado já nasce associado a um cliente; ele não existe "solto".
Manuseio de dados de cartão (PCI DSS)
Enviar PAN e CVV diretamente para esta API coloca o seu servidor no escopo PCI DSS. Sempre que possível, capture os dados do cartão por um fluxo que não passe pelo seu backend (campos hospedados / SDK de frontend) e trafegue apenas o token. Trafegue tudo exclusivamente sobre HTTPS/TLS e nunca registre PAN, CVV ou validade em logs.
Quando usar
- Salvar um cartão apresentado pelo cliente para reuso (one-click, recorrência, cobrança futura).
- Substituir um cartão vencido por um novo (crie o novo token; remova o antigo com Excluir Cartão).
Quando não usar:
- Para cobrar agora sem salvar o cartão, use o recurso de transações diretamente.
- O cartão é imutável: não há como editar número, validade ou bandeira de um token já criado. Para "atualizar", crie um novo cartão e exclua o anterior.
Requisição
Headers
| Cabeçalho | Obrigatório | Descrição |
|---|---|---|
SelectKey | Sim | Sua chave de API. Produção: sl_live_…; sandbox: sl_test_…. Veja Autenticação. |
Content-Type: application/json | Sim | O corpo é JSON. |
X-Idempotency-Key | Recomendado | Evita criar o mesmo cartão duas vezes se a requisição for repetida (timeout, retry). Veja Idempotência. |
Nunca use Authorization: Bearer/Basic — a autenticação é sempre pelo header SelectKey.
Corpo
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
customerId | string | Sim | ID do cliente dono do cartão (cus_…). Obrigatório ao usar /v1/cards de forma autônoma. |
holderName | string | Sim | Nome do titular impresso no cartão. |
numbering | string | Sim | Número do cartão (PAN). Validado por Luhn. |
expirationMonth | number | Sim | Mês de validade, de 1 a 12 (número, não string). |
expirationYear | integer | Sim | Ano de validade (2 ou 4 dígitos), ex.: 2028. |
securityCode | string | Sim | CVV/CVC, 3 ou 4 dígitos (^\d{3,4}$). |
primary | boolean | Não | Define este como cartão principal do cliente. |
Nomes de entrada vs. de saída
No corpo da requisição, a flag é primary (não isPrimary). Já na resposta os campos booleanos aparecem sem o prefixo is (primary, active, valid, …). Em respostas de lista, os mesmos campos voltam com prefixo (isPrimary, isActive, …) — veja Listar Cartões.
Exemplo de requisição
curl -X POST https://api.selectwin.io/v1/cards \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: 8f1c0c2e-2b4a-4f3e-9a6c-1d2e3f4a5b6c" \
-d '{
"customerId": "cus_01hqzvabc",
"holderName": "JOAO SILVA",
"numbering": "4111111111111111",
"expirationMonth": 12,
"expirationYear": 2028,
"securityCode": "123",
"primary": true
}'Resposta
201 Created. O corpo é o objeto completo do cartão tokenizado (a mesma forma retornada por Ler Cartão), já com bandeira detectada, dígitos mascarados e os links HATEOAS para as próximas ações.
{
"id": "card_01hqzvabc",
"holderName": "JOÃO SILVA",
"brand": "visa",
"firstDigits": "411111",
"lastDigits": "1111",
"expirationMonth": "12",
"expirationYear": "2025",
"primary": true,
"active": true,
"valid": true,
"verified": true,
"associated": true,
"metadata": {},
"createdAt": "2026-04-12T17:56:33.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"merchant": {
"name": "Seller Name",
"merchantId": "bus_1234567890",
"isSubAccount": false
},
"_links": {
"self": { "href": "https://api.selectwin.io/v1/cards/card_01hqzvabc", "method": "GET", "description": "Read a card." },
"create": { "href": "https://api.selectwin.io/v1/cards", "method": "POST", "description": "Create a new card." },
"update": { "href": "https://api.selectwin.io/v1/cards/card_01hqzvabc", "method": "PUT", "description": "Update the card." },
"delete": { "href": "https://api.selectwin.io/v1/cards/card_01hqzvabc", "method": "DELETE", "description": "Delete the card." },
"list": { "href": "https://api.selectwin.io/v1/cards", "method": "GET", "description": "List all cards." }
}
}Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Token/identificador opaco do cartão (card_…). Guarde este valor. |
holderName | string | Nome do titular (pode vir normalizado em maiúsculas). |
brand | string | Bandeira detectada (ex.: visa, mastercard). |
firstDigits | string | BIN — os 6 primeiros dígitos. |
lastDigits | string | Os 4 últimos dígitos. |
expirationMonth / expirationYear | string | Validade (na resposta vêm como string). |
primary | boolean | Se é o cartão principal do cliente. |
active | boolean | Cartão ativo. |
valid | boolean | Passou nas validações. |
verified | boolean | Cartão verificado. |
associated | boolean | Vinculado a um cliente. |
metadata | object | Metadados livres (objeto vazio se não houver). |
createdAt / updatedAt | string (date-time) | Timestamps em ISO 8601 UTC. |
merchant | object | Conta/sub-conta dona do cartão (name, merchantId, isSubAccount). |
_links | object | Links HATEOAS para as próximas ações: self, create, update, delete, list. |
O PAN não volta
Por segurança, o número completo e o CVV nunca aparecem na resposta. Para identificar o cartão na sua interface, use brand + lastDigits (ex.: "Visa •••• 1111"). Trate id como opaco: armazene a string inteira, sem fazer parsing.
Erros
A API responde com o envelope de erro padrão. Trate sempre pelo error.code, não pela message. Códigos específicos de Cards e os transversais relevantes neste endpoint:
error.code | HTTP | Quando ocorre |
|---|---|---|
invalidParameters | 400 | Validação genérica do corpo; veja error.params para o campo culpado. |
cardIdIsInvalid | 400 | Um ID de cartão informado tem formato inválido. |
cardExpired | 400 | A validade (expirationMonth/expirationYear) já passou. |
invalidCardData | 422 | Dados do cartão inválidos (ex.: número reprovado no Luhn, CVV malformado). |
cardBrandNotSupported | 422 | A bandeira detectada não é aceita. |
cardCreateNotProcessable | 422 | O cadastro não pôde ser processado (regra de negócio). |
cardAndCustomerOfCompanyNotSame | 422 | O customerId não pertence à mesma conta/empresa do cartão. |
limitReached | 403 | Limite de cartões da conta atingido. |
unauthorized | 401 | SelectKey ausente, inválida ou revogada. |
forbidden | 403 | Autenticado, mas sem permissão para a operação. |
tooManyRequests | 429 | Limite de requisições excedido — respeite error.retryAfterMinutes. |
serverError | 500 | Erro interno — repita com backoff; se persistir, contate o suporte. |
Exemplo de falha de validação (422):
{
"error": {
"code": "invalidCardData",
"statusCode": 422,
"category": "validation",
"message": "Invalid card data.",
"params": [
{ "numbering": "Invalid card number. Please check if the number is correct." }
]
}
}Consulte o Catálogo de Códigos de Erro para a lista completa.
Boas práticas
- Valide no cliente antes de enviar. Cheque Luhn, mês
1..12, ano não vencido e CVV de 3–4 dígitos no frontend — isso evita ida e volta e reduzinvalidCardData/cardExpired. - Sempre envie
X-Idempotency-Key. Um retry após timeout não deve gerar dois tokens do mesmo cartão. Veja Idempotência. - Garanta o casamento cliente×cartão. Use um
customerIdque pertença à sua conta para não cair emcardAndCustomerOfCompanyNotSame. - Nunca persista PAN/CVV. Guarde apenas o
id(token) e, para exibição,brand+lastDigits. Não registre dados sensíveis em logs. - Exiba o cartão mascarado. "Visa •••• 1111" a partir de
brand/lastDigits— o número completo não retorna. - Confirme a autorização do titular. Tenha consentimento explícito antes de salvar um cartão para cobranças futuras.
- Trate
limitReached(403) com mensagem útil. Peça ao cliente para remover um cartão antigo via Excluir Cartão antes de adicionar outro.
Veja também
- Visão geral de Cartões — modelo do objeto, ciclo de vida e todas as operações.
- Ler Cartão — consultar um cartão tokenizado pelo
id. - Listar Cartões — listar cartões com paginação e filtros.
- Excluir Cartão — remover um token da conta.
- Convenções da API · Autenticação · Idempotência · Tratamento de Erros
How is this guide?