Autenticación
Authentication
Autenticación dual: JWT + api-key
Cada request a un endpoint protegido requiere dos credenciales simultáneas:
- JWT Bearer Token — valida la identidad del usuario (usuario/contraseña)
- api-key — UUID único del usuario API, enviado en un header separado
401.
Paso 1 — Obtener JWT
Envía usuario y contraseña para obtener los tokens de sesión:
POST /api/token/
Content-Type: application/json
{
"username": "tu_usuario",
"password": "tu_contraseña"
}
const axios = require('axios');
const { data } = await axios.post('https://TU-DOMINIO/api/token/', {
username: 'tu_usuario',
password: 'tu_contraseña'
});
const { access, refresh } = data;
using var client = new HttpClient();
var body = new StringContent(
JsonSerializer.Serialize(new {
username = "tu_usuario",
password = "tu_contraseña"
}),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://TU-DOMINIO/api/token/", body);
var json = await response.Content.ReadAsStringAsync();
// Deserializa para obtener "access" y "refresh"
import java.net.URI;
import java.net.http.*;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://TU-DOMINIO/api/token/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"tu_usuario\",\"password\":\"tu_contraseña\"}"
))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Parsea response.body() para obtener "access" y "refresh"
Response 200:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
| Token | Vigencia | Uso |
|---|---|---|
access |
2 horas | Header Authorization: Bearer {token} en cada request |
refresh |
4 horas | Renovar el access token una vez sin re-autenticar |
refresh token permite un solo ciclo de renovación. Después de las 4 horas, debes hacer login nuevamente con POST /api/token/.
Paso 2 — Usar JWT en requests autenticados
Incluye ambos headers en cada llamada a endpoints protegidos:
POST /corresponsales/api/factura/consulta/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
api-key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"invoice_id": "2025407608"
}
const response = await axios.post(
'https://TU-DOMINIO/corresponsales/api/factura/consulta/',
{ invoice_id: '2025407608' },
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'api-key': '550e8400-e29b-41d4-a716-446655440000'
}
}
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("api-key", "550e8400-e29b-41d4-a716-446655440000");
var body = new StringContent(
JsonSerializer.Serialize(new { invoice_id = "2025407608" }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync(
"https://TU-DOMINIO/corresponsales/api/factura/consulta/", body
);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://TU-DOMINIO/corresponsales/api/factura/consulta/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", "550e8400-e29b-41d4-a716-446655440000")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"invoice_id\":\"2025407608\"}"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
| Header | Descripción | Ejemplo |
|---|---|---|
Authorization |
JWT Bearer token (obligatorio) | Bearer eyJhbGc... |
api-key |
UUID del usuario API (obligatorio) | 550e8400-e29b-41d4-a716-446655440000 |
Content-Type |
Tipo de contenido | application/json |
Paso 3 — Renovar token expirado
Antes de que el access token expire (8h), puedes renovarlo con el refresh token:
POST /api/token/refresh/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
const { data } = await axios.post('https://TU-DOMINIO/api/token/refresh/', {
refresh: refreshToken
});
const newAccessToken = data.access;
var body = new StringContent(
JsonSerializer.Serialize(new { refresh = refreshToken }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://TU-DOMINIO/api/token/refresh/", body);
var json = await response.Content.ReadAsStringAsync();
// Deserializa para obtener el nuevo "access"
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://TU-DOMINIO/api/token/refresh/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"refresh\":\"" + refreshToken + "\"}"
))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Parsea response.body() para obtener el nuevo "access"
Response 200:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
refresh token, el anterior queda invalidado y recibes uno nuevo. Guarda siempre el último refresh recibido.
Paso 4 — Cerrar sesión
Para invalidar el refresh token inmediatamente (cierre de sesión seguro):
POST /api/token/logout/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response 200: cuerpo vacío. El token queda en lista negra y no puede usarse nuevamente.
Errores de autenticación
| HTTP | Mensaje | Causa |
|---|---|---|
401 |
Clave API no proporcionada | Falta el header api-key |
401 |
Clave API no corresponde al usuario autenticado | JWT y api-key pertenecen a usuarios distintos, o la api-key no existe |
401 |
(respuesta del framework JWT) | JWT ausente, malformado o expirado |
403 |
Usuario no autorizado para este endpoint | El usuario no tiene permiso en el endpoint solicitado |
Ejemplo completo
import requests
BASE_URL = "https://TU-DOMINIO" # Reemplaza con la URL del ambiente
USERNAME = "tu_usuario"
PASSWORD = "tu_contraseña"
API_KEY = "550e8400-e29b-41d4-a716-446655440000" # UUID de tu API_User
# 1. Obtener JWT
resp = requests.post(f"{BASE_URL}/api/token/", json={
"username": USERNAME,
"password": PASSWORD,
})
resp.raise_for_status()
access_token = resp.json()["access"]
# 2. Consultar una factura
headers = {
"Authorization": f"Bearer {access_token}",
"api-key": API_KEY,
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE_URL}/corresponsales/api/factura/consulta/",
headers=headers,
json={"invoice_id": "2025407608"},
)
data = resp.json()
if data["status"] == "0" and data["data"].get("Usable"):
request_id = data["request_id"]
# 3. Notificar pago
resp = requests.post(
f"{BASE_URL}/corresponsales/api/factura/pago/",
headers=headers,
json={"request_id": request_id},
)
print(resp.json())
const axios = require('axios');
const BASE_URL = 'https://TU-DOMINIO';
const API_KEY = '550e8400-e29b-41d4-a716-446655440000';
// 1. Obtener JWT
const { data: tokens } = await axios.post(`${BASE_URL}/api/token/`, {
username: 'tu_usuario',
password: 'tu_contraseña'
});
const accessToken = tokens.access;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'api-key': API_KEY
};
// 2. Consultar una factura
const { data } = await axios.post(
`${BASE_URL}/corresponsales/api/factura/consulta/`,
{ invoice_id: '2025407608' },
{ headers }
);
if (data.status === '0' && data.data?.Usable) {
// 3. Notificar pago
const pago = await axios.post(
`${BASE_URL}/corresponsales/api/factura/pago/`,
{ request_id: data.request_id },
{ headers }
);
console.log(pago.data);
}
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var BASE_URL = "https://TU-DOMINIO";
var API_KEY = "550e8400-e29b-41d4-a716-446655440000";
using var client = new HttpClient();
// 1. Obtener JWT
var loginBody = new StringContent(
JsonSerializer.Serialize(new { username = "tu_usuario", password = "tu_contraseña" }),
Encoding.UTF8, "application/json"
);
var loginResp = await client.PostAsync($"{BASE_URL}/api/token/", loginBody);
var loginJson = JsonSerializer.Deserialize<JsonElement>(
await loginResp.Content.ReadAsStringAsync()
);
var accessToken = loginJson.GetProperty("access").GetString();
// 2. Consultar una factura
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("api-key", API_KEY);
var consultaBody = new StringContent(
JsonSerializer.Serialize(new { invoice_id = "2025407608" }),
Encoding.UTF8, "application/json"
);
var consultaResp = await client.PostAsync(
$"{BASE_URL}/corresponsales/api/factura/consulta/", consultaBody
);
var consultaJson = JsonSerializer.Deserialize<JsonElement>(
await consultaResp.Content.ReadAsStringAsync()
);
if (consultaJson.GetProperty("status").GetString() == "0") {
var requestId = consultaJson.GetProperty("request_id").GetString();
// 3. Notificar pago
var pagoBody = new StringContent(
JsonSerializer.Serialize(new { request_id = requestId }),
Encoding.UTF8, "application/json"
);
var pagoResp = await client.PostAsync(
$"{BASE_URL}/corresponsales/api/factura/pago/", pagoBody
);
Console.WriteLine(await pagoResp.Content.ReadAsStringAsync());
}
import java.net.URI;
import java.net.http.*;
String BASE_URL = "https://TU-DOMINIO";
String API_KEY = "550e8400-e29b-41d4-a716-446655440000";
HttpClient client = HttpClient.newHttpClient();
// 1. Obtener JWT
HttpRequest loginReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/api/token/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"tu_usuario\",\"password\":\"tu_contraseña\"}"
))
.build();
HttpResponse<String> loginResp = client.send(loginReq, HttpResponse.BodyHandlers.ofString());
// Parsea loginResp.body() para extraer accessToken (usa tu librería JSON preferida)
// 2. Consultar una factura
HttpRequest consultaReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/corresponsales/api/factura/consulta/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"invoice_id\":\"2025407608\"}"))
.build();
HttpResponse<String> consultaResp = client.send(consultaReq, HttpResponse.BodyHandlers.ofString());
// Parsea consultaResp.body() y verifica status == "0" && data.Usable
// 3. Notificar pago
HttpRequest pagoReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/corresponsales/api/factura/pago/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"request_id\":\"" + requestId + "\"}"))
.build();
HttpResponse<String> pagoResp = client.send(pagoReq, HttpResponse.BodyHandlers.ofString());
System.out.println(pagoResp.body());
Buenas prácticas
- Nunca expongas tokens ni api-keys en logs o en el código fuente
- Renueva el
accesstoken antes de que expire (antes de las 2h) - El
refreshtoken dura 4h — cada uso emite uno nuevo, guarda siempre el último - Llama a
POST /api/token/logout/al cerrar sesión para invalidar el token inmediatamente - Usa HTTPS en todos los ambientes que no sean localhost
Dual authentication: JWT + api-key
Every request to a protected endpoint requires two simultaneous credentials:
- JWT Bearer Token — validates user identity (username/password)
- api-key — UUID unique to the API user, sent in a separate header
401.
Step 1 — Get JWT
Send username and password to obtain session tokens:
POST /api/token/
Content-Type: application/json
{
"username": "your_username",
"password": "your_password"
}
const axios = require('axios');
const { data } = await axios.post('https://YOUR-DOMAIN/api/token/', {
username: 'your_username',
password: 'your_password'
});
const { access, refresh } = data;
using var client = new HttpClient();
var body = new StringContent(
JsonSerializer.Serialize(new {
username = "your_username",
password = "your_password"
}),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://YOUR-DOMAIN/api/token/", body);
var json = await response.Content.ReadAsStringAsync();
// Deserialize to get "access" and "refresh"
import java.net.URI;
import java.net.http.*;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/api/token/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"your_username\",\"password\":\"your_password\"}"
))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Parse response.body() to get "access" and "refresh"
Response 200:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
| Token | Validity | Use |
|---|---|---|
access |
2 hours | Authorization: Bearer {token} header on each request |
refresh |
4 hours | Renew the access token once without re-authenticating |
refresh token allows one renewal cycle. After 4 hours you must log in again via POST /api/token/.
Step 2 — Use JWT in authenticated requests
Include both headers on every call to protected endpoints:
POST /corresponsales/api/factura/consulta/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
api-key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"invoice_id": "2025407608"
}
const response = await axios.post(
'https://YOUR-DOMAIN/corresponsales/api/factura/consulta/',
{ invoice_id: '2025407608' },
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'api-key': '550e8400-e29b-41d4-a716-446655440000'
}
}
);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("api-key", "550e8400-e29b-41d4-a716-446655440000");
var body = new StringContent(
JsonSerializer.Serialize(new { invoice_id = "2025407608" }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync(
"https://YOUR-DOMAIN/corresponsales/api/factura/consulta/", body
);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/corresponsales/api/factura/consulta/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", "550e8400-e29b-41d4-a716-446655440000")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"invoice_id\":\"2025407608\"}"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
| Header | Description | Example |
|---|---|---|
Authorization |
JWT Bearer token (required) | Bearer eyJhbGc... |
api-key |
API user UUID (required) | 550e8400-e29b-41d4-a716-446655440000 |
Content-Type |
Content type | application/json |
Step 3 — Renew expired token
Before the access token expires (8h), renew it using the refresh token:
POST /api/token/refresh/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
const { data } = await axios.post('https://YOUR-DOMAIN/api/token/refresh/', {
refresh: refreshToken
});
const newAccessToken = data.access;
var body = new StringContent(
JsonSerializer.Serialize(new { refresh = refreshToken }),
Encoding.UTF8, "application/json"
);
var response = await client.PostAsync("https://YOUR-DOMAIN/api/token/refresh/", body);
var json = await response.Content.ReadAsStringAsync();
// Deserialize to get the new "access"
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://YOUR-DOMAIN/api/token/refresh/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"refresh\":\"" + refreshToken + "\"}"
))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Parse response.body() to get the new "access"
Response 200:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
refresh token, the previous one is invalidated and you receive a new one. Always store the latest refresh token received.
Step 4 — Logout
To immediately invalidate the refresh token (secure logout):
POST /api/token/logout/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response 200: empty body. The token is blacklisted and cannot be used again.
Authentication errors
| HTTP | Message | Cause |
|---|---|---|
401 |
Clave API no proporcionada | Missing api-key header |
401 |
Clave API no corresponde al usuario autenticado | JWT and api-key belong to different users, or api-key not found |
401 |
(JWT framework response) | JWT missing, malformed, or expired |
403 |
Usuario no autorizado para este endpoint | User has no permission on the requested endpoint |
Complete example
import requests
BASE_URL = "https://YOUR-DOMAIN" # Replace with environment URL
USERNAME = "your_username"
PASSWORD = "your_password"
API_KEY = "550e8400-e29b-41d4-a716-446655440000" # Your API_User UUID
# 1. Get JWT
resp = requests.post(f"{BASE_URL}/api/token/", json={
"username": USERNAME,
"password": PASSWORD,
})
resp.raise_for_status()
access_token = resp.json()["access"]
# 2. Query an invoice
headers = {
"Authorization": f"Bearer {access_token}",
"api-key": API_KEY,
"Content-Type": "application/json",
}
resp = requests.post(
f"{BASE_URL}/corresponsales/api/factura/consulta/",
headers=headers,
json={"invoice_id": "2025407608"},
)
data = resp.json()
if data["status"] == "0" and data["data"].get("Usable"):
request_id = data["request_id"]
# 3. Notify payment
resp = requests.post(
f"{BASE_URL}/corresponsales/api/factura/pago/",
headers=headers,
json={"request_id": request_id},
)
print(resp.json())
const axios = require('axios');
const BASE_URL = 'https://YOUR-DOMAIN';
const API_KEY = '550e8400-e29b-41d4-a716-446655440000';
// 1. Get JWT
const { data: tokens } = await axios.post(`${BASE_URL}/api/token/`, {
username: 'your_username',
password: 'your_password'
});
const accessToken = tokens.access;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'api-key': API_KEY
};
// 2. Query an invoice
const { data } = await axios.post(
`${BASE_URL}/corresponsales/api/factura/consulta/`,
{ invoice_id: '2025407608' },
{ headers }
);
if (data.status === '0' && data.data?.Usable) {
// 3. Notify payment
const pago = await axios.post(
`${BASE_URL}/corresponsales/api/factura/pago/`,
{ request_id: data.request_id },
{ headers }
);
console.log(pago.data);
}
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var BASE_URL = "https://YOUR-DOMAIN";
var API_KEY = "550e8400-e29b-41d4-a716-446655440000";
using var client = new HttpClient();
// 1. Get JWT
var loginBody = new StringContent(
JsonSerializer.Serialize(new { username = "your_username", password = "your_password" }),
Encoding.UTF8, "application/json"
);
var loginResp = await client.PostAsync($"{BASE_URL}/api/token/", loginBody);
var loginJson = JsonSerializer.Deserialize<JsonElement>(
await loginResp.Content.ReadAsStringAsync()
);
var accessToken = loginJson.GetProperty("access").GetString();
// 2. Query an invoice
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("api-key", API_KEY);
var consultaBody = new StringContent(
JsonSerializer.Serialize(new { invoice_id = "2025407608" }),
Encoding.UTF8, "application/json"
);
var consultaResp = await client.PostAsync(
$"{BASE_URL}/corresponsales/api/factura/consulta/", consultaBody
);
var consultaJson = JsonSerializer.Deserialize<JsonElement>(
await consultaResp.Content.ReadAsStringAsync()
);
if (consultaJson.GetProperty("status").GetString() == "0") {
var requestId = consultaJson.GetProperty("request_id").GetString();
// 3. Notify payment
var pagoBody = new StringContent(
JsonSerializer.Serialize(new { request_id = requestId }),
Encoding.UTF8, "application/json"
);
var pagoResp = await client.PostAsync(
$"{BASE_URL}/corresponsales/api/factura/pago/", pagoBody
);
Console.WriteLine(await pagoResp.Content.ReadAsStringAsync());
}
import java.net.URI;
import java.net.http.*;
String BASE_URL = "https://YOUR-DOMAIN";
String API_KEY = "550e8400-e29b-41d4-a716-446655440000";
HttpClient client = HttpClient.newHttpClient();
// 1. Get JWT
HttpRequest loginReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/api/token/"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"username\":\"your_username\",\"password\":\"your_password\"}"
))
.build();
HttpResponse<String> loginResp = client.send(loginReq, HttpResponse.BodyHandlers.ofString());
// Parse loginResp.body() to extract accessToken using your preferred JSON library
// 2. Query an invoice
HttpRequest consultaReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/corresponsales/api/factura/consulta/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"invoice_id\":\"2025407608\"}"))
.build();
HttpResponse<String> consultaResp = client.send(consultaReq, HttpResponse.BodyHandlers.ofString());
// Parse consultaResp.body() and check status == "0" && data.Usable
// 3. Notify payment
HttpRequest pagoReq = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/corresponsales/api/factura/pago/"))
.header("Authorization", "Bearer " + accessToken)
.header("api-key", API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"request_id\":\"" + requestId + "\"}"))
.build();
HttpResponse<String> pagoResp = client.send(pagoReq, HttpResponse.BodyHandlers.ofString());
System.out.println(pagoResp.body());
Best practices
- Never expose tokens or api-keys in logs or source code
- Renew the
accesstoken before it expires (before the 2h mark) - The
refreshtoken lasts 4h — each use issues a new one, always store the latest - Call
POST /api/token/logout/on logout to immediately invalidate the token - Use HTTPS in all environments other than localhost