Overview
Tresa Contafy uses JWT (JSON Web Tokens) for authentication. The API provides two types of tokens:
Access Token : Short-lived token (15 minutes) used to authorize API requests
Refresh Token : Long-lived token (7 days) used to obtain new access tokens
Authentication Flow
Register or Login
Obtain your initial tokens by registering a new account or logging in with existing credentials.
Include Access Token in Requests
Add the access token to the Authorization header of all API requests.
Refresh When Expired
When the access token expires (after 15 minutes), use the refresh token to get a new one.
Registration
Create a new account to get started.
Endpoint
Request Body
{
"email" : "[email protected] " ,
"password" : "securePassword123" ,
"nombre" : "Juan" ,
"apellido" : "Pérez" ,
"telefono" : "+52 55 1234 5678"
}
Valid email address (validated)
Password with minimum 8 characters
Response
{
"message" : "Usuario registrado correctamente. Por favor verifica tu email." ,
"user" : {
"id" : "123e4567-e89b-12d3-a456-426614174000" ,
"email" : "[email protected] " ,
"nombre" : "Juan" ,
"apellido" : "Pérez" ,
"telefono" : "+52 55 1234 5678" ,
"email_verified" : false
}
}
After registration, a verification email is sent. You can still use the API without verifying your email, but some features may be restricted.
Login
Authenticate with your credentials to receive JWT tokens.
Endpoint
Request Body
Response
{
"message" : "Login exitoso" ,
"accessToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJpYXQiOjE3MTA0MjA4MDAsImV4cCI6MTcxMDQyMTcwMH0.signature" ,
"refreshToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJpYXQiOjE3MTA0MjA4MDAsImV4cCI6MTcxMTAyNTYwMH0.signature" ,
"user" : {
"id" : "123e4567-e89b-12d3-a456-426614174000" ,
"email" : "[email protected] " ,
"nombre" : "Juan" ,
"apellido" : "Pérez" ,
"telefono" : "+52 55 1234 5678" ,
"email_verified" : true
}
}
Error Responses
Invalid Credentials
Google Account
{
"error" : "Credenciales inválidas" ,
"message" : "El email o la contraseña son incorrectos"
}
Google Authentication
Authenticate using Google Sign-In with Firebase.
Endpoint
Request Body
{
"idToken" : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ..."
}
Firebase ID token obtained from Google Sign-In client
Response
Returns the same format as standard login:
{
"message" : "Login exitoso" ,
"accessToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"refreshToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"user" : {
"id" : "123e4567-e89b-12d3-a456-426614174000" ,
"email" : "[email protected] " ,
"nombre" : "Juan" ,
"apellido" : null ,
"telefono" : null ,
"email_verified" : true
}
}
If this is the first time signing in with Google, a new account is automatically created with a FREE subscription plan.
Using Access Tokens
Include the access token in the Authorization header using the Bearer scheme.
Authorization: Bearer YOUR_ACCESS_TOKEN
Example Request
curl -X GET https://api.contafy.com/api/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Response
{
"user" : {
"id" : "123e4567-e89b-12d3-a456-426614174000" ,
"email" : "[email protected] " ,
"nombre" : "Juan" ,
"apellido" : "Pérez" ,
"telefono" : "+52 55 1234 5678" ,
"email_verified" : true ,
"logo_url" : null ,
"nombre_comercial" : null
}
}
Token Expiration and Refresh
Access tokens expire after 15 minutes . When you receive a 403 error with message “Token inválido o expirado”, use your refresh token to obtain a new access token.
Endpoint
Request Body
{
"refreshToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response
{
"accessToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Error Responses
Expired Refresh Token
Invalid Refresh Token
{
"error" : "Refresh token expirado" ,
"message" : "Tu sesión ha expirado. Por favor inicia sesión nuevamente."
}
Refresh tokens expire after 7 days . After expiration, users must log in again to obtain new tokens.
Token Payload
Both access and refresh tokens contain the following payload:
{
"userId" : "123e4567-e89b-12d3-a456-426614174000" ,
"email" : "[email protected] " ,
"iat" : 1710420800 ,
"exp" : 1710421700
}
userId: Unique user identifier
email: User’s email address
iat: Issued at timestamp
exp: Expiration timestamp
Logout
Invalidate the current session.
Endpoint
Authorization: Bearer YOUR_ACCESS_TOKEN
Response
{
"message" : "Logout exitoso"
}
Currently, logout is client-side. After logout, discard both access and refresh tokens. Server-side token invalidation is planned for future releases.
Email Verification
Verify Email
POST /api/auth/verify-email
Request:
{
"token" : "verification-token-from-email"
}
Response:
{
"message" : "Email verificado correctamente"
}
Resend Verification Email
POST /api/auth/resend-verification-email
Request:
Response:
{
"message" : "Email de verificación reenviado correctamente. Por favor revisa tu bandeja de entrada."
}
Verification tokens expire after 24 hours . If your token expires, request a new verification email.
Password Reset
Request Password Reset
POST /api/auth/forgot-password
Request:
Response:
{
"message" : "Si el email está registrado, se enviará un correo con las instrucciones para restablecer tu contraseña."
}
Reset Password
POST /api/auth/reset-password
Request:
{
"token" : "reset-token-from-email" ,
"password" : "newSecurePassword123"
}
Response:
{
"message" : "Contraseña restablecida correctamente. Ya puedes iniciar sesión con tu nueva contraseña."
}
Password reset tokens expire after 1 hour . The new password must be at least 8 characters long.
Security Best Practices
Store Tokens Securely Never expose tokens in URLs or logs. Store them securely using environment variables or secure storage.
Use HTTPS Only Always use HTTPS in production to prevent token interception.
Implement Token Refresh Automatically refresh access tokens before they expire to maintain seamless user experience.
Handle Expiration Gracefully Implement proper error handling for expired tokens and redirect users to login when refresh fails.
Rate Limiting
Authentication endpoints are protected by rate limiting:
Registration/Login : 10 requests per 15 minutes per IP
Refresh Token : 20 requests per 15 minutes per user
Exceeding these limits results in a 429 Too Many Requests response.
Error Codes
Status Code Error Description 400 Bad Request Missing or invalid parameters 401 Unauthorized Invalid credentials or missing token 403 Forbidden Token expired or invalid 409 Conflict Email already registered 429 Too Many Requests Rate limit exceeded 500 Internal Server Error Server error during authentication
Example: Complete Authentication Flow
// 1. Login
const loginResponse = await fetch ( 'https://api.contafy.com/api/auth/login' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
email: '[email protected] ' ,
password: 'securePassword123'
})
});
const { accessToken , refreshToken } = await loginResponse . json ();
// 2. Make authenticated request
const invoicesResponse = await fetch ( 'https://api.contafy.com/api/invoices' , {
headers: {
'Authorization' : `Bearer ${ accessToken } `
}
});
// 3. Handle token expiration
if ( invoicesResponse . status === 403 ) {
// Refresh access token
const refreshResponse = await fetch ( 'https://api.contafy.com/api/auth/refresh' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({ refreshToken })
});
const { accessToken : newAccessToken } = await refreshResponse . json ();
// Retry original request with new token
const retryResponse = await fetch ( 'https://api.contafy.com/api/invoices' , {
headers: {
'Authorization' : `Bearer ${ newAccessToken } `
}
});
}
Next Steps
Quickstart Guide Complete end-to-end tutorial for your first API integration
User Profile Manage user profile and account settings
Profiles API Create and manage fiscal profiles for invoice processing
Error Handling Learn how to handle API errors effectively