Autenticación API REST
Seguridad del API REST
Section titled “Seguridad del API REST”Para poder utilizar los recursos de la API REST de Prisma, es necesario obtener primero un token de autenticación válido que se utilizará para autenticar todas las solicitudes subsiguientes.
Este token valida que el cliente posea los permisos adecuados para acceder a los recursos solicitados.
Obtener el Token de Autenticación
Section titled “Obtener el Token de Autenticación”Credenciales Necesarias
Section titled “Credenciales Necesarias”Para obtener el token, necesitarás las siguientes credenciales proporcionadas por PRISMA:
client_id: Identificador único del clienteclient_secret: Clave secreta del cliente
Endpoint de Autenticación
Section titled “Endpoint de Autenticación”Método: POST
URL: {{URL-cliente}}/connect/token
Content-Type: application/x-www-form-urlencoded
Request Body
Section titled “Request Body”Envía los siguientes parámetros en formato application/x-www-form-urlencoded:
| Parámetro | Valor | Descripción |
|---|---|---|
client_id | Tu client ID | Proporcionado por Prisma |
client_secret | Tu client secret | Proporcionado por Prisma |
grant_type | client_credentials | Tipo de autenticación OAuth2 |
Ejemplo de Request
Section titled “Ejemplo de Request”curl -X POST "https://tu-cliente.prismaretail.ai/connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=PosClient" \ -d "client_secret=412536EF-F270-4058-80CA-1C89C192F87" \ -d "grant_type=client_credentials"HTTP Raw
Section titled “HTTP Raw”POST /connect/token HTTP/1.1Host: tu-cliente.prismaretail.aiContent-Type: application/x-www-form-urlencoded
client_id=PosClient&client_secret=412536EF-F270-4058-80CA-1C89C192F87&grant_type=client_credentialsPython (requests)
Section titled “Python (requests)”import requests
url = "https://tu-cliente.prismaretail.ai/connect/token"
payload = { "client_id": "PosClient", "client_secret": "412536EF-F270-4058-80CA-1C89C192F87", "grant_type": "client_credentials"}
headers = { "Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=payload, headers=headers)token_data = response.json()
print(token_data["access_token"])JavaScript (fetch)
Section titled “JavaScript (fetch)”const url = "https://tu-cliente.prismaretail.ai/connect/token";
const params = new URLSearchParams({ client_id: "PosClient", client_secret: "412536EF-F270-4058-80CA-1C89C192F87", grant_type: "client_credentials"});
fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params}).then(response => response.json()).then(data => { console.log("Access Token:", data.access_token);}).catch(error => console.error("Error:", error));Response Exitosa (Status 200)
Section titled “Response Exitosa (Status 200)”Content-Type: application/json
{ "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImxGZFN1UENYY0lYcVl6TUFPRklXVEEiLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE3MDI2ODI4NDEsImV4cCI6MTcwMjY4NjQ0MSwiaXNzIjoiaHR0cHM6Ly95cGZ0aWVuZGFzLnByaXNtYXJldGFpbC5haSIsImF1ZCI6WyJhc3NvcnRtZW50IiwiaW50ZXJmYWNlcyIsInByaWNlcyIsInByb21vdGlvbnMiLCJzYWxlc2FuZHN0b2NrIl0sImNsaWVudF9pZCI6IkZBUk8iLCJzY29wZSI6WyJhc3NvcnRtZW50LnB1YmxpY19hY2Nlc3MiLCJpbnRlcmZhY2VzLnB1YmxpY19hY2Nlc3MiLCJwcmljZXMucHVibGljX2FjY2VzcyIsInByb21vdGlvbnMucHVibGljX2FjY2VzcyIsInNhbGVzYW5kc3RvY2sucHVibGljX2FjY2VzcyJdfQ.QvqCFdMCRl4XJZpM6yx8gnrcy1cKir-mg7o7ZC2Vrp3Yry-nUWNX-Qn3Rb5tBU4nsnmU3ArRR6xOHTzv5V59n7Cl_oxLhcg719eUPsKs94MI5KXCLekUh0iULW5ckcgRNDjnc0F_B_EDEgRMtXEPG0tAnHXHR4K0zXweMvk9B8fK-od7s3uKA0NVmrmb-SMBNvi7suL0Om9mdySJJnHVvr0BCK3da2peuTwaeQmYeiVovvjZNjwv7Rvp-f3IjPUMBD9hh_13z2lPpjo2QgN10_PnJG3lsnAxFye3L-SlzAUtt2fOiS1nJzwCjvABDDN-GLEVsQ--du4UIxuK-ToIjQ", "expires_in": 3600, "token_type": "Bearer", "scope": "assortment.public_access interfaces.public_access prices.public_access promotions.public_access salesandstock.public_access"}Campos de la Respuesta
Section titled “Campos de la Respuesta”| Campo | Tipo | Descripción |
|---|---|---|
access_token | string | Token JWT para autenticar requests |
expires_in | number | Duración del token en segundos (ej: 3600 = 1 hora) |
token_type | string | Tipo de token (siempre Bearer) |
scope | string | Permisos asociados al token |
Duración y Renovación del Token
Section titled “Duración y Renovación del Token”Recomendaciones
Section titled “Recomendaciones”- Guarda la fecha de obtención del token
- Calcula el tiempo de expiración sumando
expires_ina la fecha actual - Renueva el token antes de que expire (por ejemplo, 5 minutos antes)
- Si recibes un error 401 Unauthorized, significa que el token ha caducado
Ejemplo: Gestión de Token en Python
Section titled “Ejemplo: Gestión de Token en Python”import requestsfrom datetime import datetime, timedelta
class PrismaAuth: def __init__(self, base_url, client_id, client_secret): self.base_url = base_url self.client_id = client_id self.client_secret = client_secret self.token = None self.token_expires_at = None
def get_token(self): """Obtiene un nuevo token de autenticación""" url = f"{self.base_url}/connect/token"
payload = { "client_id": self.client_id, "client_secret": self.client_secret, "grant_type": "client_credentials" }
response = requests.post(url, data=payload) response.raise_for_status()
data = response.json() self.token = data["access_token"]
# Calcular tiempo de expiración (restar 5 min de margen) expires_in = data["expires_in"] - 300 self.token_expires_at = datetime.now() + timedelta(seconds=expires_in)
return self.token
def is_token_valid(self): """Verifica si el token sigue vigente""" if not self.token or not self.token_expires_at: return False return datetime.now() < self.token_expires_at
def get_valid_token(self): """Obtiene un token válido (renueva si es necesario)""" if not self.is_token_valid(): return self.get_token() return self.token
# Usoauth = PrismaAuth( base_url="https://tu-cliente.prismaretail.ai", client_id="PosClient", client_secret="412536EF-F270-4058-80CA-1C89C192F87")
# Siempre obtienes un token válidotoken = auth.get_valid_token()Utilización del Token
Section titled “Utilización del Token”Una vez obtenido el token de autorización, se utiliza en cada petición incorporándolo en el header Authorization.
Formato del Header
Section titled “Formato del Header”Authorization: {token_type} {access_token}Componentes:
token_type: GeneralmenteBeareraccess_token: El token JWT recibido
Ejemplo de Header Authorization
Section titled “Ejemplo de Header Authorization”Si el token obtenido es:
eyJhbGciOiJSUzI1NiIsImtpZCI6ImxGZFN1UENYY0lYcVl6TUFPRklXVEEiLCJ0eXAiOiJhdCtqd3QifQ...El header quedaría:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImxGZFN1UENYY0lYcVl6TUFPRklXVEEiLCJ0eXAiOiJhdCtqd3QifQ...Ejemplos de Uso del Token
Section titled “Ejemplos de Uso del Token”curl -X GET "https://tu-cliente.prismaretail.ai/api/products" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImxGZFN1UENYY0lYcVl6TUFPRklXVEEiLCJ0eXAiOiJhdCtqd3QifQ..."Python (requests)
Section titled “Python (requests)”import requests
url = "https://tu-cliente.prismaretail.ai/api/products"
headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}
response = requests.get(url, headers=headers)products = response.json()JavaScript (fetch)
Section titled “JavaScript (fetch)”const url = "https://tu-cliente.prismaretail.ai/api/products";
fetch(url, { method: "GET", headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json" }}).then(response => response.json()).then(data => console.log(data)).catch(error => console.error("Error:", error));Postman
Section titled “Postman”- Abre Postman
- Selecciona la pestaña “Authorization”
- En “Type”, selecciona “Bearer Token”
- Pega el
access_tokenen el campo “Token” - Postman agregará automáticamente el header correcto
Ejemplo Completo: Obtener Token y Hacer Request
Section titled “Ejemplo Completo: Obtener Token y Hacer Request”Python
Section titled “Python”import requests
# Paso 1: Obtener el tokenauth_url = "https://tu-cliente.prismaretail.ai/connect/token"
auth_payload = { "client_id": "PosClient", "client_secret": "412536EF-F270-4058-80CA-1C89C192F87", "grant_type": "client_credentials"}
auth_response = requests.post(auth_url, data=auth_payload)auth_response.raise_for_status()
token_data = auth_response.json()access_token = token_data["access_token"]
print(f"Token obtenido: {access_token[:50]}...")print(f"Expira en: {token_data['expires_in']} segundos")
# Paso 2: Usar el token para hacer un requestapi_url = "https://tu-cliente.prismaretail.ai/api/products"
headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}
api_response = requests.get(api_url, headers=headers)api_response.raise_for_status()
products = api_response.json()print(f"Productos obtenidos: {len(products)}")Manejo de Errores
Section titled “Manejo de Errores”Error 401: Unauthorized
Section titled “Error 401: Unauthorized”Causa: Token expirado o inválido
Solución:
- Obtén un nuevo token
- Verifica que el
client_idyclient_secretsean correctos - Verifica que el token esté correctamente formateado en el header
if response.status_code == 401: print("Token expirado. Obteniendo nuevo token...") access_token = get_new_token() # Reintentar el request con el nuevo tokenError 400: Bad Request
Section titled “Error 400: Bad Request”Causa: Credenciales incorrectas o parámetros faltantes
Solución:
- Verifica que
client_idyclient_secretsean correctos - Verifica que
grant_typeseaclient_credentials - Verifica que el
Content-Typeseaapplication/x-www-form-urlencoded
Error 403: Forbidden
Section titled “Error 403: Forbidden”Causa: El token es válido pero no tienes permisos para el recurso
Solución:
- Verifica los
scopesincluidos en el token - Contacta al administrador para solicitar permisos adicionales
Mejores Prácticas
Section titled “Mejores Prácticas”1. Almacenamiento Seguro de Credenciales
Section titled “1. Almacenamiento Seguro de Credenciales”Usa variables de entorno:
import os
client_id = os.environ.get("PRISMA_CLIENT_ID")client_secret = os.environ.get("PRISMA_CLIENT_SECRET")Archivo .env:
PRISMA_CLIENT_ID=PosClientPRISMA_CLIENT_SECRET=412536EF-F270-4058-80CA-1C89C192F87PRISMA_BASE_URL=https://tu-cliente.prismaretail.ai2. Renovación Proactiva
Section titled “2. Renovación Proactiva”Renueva el token antes de que expire:
# Renovar 5 minutos antes de la expiraciónif (token_expires_at - datetime.now()).total_seconds() < 300: token = get_new_token()3. Reintentos Automáticos
Section titled “3. Reintentos Automáticos”Implementa reintentos automáticos para errores 401:
def make_request_with_retry(url, headers, max_retries=1): for attempt in range(max_retries + 1): response = requests.get(url, headers=headers)
if response.status_code == 401 and attempt < max_retries: # Renovar token y reintentar headers["Authorization"] = f"Bearer {get_new_token()}" continue
return response4. Logging de Tokens
Section titled “4. Logging de Tokens”# ✅ Correctoprint(f"Token obtenido: {access_token[:20]}...")
# ❌ Incorrecto (expone el token)print(f"Token obtenido: {access_token}")Recursos Relacionados
Section titled “Recursos Relacionados”- Introducción a Interfaces - Métodos de integración
- Etiquetas en API - Formato JSON para etiquetas
- Códigos en API - Formato JSON para códigos
Soporte
Section titled “Soporte”¿Necesitas ayuda con la autenticación?
- 📧 Solicita credenciales (
client_idyclient_secret) a tu account manager - 🔑 Reporta problemas de autenticación al soporte técnico
- 📋 Consulta sobre permisos y scopes disponibles