mTLS Connection
How to establish the mTLS connection required by transactional endpoints (VCN issuance)
🚧 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
Transactional endpoints — such as VCN issuance (POST /credit-cards/v1/vcns) — 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 only on transactional endpoints (VCN issuance). Read-only queries keep using credential authentication alone. The key alone won't work 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.
Troubleshooting
Common causes:
- Client certificate missing or not presented (
--cert/--key) - Certificate not registered in the trust store (still onboarding)
- Wrong host (use the dedicated mTLS host, not the default host)
Fix: confirm the certificate, the host, and that onboarding is complete.
Common causes:
- Expired certificate or unexpected issuer
- Missing or invalid credential (Bearer)
Fix: check certificate validity and the OAuth credential.