SelectwinDOCS
Transações

Criar uma transação

Crie uma cobrança enviando o meio de pagamento (cartão, Pix, boleto, NuPay ou débito), o valor e os dados do cliente para POST /v1/transactions. A Selectwin processa o pagamento junto ao adquirente e

Crie uma cobrança enviando o meio de pagamento (cartão, Pix, boleto, NuPay ou débito), o valor e os dados do cliente para POST /v1/transactions. A Selectwin processa o pagamento junto ao adquirente e devolve a transação criada com seu id, status e os artefatos necessários para cobrar (QR Code Pix, linha digitável do boleto ou o resultado da autorização do cartão).

POST /v1/transactions

Como funciona

Uma transação é o registro de uma tentativa de cobrança. Quando você envia a requisição, a API:

  1. Valida o corpo (campos obrigatórios, formatos, faixas de valor).
  2. Resolve o cliente: usa customer.id se informado, ou cria/atualiza um cliente a partir dos dados completos.
  3. Calcula o valor: a partir de amount (valor total em centavos) ou da soma dos items (ver Definição do valor).
  4. Aciona o meio de pagamento correspondente ao payment.method e registra o resultado.
  5. Responde 201 Created com a transação e seu status inicial.

O status inicial depende do método e é assíncrono na maioria dos casos — você não deve assumir que a transação já está paga ao receber a resposta:

  • Pix e boleto nascem em pending: a resposta traz o QR Code / linha digitável, e a transação só vira approved quando o cliente paga.
  • Cartão com capture: true (padrão) tenta autorizar e capturar de uma vez, indo direto para approved (ou refused).
  • Cartão com capture: false apenas autoriza (reserva o limite), ficando pre-authorized até você capturar ou o prazo do adquirente expirar.

Não faça polling

Nunca fique consultando GET /v1/transactions/{id} em loop para saber se a transação foi paga. Configure webhooks e reaja ao evento transaction.approved. Veja Proibição de polling.

Idempotência

Criar transação é uma operação de escrita: uma falha de rede pode deixar você sem saber se a cobrança aconteceu. Envie o header X-Idempotency-Key (um UUID v4 novo por tentativa de cobrança) para que, se você repetir a mesma requisição, a API retorne a transação original em vez de cobrar o cliente duas vezes. Reutilize a mesma chave apenas ao reenviar a mesma operação. Detalhes em Chave de idempotência.

Quando usar

Use POST /v1/transactions sempre que precisar cobrar um pagamento avulso (checkout, venda única, fatura). Para cobranças recorrentes com ciclo gerenciado pela plataforma, prefira as Assinaturas (Subscriptions). Para apenas autorizar agora e capturar depois (ex.: confirmar estoque antes de cobrar), use payment.capture: false e depois Capturar.

Requisição

Headers

HeaderObrigatórioDescrição
SelectKeySimSua chave de API. Produção: sl_live_…; sandbox: sl_test_…. Nunca use Authorization: Bearer/Basic. Veja Autenticação.
Content-TypeSimapplication/json.
X-Idempotency-KeyRecomendadoUUID v4 único por cobrança, para evitar duplicidade. Veja Idempotência.

Definição do valor {#definicao-do-valor}

Há duas formas de definir o total da transação — escolha uma:

FormaComoQuando
amountInteiro em centavos com o total. Obrigatório quando items é omitido.Cobrança simples sem detalhar produtos.
items[]Lista de linhas; o total é a soma de unitPrice × quantity. Obrigatório (≥1 linha) quando amount é omitido.Carrinho com produtos discriminados.

Faixa de amount: mínimo 500 (R$ 5,00) e máximo 20000000 (R$ 200.000,00).

Corpo — campos de nível raiz

CampoTipoObrigatórioDescrição
paymentobjectSimMeio de pagamento (ver tabelas abaixo).
customerobjectSimCliente: por id ou com dados completos.
amountinteger (500..20000000)CondicionalTotal em centavos (BRL). Obrigatório se items não for enviado.
itemsarrayCondicionalLinhas do carrinho. Obrigatório (≥1) se amount não for enviado.
descriptionstringNãoDescrição legível da transação (não confundir com a descrição de cada item).
externalReferencestringNãoID do pedido no seu sistema, para conciliação.
metadataobjectNãoPares chave/valor livres (máx. 40 chaves). Veja Metadata.
tagsarray (string)NãoEtiquetas para filtros e relatórios (máx. 40).
billingobjectNãoEndereço de cobrança (billing.address, com id para reutilizar um já salvo).
shippingobjectNãoDados de entrega (shipping.address, frete, rastreio). Veja Shipping.
callbackobjectNãocallback.webhookUrl (URI) para callbacks de status desta transação.
geolocationobjectNãoSinais antifraude do cliente. Recomendado para cartão (ver abaixo).
discountobjectNãoDesconto aplicado à transação (ver Desconto).
splitsarrayNãoRegras de repasse (split) entre recebedores.

Corpo — payment (obrigatório em todo método)

CampoTipoObrigatórioDescrição
payment.methodstringSimUm de credit, billet, pix, nupay, debit.
payment.currencystringSimISO 4217, atualmente BRL.
payment.capturebooleanNãotrue (padrão) captura na hora; false apenas autoriza (cartão).
payment.installmentsnumber (1..12)CartãoNúmero de parcelas, de 1 a 12.

Cartão — payment.card

Informe id (cartão tokenizado, recomendado) ou os dados completos. Nunca envie dados de cartão em claro a partir do seu servidor sem cumprir o escopo PCI — veja Segurança PCI.

CampoTipoObrigatórioDescrição
payment.card.idstring (prefixo_valor)AlternativaID público de um cartão já salvo. Quando presente, dispensa os demais campos.
payment.card.holderNamestringSe sem idNome impresso no cartão.
payment.card.numberingstringSe sem idNúmero do cartão (validado por Luhn).
payment.card.expirationMonthnumber (1..12)Se sem idMês de expiração.
payment.card.expirationYearintegerSe sem idAno de expiração (2 ou 4 dígitos).
payment.card.securityCodestring (^\d{3,4}$)Se sem idCVV/CVC (3 ou 4 dígitos).

Pix — payment.pix

CampoTipoObrigatórioDescrição
payment.pix.expiresInMinutesinteger (15..525600)NãoValidade do QR Code em minutos (15 min a 1 ano).

Boleto — payment.billet

CampoTipoObrigatórioDescrição
payment.billet.instructionsstringNãoInstruções impressas no boleto.
payment.billet.expirationDatestring (YYYY-MM-DD)NãoData de vencimento.
payment.billet.paymentLimitDatestring (date-time)NãoData-hora limite para pagamento.
payment.billet.expiresInDaysnumber (até 365)NãoDias até expirar (alternativa às datas fixas).

Corpo — customer

Informe customer.id (cliente já cadastrado) ou os dados completos. Com dados completos, a API cria/atualiza o cliente automaticamente.

CampoTipoObrigatórioDescrição
customer.idstring (cus_…)AlternativaID de cliente existente; dispensa os campos abaixo.
customer.firstNamestringSe sem idPrimeiro nome.
customer.lastNamestringSe sem idSobrenome.
customer.emailstring (email)Se sem idE-mail.
customer.document.typestringSe sem idcpf, cnpj ou passport.
customer.document.numberstring (^\d+$)Se sem idNúmero do documento (só dígitos para cpf/cnpj).
customer.telephone.countryCodestringSe sem idCódigo do país (ex.: 55).
customer.telephone.areaCodestringSe sem idDDD.
customer.telephone.numberstringSe sem idNúmero do telefone.
customer.birthdatestring (YYYY-MM-DD)NãoData de nascimento.
customer.genderstringNãomale, female ou other.
customer.externalReferencestringNãoReferência do cliente no seu CRM.
customer.additionalEmailsarrayNãoE-mails adicionais (máx. 20).
customer.metadataobjectNãoMetadados do cliente (máx. 20 chaves).

Para boleto, o endereço do cliente costuma ser exigido pelo emissor — envie billing.address (ou um customer com endereço).

Corpo — discount {#desconto}

Desconto único aplicado à transação. Informe id (desconto já cadastrado na plataforma) ou os campos inline type + value.

CampoTipoObrigatórioDescrição
discount.idstring (dis_…)AlternativaID de um desconto da plataforma a reutilizar.
discount.typestringInlineflat (valor fixo em centavos) ou percentage (percentual).
discount.valueintegerInlineCentavos quando flat; percentual quando percentage.

Importante

O type aceita apenas flat ou percentage — não existe percent. Para flat, value é em centavos (500 = R$ 5,00).

Corpo — geolocation (recomendado para cartão)

Esses campos alimentam a análise antifraude e ajudam a aprovar pagamentos legítimos.

CampoTipoObrigatórioDescrição
geolocation.ipAddressstring (IPv4)Sim (se enviar o objeto)IP do cliente.
geolocation.latitudenumber (-90..90)NãoLatitude.
geolocation.longitudenumber (-180..180)NãoLongitude.
geolocation.userAgentstringNãoUser-Agent do navegador do cliente.
geolocation.acceptLanguagestringNãoHeader Accept-Language (sinal de localidade).
geolocation.deviceFingerprintstringNãoHash estável de dispositivo (fornecido pelo SDK do cliente).

Exemplos de requisição

Pix (com cliente novo)

curl -X POST https://api.selectwin.io/v1/transactions \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ff" \
  -d '{
    "amount": 5000,
    "payment": { "method": "pix", "currency": "BRL", "pix": { "expiresInMinutes": 30 } },
    "customer": {
      "firstName": "João",
      "lastName": "Silva",
      "email": "[email protected]",
      "document": { "type": "cpf", "number": "12345678901" },
      "telephone": { "countryCode": "55", "areaCode": "11", "number": "999999999" }
    },
    "externalReference": "ORDER-1001"
  }'

Cartão tokenizado, capturando na hora, em 3x

{
  "amount": 10000,
  "payment": {
    "method": "credit",
    "currency": "BRL",
    "capture": true,
    "installments": 3,
    "card": { "id": "card_abc123" }
  },
  "customer": { "id": "cus_01hqzvabc" },
  "geolocation": { "ipAddress": "189.44.12.1" }
}

Cartão com dados completos (autorizar agora, capturar depois)

{
  "payment": {
    "method": "credit",
    "currency": "BRL",
    "capture": false,
    "installments": 1,
    "card": {
      "holderName": "JOAO SILVA",
      "numbering": "4111111111111111",
      "expirationMonth": 12,
      "expirationYear": 2028,
      "securityCode": "123"
    }
  },
  "items": [
    { "name": "Produto Premium", "unitPrice": 10000, "quantity": 1, "currency": "BRL" }
  ],
  "customer": { "id": "cus_01hqzvabc" }
}

Com capture: false, a transação volta pre-authorized. Capture depois com POST /v1/transactions/{id}/capture.

Boleto

{
  "amount": 18900,
  "payment": {
    "method": "billet",
    "currency": "BRL",
    "billet": { "instructions": "Pagar até o vencimento", "expiresInDays": 3 }
  },
  "customer": { "id": "cus_01hqzvabc" },
  "billing": {
    "address": {
      "street": "Rua Augusta", "number": "500", "district": "Consolação",
      "city": "São Paulo", "state": "SP", "country": "BR", "postcode": "01304-000"
    }
  }
}

Resposta

Sucesso retorna 201 Created com a transação completa. Os artefatos de pagamento variam conforme o método: Pix preenche payment.pixQrCodeEmv/pixQrCodeUrl; boleto preenche payment.billetUrl/billetBarcode; cartão preenche payment.cardBrand/cardLastDigits/installments. Campos não aplicáveis vêm null.

{
  "id": "tra_01hqzvabc",
  "customId": "PEDIDO-1042",
  "amount": 5000,
  "originalAmount": 5000,
  "status": "pending",
  "method": "pix",
  "currency": "BRL",
  "payment": {
    "provider": "selectwin",
    "refused": null,
    "reusable": false,
    "pixQrCodeEmv": "00020126580014br.gov.bcb.pix0136a1b2c3d4-...6304ABCD",
    "pixQrCodeUrl": "https://api.selectwin.io/pix/qr/tra_01hqzvabc.png",
    "cardRegistered": false,
    "installments": null,
    "expirationDate": "2026-04-12T18:26:33.000Z",
    "paidAt": null,
    "allowRenewPayment": true,
    "invoiceLink": "https://selectwin.io/invoices/tra_01hqzvabc"
  },
  "discount": null,
  "customer": { "id": "cus_01hqzvabc", "firstName": "João", "lastName": "Silva", "email": "[email protected]" },
  "items": [
    { "id": "item_01hqzvabc", "name": "Premium Plan", "unitPrice": 5000, "quantity": 1, "currency": "BRL" }
  ],
  "externalReference": "ORDER-1001",
  "shippable": false,
  "spplited": false,
  "timeline": [
    { "id": "tml_01hqzvabc", "message": "Transaction created", "type": "status", "createdAt": "2026-04-12T17:56:33.000Z" }
  ],
  "callback": { "webhookUrl": "https://api.example.com/webhooks/transaction", "active": true },
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "updatedAt": "2026-04-12T17:56:33.000Z",
  "createdAt": "2026-04-12T17:56:33.000Z",
  "_links": {
    "self": { "href": "https://api.selectwin.io/v1/transactions/tra_01hqzvabc", "method": "GET", "description": "Read a transaction." }
  }
}

Campos-chave da resposta

CampoDescrição
idID público da transação (tra_…). Trate como string opaca.
customIdIdentificador legível/curto da transação.
statusEstado inicial: pending, pre-authorized, approved ou refused (ver ciclo de vida).
methodMétodo efetivamente usado.
amountTotal cobrado, em centavos.
originalAmountTotal antes de descontos.
payment.pixQrCodeEmv / pixQrCodeUrlCopia-e-cola e imagem do QR para Pix.
payment.billetUrl / billetBarcodeLink e linha digitável do boleto.
payment.installmentsParcelas confirmadas (cartão).
payment.expirationDateExpiração do QR/boleto (ISO 8601 UTC).
timeline[]Histórico de eventos da transação.
_linksLinks HATEOAS para as próximas ações (ler, capturar, estornar, contestar).

Dica

Em vez de montar URLs à mão, siga os _links da resposta — eles já apontam o método e o caminho de cada próxima ação (capturar, estornar, ler).

Erros

Trate sempre pelo error.code, nunca pela message. Os específicos de Transactions e os transversais mais comuns ao criar:

error.codeHTTPQuando ocorre
invalidParameters400Campo ausente/ inválido. Veja error.params para o campo.
transactionCardInvalid400Dados do cartão inválidos (ex.: número falha no Luhn).
transactionCardIdInvalid / cardIdIsInvalid400payment.card.id mal formado.
cardExpired400Cartão expirado.
invalidCardData422Dados do cartão não processáveis.
cardBrandNotSupported422Bandeira não suportada.
missingFeeConfiguration422Falta configuração de taxas para processar a cobrança.
paymentProcessingFailed503Serviço de pagamento/adquirente indisponível — repita com backoff.
unauthorized401SelectKey ausente, inválida ou revogada.
forbidden403Autenticada, mas sem permissão / limite atingido.
tooManyRequests429Rate limit. Respeite error.retryAfterMinutes.
serverError500Erro interno — repita; se persistir, contate o suporte.

Atenção

Uma transação pode ser criada com sucesso (201) e ainda assim ser recusada pelo adquirente — nesse caso status vem refused e payment.refused indica o motivo. Recusa de pagamento não é um erro HTTP. Veja Recusas de pagamento.

Lista completa em Códigos de erro e o envelope em Tratamento de erros.

Boas práticas

  • Sempre envie X-Idempotency-Key (UUID v4 por cobrança) para nunca cobrar o cliente duas vezes em reenvios. Guarde a chave junto ao pedido.
  • Prefira cartão tokenizado (payment.card.id) a enviar dados em claro — reduz seu escopo PCI e melhora a aprovação. Veja Segurança PCI.
  • Use capture: false quando precisar confirmar algo (estoque, antifraude) antes de cobrar; capture só o que for vender.
  • Envie geolocation (com ipAddress) em pagamentos com cartão para melhorar a análise antifraude.
  • Reaja a webhooks, não a polling: confirme pagamento de Pix/boleto pelo evento transaction.approved. Veja Proibição de polling.
  • Grave o id (e use externalReference) para conciliar a transação com o pedido no seu sistema.
  • Defina expiração realista para Pix (expiresInMinutes) e boleto (expiresInDays) conforme seu fluxo de checkout.
  • Diferencie recusa de erro: 201 com status: refused é uma recusa do adquirente, não falha de integração — não retente cegamente.

Veja também

How is this guide?

On this page