Precio de Góndola

API para desarrolladores

Con esta API, el sistema de gestión del comercio (su ERP) mantiene al día en Precio de Góndola los artículos, sus códigos de barras y sus precios. Lo que llega por la API aparece en el portal y en las terminales de mano, igual que si se hubiera cargado a mano.

Está incluida en el plan Clásica.

1. Para empezar

Todo se habla en JSON, por HTTPS, contra https://preciodegondola.com/api/v1. Probá que la llave anda con:

curl https://preciodegondola.com/api/v1/yo \
  -H "Authorization: Bearer pdg_api_TU_LLAVE"

2. La llave

La crea alguien del comercio en el portal, en Configuración › Conexión con tu sistema (API). Empieza con pdg_api_ y se ve una sola vez: guardala como un secreto (en una variable de entorno, nunca en el código ni en un repositorio). Viaja en cada pedido en la cabecera:

Authorization: Bearer pdg_api_TU_LLAVE

La API cambia cosas en nombre de la persona que creó la llave. Si a esa persona le sacan el permiso de cargar artículos, o el comercio la revoca desde el portal, la llave deja de andar en el acto (vas a recibir un 401 o un 403).

3. Reglas generales

4. Quién soy: listas y campos

GET/api/v1/yo

De qué comercio es la llave, si puede escribir, sus listas de precios y los campos que usa. Llamalo al conectar para saber qué listas y campos existen.

{
  "comercio": "Supermercado Demo",
  "llave": "Mi ERP",
  "puede_escribir": true,
  "motivo_sin_escritura": null,
  "listas": [
    { "id": "4f6a…", "nombre": "Minorista" },
    { "id": "9b21…", "nombre": "Mayorista" }
  ],
  "campos": [
    { "clave": "sku", "nombre": "Código interno", "tipo": "texto", "opciones": [], "del_sistema": true },
    { "clave": "pasillo", "nombre": "Pasillo", "tipo": "lista", "opciones": ["1", "2", "3"], "del_sistema": false }
  ],
  "limites": { "por_pedido": 5000, "pedidos_por_minuto": 120, "por_pagina": 1000 }
}

5. Leer artículos

GET/api/v1/articulos

Los artículos, ordenados por código interno, de a páginas.

ParámetroQué es
despues_dePara la página siguiente: el valor de siguiente que vino en la respuesta anterior. En la primera, no se manda.
por_paginaCuántos por página (hasta 1000; si no se dice, 500).
modificados_desdeSólo los que cambiaron (datos, precios o códigos) después de esa fecha y hora, en ISO 8601. Ej.: 2026-10-03T08:00:00-03:00.
incluir_bajasCon true trae también los dados de baja.
curl "https://preciodegondola.com/api/v1/articulos?por_pagina=500" \
  -H "Authorization: Bearer pdg_api_TU_LLAVE"
{
  "por_pagina": 500,
  "hay_mas": true,
  "siguiente": "1500",
  "articulos": [
    {
      "sku": "1001",
      "descripcion": "Yerba Playadito 1 kg",
      "descripcion_corta": "Yerba Playadito",
      "marca": "Playadito",
      "rubro": "Almacén",
      "unidad_venta": "UN",
      "contenido": 1,
      "unidad_contenido": "KG",
      "campos": { "pasillo": "3" },
      "codigos_de_barras": ["7790001000012"],
      "precios": [
        { "lista_id": "4f6a…", "lista": "Minorista", "precio": 4500 },
        { "lista_id": "9b21…", "lista": "Mayorista", "precio": 3900 }
      ],
      "activo": true,
      "actualizado_en": "2026-10-03T11:20:00.000Z"
    }
  ]
}

Mientras hay_mas sea true, pedí la siguiente con despues_de=<valor de siguiente>.

GET/api/v1/articulos/{sku}

Un artículo por su código interno (con el mismo formato). Si no existe: 404 articulo_inexistente.

6. Crear y modificar artículos

POST/api/v1/articulos

Si el código interno existe, se actualiza; si no, se crea (para crearlo hace falta descripcion). Se pueden mandar los datos, los códigos de barras y los precios juntos.

curl -X POST https://preciodegondola.com/api/v1/articulos \
  -H "Authorization: Bearer pdg_api_TU_LLAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "articulos": [
      {
        "sku": "1001",
        "descripcion": "Yerba Playadito 1 kg",
        "marca": "Playadito",
        "rubro": "Almacén",
        "unidad_venta": "UN",
        "contenido": 1,
        "unidad_contenido": "KG",
        "codigos_de_barras": ["7790001000012"],
        "precios": { "Minorista": 4500, "Mayorista": 3900 }
      },
      { "sku": "1002", "marca": "Cocinero" }
    ]
  }'
DatoTipoQué es
skutextoObligatorio. El código interno del artículo en tu sistema.
descripciontextoEl nombre. Obligatorio para crear.
descripcion_cortatextoEl nombre para la etiqueta chica.
marcatexto
rubrotextoSi no existe, se crea.
unidad_ventatextoCómo se vende: UN, KG o LT.
contenidonúmeroCuánto trae el envase (1.5 para 1,5 litros). Va con su unidad.
unidad_contenidotextoKG, GR, LT, ML o UN.
camposobjetoLos campos propios del comercio, por su clave: { "pasillo": "3" }. Las claves salen de /yo (los que tienen del_sistema: false). Cada valor según su tipo: texto y lista como texto (en una lista, una de sus opciones), numero como número, si_no como true/false, fecha como "AAAA-MM-DD".
codigos_de_barraslista de textosEl artículo queda con exactamente estos códigos: se agregan los nuevos y se quitan los que no están. Una lista vacía no quita nada. Van como texto (un número pierde los ceros de adelante) y sin comas, punto y coma ni barras.
preciosobjetoPrecio final por lista: la clave es el nombre o el id de la lista. { "Minorista": 4500 }.
activotrue / falsefalse lo da de baja y true lo reactiva. Si no viene, no cambia.

Un dato que no está en esta tabla hace que se rechace ese artículo (así un error de tipeo no pasa en silencio). También se rechaza uno que el comercio no usa: si apagó la marca en su ficha, mandar marca rechaza el artículo. Los datos que usa están en /yo.

7. Cambiar precios

POST/api/v1/precios

Para cuando sólo cambian precios: más liviano que mandar el artículo entero. La lista va por su nombre o id. Un código interno que no existe se rechaza (los artículos se crean por /articulos).

curl -X POST https://preciodegondola.com/api/v1/precios \
  -H "Authorization: Bearer pdg_api_TU_LLAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "precios": [
      { "sku": "1001", "lista": "Minorista", "precio": 4650 },
      { "sku": "1001", "lista": "Mayorista", "precio": 3990.5 },
      { "sku": "1002", "lista": "Minorista", "precio": 2100 }
    ]
  }'

8. Dar de baja

POST/api/v1/bajas

Da de baja artículos por su código interno. No se borra nada: el artículo, su historial de precios y lo que se imprimió quedan, y se reactiva mandándolo con "activo": true. También se puede dar de baja con "activo": false en /articulos.

curl -X POST https://preciodegondola.com/api/v1/bajas \
  -H "Authorization: Bearer pdg_api_TU_LLAVE" \
  -H "Content-Type: application/json" \
  -d '{ "skus": ["1005", "1006"] }'

9. Respuestas y rechazos

Los pedidos que escriben contestan 200 con lo que se hizo, aunque algo se haya rechazado:

{
  "recibidos": 3,
  "creados": 1,
  "actualizados": 1,
  "precios_cambiados": 2,
  "codigos_agregados": 1,
  "codigos_quitados": 0,
  "dados_de_baja": 0,
  "reactivados": 0,
  "rechazados": [
    { "posicion": 3, "sku": "1003", "motivo": "El precio de «Minorista» tiene que ser un número JSON mayor o igual a 0 (1234.5), no un texto." }
  ],
  "opciones_creadas": []
}

posicion es el lugar del elemento en la lista que mandaste, contando desde 1. Revisá siempre rechazados: lo que está ahí no entró. Corregilo y volvé a mandar sólo eso. precios_cambiados cuenta los precios que se escribieron, aunque alguno haya quedado igual que antes.

10. Errores

Cuando el pedido entero no se puede atender, la respuesta trae un código HTTP de error y siempre la misma forma:

{ "error": { "codigo": "llave_invalida", "mensaje": "La llave no existe o fue revocada." } }
HTTPCódigoQué pasó
400pedido_invalido · json_invalido · fecha_invalidaFalta la lista (articulos, precios o skus), el cuerpo no es un JSON válido o «modificados_desde» no es una fecha.
401sin_llave · llave_invalidaFalta la llave, o no existe, o fue revocada.
403usuario_sin_permiso · plan_sin_api · comercio_suspendido · cuenta_limitadaLa llave existe pero no puede hacer eso.
404articulo_inexistenteNo hay un artículo con ese código interno.
409conflictoOtro pedido estaba cambiando los mismos artículos al mismo tiempo. Reintentá.
413pedido_grandeMás de 5.000 elementos: partilo en tandas. (Un cuerpo de más de 4 MB lo corta el servidor antes, con un 413 que no es JSON.)
429demasiados_pedidosMás de 120 pedidos en un minuto: esperá y mandá en tandas más grandes.
500error_internoFalló algo de nuestro lado. Reintentá en unos minutos.

Ante un 409, un 429 o un 500, reintentá con espera creciente (por ejemplo 1, 2, 4 y 8 minutos). Reintentar es seguro.

11. Cómo sincronizar

La primera vez

Llamá a /yo para conocer las listas. Mandá todo el catálogo por /articulos, en tandas de hasta 5.000.

Después

Mandá sólo lo que cambió en tu sistema: precios por /precios, artículos nuevos o modificados por /articulos, y bajas por /bajas. Lo habitual es cada pocos minutos, o cuando se guarda un cambio.

Si querés traer lo que se cambió en el portal

Guardá el actualizado_en más nuevo que recibiste y la próxima vez pedí /articulos?modificados_desde=ESA_HORA_MENOS_5_MINUTOS&incluir_bajas=true. Restale 5 minutos: una carga grande que estaba en curso mientras leías puede quedar con una hora un poco anterior, y así no se pierde. Volver a recibir un artículo no hace daño. Con incluir_bajas=true te enterás también de los que se dieron de baja desde el portal ("activo": false).

Ojo: si reenviás todo el catálogo, todos los artículos quedan como modificados y la próxima lectura los trae a todos.

12. Especificación OpenAPI

Para generar un cliente o probar desde Postman o Insomnia: /api/v1/openapi.json (OpenAPI 3.1).

¿Dudas con la integración? Escribinos a hola@preciodegondola.com.