Authentication
Overview
The PIX Bacen API uses exactly the same authentication system as the standard FyPay API. There is no Bacen-specific token route: the token is generated at POST https://api.fypay.me/api/auth/token, and every request to the Bacen endpoints must include that Bearer token in the Authorization header.
Authentication is identical to the standard API. If you already have credentials and a certificate, you can use them directly.
Obtaining the Token
Endpoint
POST https://api.fypay.me/api/auth/tokenThis route requires mTLS: the X.509 client certificate (PEM, RSA 2048, valid for 2 years, linked to your account) and its private key are presented in the TLS handshake, not in an HTTP header. The Bacen endpoints themselves do not require a certificate, only the Bearer token.
Request
curl -X POST https://api.fypay.me/api/auth/token \
--cert client.crt \
--key client.key \
-H "Content-Type: application/json" \
-d '{
"clientId": "6967c0a0-3566-48d0-8c13-717038b52279",
"clientSecret": "your-client-secret"
}'import fs from 'node:fs';
import { Agent, request } from 'undici';
const mtlsAgent = new Agent({
connect: {
cert: fs.readFileSync('./client.crt'),
key: fs.readFileSync('./client.key'),
},
});
const { body } = await request('https://api.fypay.me/api/auth/token', {
method: 'POST',
dispatcher: mtlsAgent,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: process.env.FYPAY_CLIENT_ID,
clientSecret: process.env.FYPAY_CLIENT_SECRET,
}),
});
const { access_token, expires_in } = await body.json();import os
import requests
response = requests.post(
'https://api.fypay.me/api/auth/token',
json={
'clientId': os.environ['FYPAY_CLIENT_ID'],
'clientSecret': os.environ['FYPAY_CLIENT_SECRET'],
},
cert=('client.crt', 'client.key'),
)
access_token = response.json()['access_token']Response (201 Created)
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 600,
"scope": "email profile"
}Using the Token
Include the token in every PIX Bacen API request:
curl -X PUT https://api.fypay.me/api/cob/7978c0c97ea847e78e8849634473c1f1 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{...}'Authentication Parameters
stringobrigatorioCredential identifier, in UUID v4 format. Generated in the FyPay Dashboard, under Settings → Credentials.
stringobrigatorioCredential secret. It is shown only once in the dashboard, at generation time.
Never expose the clientSecret, the certificate, or the private key in frontend code or public repositories.
Response Fields
access_tokenstringJWT token used to authenticate requests.
token_typestringToken type. Always "Bearer".
expires_innumberToken lifetime in seconds. Do not assume a fixed value: use this field to schedule renewal.
scopestringToken scope.
Token Renewal
The token expires after expires_in seconds. Implement automatic renewal:
import fs from 'node:fs';
import { Agent, request } from 'undici';
class TokenManager {
private token: string | null = null;
private expiresAt = 0;
private readonly agent = new Agent({
connect: {
cert: fs.readFileSync(process.env.FYPAY_CLIENT_CERT_PATH!),
key: fs.readFileSync(process.env.FYPAY_CLIENT_KEY_PATH!),
},
});
async getToken(): Promise<string> {
const safetyMarginMs = 30_000;
if (!this.token || Date.now() >= this.expiresAt - safetyMarginMs) {
await this.refreshToken();
}
return this.token!;
}
private async refreshToken(): Promise<void> {
const { body } = await request('https://api.fypay.me/api/auth/token', {
method: 'POST',
dispatcher: this.agent,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: process.env.FYPAY_CLIENT_ID,
clientSecret: process.env.FYPAY_CLIENT_SECRET,
}),
});
const data = (await body.json()) as { access_token: string; expires_in: number };
this.token = data.access_token;
this.expiresAt = Date.now() + data.expires_in * 1000;
}
}Authentication Errors
| Code | Description | Solution |
|---|---|---|
| 401 | Token not provided | Include the Authorization: Bearer <token> header |
| 401 | Invalid token | Check that the token is correct and has not expired |
| 401 | Expired token | Obtain a new token via POST /api/auth/token |
| 400/401/403 | Certificate or credential error at /api/auth/token (PUB_* codes such as PUB_CERT_HEADER_MISSING, PUB_INVALID_CREDENTIALS, and PUB_CERT_NOT_AUTHORIZED_FOR_ACCOUNT) | See the error reference in the standard authentication guide |