docs

Generar token de acceso JWT

POST /api/auth/token

POST https://api.fypay.me/api/auth/token

Autentíquese con el certificado de cliente X.509 + credenciales (clientId/clientSecret) y reciba un token JWT. La validez del token viene en el campo expires_in (en segundos): use ese valor para renovar el token antes de que expire, sin asumir un tiempo fijo.

Autenticación (mTLS)

Esta ruta exige mTLS: el certificado de cliente emitido por FyPay se presenta en el handshake TLS, no en un header HTTP. Use el mecanismo nativo de certificado de cliente de su biblioteca HTTP (por ejemplo, curl --cert client.crt --key client.key).

  • El certificado es PEM, RSA 2048, válido por 2 años y vinculado a su cuenta.
  • El mTLS se exige solo en esta ruta. Las demás rutas usan Authorization: Bearer <token>, sin certificado.

No envíe el certificado en headers HTTP: ese modelo no se acepta. Sin el certificado en el handshake, la API responde 400 con PUB_CERT_HEADER_MISSING.

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
clientIdstring (UUID v4)SíClient ID generado en el panel (https://banking.fypay.me), en Configuración → Credenciales
clientSecretstringSíClient secret generado junto con el clientId. Se muestra una única vez en el panel. No puede estar vacío
{
  "clientId": "6967c0a0-3566-48d0-8c13-717038b52279",
  "clientSecret": "SU_CLIENT_SECRET"
}

Ejemplo con cURL

curl -X POST https://api.fypay.me/api/auth/token \
  --cert ./client.crt \
  --key ./client.key \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "SU_CLIENT_ID",
    "clientSecret": "SU_CLIENT_SECRET"
  }'

Ejemplos de Código

const https = require('https');
const fs = require('fs');
const axios = require('axios');

const httpsAgent = new https.Agent({
  cert: fs.readFileSync('./client.crt'),
  key: fs.readFileSync('./client.key'),
});

const response = await axios.post(
  'https://api.fypay.me/api/auth/token',
  {
    clientId: process.env.FYPAY_CLIENT_ID,
    clientSecret: process.env.FYPAY_CLIENT_SECRET,
  },
  { httpsAgent },
);

console.log('Token:', response.data.access_token);
console.log('Expira en:', response.data.expires_in, 'segundos');
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'),
)
response.raise_for_status()

data = response.json()
print(f"Token: {data['access_token']}")
print(f"Expira en: {data['expires_in']} segundos")
<?php
$ch = curl_init('https://api.fypay.me/api/auth/token');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSLCERT => __DIR__ . '/client.crt',
    CURLOPT_SSLKEY => __DIR__ . '/client.key',
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'clientId' => getenv('FYPAY_CLIENT_ID'),
        'clientSecret' => getenv('FYPAY_CLIENT_SECRET'),
    ]),
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo "Token: " . $data['access_token'] . "\n";
echo "Expira en: " . $data['expires_in'] . " segundos\n";
using System.Net.Http.Json;
using System.Security.Cryptography.X509Certificates;

var certificate = X509Certificate2.CreateFromPemFile("client.crt", "client.key");

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);

using var client = new HttpClient(handler);
var response = await client.PostAsJsonAsync(
    "https://api.fypay.me/api/auth/token",
    new
    {
        clientId = Environment.GetEnvironmentVariable("FYPAY_CLIENT_ID"),
        clientSecret = Environment.GetEnvironmentVariable("FYPAY_CLIENT_SECRET"),
    });

response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

func main() {
	cert, err := tls.LoadX509KeyPair("client.crt", "client.key")
	if err != nil {
		panic(err)
	}

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{Certificates: []tls.Certificate{cert}},
		},
	}

	body, _ := json.Marshal(map[string]string{
		"clientId":     os.Getenv("FYPAY_CLIENT_ID"),
		"clientSecret": os.Getenv("FYPAY_CLIENT_SECRET"),
	})

	resp, err := client.Post("https://api.fypay.me/api/auth/token", "application/json", bytes.NewReader(body))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var data map[string]any
	json.NewDecoder(resp.Body).Decode(&data)
	fmt.Println("Token:", data["access_token"])
	fmt.Println("Expira en:", data["expires_in"], "segundos")
}
import java.io.FileInputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

char[] password = System.getenv("FYPAY_KEYSTORE_PASSWORD").toCharArray();

KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream in = new FileInputStream("client.p12")) {
    keyStore.load(in, password);
}

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, password);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);

String body = String.format(
    "{\"clientId\":\"%s\",\"clientSecret\":\"%s\"}",
    System.getenv("FYPAY_CLIENT_ID"),
    System.getenv("FYPAY_CLIENT_SECRET")
);

HttpClient client = HttpClient.newBuilder().sslContext(sslContext).build();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.fypay.me/api/auth/token"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

FyPay entrega el certificado en PEM (client.crt + client.key). Si su plataforma exige un archivo .pfx/.p12 (común en Java y en algunos entornos Windows/.NET), conviértalo localmente:

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12

La conversión se hace en su máquina; FyPay no proporciona archivos PFX.

Respuesta (201)

CampoTipoDescripción
access_tokenstringToken JWT para el header Authorization: Bearer <token>
token_typestringSiempre Bearer
expires_innumberValidez del token en segundos. Renueve antes de que expire según este valor
scopestringAlcance del token
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 600,
  "scope": "email profile"
}

Errores

StatusCódigoDescripción
400PUB_CERT_HEADER_MISSINGCertificado de cliente no presentado en el handshake TLS
400PUB_CERT_MALFORMED_PEMCertificado en formato PEM inválido
400PUB_REQUEST_BODY_INVALIDBody inválido (ej.: clientId no es UUID v4, clientSecret vacío, campos extra). Los campos con problemas vienen en details.violations
401PUB_INVALID_CREDENTIALSclientId/clientSecret inválidos
401PUB_CERT_NOT_VERIFIEDEl certificado no pudo verificarse en la conexión
401PUB_CERT_NOT_REGISTEREDCertificado no registrado
401PUB_CERT_EXPIREDCertificado expirado
401PUB_CERT_NOT_YET_VALIDEl certificado aún no está en su período de validez
403PUB_CERT_NOT_AUTHORIZED_FOR_ACCOUNTEl certificado no está vinculado a la cuenta de las credenciales
502PUB_AUTH_UPSTREAM_ERRORError inesperado en el servicio de autenticación
503PUB_AUTH_UPSTREAM_UNAVAILABLEServicio de autenticación temporalmente no disponible. Intente nuevamente
{
  "statusCode": 401,
  "timestamp": "2026-04-17T15:24:28.809Z",
  "path": "/api/auth/token",
  "method": "POST",
  "code": "PUB_INVALID_CREDENTIALS",
  "message": "Invalid credentials provided",
  "userMessage": "Invalid credentials.",
  "errorId": "75d7999d6d7656b737e83435ced86ec6"
}

Para una guía completa de autenticación con patrones de renovación de token, vea Guía de Autenticación.

En esta página