Autenticación

Authentication

Autenticación dual: JWT + api-key

Cada request a un endpoint protegido requiere dos credenciales simultáneas:

  1. JWT Bearer Token — valida la identidad del usuario (usuario/contraseña)
  2. api-key — UUID único del usuario API, enviado en un header separado
Ambas credenciales son obligatorias y deben pertenecer al mismo usuario. Un JWT de usuario A con api-key de usuario B es rechazado con 401.

Paso 1 — Obtener JWT

Las credenciales de acceso (usuario y contraseña) son entregadas por Prixmasol.

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..."
}
TokenVigenciaUso
access 2 horas Header Authorization: Bearer {token} en cada request
refresh 4 horas Renovar el access token una vez sin re-autenticar
El 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());
HeaderDescripciónEjemplo
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..."
}
Cada vez que usas el 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

HTTPMensajeCausa
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 access token antes de que expire (antes de las 2h)
  • El refresh token 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