docs

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/token

This 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

stringobrigatorio

Credential identifier, in UUID v4 format. Generated in the FyPay Dashboard, under Settings → Credentials.

stringobrigatorio

Credential 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_tokenstring

JWT token used to authenticate requests.

token_typestring

Token type. Always "Bearer".

expires_innumber

Token lifetime in seconds. Do not assume a fixed value: use this field to schedule renewal.

scopestring

Token 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

CodeDescriptionSolution
401Token not providedInclude the Authorization: Bearer <token> header
401Invalid tokenCheck that the token is correct and has not expired
401Expired tokenObtain a new token via POST /api/auth/token
400/401/403Certificate 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

Best Practices

Next Steps

On this page