Pular para o conteúdo principal

Autenticar na API Pix (token + mTLS)

Resposta rápida: Chame o endpoint de token com Basic client_id:client_secret, grant_type=client_credentials e o certificado mTLS; use o access_token como 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

  1. Substitua placeholders nos snippets abaixo (não commite o arquivo preenchido).
  2. Execute o snippet da sua stack.
  3. Confirme JSON com access_token e expires_in (nomes podem variar levemente — confira resposta real).
  4. Armazene o token em memória/redis com TTL menor que expires_in.

Código

Fontes canônicas em snippets/:

  • snippets/curl/token.sh
  • snippets/node/token.mjs
  • snippets/python/token.py
  • snippets/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

SintomaCausaAção
TLS handshake errorCert/key erradosConferir paths e formato
401 no tokenSecret inválidoRegerar só se necessário; atualizar cofre
403 depois com BearerEscopo/produtoerros 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.