Referencia de la API
Cada ruta que sirve la API, quién puede llamarla y cómo funcionan el inicio de sesión, los permisos, los errores y la paginación.
Para el paquete Full Stack
URL base y formato de respuesta
Todas las rutas se sirven con el prefijo /api. En local, la URL base es http://localhost:8000/api. En un servidor es la dirección de tu API seguida de /api, el mismo valor que ambos frontends leen de NEXT_PUBLIC_API_BASE_URL (Variables de entorno).
La API sirve a dos públicos que nunca comparten un token: los clientes, que usan las rutas de la tienda, y el personal, que usa las del panel de administración. Los cuerpos de las solicitudes son JSON, salvo las subidas de archivos. Cada respuesta llega en el mismo envoltorio:
{
"success": true,
"data": { },
"message": ""
}data contiene el resultado. message es una frase corta que rellenan algunas escrituras, traducida al idioma de la solicitud, y vacía en los demás casos.
La comprobación de estado es la única ruta fuera del envoltorio. No necesita token:
curl http://localhost:8000/api/health{"status":"ok"}Responde 503 con {"status":"unavailable"} mientras no se puede acceder a la base de datos o esta no tiene tablas, así que un balanceador de carga puede usarla como sonda de disponibilidad.
Errores
Una solicitud fallida responde con el estado HTTP correspondiente y el mismo envoltorio, con success: false, data: null y, en la validación, los problemas por campo:
{
"success": false,
"data": null,
"message": "<the first field's problem>",
"errors": {
"email": ["<the problem with email>"]
}
}| Estado | Cuándo |
|---|---|
400 | Un campo no superó la validación, o el cuerpo contiene un campo que la ruta no acepta. Los campos desconocidos se rechazan, no se ignoran. |
401 | El token falta, ha caducado o pertenece al otro público. También un inicio de sesión fallido, tanto si el email no tiene cuenta como si la contraseña es incorrecta. |
402 | El probador en una demostración pública, cuando el comprador no envió una clave propia. |
403 | Los roles del administrador no conceden el permiso de la ruta: "You do not have permission to perform this action". |
404 | No existe ese registro. |
409 | La escritura choca con un registro existente, como un correo, un slug o un SKU que ya están en uso. |
429 | Demasiados intentos desde una dirección en una ruta de inicio de sesión, registro, contraseña o seguimiento, o demasiadas pruebas en el probador. En las rutas de inicio de sesión, la cabecera Retry-After indica cuántos segundos esperar. |
503 | Una función que no está configurada: las subidas sin bucket, una función de IA sin su clave, o la comprobación de estado antes de que existan las tablas. |
500 | Un fallo inesperado. El mensaje sigue siendo genérico y los detalles van al registro de la API. |
Las escrituras correctas responden 201 para POST y 200 para los demás métodos.
Paginación y ordenación
Las listas reciben page, desde 1, y page_count, el tamaño de página. Una página contiene como máximo 100 filas: un tamaño mayor se lee como 100, uno menor como 1, y uno ausente o ilegible recurre al valor por defecto de la lista. Una lista responde siempre con la misma forma:
{
"success": true,
"data": { "data": [ ], "page": 1, "limit": 15, "total": 35, "totalPages": 3 },
"message": ""
}| Lista | Tamaño de página por defecto |
|---|---|
| Productos, categorías, clientes, pedidos de administración | 15 |
| Personal, roles, ajustes, reseñas, los pedidos propios de un cliente | 10 |
/api/products/featured (limit) | 8 |
/api/products/:id/related (limit) | 4 |
order=ascuorder=descfija el sentido en productos, categorías, clientes y pedidos. Las categorías van por defecto en orden ascendente, y las demás de más reciente a más antiguo.- Los productos también se ordenan con
sort:created_at,updated_at,price,ratingobest_selling. Un valor desconocido recurre al orden por defecto, de actualización más reciente a más antigua, con los empates resueltos porid.order_by_featured=truepone primero los productos destacados y los más vendidos. - La lista de productos filtra por
search(nombre en cualquiera de los dos idiomas, o SKU),category_id,is_active,is_featured,is_best_seller,min_price,max_price,tagyon_sale.
Idioma
Envía el idioma del lector en la cabecera Accept-Language: en o ar tal como se entrega. ar-SA cuenta como árabe, y cualquier idioma que la API no tenga se responde en inglés. No hay ningún parámetro de consulta para el idioma.
- Los mensajes de error y el
messagede una escritura correcta se traducen. - El texto guardado en ambos idiomas, como los nombres de productos y categorías, vuelve como
{ "en": "...", "ar": "..." }y el cliente elige uno.
Autenticación
Los clientes y el personal inician sesión en endpoints distintos, contra tablas distintas, y reciben tokens que solo aceptan sus propias rutas.
| Público | Inicio de sesión | Token en la respuesta | Aceptado en |
|---|---|---|---|
| Cliente | POST /api/auth/customer/login | data.token, con data.user | Rutas de clientes |
| Personal | POST /api/auth/login | data.access_token, con data.admin (roles y permisos) | Rutas de administración |
- Ambos son JWT firmados con
JWT_SECRET. Envíalos comoAuthorization: Bearer <token>. - Un token dura
JWT_EXPIRATION,7dpor defecto (Variables de entorno). El inicio de sesión del personal indica el mismo valor comoexpires_in. - No hay endpoint de renovación. Cuando un token caduca, la siguiente solicitud responde
401y el cliente vuelve a iniciar sesión. - Un token de cliente se rechaza en las rutas de administración y un token de personal en las rutas de clientes, aunque ambos usan el mismo secreto.
- Un inicio de sesión fallido responde
401con un único mensaje, tanto si el correo no tiene cuenta como si la contraseña es incorrecta. - Las rutas de inicio de sesión, registro, contraseña y seguimiento de pedidos aceptan 10 intentos por minuto desde una misma dirección, contados por ruta. Pasado ese límite responden
429con una cabeceraRetry-After. El recuento se guarda en la memoria de la API, así que vuelve a empezar con un reinicio y cada instancia lo cuenta por separado. Detrás de un proxy, consultaTRUST_PROXY(Solución de problemas).
Inicia sesión como el Super Admin de los datos iniciales
Terminalcurl -X POST http://localhost:8000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@example.com","password":"Admin@123"}'Respuesta{ "success": true, "data": { "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": "7d", "admin": { "id": 1, "email": "admin@example.com", "roles": [{ "id": 1, "name": "Super Admin", "guard_name": "web" }], "permissions": ["admins.view", "admins.create", "..."] } }, "message": "..." }Llama a una ruta protegida con el token
Terminalcurl "http://localhost:8000/api/orders?page=1&page_count=5" \ -H "Authorization: Bearer <access_token>"Resultado esperado: Los cinco pedidos más recientes, con la forma de lista.
Inicia sesión como un cliente de los datos iniciales
La tienda de demostración también incluye clientes, como
john.doe@example.comcon la contraseñapassword123:Terminalcurl -X POST http://localhost:8000/api/auth/customer/login \ -H "Content-Type: application/json" \ -d '{"email":"john.doe@example.com","password":"password123"}'Después pasa
data.tokende la misma forma, por ejemplo aGET /api/orders/my.
Cambia las contraseñas de los datos iniciales
Las cuentas de la tienda de demostración usan contraseñas publicadas: Admin@123 para el Super Admin, admin123 para el resto del personal y password123 para los clientes. Cámbialas, o empieza con tablas vacías, antes de poner un sitio en producción.
Permisos
Cada ruta de administración comprueba primero el token y luego el permiso que indica. Un administrador tiene todos los permisos de todos sus roles; cuando una ruta indica varios, basta con uno de ellos. En las tablas de administración de abajo, un nombre de permiso en la columna Quién puede llamarla significa un administrador cuyos roles lo conceden.
| Módulo | Permisos |
|---|---|
| Personal | admins.view, admins.create, admins.edit, admins.delete, admins.assign_roles |
| Roles | roles.view, roles.create, roles.edit, roles.delete, roles.assign_permissions |
| Ajustes | settings.view, settings.edit |
| Clientes | users.view, users.create, users.update, users.delete, users.restore, users.verify |
| Categorías | categories.view, categories.create, categories.edit, categories.delete, categories.restore |
| Productos | products.view, products.create, products.edit, products.delete, products.restore |
| Pedidos | orders.view, orders.edit |
| Asistente de IA | ai_chat.use, ai_chat.view_models |
Las secciones de la página de inicio y el estudio de IA usan los permisos de productos. Las reseñas no tienen permiso propio: el panel las lee a través de los productos.
| Rol de los datos iniciales | Concede |
|---|---|
| Super Admin | Todos los permisos |
| Viewer | Todos los permisos que terminan en .view |
| Admin, Manager, Editor | Ninguno hasta que los concedas |
Volver a ejecutar la carga de datos crea lo que falta y deja los permisos de los roles existentes tal como los configuraste.
Catálogo público
No se necesita token. Los compradores solo ven productos activos: sin un token de administrador, un producto inactivo o eliminado no existe.
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/products | Cualquiera | La lista de productos, con los filtros y la ordenación de arriba. Sin un token de administrador solo muestra productos activos, pida lo que pida is_active; con uno, cada filtro funciona tal como se envía, incluidos los productos inactivos. |
GET | /api/products/featured | Cualquiera | Productos destacados activos (limit, 8 por defecto). |
GET | /api/products/slug/:slug | Cualquiera | Un producto por su slug, con imágenes, variantes y categoría. Un producto inactivo o eliminado responde 404 sin un token de administrador. |
GET | /api/products/:id | Cualquiera | Un producto por id, con la misma regla del 404. |
GET | /api/products/:id/related | Cualquiera | Productos activos relacionados con él (limit, 4 por defecto); 404 para un producto inactivo sin un token de administrador. |
GET | /api/categories | Cualquiera | La lista de categorías (search, is_active, parent_id, order). |
GET | /api/categories/roots | Cualquiera | Categorías sin categoría padre. |
GET | /api/categories/slug/:slug | Cualquiera | Una categoría por su slug. |
GET | /api/categories/:id | Cualquiera | Una categoría por id. |
GET | /api/homepage-sections/:key/products | Cualquiera | Los productos elegidos para una sección de la página de inicio, como best-sellers. |
GET | /api/reviews/product/:productId | Cualquiera | Las reseñas de un producto, 10 por página. |
GET | /api/reviews/product/:productId/summary | Cualquiera | Su valoración media y el recuento por estrella. |
GET | /api/helpers/countries | Cualquiera | Países para un selector, en el idioma de la solicitud. |
Registro y cuentas de clientes
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/auth/customer/register | Cualquiera | Crea un cliente (first_name, last_name, email, password, phone opcional) e inicia su sesión. Con límite de frecuencia. |
POST | /api/auth/customer/login | Cualquiera | Inicia la sesión de un cliente. Con límite de frecuencia. |
GET | /api/auth/customer/me | Cliente | El cliente con sesión iniciada. |
PATCH | /api/auth/customer/me | Cliente | Actualiza sus datos. |
PATCH | /api/auth/customer/me/password | Cliente | Cambia su contraseña. |
POST | /api/auth/customer/forgot-password | Cualquiera | Emite un token de restablecimiento de un solo uso, válido durante una hora. Fuera de producción se escribe en el registro de la API; no se envía ningún correo. Con límite de frecuencia. |
POST | /api/auth/customer/reset-password | Cualquiera | Fija una contraseña nueva con ese token. Con límite de frecuencia. |
GET | /api/addresses | Cliente | Sus direcciones guardadas. |
GET | /api/addresses/:id | Cliente | Una de ellas. |
POST | /api/addresses | Cliente | Guarda una dirección. |
PATCH | /api/addresses/:id | Cliente | La edita. |
PATCH | /api/addresses/:id/default | Cliente | La marca como predeterminada. |
DELETE | /api/addresses/:id | Cliente | La elimina. |
POST | /api/reviews | Cliente | Reseña un producto, una reseña por cliente y producto: volver a enviarla la actualiza. |
PATCH | /api/reviews/:id | Cliente | Edita su reseña. |
DELETE | /api/reviews/:id | Cliente | Elimina su reseña. |
Los clientes con sesión iniciada también tienen disponible un carrito en el servidor. La tienda incluida guarda su carrito en el navegador y no lo llama.
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/cart | Cliente | El carrito del cliente. |
POST | /api/cart/items | Cliente | Añade product_id, variant_id opcional y quantity. |
PATCH | /api/cart/items/:id | Cliente | Cambia la cantidad de una línea. |
DELETE | /api/cart/items/:id | Cliente | Quita una línea. |
DELETE | /api/cart | Cliente | Vacía el carrito. |
Pedidos, pago y seguimiento
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/orders | Cualquiera; si se envía un token de cliente, se lee | Realiza un pedido. Un invitado envía items, email y la dirección; un cliente con sesión iniciada puede no enviar items para pedir el contenido de su carrito del servidor. payment_method es stripe o cod (paypal se acepta, pero nada lo procesa). Los precios vienen del catálogo, no de la solicitud. |
GET | /api/orders/track | Cualquiera | El progreso de un pedido por order_number y email juntos. Con límite de frecuencia. |
GET | /api/orders/my | Cliente | Los pedidos del cliente, 10 por página. |
GET | /api/orders/number/:orderNumber | Cliente | Uno de sus pedidos por su número. |
POST | /api/payments/webhook | Stripe, firmado con STRIPE_WEBHOOK_SECRET | Marca un pedido con tarjeta como pagado (payment_intent.succeeded) o fallido (payment_intent.payment_failed). |
Con payment_method: "stripe" y Stripe configurado, la respuesta incluye un client_secret que la tienda confirma con Stripe. El envío es gratis a partir de un subtotal de 75 y cuesta 9.99 por debajo; el impuesto es 0. Un promo_code se guarda en el pedido, pero no se aplica.
Inicio de sesión y cuentas del personal
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/auth/login | Cualquiera | Inicia la sesión de un miembro del personal. Con límite de frecuencia. |
GET | /api/auth/me | Cualquier administrador con sesión iniciada | El administrador con sesión iniciada, con sus roles y permisos. |
GET | /api/admins | admins.view | La lista del personal. |
GET | /api/admins/statistics | admins.view | Recuentos del personal. |
GET | /api/admins/:id | admins.view | Un administrador. |
POST | /api/admins | admins.create | Crea un administrador. |
PATCH | /api/admins/:id | admins.edit | Edita un administrador. |
PATCH | /api/admins/:id/roles | admins.assign_roles | Fija los roles de un administrador. |
DELETE | /api/admins/:id | admins.delete | Elimina un administrador. |
PATCH | /api/admins/profile | admins.edit | Edita el perfil propio del administrador con sesión iniciada. |
PATCH | /api/admins/profile/password | Cualquier administrador con sesión iniciada | Cambia la contraseña propia del administrador con sesión iniciada. |
Roles
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/roles | roles.view | Los roles. Sin parámetros de página, todos. |
GET | /api/roles/statistics | roles.view | Recuentos de roles. |
GET | /api/roles/select | roles.view | Roles para un selector. |
GET | /api/roles/permissions | roles.view | Todos los permisos, agrupados por módulo. |
GET | /api/roles/:id | roles.view | Un rol con sus permisos. |
POST | /api/roles | roles.create | Crea un rol. |
PUT | /api/roles/:id | roles.edit | Renombra o edita un rol. |
POST | /api/roles/:id/permissions | roles.assign_permissions | Fija los permisos de un rol. Los administradores con sesión iniciada que lo tienen reciben el cambio en directo. |
DELETE | /api/roles/:id | roles.delete | Elimina un rol. |
Clientes
A los clientes se les identifica por su nombre de usuario. La lista filtra por search, email, phone, country_id, username, first_name, last_name, verified, from_date y to_date.
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/users | users.view | La lista de clientes. |
GET | /api/users/statistic | users.view | Recuentos de clientes. |
GET | /api/users/deleted | users.view | Clientes eliminados. |
GET | /api/users/deleted/:username | users.view | Un cliente eliminado. |
GET | /api/users/:username | users.view | Un cliente. |
POST | /api/users | users.create | Crea un cliente. |
PATCH | /api/users/:username | users.update | Edita un cliente. |
PATCH | /api/users/:username/change-password | users.update | Fija la contraseña de un cliente. |
POST | /api/users/:username/resend-verification-email | users.update | Responde con éxito y no envía nada: la plantilla no incluye ningún sistema de envío de correo. Conecta aquí tu sistema de envío. |
POST | /api/users/:username/make-verified | users.verify | Marca el correo como verificado. |
POST | /api/users/:username/make-unverified | users.verify | Lo marca como no verificado. |
DELETE | /api/users/:username | users.delete | Mueve un cliente a la lista de eliminados. |
POST | /api/users/deleted/:username/restore | users.restore | Restaura un cliente eliminado. |
Productos y categorías
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/products | products.create | Crea un producto con sus imágenes y variantes. |
PATCH | /api/products/:id | products.edit | Edita un producto. |
DELETE | /api/products/:id | products.delete | Lo mueve a la lista de eliminados. |
GET | /api/products/deleted | products.delete | Productos eliminados. |
POST | /api/products/deleted/:id/restore | products.restore | Restaura uno. |
GET | /api/products/statistic | products.view | Recuentos de productos. |
GET | /api/products/drafts | Cualquier administrador con sesión iniciada | El borrador sin guardar del formulario de producto del administrador (product_id para un producto existente). |
PUT | /api/products/drafts | Cualquier administrador con sesión iniciada | Guarda ese borrador. |
DELETE | /api/products/drafts | Cualquier administrador con sesión iniciada | Lo descarta. |
POST | /api/categories | categories.create | Crea una categoría. |
PATCH | /api/categories/:id | categories.edit | Edita una categoría, incluido su orden. |
DELETE | /api/categories/:id | categories.delete | Lo mueve a la lista de eliminados. |
GET | /api/categories/deleted | categories.delete | Categorías eliminadas. |
POST | /api/categories/deleted/:id/restore | categories.restore | Restaura uno. |
GET | /api/categories/statistic | categories.view | Recuentos de categorías. |
GET | /api/homepage-sections/:key | products.view | Los ajustes y los productos de una sección de la página de inicio. |
PUT | /api/homepage-sections/:key | products.edit | Los fija. |
Las claves de las secciones son style-pillars, editorial-split, new-drops, best-sellers, spotlight, lux-difference y editorial-slider.
Pedidos
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/orders | orders.view | La lista de pedidos: search, status (uno o varios, separados por comas), payment_status, from_date, to_date, order. |
GET | /api/orders/statistic | orders.view | Recuentos por estado e ingresos. |
GET | /api/orders/:id | orders.view | Un pedido con sus artículos. |
PATCH | /api/orders/:id/status | orders.edit | Fija el estado (pending, confirmed, processing, shipped, delivered, cancelled, refunded) y el número de seguimiento. |
La API acepta cualquier cambio de estado; el panel solo ofrece el paso siguiente o una cancelación.
Ajustes
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/settings | settings.view | Los ajustes de la aplicación, 10 por página. |
GET | /api/settings/:key | settings.view | Un ajuste. |
PATCH | /api/settings/:key | settings.edit | Cambia su valor. |
DELETE | /api/settings/:key | settings.edit | La elimina. |
No hay ninguna ruta para crear un ajuste: los crea la carga de datos. Nada en el código incluido lee sus valores.
Subida de archivos multimedia
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/helpers/upload | Cualquier administrador con sesión iniciada | Sube un archivo al bucket. |
- Formulario multipart: el archivo en
file, la carpeta enpath(uploadspor defecto) y, de forma opcional, un tamaño predefinido enfor. - Hasta 150 MB. Los videos (MP4, WebM, MOV, M4V) se guardan tal cual y responden
{ "original": url }. - Las imágenes se vuelven a codificar en JPEG, con 1920 píxeles de ancho como máximo, más el tamaño predefinido, y responden con cada URL, como
{ "original": url, "250x250": url }. - Sin las cinco variables
R2_*responde503: "File uploads are not set up yet."
Notificaciones
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/notifications | Cualquier administrador con sesión iniciada | Las 30 notificaciones más recientes del administrador, que se guardan durante 30 días. |
PATCH | /api/notifications/read-all | Cualquier administrador con sesión iniciada | Las marca todas como leídas. |
PATCH | /api/notifications/:id/read | Cualquier administrador con sesión iniciada | Marca una como leída. |
DELETE | /api/notifications/:id | Cualquier administrador con sesión iniciada | Elimina una. |
- Las notificaciones en directo usan Socket.IO en el espacio de nombres
/notifications, en la dirección de la API sin/api. Envía el token del personal enauth.tokendel handshake; los tokens de clientes se desconectan. - Cada una nueva llega como
notification:created. Los tipos sonorder_created, para todos los administradores que pueden ver pedidos, ystudio_generation_completedystudio_generation_failed, para el administrador que inició la generación. - Un segundo espacio de nombres,
/auth, envíapermissions-updatedcuando cambian los roles o los permisos de un administrador. - El socket solo acepta conexiones desde
FRONTEND_URL.
Asistente de IA
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Las rutas de chat, de modelos y de historial de chat del asistente.
Estudio de IA
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Las rutas de generación y de archivos multimedia del estudio de productos con IA.
Probador
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Las rutas públicas del probador de la tienda y sus límites.
Rutas del modo demostración
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
La ruta que usa una demostración pública para dar una cuenta a cada visitante.