Autenticar na API Pix (token + mTLS)
Resposta rápida: Chame o endpoint de token com Basic
client_id:client_secret,grant_type=client_credentialse o certificado mTLS; use oaccess_tokencomo Bearer nas próximas requisições.
Pré-requisitos
- Credenciais
- Conceitos: autenticação, mTLS
- Placeholders:
{{TOKEN_URL}},{{YOUR_CLIENT_ID}},{{YOUR_CLIENT_SECRET}},{{PATH_TO_CERT}},{{PATH_TO_KEY}}
Passo a passo
- Substitua placeholders nos snippets abaixo (não commite o arquivo preenchido).
- Execute o snippet da sua stack.
- Confirme JSON com
access_tokeneexpires_in(nomes podem variar levemente — confira resposta real). - Armazene o token em memória/redis com TTL menor que
expires_in.
Código
Fontes canônicas em snippets/:
snippets/curl/token.shsnippets/node/token.mjssnippets/python/token.pysnippets/php/token.php
curl
# source: snippets/curl/token.sh
#!/usr/bin/env bash
# operation: oauth-token
# placeholders: {{TOKEN_URL}} {{YOUR_CLIENT_ID}} {{YOUR_CLIENT_SECRET}} {{PATH_TO_CERT}} {{PATH_TO_KEY}}
# do not commit secrets
set -euo pipefail
curl -sS -X POST '{{TOKEN_URL}}' \
--cert '{{PATH_TO_CERT}}' \
--key '{{PATH_TO_KEY}}' \
-u '{{YOUR_CLIENT_ID}}:{{YOUR_CLIENT_SECRET}}' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials'
Node.js
// source: snippets/node/token.mjs
// operation: oauth-token
// do not commit secrets
import fs from 'node:fs';
import https from 'node:https';
import { URL } from 'node:url';
const url = new URL('{{TOKEN_URL}}');
const auth = Buffer.from('{{YOUR_CLIENT_ID}}:{{YOUR_CLIENT_SECRET}}').toString('base64');
const body = 'grant_type=client_credentials';
const req = https.request(
{
method: 'POST',
hostname: url.hostname,
path: url.pathname + url.search,
port: url.port || 443,
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(body),
},
cert: fs.readFileSync('{{PATH_TO_CERT}}'),
key: fs.readFileSync('{{PATH_TO_KEY}}'),
},
(res) => {
let data = '';
res.on('data', (c) => (data += c));
res.on('end', () => console.log(data));
},
);
req.on('error', (e) => {
console.error(e);
process.exit(1);
});
req.write(body);
req.end();
Python
# source: snippets/python/token.py
# operation: oauth-token
# do not commit secrets
import requests
resp = requests.post(
"{{TOKEN_URL}}",
data={"grant_type": "client_credentials"},
auth=("{{YOUR_CLIENT_ID}}", "{{YOUR_CLIENT_SECRET}}"),
cert=("{{PATH_TO_CERT}}", "{{PATH_TO_KEY}}"),
timeout=30,
)
print(resp.status_code, resp.text)
PHP
// source: snippets/php/token.php
// operation: oauth-token
// do not commit secrets
$ch = curl_init('{{TOKEN_URL}}');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['grant_type' => 'client_credentials']),
CURLOPT_USERPWD => '{{YOUR_CLIENT_ID}}:{{YOUR_CLIENT_SECRET}}',
CURLOPT_SSLCERT => '{{PATH_TO_CERT}}',
CURLOPT_SSLKEY => '{{PATH_TO_KEY}}',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
]);
$body = curl_exec($ch);
if ($body === false) {
fwrite(STDERR, curl_error($ch) . PHP_EOL);
exit(1);
}
echo $body, PHP_EOL;
Se der errado
| Sintoma | Causa | Ação |
|---|---|---|
| TLS handshake error | Cert/key errados | Conferir paths e formato |
| 401 no token | Secret inválido | Regerar só se necessário; atualizar cofre |
| 403 depois com Bearer | Escopo/produto | erros comuns + suporte |
Checklist
- Token obtido em HML
- Cert usado na chamada de token
- Secret não está no git
Próximo passo
→ 03 — Criar cobrança imediata
FAQ
P: O token vale para sempre?
R: Não. Renove com base em expires_in.