API de e-commerce
Gestiona tu catálogo de productos, rastrea pedidos, supervisa la actividad de los carritos y analiza segmentos RFM de clientes.
Todos los endpoints de esta página son relativos a la URL base: https://api-eu1.joryio.com. Consulta el resumen de la API.
Convención de nombres de ID
Joryio usa una convención clara para los identificadores:
Tus ID (úsalos al crear o rastrear datos)
| Campo | Descripción | Ejemplo |
|---|---|---|
productId | Tu identificador de producto (SKU o ID de producto de tu plataforma de e-commerce). | "SKU-12345" |
orderId | Tu identificador de pedido (número de pedido de tu plataforma). | "ORD-2024-001" |
userId | Tu identificador de usuario. | "user-123" |
ID de Joryio (devueltos en las respuestas API)
| Campo | Descripción | Cuándo usarlo |
|---|---|---|
id | ID interno de Joryio para productos/pedidos. | Se devuelve en respuestas API; úsalo para actualizar/eliminar. |
joryioUserId | ID de usuario interno de Joryio (el id de 24 caracteres hexadecimales devuelto por la API de usuarios). | Alternativa a userId cuando quieras referenciar mediante el ID de Joryio. |
Identificación flexible de usuario
Al crear pedidos o rastrear eventos, puedes identificar usuarios mediante uno de estos campos:
userId: tu identificador de usuario (el más habitual).joryioUserId: ID de usuario interno de Joryio.
// Usando tu ID de usuario (recomendado)
{ "orderId": "ORD-001", "userId": "user-123", ... }
// Usando el ID de usuario interno de Joryio
{ "orderId": "ORD-001", "joryioUserId": "66a1f2c3d4e5f6a7b8c9d0e1", ... }
Autenticación
Todas las solicitudes requieren autenticación JWT:
Authorization: Bearer your_jwt_token
Content-Type: application/json
X-Workspace-Id: your_workspace_id
Catálogo de productos
Crear un producto
Crea un producto nuevo en tu catálogo.
POST /catalog/products
Cuerpo de la solicitud:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
productId | cadena | Sí | Tu identificador de producto único (SKU o ID de producto). |
name | cadena | Sí | Nombre del producto. |
price | número | Sí | Precio del producto. |
description | cadena | No | Descripción del producto. |
compareAtPrice | número | No | Precio original (para descuentos). |
currency | cadena | No | Código de moneda (predeterminado: USD). |
categories | cadena[] | No | Categorías de producto. |
tags | cadena[] | No | Etiquetas de producto. |
brand | cadena | No | Nombre de la marca. |
imageUrl | cadena | No | URL de imagen principal de producto. |
url | cadena | No | URL de página de producto. |
inStock | booleano | No | Disponibilidad de stock (predeterminado: true). |
sku | cadena | No | Unidad de mantenimiento de stock. |
variants | objeto[] | No | Variantes de producto. |
customFields | objeto | No | Atributos personalizados. |
Solicitud de ejemplo:
curl -X POST https://api-eu1.joryio.com/catalog/products \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"productId": "SKU-12345",
"name": "Classic Blue T-Shirt",
"price": 29.99,
"compareAtPrice": 39.99,
"currency": "USD",
"categories": ["Clothing", "T-Shirts"],
"tags": ["sale", "bestseller"],
"brand": "Acme Apparel",
"imageUrl": "https://example.com/images/blue-tshirt.jpg",
"url": "https://example.com/products/blue-tshirt",
"inStock": true,
"sku": "BTS-001-BL",
"variants": [
{
"id": "var-s",
"name": "Small",
"sku": "BTS-001-BL-S",
"price": 29.99,
"inStock": true,
"options": { "size": "S", "color": "Blue" }
},
{
"id": "var-m",
"name": "Medium",
"sku": "BTS-001-BL-M",
"price": 29.99,
"inStock": true,
"options": { "size": "M", "color": "Blue" }
}
]
}'
Respuesta:
{
"id": "prod_abc123",
"productId": "SKU-12345",
"name": "Classic Blue T-Shirt",
"price": 29.99,
"createdAt": "2024-01-20T10:00:00.000Z"
}
Upsert masivo de productos (cuerpo de matriz)
No hay un endpoint masivo independiente: POST /catalog/products acepta un objeto de producto único o una matriz JSON de objetos de producto, sin objeto envoltorio. El formato de matriz crea o actualiza hasta 500 productos en una solicitud, mediante upsert por productId.
POST /catalog/products
Cuerpo de la solicitud:
Una matriz JSON de hasta 500 elementos; una matriz vacía o con más de 500 devuelve 400. Cada elemento sigue el mismo formato que el objeto único, incluido el campo opcional source por producto.
Cada elemento recibe una validación completa. Un elemento no válido se informa en failed mediante su índice de matriz, nunca se acepta silenciosamente, y los elementos válidos restantes reciben upsert de todos modos.
[
{ "productId": "SKU-001", "name": "Product 1", "price": 19.99 },
{ "productId": "SKU-002", "name": "Product 2", "price": 29.99, "source": "shopify" }
]
Respuesta:
A diferencia del formato de objeto, que devuelve el producto creado, el formato de matriz devuelve un resumen agregado:
{
"processed": 2,
"upserted": 2,
"failed": []
}
| Campo | Descripción |
|---|---|
processed | Número de elementos recibidos en la matriz de solicitud. |
upserted | Productos creados o actualizados realmente. |
failed | Errores por elemento: index (posición en la matriz de solicitud), productId / sku (cuando existen en el elemento) y reason. |
Listar productos
Consulta productos con filtrado y paginación.
GET /catalog/products
Parámetros de consulta:
| Parámetro | Tipo | Descripción |
|---|---|---|
search | cadena | Busca por nombre, descripción o SKU. |
categories | cadena[] | Filtra por categorías. |
tags | cadena[] | Filtra por etiquetas. |
brand | cadena | Filtra por marca. |
inStock | booleano | Filtra por estado de stock. |
minPrice | número | Precio mínimo. |
maxPrice | número | Precio máximo. |
limit | número | Resultados por página (predeterminado: 50). |
offset | número | Desplazamiento de paginación. |
sortBy | cadena | Campo de orden: name, price, createdAt, updatedAt. |
sortOrder | cadena | asc o desc. |
Ejemplo:
curl "https://api-eu1.joryio.com/catalog/products?categories=T-Shirts&inStock=true&limit=20" \
-H "Authorization: Bearer $TOKEN"
Obtener categorías
Lista todas las categorías de producto.
GET /catalog/categories
Obtener marcas
Lista todas las marcas de producto.
GET /catalog/brands
Pedidos
Crear un pedido
Rastrea un pedido nuevo.
POST /orders
Cuerpo de la solicitud:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
orderId | cadena | Sí | Tu ID de pedido (número de pedido de tu plataforma). |
userId | cadena | Uno de los dos | ID de usuario de tu cliente. |
joryioUserId | cadena | Uno de los dos | ID de usuario interno de Joryio (alternativa a userId). |
total | número | Sí | Total del pedido. |
items | objeto[] | Sí | Líneas de pedido. |
status | cadena | No | Estado del pedido (predeterminado: pending). |
currency | cadena | No | Código de moneda. |
subtotal | número | No | Subtotal antes de descuentos. |
discount | número | No | Importe del descuento. |
shipping | número | No | Coste de envío. |
tax | número | No | Importe de impuestos. |
totalRefunded | número | No | Importe reembolsado hasta ahora, en la moneda del pedido (predeterminado 0). Para un reembolso parcial, envía el importe parcial con status: partiallyRefunded; para un reembolso total, define total con status: refunded. Los reembolsos se deducen de los ingresos atribuidos. |
couponCode | cadena | No | Cupón aplicado. |
shippingAddress | objeto | No | Dirección de envío. |
campaignId | cadena | No | Campaña de atribución. |
canvasId | cadena | No | Canvas de atribución. |
source | cadena | No | Fuente del pedido (email, sms, direct). |
utmSource | cadena | No | Fuente UTM. |
utmMedium | cadena | No | Medio UTM. |
utmCampaign | cadena | No | Campaña UTM. |
Debes proporcionar userId o joryioUserId. Usa userId con tus propios identificadores de usuario (lo más habitual). Usa joryioUserId si dispones del ID de usuario interno de Joryio (el id de 24 caracteres hexadecimales devuelto por la API de usuarios).
Estructura de línea de pedido:
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"sku": "BTS-001",
"quantity": 2,
"price": 29.99,
"total": 59.98,
"imageUrl": "https://example.com/image.jpg"
}
Solicitud de ejemplo:
curl -X POST https://api-eu1.joryio.com/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"orderId": "ORD-2024-001",
"userId": "user-123",
"total": 89.97,
"subtotal": 99.97,
"discount": 10.00,
"shipping": 5.99,
"tax": 4.99,
"currency": "USD",
"couponCode": "SAVE10",
"items": [
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"quantity": 2,
"price": 29.99,
"total": 59.98
},
{
"productId": "prod_def456",
"name": "Black Jeans",
"quantity": 1,
"price": 49.99,
"total": 49.99
}
],
"source": "email",
"campaignId": "camp_xyz789"
}'
Completar un pedido
Marca un pedido como enviado.
POST /orders/:id/fulfill
Cuerpo de la solicitud:
{
"trackingNumber": "1Z999AA10123456784",
"carrier": "UPS"
}
Cancelar un pedido
Cancela un pedido.
POST /orders/:id/cancel
Cuerpo de la solicitud:
{
"reason": "Customer requested cancellation"
}
Reembolsar un pedido
Procesa un reembolso.
POST /orders/:id/refund
Cuerpo de la solicitud:
{
"refundAmount": 29.99,
"reason": "Product defective",
"partial": true
}
Estadísticas de pedidos
Obtiene estadísticas de pedidos para un intervalo de fechas.
GET /orders/stats?startDate=2024-01-01&endDate=2024-01-31
Respuesta:
{
"totalOrders": 156,
"totalRevenue": 12450.50,
"averageOrderValue": 79.81,
"ordersByStatus": {
"pending": 5,
"processing": 12,
"shipped": 45,
"delivered": 90,
"cancelled": 4
}
}
Rastreo de carritos
Actualizar un carrito
Rastrea o actualiza el carrito de un usuario.
PUT /carts
Cuerpo de la solicitud:
{
"userId": "user_123",
"items": [
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"price": 29.99,
"quantity": 2,
"total": 59.98,
"imageUrl": "https://example.com/image.jpg"
}
],
"value": 59.98,
"currency": "USD",
"checkoutUrl": "https://store.example.com/checkout?cart=abc123"
}
Añadir al carrito
Añade un artículo al carrito de un usuario.
POST /carts/add
Cuerpo de la solicitud:
{
"userId": "user_123",
"item": {
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"price": 29.99,
"quantity": 1,
"total": 29.99
}
}
Obtener carritos abandonados
Lista carritos abandonados para campañas de recuperación.
GET /carts/abandoned
Parámetros de consulta:
| Parámetro | Tipo | Descripción |
|---|---|---|
minValue | número | Valor mínimo del carrito. |
abandonedMinutesAgo | número | Máximo de minutos desde el abandono. |
limit | número | Resultados por página. |
offset | número | Desplazamiento de paginación. |
Respuesta:
{
"data": [
{
"id": "cart_123",
"userId": "user_456",
"items": [...],
"value": 149.99,
"abandonedAt": "2024-01-20T15:30:00.000Z",
"checkoutUrl": "https://store.example.com/checkout?cart=abc"
}
],
"total": 42,
"hasMore": true
}
Estadísticas de carritos
Obtiene estadísticas de carritos y abandonos.
GET /carts/stats
Respuesta:
{
"totalCarts": 1250,
"abandonedCarts": 312,
"recoveredCarts": 87,
"totalAbandonedValue": 45670.50,
"recoveryRate": 27.88
}
Análisis RFM
El análisis RFM (recencia, frecuencia y valor monetario) segmenta a los clientes según su comportamiento de compra.
Obtener datos RFM de un usuario
Obtiene las puntuaciones y el segmento RFM de un usuario concreto.
GET /rfm/user/:userId
Respuesta:
{
"totalOrders": 12,
"totalSpent": 849.50,
"averageOrderValue": 70.79,
"firstOrderDate": "2023-06-15T10:00:00.000Z",
"lastOrderDate": "2024-01-18T14:30:00.000Z",
"daysSinceLastOrder": 2,
"hasActiveCart": false,
"rfmRecency": 5,
"rfmFrequency": 4,
"rfmMonetary": 4,
"rfmScore": "544",
"rfmSegment": "champions"
}
Obtener distribución RFM
Obtiene la distribución de clientes entre los segmentos RFM.
GET /rfm/distribution
Respuesta:
{
"champions": { "count": 150, "totalValue": 125000 },
"loyal": { "count": 320, "totalValue": 89000 },
"potential_loyalists": { "count": 180, "totalValue": 32000 },
"new_customers": { "count": 450, "totalValue": 28000 },
"at_risk": { "count": 95, "totalValue": 42000 },
"lost": { "count": 280, "totalValue": 15000 }
}
Segmentos RFM
| Segmento | Descripción | Puntuaciones RFM típicas |
|---|---|---|
| Campeones | Mejores clientes; compran a menudo y gastan más. | 555, 554, 545 |
| Leales | Clientes constantes. | 444, 443, 434 |
| Leales potenciales | Recientes, con frecuencia media. | 433, 343, 333 |
| Clientes nuevos | Acaban de hacer su primera compra. | 511, 512, 411 |
| Prometedores | Recientes, pero con frecuencia baja. | 422, 322, 312 |
| Necesitan atención | Interacción media en descenso. | 332, 322, 233 |
| A punto de dormirse | Por debajo de la media, en riesgo. | 211, 212, 221 |
| En riesgo | Fueron leales, pero no han comprado recientemente. | 144, 143, 244 |
| No se pueden perder | Fueron los mejores clientes y ahora están inactivos. | 155, 154, 255 |
| Hibernando | Interacción baja, inactivos desde hace tiempo. | 122, 121, 112 |
| Perdidos | Puntuaciones más bajas, probablemente abandonaron. | 111 |
Webhooks
Los eventos de e-commerce emiten webhooks que pueden activar flujos de Canvas:
| Evento | Descripción |
|---|---|
ecommerce.order.created | Se realizó un pedido nuevo. |
ecommerce.order.fulfilled | Pedido enviado. |
ecommerce.order.cancelled | Pedido cancelado. |
ecommerce.order.refunded | Pedido reembolsado. |
ecommerce.order.status_changed | Cambió el estado del pedido. |
ecommerce.cart.abandoned | Carrito marcado como abandonado. |
ecommerce.cart.recovered | Carrito abandonado recuperado. |
ecommerce.cart.updated | Cambió el contenido del carrito. |
Consultar por tus ID
Obtener un producto por tu ID de producto
Recupera un producto mediante tu identificador de producto.
GET /catalog/products/by-product-id/:productId
Ejemplo:
curl "https://api-eu1.joryio.com/catalog/products/by-product-id/SKU-12345" \
-H "Authorization: Bearer $TOKEN"
Obtener un pedido por tu ID de pedido
Recupera un pedido mediante tu identificador de pedido.
GET /orders/by-order-id/:orderId
Ejemplo:
curl "https://api-eu1.joryio.com/orders/by-order-id/ORD-2024-001" \
-H "Authorization: Bearer $TOKEN"
Respuestas de error
{
"statusCode": 404,
"message": "Product SKU-12345 not found",
"error": "Not Found"
}
| Código de estado | Descripción |
|---|---|
| 400 | Cuerpo de solicitud no válido. |
| 401 | Se requiere autenticación. |
| 403 | Permisos insuficientes. |
| 404 | Recurso no encontrado. |
| 409 | Conflicto (ID externo duplicado). |
| 500 | Error interno del servidor. |