API: productos y perfiles
Contrato general en Cómo funciona la API. Todo queda acotado a la cuenta de la key,
que no necesita enviar clientId ni accountId al crear (se ignoran si apuntan a otra cuenta).
Productos
POST /products
GET /products
GET /products/:id
PATCH /products/:id
PATCH /products/:id/deactivate
PATCH /products/:id/activate
DELETE /products/:id
Crear un producto — 201
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
businessLine | 'vending' | 'eas' | sí | debe estar habilitada en la cuenta |
name | string | sí | mín. 2 |
type | string | sí | clave del selector product_types (GET /selectors/product_types) |
cost | entero | sí | unidades menores, ≥ 0 |
code | string | no | informativo, único por cuenta entre los vivos |
description | string | no | — |
currency | string | no | si se envía debe coincidir con la de la cuenta |
attributes | objeto | sí | su forma depende de la línea (abajo) |
attributes para EAS:
{ "returnPolicy": { "isReturnable": true, "restrictDelivery": false } }
attributes para vending:
{ "taxRate": 19, "listPrice": 3000, "suggestedPrice": 3000 }
Ejemplo completo:
curl -X POST https://api.inssacs.com/products \
-H 'x-api-key: ics_…' -H 'content-type: application/json' \
-d '{
"businessLine": "eas",
"name": "Casco de seguridad",
"type": "epp",
"code": "EPP-CAS",
"cost": 38000,
"attributes": { "returnPolicy": { "isReturnable": true, "restrictDelivery": true } }
}'
Editar — 200
PATCH /products/:id acepta name, code, description, cost, type, easAttributes y
vendingAttributes (todos opcionales). No se cambia la línea de negocio ni la cuenta.
Listar
Query: businessLine, isActive, search (nombre, código o tipo), code, page, pageSize
(máx. 1000). Respuesta { items, total, page, pageSize }.
Bajas
deactivate / activate responden 204. DELETE responde 204 y quita el producto del planograma
de todos los dispositivos y de los perfiles EAS que lo incluyan; las entregas históricas se conservan.
Errores: 404 products.not_found, 409 products.code_exists,
400 products.attributes_mismatch, 400 products.currency_mismatch,
403 products.not_visible_to_scope.
Perfiles
POST /profiles
GET /profiles
GET /profiles/:id
PATCH /profiles/:id
PATCH /profiles/:id/deactivate
PATCH /profiles/:id/activate
DELETE /profiles/:id
Un perfil es de la cuenta y de una línea; dónde funciona lo define allowedDevices. Concepto en
Códigos y perfiles.
Crear un perfil — 201
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
accountId | string | sí | la cuenta de la key |
businessLine | 'vending' | 'eas' | sí | — |
name | string | sí | mín. 2, único por cuenta |
period | objeto | sí | ver abajo |
policy | objeto | sí | su forma depende de la línea |
allowedDevices | string[] | no | ids de dispositivo, hasta 5000. Vacío = no dispensa en ninguna parte |
consumptionSchedule | objeto | null | no | días permitidos |
period — predefinido o fechas concretas:
{ "type": "preset", "value": "monthly" }
{ "type": "custom", "dates": ["2026-09-01T00:00:00.000Z", "2026-09-15T00:00:00.000Z"] }
Valores de value: daily, weekly, biweekly, monthly, quarterly, semiannual, annual.
policy para vending (importes en unidades menores):
{ "defaultReloadValue": 50000, "maxBalance": 200000, "cumulative": false }
policy para EAS (al menos un producto; quantity: null = ilimitado):
{
"products": [
{ "productId": "665f…d0", "quantity": 1, "minutesBetweenDeliveries": 43200 },
{ "productId": "665f…d1", "quantity": null, "minutesBetweenDeliveries": 720 }
]
}
consumptionSchedule — su presencia es la que restringe; un objeto vacío bloquea todos los días:
{
"weekdays": [1, 2, 3, 4, 5],
"includeDates": ["2026-12-24T00:00:00.000Z"],
"excludeDates": ["2026-12-25T00:00:00.000Z"]
}
weekdays va de 0 (domingo) a 6 (sábado).
Ejemplo:
curl -X POST https://api.inssacs.com/profiles \
-H 'x-api-key: ics_…' -H 'content-type: application/json' \
-d '{
"accountId": "665f0f1c2e8a4b0012a3b4c6",
"businessLine": "vending",
"name": "Subsidio Operarios",
"period": { "type": "preset", "value": "monthly" },
"policy": { "defaultReloadValue": 50000, "maxBalance": 100000, "cumulative": true },
"allowedDevices": ["665f…d1", "665f…d2"]
}'
Editar — 200
PATCH /profiles/:id acepta name, period, consumptionSchedule, allowedDevices, easPolicy y
vendingPolicy. allowedDevices se reemplaza completo: hay que enviar la lista final, no un
delta.
Listar
Query: businessLine, isActive, search (nombre), page, pageSize.
Bajas
deactivate / activate → 204. DELETE → 204, pero 409 profiles.in_use si el perfil tiene
códigos asignados: primero reasígnalos.
Errores propios: 404 profiles.not_found, 409 profiles.name_exists,
400 profiles.device_not_in_account, 400 profiles.duplicate_device,
400 profiles.device_business_line_mismatch, 400 profiles.product_not_visible_to_account,
400 profiles.invalid_consumption_schedule, 403 profiles.actor_scope_not_allowed.