mTLS Connection
How to establish the mTLS connection required by all VCN endpoints (issuance, reveal card data, and list transactions)
🚧 Coming soon — the mTLS connection is not yet available in Sandbox or Production. This page describes how it will work so you can prepare; we'll announce in the changelog when it's enabled.
Overview
The transactional VCN endpoints — issuance (POST /credit-cards/v1/vcns), reveal card data (GET /credit-cards/v1/vcns/{vcnId}/card) and list transactions (GET /credit-cards/v1/vcns/{vcnId}/transactions) — require mTLS (Mutual TLS) in addition to credential authentication.
These are two independent, complementary layers:
| Layer | What it is | Purpose |
|---|---|---|
| mTLS | Client certificate presented during the TLS handshake | Authenticates the channel (transport) — only connections with a trusted certificate reach the API |
| Credential | API Key + Secret → Bearer token (OAuth 2.0) | Identifies the client and authorizes the operation |
mTLS is required on all VCN endpoints — issuance, reveal card data, and list transactions — which live on the dedicated mTLS host. The rest of the public API (non-VCN) continues with the credential only. The key alone won't work on VCN endpoints without the certificate.
mTLS endpoint
Transactional calls use a dedicated host, separate from the default API host:
| Environment | mTLS host |
|---|---|
| Sandbox | mtls-sandbox.contasimples.com |
| Production | mtls.contasimples.com |
The hosts above are provisional — the final host and port are confirmed by Conta Simples during onboarding. Do not hardcode them until confirmed. The rest of the contract (paths, payloads) is identical to the published API reference.
Obtaining your client certificate
The client certificate is provisioned during onboarding, coordinated by the Conta Simples security team.
Request at onboarding
When you start the integration, Conta Simples kicks off the issuance of your client certificate.
Generation and signing
You generate the key pair and CSR in your own environment — the private key never leaves it. You send only the CSR; Conta Simples signs and registers your CA in the API trust store.
Installation
You install the client certificate and private key in the HTTP client that will make the calls (your platform's integration server).
Validation
Make a test call in Sandbox and confirm the mTLS handshake is accepted.
The certificate private key is a sensitive credential. Store it in a vault (AWS Secrets Manager, Vault) and never commit it to a repository or expose it in logs.
Making a call with mTLS
Present the client certificate and private key in the HTTP client, keeping the OAuth credential in the Authorization header. Get the {TOKEN} via OAuth (API key/secret) — see Authentication.
cURL
curl -X POST https://mtls-sandbox.contasimples.com/credit-cards/v1/vcns \
--cert ./client-cert.pem \
--key ./client-key.pem \
-H "Authorization: Bearer {TOKEN}" \
-H "Idempotency-Key: {bookingId}" \
-H "Content-Type: application/json" \
-d '{
"type": "AIR",
"bookingId": "ACME-AIR-554433",
"amount": { "rate": 100.0, "taxes": 1.0, "currency": "BRL" },
"flightBooking": { "departureDate": "2026-06-10", "passengers": 1 }
}'
Node.js
import https from "node:https";
import fs from "node:fs";
const agent = new https.Agent({
cert: fs.readFileSync("./client-cert.pem"),
key: fs.readFileSync("./client-key.pem"), // the private key stays only in your environment
});
const res = await fetch("https://mtls-sandbox.contasimples.com/credit-cards/v1/vcns", {
method: "POST",
agent,
headers: {
Authorization: `Bearer ${token}`,
"Idempotency-Key": bookingId,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
Python
import requests
res = requests.post(
"https://mtls-sandbox.contasimples.com/credit-cards/v1/vcns",
cert=("./client-cert.pem", "./client-key.pem"), # the private key stays only in your environment
headers={
"Authorization": f"Bearer {token}",
"Idempotency-Key": booking_id,
"Content-Type": "application/json",
},
json=payload,
)
Response (201)
{
"vcnId": "21624502",
"bookingId": "ACME-AIR-554433",
"type": "AIR",
"card": { "pan": "465635******6026", "cvv": "***", "expirationDate": "06/31" },
"status": "ACTIVE"
}
The real response returns the PAN and CVV in clear text (masked above) — treat them as sensitive data: keep them in memory only, never log them or expose them client-side.
If the client certificate is not presented (or is not trusted), the handshake fails before reaching the application — you get a TLS error, not a JSON body:
curl: (56) OpenSSL SSL_read: error:0A000412:SSL routines::sslv3 alert certificate required
Technical requirements
| Item | Requirement |
|---|---|
| TLS version | TLS 1.2 (minimum) |
| Ciphers | Support for modern ciphers (e.g. ECDHE-RSA-AES256-GCM-SHA384) |
| Key | RSA 2048 bits, SHA-256 |
| Certificate | Client, issued/registered at onboarding |
Renewal
Certificates expire. Conta Simples communicates the renewal window in advance. Plan the certificate rotation before expiration to avoid interrupting issuance — mTLS renewal is not automatic.