Documentación de la API
API para que el sistema de una empresa cliente registre solicitudes de compra en nombre de sus empleados.
URL base: https://tiendagem.com · Todo viaja en JSON (Content-Type: application/json).
Requested y solo GEM la pasa a Sold.
1. Autenticación
GEM le entrega un clientId y un clientSecret. El secreto se
muestra una sola vez: si se pierde, hay que regenerarlo. Con ellos se pide un token
que dura 60 minutos y se envía en cada llamada.
POST /api/auth/token
{
"clientId": "su-client-id",
"clientSecret": "su-client-secret"
}
Respuesta 200:
{
"accessToken": "eyJhbGciOi...",
"tokenType": "Bearer",
"expiresInSeconds": 3600,
"expiresAt": "2026-08-14T15:30:00"
}
En las demás llamadas incluya la cabecera:
Authorization: Bearer <accessToken>
401 en el token significa siempre lo mismo —credenciales inválidas o
empresa inactiva— sin decir cuál de las dos. Si le ocurre de repente, es probable
que GEM haya revocado el token o regenerado el secreto.
2. Catálogo
Los precios ya vienen con el descuento de su empresa aplicado.
price es lo que paga el empleado; listPrice es el precio
de lista y se incluye solo como referencia.
| Método | Ruta | Devuelve |
|---|---|---|
| GET | /api/products | Arreglo de productos |
| GET | /api/products/{id} | Un objeto, sin arreglo |
GET /api/products → un arreglo, vacío ([]) si no hay nada asignado:
[
{
"id": 1,
"name": "Gafas formuladas",
"description": "Montura y lentes",
"sku": "GAF-001",
"listPrice": 150000.00,
"discountPercentage": 10.00,
"price": 135000.00,
"imageUrl": "https://..."
}
]
GET /api/products/1 → el objeto solo, no un arreglo de uno:
{
"id": 1,
"name": "Gafas formuladas",
"description": "Montura y lentes",
"sku": "GAF-001",
"listPrice": 150000.00,
"discountPercentage": 10.00,
"price": 135000.00,
"imageUrl": "https://..."
}
Si el producto no existe —o no está asignado a su empresa— la respuesta es
404 con el cuerpo de error, nunca un arreglo vacío.
imageUrl es un enlace temporal: genérelo de nuevo cuando lo necesite,
no lo guarde.
3. Solicitudes
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /api/sales | Arreglo de sus solicitudes |
| GET | /api/sales/{id} | Un objeto, sin arreglo |
| POST | /api/sales | Registrar una compra |
| PUT | /api/sales/{id}/cancel | Cancelar |
POST /api/sales
{
"employee": {
"name": "Juan",
"lastName": "Pérez",
"documentNumber": 1020304050,
"documentType": 0,
"phone": "3001234567",
"email": "juan.perez@empresa.com",
"city": "Bogotá"
},
"lines": [
{ "productId": 1, "quantity": 2 }
],
"externalReference": "SOL-001",
"notes": "Opcional"
}
Respuesta 201 — un objeto. Es la misma forma que devuelven
GET /api/sales/{id} y PUT /api/sales/{id}/cancel;
GET /api/sales devuelve un arreglo de estos:
{
"id": 15,
"status": "Requested",
"statusLabel": "Solicitado",
"saleDate": "2026-08-14T10:22:00",
"grossTotal": 300000.00,
"discountPercentage": 10.00,
"total": 270000.00,
"phone": "3001234567",
"email": "juan.perez@empresa.com",
"city": "Bogotá",
"externalReference": "SOL-001",
"notes": null,
"cancelledAt": null,
"employee": { "id": 3, "name": "Juan", "lastName": "Pérez", "phone": "3001234567", ... },
"lines": [
{ "productId": 1, "productName": "Gafas formuladas",
"quantity": 2, "unitPrice": 150000.00, "subtotal": 300000.00 }
]
}
Cinco cosas que conviene saber
-
phone,emailycityson opcionales, para no romper integraciones ya en marcha, pero envíelos: quedan guardados en la solicitud tal como llegaron y GEM los usa para contactar y entregar. Si los manda distintos a los de una compra anterior, se actualiza la ficha del empleado; si los omite, se conserva lo que ya había. - No hace falta registrar empleados. Se crean solos la primera vez que compra ese documento. Si el mismo documento vuelve, se reutiliza el registro, y así las compras quedan agrupadas por persona.
-
externalReferencehace el POST idempotente. Si su sistema reintenta con la misma referencia, recibe la solicitud existente en vez de crear una segunda. Úselo siempre: es su seguro contra cobros duplicados. - El precio se congela al momento de registrar. Un cambio posterior en el catálogo, o en el descuento de su empresa, no altera lo ya solicitado.
-
Los valores los calcula GEM. Usted envía únicamente
productIdyquantity. La petición no acepta precios ni totales: si los envía, se ignoran.grossTotales la suma a precio de lista, se le aplicadiscountPercentagey el resultado estotal.
PUT /api/sales/{id}/cancel
Sin cuerpo. Solo funciona dentro del plazo acordado con su empresa y mientras la
solicitud siga en Requested. Cancelar dos veces no da error.
4. Datos personales
Cada POST /api/sales transporta datos identificables de un empleado suyo.
Esta sección dice qué hace GEM con ellos y qué se espera de usted, según la
Ley 1581 de 2012.
Qué guarda GEM de cada solicitud
Nombres y apellidos, tipo y número de documento, la empresa a la que pertenece y el detalle de la compra. Nada más: no pedimos correo, teléfono, dirección ni cargo, y no hay pasarela de pago, así que por esta API no viaja ningún dato financiero.
Envíe lo mínimo
-
No use
notesniexternalReferencepara datos personales. Son campos de texto libre pensados para su número de caso o una observación logística. Un correo, un teléfono o un diagnóstico ahí terminan almacenados sin necesidad y fuera de lo acordado. - No envíe datos sensibles. Ni fórmulas médicas, ni diagnósticos, ni historia clínica, ni datos biométricos o sindicales. La API no tiene dónde ponerlos y GEM no los quiere: son datos sensibles del artículo 5 de la Ley 1581 y exigen un régimen que esta integración no contempla.
- Solo empleados mayores de edad. Aunque el catálogo de tipos de documento incluye la tarjeta de identidad, la tienda está dirigida a trabajadores adultos.
POST como
registro de auditoría de la integración, salvo el de /api/auth/token,
que se excluye por contener el clientSecret. Téngalo presente al decidir
qué incluye en la petición: es otra razón para no mandar de más.
Si un empleado ejerce sus derechos
Un empleado puede pedir conocer, actualizar, rectificar o suprimir sus datos. Si la petición le llega a usted y se refiere a lo que está en la tienda, remítala al canal de la política de tratamiento de GEM. Los plazos legales —10 días hábiles para una consulta, 15 para un reclamo— corren desde que la petición se recibe, así que no la deje reposar.
Seguridad de la integración
- Llame siempre por
https. Una petición en claro expone documentos de identidad. -
Guarde el
clientSecreten un almacén de secretos, nunca en el código fuente ni en un archivo de configuración versionado. -
No reenvíe el
accessTokenal navegador del empleado ni a sistemas de terceros: identifica a su empresa entera, no a una persona. - Si sospecha que el secreto se filtró, pida a GEM regenerarlo. Eso revoca de inmediato todos los tokens emitidos con el anterior.
Tipos de documento
| Valor | Significado |
|---|---|
0 | Cédula de ciudadanía |
1 | Tarjeta de identidad |
2 | Cédula de extranjería |
3 | Otra |
4 | Permiso especial de permanencia |
5 | Permiso por protección temporal |
6 | Pasaporte |
Estados de una solicitud
status | statusLabel |
|---|---|
Requested | Solicitado |
Sold | Vendido |
CancelledByCustomer | Cancelada por el cliente |
Compare siempre contra status, no contra statusLabel:
la etiqueta es texto para mostrar y puede cambiar.
Códigos de respuesta
200 / 201 | Todo bien. |
400 | Datos incompletos, o producto inexistente o no asignado a su empresa. |
401 | Token ausente, vencido o revocado. |
404 | El recurso no existe para su empresa. |
409 | Venció el plazo de cancelación, o ya fue vendida. |
Los errores siempre traen la misma forma:
{ "message": "El plazo para cancelar esta solicitud venció el 14/08/2026 10:22." }
404, no 403, para no revelar
siquiera que existe.
¿Dudas o necesita credenciales? Escriba a su contacto en GEM — Grupo Empresarial Masa.