PZCollector API

Referencia de endpoints REST en JSON. Contratos de request y response.

BASE URL  http://pzcolector.faceticket.com.mx
v2.1.260525BB05

01 Overview

Todos los endpoints usan POST salvo GET /health. Respuestas en JSON.

  • Error: { "error": "mensaje en minúsculas" }
  • Éxito simple: { "mensaje": "..." }
GET/health
Response 200
{
  "status": "ok",
  "service": "pzcollector-api",
  "version": "2.x.x"
}

02 Autenticación

Endpoints protegidos requieren credencial en body.key o header x-api-key (valor entregado por canal interno).

Exentos: GET /health, POST /auth/login y rutas /api/obtener_productos* (solo envían dispositivo).

POST/auth/login
Request
{
  "correo": "usuario@ejemplo.com",
  "password": "tu_password"
}
Response 200
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "usuario": {
    "id": 1,
    "nombre": "Nombre Apellido",
    "correo": "usuario@ejemplo.com"
  }
}

03 Productos (uso general)

Rutas bajo /api/. Body: solo dispositivo (ID del equipo).

POST/api/obtener_productos
Request
{
  "dispositivo": "98e9f34eb33cf873"
}
Response 200
{
  "productos": [
    {
      "id": 12,
      "identificador": "QWERTYUIOP",
      "nombre": "casa madero",
      "clave": "7503002087718",
      "costo": 20
    }
  ]
}
POST/api/obtener_productos_claves
Request
{
  "dispositivo": "98e9f34eb33cf873"
}
Response 200
{
  "productos": [
    {
      "id": 12,
      "identificador": "QWERTYUIOP",
      "nombre": "casa madero",
      "clave": "7503002087718",
      "claves_alternas": "7503002087718",
      "costo": 20
    }
  ]
}
POST/api/sincronizar_productos
Request
{
  "dispositivo": "98e9f34eb33cf873",
  "productos": [
    {
      "identificador": "QWERTYUIOP",
      "nombre": "Producto ejemplo",
      "clave": "987654321123",
      "claves_alternas": "987654321123|987654321124",
      "costo": 10
    }
  ]
}

id solo al actualizar. claves_alternas separadas por |. eliminar: true + id para borrar.

Response 200
{
  "mensaje": "sincronización de productos terminada correctamente",
  "resultados": []
}

04 Dispositivos

POST/dispositivos/validar
Request
{
  "dispositivo": "98e9f34eb33cf873"
}
Response 200
{
  "validado": true,
  "mensaje": "dispositivo validado y activo"
}
POST/dispositivos/sincronizar
Request
{
  "dispositivo": "98e9f34eb33cf873"
}
Response 200
{
  "usuario": {
    "id": 1,
    "nombre": "Nombre Apellido",
    "correo": "correo@ejemplo.com",
    "telefono": "+523331234567"
  },
  "sucursal": {
    "id": 1,
    "nombre": "Sucursal Centro",
    "foto": "",
    "portada": ""
  },
  "productos": [
    {
      "id": 1,
      "clave": "7503002087718",
      "nombre": "Producto ejemplo",
      "precio": 100,
      "existencias": 5
    }
  ]
}
POST/dispositivos/activar
Request
{
  "dispositivo": "98e9f34eb33cf873"
}
Response 200
{
  "mensaje": "dispositivo activado correctamente"
}

05 Transacciones

obtener: dispositivo obligatorio; id opcional (un registro). Sin id devuelve lista plural; con id devuelve clave singular.

POST/inventarios/obtener
Request
{
  "dispositivo": "98e9f34eb33cf873",
  "id": 19
}
Response 200 (lista)
{
  "inventarios": [
    {
      "id": 19,
      "identificador": "QWERTYUIOP",
      "fecha": "2023-01-30",
      "costo total": 355,
      "productos": 55,
      "conceptos": [
        {
          "id": 19,
          "identificador": "QWERTYUIOP",
          "clave": "7501011126244",
          "nombre": "producto 1",
          "costo": 25,
          "cantidad": 7
        }
      ]
    }
  ]
}

Con id la clave es inventario (array). Misma forma en cada ítem.

POST/pickings/obtener
Request
{
  "dispositivo": "98e9f34eb33cf873",
  "id": 19
}
Response 200
{
  "pickings": []
}

Con idpicking.

POST/rompefilas/obtener
Request
{
  "dispositivo": "98e9f34eb33cf873",
  "id": 19
}
Response 200
{
  "rompefilas": []
}

Con idrompefila.

POST/inventarios/guardar
Request
{
  "dispositivo": "98e9f34eb33cf873",
  "factura": 123,
  "total": 100,
  "productos": 3,
  "detalles": [
    {
      "claveUnidad": "7503002087718",
      "valorUnitario": 10,
      "cantidad": 1
    }
  ]
}
Response 200
{
  "mensaje": "inventario guardado correctamente"
}
POST/pickings/guardar

Mismo body y respuesta que /inventarios/guardar (mensaje: picking guardado).

POST/rompefilas/guardar

Mismo body que inventarios/guardar (mensaje: rompefila guardado).

06 Código QR

Formato: idproducto_cantidad#idproducto_cantidad#...

  • Separador entre pares: #
  • Separador id/cantidad: _
  • Máximo ~2,953 caracteres (~200–300 productos según longitud de IDs)

Ejemplo: 230_20.50#235_10#240_5#2300_2000#2500_55#

07 Errores

Todas las respuestas de error usan un solo campo error (string en minúsculas). No se expone statusCode ni stack traces.

  • 400 — validación o regla de negocio (dispositivo, datos vacíos, etc.)
  • 401 — falta o clave incorrecta en endpoints protegidos
  • 503 — base de datos (tabla/columna faltante, conexión)

400 — negocio

{
  "error": "no se encontro el dispositivo"
}

401 — autenticación

{
  "error": "envia la key"
}

503 — base de datos

{
  "error": "tabla de base de datos no encontrada — ejecuta migration.sql o import-mysql-dump.mjs"
}