Ir al contenido
Pide tu alta

Usar la API

En corto

Todo /public/v1 usa cursor para paginar, Idempotency-Key para no duplicar una venta o un contacto, y devuelve 429 con Retry-After si te pasas de 120 lecturas o 30 escrituras por minuto. El dinero siempre va en _usd/_ves como texto, nunca como número.

https://api.wink-pos.com/public/v1

Todas las listas usan un cursor opaco: ?limit= (1 a 100, 50 por defecto) y ?cursor=.

{ "data": [/* ... */], "nextCursor": "eyJvZmZzZXQiOjUwfQ" }
  • Sin cursor: empieza en la primera página.
  • nextCursor: null: no hay más páginas.
  • Un cursor inválido o de otra instalación responde 400 invalid_cursor: nunca vuelve en silencio al principio. Si tu sincronización guarda un cursor viejo, tienes que enterarte, no repetir el mismo tramo para siempre.

Productos, ubicaciones, categorías, existencias, ventas y contactos aceptan ?updatedSince= (fecha ISO 8601). No está disponible en listas de precios.

Una fila que cambia durante el recorrido puede aparecer dos veces en la misma pasada (nunca se pierde): deduplica siempre por id.

Usa el mismo updatedSince en todas las páginas de un recorrido: el nextCursor que recibes con updatedSince solo sirve con updatedSince y en ese mismo recurso. Si lo mandas sin él, o a otro recurso, responde 400 invalid_cursor. Ante ese 400, vuelve a empezar el recorrido desde tu último updatedSince: es seguro, porque deduplicas por id.

Todo POST que crea un documento exige el encabezado Idempotency-Key:

POST /public/v1/sales
Idempotency-Key: 8f2c4e10-3b7a-4e2a-9b1a-6a7c4e1a2b3c
  • Sin el encabezado: 400 idempotency_key_required.
  • Clave repetida, mismo cuerpo: 200 con el documento que ya existía (no 201: no crea uno nuevo).
  • Clave repetida, cuerpo distinto: 422 idempotency_key_reused. La comparación es aproximada (ubicación, canal, cliente y líneas/cobros en el mismo orden), no un hash exacto del JSON.
  • Usa un id estable de tu lado como clave: por ejemplo, el id del pedido en tu sistema. Reenviar la misma clave ante un timeout o un reintento de red siempre es seguro.
  • Un PATCH no necesita Idempotency-Key: aplicarlo dos veces deja el recurso en el mismo estado.
Cupo Límite
Lectura (GET) 120 por minuto por instalación
Escritura (el resto de métodos) 30 por minuto por instalación

Pasado el límite: 429 rate_limited, con Retry-After, RateLimit-Limit y RateLimit-Remaining del cupo que tocaste. Respeta Retry-After antes de reintentar.

{
"error": {
"code": "insufficient_scope",
"message": "Falta el permiso catalog.view",
"details": [{ "field": "scope", "issue": "catalog.view" }]
}
}

details solo aparece en errores de validación, con el campo exacto que falló. La lista completa de códigos estables está en Referencia › Errores.

  • Fechas en ISO 8601, UTC.
  • Montos en dos monedas, siempre como string decimal, nunca número: amountUsd y amountVes, más exchangeRate cuando aplica. No los parsees como float: usa una librería decimal de tu lenguaje para sumarlos o compararlos.

Vives en v1. Dentro de v1 solo hay cambios compatibles: campos nuevos opcionales y endpoints nuevos. Un cambio que rompe algo existente sale como v2, con al menos 6 meses de convivencia con v1. Revisa Cambios para el historial de cada versión del contrato.