Criar VCN
Use o Sandbox para preparar a integração e validar a autenticação e o contrato.
Emite um cartão virtual (VCN) para uma reserva de hospedagem (HOTEL), uma reserva aérea (AERIAL) ou um uso definido por você (CUSTOM, ex.: um cartão por fornecedor). PAN, CVV e validade voltam na hora.
Antes de chamar
- Envie o identificador do seu
type, que é também a chave de idempotência:hotelBooking.reservationId,flightBooking.recordLocatoroureference, noCUSTOM. - Nos tipos de reserva, informe o custo em
amount; noCUSTOM, informe o teto emlimit. - As datas são dias de calendário no horário de Brasília, e o
endDateé inclusivo. - Guarde o
vcnIddo201com a sua chave: ele endereça Consultar VCN, Atualizar VCN, Revelar dados do VCN e Cancelar VCN, e nenhum erro o devolve.
Segurança
O 201 traz PAN e CVV em claro e vem com Cache-Control: no-store e Pragma: no-cache. Não logue nem cacheie o bloco card.
Erros
400 bad-request-exception— corpo fora do formato;errors[]aponta cada campo. Inclui o identificador de outro tipo (ex.:referencefora doCUSTOM) eendDateigual ou anterior aostartDatequando as duas datas vêm no pedido.400 invalid-vcn-request— as datas ou o valor não formam uma janela ou um teto válidos; o motivo vem nomessage. Veja Janela de uso.400 active-funding-card-not-found— otypenão está habilitado para a sua credencial. Acione a Conta Simples.400 bad-request-exception—X-Partner-Idausente ou fora do formato (fieldheaders.x-partner-id). Veja Identificação da plataforma.403 caller-not-authorized— o partner doX-Partner-Idnão está vinculado à sua credencial (details.reasonPARTNER_NOT_BOUND), ou falta à credencial o escopo da rota (details.requiredScope). Veja Identificação da plataforma.409 vcn-already-issued— já existe uma VCN viva para esta chave. NoCUSTOM, recarregue-a em Atualizar VCN. Veja Idempotência e reemissão.500 internal-exception— erro interno, inclusive falha do provedor ou tempo esgotado. Não repita automaticamente: o cartão pode ter sido emitido. Acione o suporte com o horário, orequestIde a chave.
Regras
Janela de uso · Idempotência e reemissão · Teto e recarga · Corpo da requisição
curl -X POST "https://api-sandbox.contasimples.com/credit-cards/v1/vcns" \
-H "Content-Type: application/json" \
-H "X-Partner-Id: ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XY" \
-H "Signature-Input: example_string" \
-H "Signature: example_string" \
-H "Content-Digest: example_string" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"type": "HOTEL",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"customFields": [
{
"name": "costCenter",
"value": "CC-042",
"dataType": "string"
}
],
"requestor": "agente@exemplo.test"
}'
import requests
import json
url = "https://api-sandbox.contasimples.com/credit-cards/v1/vcns"
headers = {
"Content-Type": "application/json",
"X-Partner-Id": "ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XY",
"Signature-Input": "example_string",
"Signature": "example_string",
"Content-Digest": "example_string",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"type": "HOTEL",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"customFields": [
{
"name": "costCenter",
"value": "CC-042",
"dataType": "string"
}
],
"requestor": "agente@exemplo.test"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://api-sandbox.contasimples.com/credit-cards/v1/vcns", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Partner-Id": "ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XY",
"Signature-Input": "example_string",
"Signature": "example_string",
"Content-Digest": "example_string",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
"type": "HOTEL",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"customFields": [
{
"name": "costCenter",
"value": "CC-042",
"dataType": "string"
}
],
"requestor": "agente@exemplo.test"
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"type": "HOTEL",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"customFields": [
{
"name": "costCenter",
"value": "CC-042",
"dataType": "string"
}
],
"requestor": "agente@exemplo.test"
}`)
req, err := http.NewRequest("POST", "https://api-sandbox.contasimples.com/credit-cards/v1/vcns", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Partner-Id", "ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XY")
req.Header.Set("Signature-Input", "example_string")
req.Header.Set("Signature", "example_string")
req.Header.Set("Content-Digest", "example_string")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://api-sandbox.contasimples.com/credit-cards/v1/vcns')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-Partner-Id'] = 'ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XY'
request['Signature-Input'] = 'example_string'
request['Signature'] = 'example_string'
request['Content-Digest'] = 'example_string'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request.body = '{
"type": "HOTEL",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"customFields": [
{
"name": "costCenter",
"value": "CC-042",
"dataType": "string"
}
],
"requestor": "agente@exemplo.test"
}'
response = http.request(request)
puts response.body
{
"vcnId": "01JQ8ZK7X4M8N2P5R6T7V8W9XY",
"type": "HOTEL",
"reference": "ACME-RES-998877",
"hotelBooking": {
"reservationId": "ACME-RES-998877",
"checkIn": "2027-03-15",
"checkOut": "2027-03-18",
"propertyId": "PROP-000123",
"hotelName": "Hotel Exemplo",
"guests": [
{
"name": "Ana",
"surname": "Ribeiro"
},
{
"name": "Bruno",
"surname": "Alves"
}
],
"allowExtraCharges": true,
"extraChargesMargin": 150
},
"status": "ACTIVE",
"startDate": "2027-03-01",
"endDate": "2027-04-07",
"amount": {
"rate": 1250,
"taxes": 187.5,
"fees": 35,
"currency": "BRL"
},
"limit": {
"value": 1622.5,
"currency": "BRL"
},
"maxPurchaseQuantity": 3,
"spendLimitPeriod": "TOTAL",
"card": {
"pan": "4111111111111111",
"cvv": "123",
"expirationDate": "06/2031"
}
}
{
"vcnId": "01JQ8ZM3T6R9V2X5Y7Z8A9B0CD",
"type": "AERIAL",
"reference": "ABC123",
"flightBooking": {
"recordLocator": "ABC123",
"passengerName": "Carla",
"passengerSurname": "Nogueira",
"issuingCarrier": "ZZ",
"issueDate": "2027-03-01",
"numOfLegs": 2,
"legsDescription": "GRU-BSB-GRU",
"domesticIndicator": "DOMESTIC",
"finalDestinationCity": "BSB",
"tripLegs": [
{
"legNumber": 1,
"origin": "GRU",
"destination": "BSB",
"departureDate": "2027-03-10"
},
{
"legNumber": 2,
"origin": "BSB",
"destination": "GRU",
"departureDate": "2027-03-14"
}
]
},
"status": "ACTIVE",
"startDate": "2027-03-01",
"endDate": "2027-03-02",
"amount": {
"rate": 890,
"taxes": 112.4,
"fees": 0,
"currency": "BRL"
},
"limit": {
"value": 1002.4,
"currency": "BRL"
},
"maxPurchaseQuantity": 2,
"spendLimitPeriod": "TOTAL",
"card": {
"pan": "4111111111111111",
"cvv": "456",
"expirationDate": "06/2031"
}
}
{
"vcnId": "01JQ8ZP4C7D9F1G3H5J7K9J2MN",
"type": "CUSTOM",
"reference": "SUP-000123",
"status": "ACTIVE",
"startDate": "2027-03-01",
"endDate": "2027-05-07",
"limit": {
"value": 0.01,
"currency": "BRL"
},
"maxPurchaseQuantity": 10000,
"spendLimitPeriod": "TOTAL",
"card": {
"pan": "4111111111111111",
"cvv": "789",
"expirationDate": "06/2031"
}
}
{
"code": "bad-request-exception",
"message": "Event failed validation",
"errors": [
{
"field": "body.hotelBooking",
"message": "hotelBooking is required for a lodging booking"
}
]
}
{
"code": "bad-request-exception",
"message": "Event failed validation",
"errors": [
{
"field": "body.hotelBooking",
"message": "hotelBooking is only accepted for a lodging booking"
}
]
}
{
"code": "bad-request-exception",
"message": "Event failed validation",
"errors": [
{
"field": "body.amount.rate",
"message": "must be a non-negative amount with at most 2 decimal places"
}
]
}
{
"code": "active-funding-card-not-found",
"message": "There is no active funding card. Check the request or provision the company for this combination, then retry."
}
{
"code": "invalid-vcn-request",
"message": "Unable to issue a VCN for this request: validity window must end after it starts"
}
{
"code": "bad-request-exception",
"message": "Event failed validation",
"errors": [
{
"field": "body.endDate",
"message": "endDate must be later than startDate"
}
]
}
{
"code": "invalid-vcn-request",
"message": "Unable to issue a VCN for this request: end date must not exceed the funding card expiration"
}
{
"code": "bad-request-exception",
"message": "Event failed validation",
"errors": [
{
"field": "headers.x-partner-id",
"message": "x-partner-id must be a valid partner identifier"
}
]
}
{
"code": "unauthorized",
"message": "Authentication failed. Check the API token and the request signature",
"requestId": "123e4567-e89b-12d3-a456-426614174000"
}
{
"code": "unauthorized",
"message": "Authentication failed. Check the API token and the request signature",
"details": {
"reason": "SIGNATURE_REQUIRED"
},
"requestId": "123e4567-e89b-12d3-a456-426614174000"
}
{
"code": "unauthorized",
"message": "Authentication failed. Check the API token and the request signature",
"details": {
"reason": "INVALID_SIGNATURE"
},
"requestId": "123e4567-e89b-12d3-a456-426614174000"
}
{
"code": "caller-not-authorized",
"message": "The request is not allowed for the current credentials",
"details": {
"requiredScope": "createVcn"
},
"requestId": "123e4567-e89b-12d3-a456-426614174000"
}
{
"code": "caller-not-authorized",
"message": "The request is not allowed for the current credentials",
"details": {
"reason": "PARTNER_NOT_BOUND"
},
"requestId": "123e4567-e89b-12d3-a456-426614174000"
}
{
"code": "vcn-already-issued",
"message": "An active VCN already exists for this key."
}
{
"code": "internal-exception",
"message": "An unexpected error occurred on the server"
}
/credit-cards/v1/vcns
Target server for requests. Edit to use your own host.
Token Bearer obtido via OAuth 2.0 Client Credentials. Formato: Bearer TOKEN
Bearer TOKENThe media type of the request body
Identificador da plataforma integradora (partner) pela qual a chamada é feita: ptn_ seguido de um ULID de 26 caracteres. É gerado pela Conta Simples e entregue a você no onboarding. Veja Identificação da plataforma.
O que foi assinado e os parâmetros da assinatura, no formato da RFC 9421. Uma credencial com chave pública precisa enviar este header em todas as chamadas, inclusive as de leitura, ou a requisição é recusada com 401. A assinatura cobre os componentes @method, @path e @query, e também content-digest quando houver corpo. created e alg são obrigatórios, e o created vale por 300 segundos. O formato completo, com exemplos, está em Assinatura de Requisições.
A assinatura da base definida pela RFC 9421, em base64, entre : e com o mesmo rótulo usado no Signature-Input, por exemplo sig=:SGVsbG8gd29ybGQ=:. Vai sempre junto com o Signature-Input.
Hash do corpo da requisição no formato da RFC 9530, com sha-256 ou sha-512, por exemplo sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:. É obrigatório quando a requisição tem corpo e a credencial tem chave pública, e nesse caso o Signature-Input precisa incluir o componente content-digest.
Vínculo do cartão. Define o identificador obrigatório (HOTEL → hotelBooking, AERIAL → flightBooking, CUSTOM → reference) e como o teto nasce: derivado do amount nos tipos de reserva, informado em limit no CUSTOM.
Custo da reserva, decimal com até 2 casas (ex.: 1250.00), em BRL. Obrigatório em HOTEL e AERIAL, proibido no CUSTOM. A soma rate + taxes + fees precisa ser maior que zero e define o teto.
Teto de gasto do cartão. Obrigatório em CUSTOM; proibido em HOTEL/AERIAL, em que o teto é derivado do amount.
Início da janela de uso, YYYY-MM-DD, em dia de Brasília. Omitido, vale o dia da emissão. Não pode ser anterior a hoje. Veja Janela de uso.
Fim da janela de uso, YYYY-MM-DD, inclusivo, em dia de Brasília. Omitido, vale o padrão do tipo: checkOut + 20 dias no HOTEL, emissão + 1 dia no AERIAL, emissão + 60 dias no CUSTOM. Máximo de 365 dias do dia da emissão. Veja Limites das datas.
Número máximo de autorizações no cartão, até 100000. Sobrescreve o default do tipo (AERIAL 2 · HOTEL 3 · CUSTOM 10000).
Período do teto: TOTAL (padrão, a janela inteira), MONTHLY (renova a cada mês) ou DAILY (renova a cada dia). Aceito nos três tipos. Veja Período do teto.
Dados da hospedagem. Obrigatório quando type for HOTEL e proibido nos outros tipos.
Dados da reserva aérea. Obrigatório quando type for AERIAL e proibido nos outros tipos.
Identificador do que o cartão CUSTOM paga, definido por você (ex.: o id do fornecedor), em texto de 1 a 255 caracteres; é a chave de idempotência, então não use dados pessoais. Só o CUSTOM envia este campo: em HOTEL e AERIAL, a chave vem de hotelBooking.reservationId ou flightBooking.recordLocator e volta em reference na resposta, e enviar reference dá 400 bad-request-exception com field body.reference. Veja Idempotência e reemissão.
Campos de governança (ex.: centro de custo), de 1 a 50 itens. Aparecem nos dados da transação na rede do cartão, para conciliação: nunca use dados pessoais (CPF, nome de passageiro, e-mail, telefone).
Quem pede a emissão, a atualização ou o cancelamento, para auditoria. Envie o e-mail de um usuário ou, numa chamada automatizada, um identificador do seu sistema. Texto livre de 1 a 100 caracteres.
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token. Token Bearer obtido via OAuth 2.0 Client Credentials. Formato: Bearer TOKEN
Headers
Identificador da plataforma integradora (partner) pela qual a chamada é feita: ptn_ seguido de um ULID de 26 caracteres. É gerado pela Conta Simples e entregue a você no onboarding. Veja Identificação da plataforma.
ptn_01JQ8ZK7X4M8N2P5R6T7V8W9XYO que foi assinado e os parâmetros da assinatura, no formato da RFC 9421. Uma credencial com chave pública precisa enviar este header em todas as chamadas, inclusive as de leitura, ou a requisição é recusada com 401. A assinatura cobre os componentes @method, @path e @query, e também content-digest quando houver corpo. created e alg são obrigatórios, e o created vale por 300 segundos. O formato completo, com exemplos, está em Assinatura de Requisições.
A assinatura da base definida pela RFC 9421, em base64, entre : e com o mesmo rótulo usado no Signature-Input, por exemplo sig=:SGVsbG8gd29ybGQ=:. Vai sempre junto com o Signature-Input.
Hash do corpo da requisição no formato da RFC 9530, com sha-256 ou sha-512, por exemplo sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:. É obrigatório quando a requisição tem corpo e a credencial tem chave pública, e nesse caso o Signature-Input precisa incluir o componente content-digest.
Body
Vínculo do cartão. Define o identificador obrigatório (HOTEL → hotelBooking, AERIAL → flightBooking, CUSTOM → reference) e como o teto nasce: derivado do amount nos tipos de reserva, informado em limit no CUSTOM.
HOTELAERIALCUSTOMCusto da reserva, decimal com até 2 casas (ex.: 1250.00), em BRL. Obrigatório em HOTEL e AERIAL, proibido no CUSTOM. A soma rate + taxes + fees precisa ser maior que zero e define o teto.
Teto de gasto do cartão. Obrigatório em CUSTOM; proibido em HOTEL/AERIAL, em que o teto é derivado do amount.
Início da janela de uso, YYYY-MM-DD, em dia de Brasília. Omitido, vale o dia da emissão. Não pode ser anterior a hoje. Veja Janela de uso.
2027-03-10Fim da janela de uso, YYYY-MM-DD, inclusivo, em dia de Brasília. Omitido, vale o padrão do tipo: checkOut + 20 dias no HOTEL, emissão + 1 dia no AERIAL, emissão + 60 dias no CUSTOM. Máximo de 365 dias do dia da emissão. Veja Limites das datas.
2027-05-07Número máximo de autorizações no cartão, até 100000. Sobrescreve o default do tipo (AERIAL 2 · HOTEL 3 · CUSTOM 10000).
3Período do teto: TOTAL (padrão, a janela inteira), MONTHLY (renova a cada mês) ou DAILY (renova a cada dia). Aceito nos três tipos. Veja Período do teto.
TOTALMONTHLYDAILYDados da hospedagem. Obrigatório quando type for HOTEL e proibido nos outros tipos.
Dados da reserva aérea. Obrigatório quando type for AERIAL e proibido nos outros tipos.
Identificador do que o cartão CUSTOM paga, definido por você (ex.: o id do fornecedor), em texto de 1 a 255 caracteres; é a chave de idempotência, então não use dados pessoais. Só o CUSTOM envia este campo: em HOTEL e AERIAL, a chave vem de hotelBooking.reservationId ou flightBooking.recordLocator e volta em reference na resposta, e enviar reference dá 400 bad-request-exception com field body.reference. Veja Idempotência e reemissão.
SUP-000123Campos de governança (ex.: centro de custo), de 1 a 50 itens. Aparecem nos dados da transação na rede do cartão, para conciliação: nunca use dados pessoais (CPF, nome de passageiro, e-mail, telefone).
Quem pede a emissão, a atualização ou o cancelamento, para auditoria. Envie o e-mail de um usuário ou, numa chamada automatizada, um identificador do seu sistema. Texto livre de 1 a 100 caracteres.
agente@exemplo.test