API de Pickea
Si tu tienda no está en Mercado Libre, Tiendanube ni Shopify, la conectás por acá. Consultás cuánto stock tenés, nos mandás las ventas, y te avisamos cuando pasa algo con ellas.
Todo bajo https://app.pickea.com.ar/api/v1. JSON entra y JSON sale.
Autenticación
Una llave por integración, en el header Authorization. La creás desde tu cuenta, en API.
Authorization: Bearer pk_xxxxxxxxxxxxxxxxxxxxxxxxLa llave puede crear ventas a tu nombre, así que tratala como una contraseña: en una variable de entorno del servidor, nunca en el código de tu página. Cualquier llamada desde el navegador de un comprador expone la llave a quien abra las herramientas de desarrollo.
Consultar stock
GET/api/v1/stock
Lo que tenés en nuestro galpón, SKU por SKU. Parámetros opcionales: sku (separados por coma) y pagina.
Pedido
curl https://app.pickea.com.ar/api/v1/stock?sku=REM-M,REM-L \
-H "Authorization: Bearer $PICKEA_API_KEY"Respuesta
{
"stock": [
{
"sku": "REM-M",
"nombre": "Remera M",
"codigoInterno": "2000000001",
"disponible": 42,
"reservado": 3,
"propio": { "PROPIO_VENDEDOR": 10, "MELI_FULL": 5 }
}
],
"pagina": 1,
"porPagina": 200,
"total": 1
}| Campo | Qué es |
|---|---|
| disponible | Lo que se puede vender ya mismo desde nuestro galpón. Es el número que se publica. |
| reservado | Comprometido con una venta que todavía no salió. No se puede vender, pero explica la diferencia con lo que tenés guardado. |
| propio | Lo que declaraste que tenés fuera de Pickea, por origen. Vacío si no declaraste nada. |
Cargar una venta
POST/api/v1/ordenes
Entra por el mismo camino que una venta cargada a mano: reserva stock al crearse y, si no alcanza, nace frenada en SIN_STOCK y sigue sola cuando entre mercadería. No hay un camino de creación “para la API”.
Pedido
curl -X POST https://app.pickea.com.ar/api/v1/ordenes \
-H "Authorization: Bearer $PICKEA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"claveIdempotencia": "venta-8842",
"numeroExterno": "#8842",
"comprador": {
"nombre": "Ana Gómez",
"documento": "30111222",
"email": "ana@ejemplo.com",
"telefono": "1155667788"
},
"envioA": {
"calle": "Av. Rivadavia",
"numero": "5400",
"piso": "3",
"depto": "B",
"codigoPostal": "C1424",
"localidad": "Caballito",
"provincia": "CABA"
},
"lineas": [
{ "sku": "REM-M", "cantidad": 2, "precioUnitarioCentavos": 1899000 }
]
}'Respuesta · 201
{
"ordenId": "cm...",
"numero": "ORD-ACME-000123",
"estado": "PENDIENTE",
"diaOperativo": "2026-08-27"
}| Campo | Obligatorio | Detalle |
|---|---|---|
| claveIdempotencia | Sí | Tu id de venta. Hasta 120 caracteres. |
| lineas[].sku | Sí | El SKU tal como está en tu catálogo de Pickea. |
| lineas[].cantidad | Sí | Entero mayor a cero. |
| lineas[].precioUnitarioCentavos | No | Centavos de ARS, entero. Nunca decimales. |
| numeroExterno | No | El número que ve tu comprador. Aparece en el remito. |
| comprador | No | Nombre, documento, email y teléfono. |
| envioA | No | Opcional a propósito: una venta ya hecha no se rechaza por un dato que falta. La orden nace sin destino y queda marcada — lo que sí se bloquea es empaquetarla así. Mandalo siempre y el pedido sale solo. |
| observaciones | No | Hasta 500 caracteres. Los ve quien prepara el pedido. |
El dinero va en centavos, siempre entero. 1899000 son $18.990. Nunca mandes decimales: un 18990.00 en punto flotante pierde centavos, y acá los centavos son plata de verdad.
Errores
Siempre JSON con error. El código dice qué hacer.
| Código | Qué pasó | Qué hacer |
|---|---|---|
| 401 | Llave inválida o revocada. | No reintentes. Revisá la llave. |
| 409 | Esa clave de idempotencia se está procesando ahora mismo. | Reintentá en unos segundos. La orden se está creando. |
| 422 | El cuerpo no cumple el contrato, o hay SKU que no están en tu catálogo (vienen en `skus`). | No reintentes igual: corregí y volvé a mandar. |
| 429 | Pasaste el tope por minuto. | Esperá lo que dice `retry-after` (en segundos) y reintentá. |
| 5xx | Se rompió de nuestro lado. | Reintentá con la MISMA clave de idempotencia: es seguro. |
422 con SKU desconocidos
{
"error": "Hay SKU que no están en tu catálogo.",
"skus": ["REM-XXL"]
}Webhooks: te avisamos a vos
Configurás una URL y te mandamos un POST cuando pasa algo con tus pedidos. Así no tenés que preguntar cada cinco minutos si ya salió.
Lo que te llega
POST https://tu-sistema.com/hook
x-pickea-evento: orden.despachada
x-pickea-fecha: 2026-08-27T14:03:11.000Z
x-pickea-firma: 9f2c...
x-pickea-entrega: cm...
Content-Type: application/json
{ "titulo": "Tu pedido salió", "cuerpo": "...", "ordenId": "cm..." }Verificá la firma antes de hacerle caso a un aviso. Es un HMAC-SHA256 sobre {fecha}.{cuerpo crudo} con el secreto que te damos al configurar el webhook. La fecha entra en la firma para que una entrega vieja capturada no se pueda reenviar como si fuera de ahora.
Verificarla (Node)
import { createHmac, timingSafeEqual } from "node:crypto";
function firmaValida(fecha, cuerpoCrudo, firmaRecibida, secreto) {
const esperada = createHmac("sha256", secreto)
.update(`${fecha}.${cuerpoCrudo}`, "utf8")
.digest("hex");
const a = Buffer.from(esperada, "utf8");
const b = Buffer.from(firmaRecibida.trim(), "utf8");
// Comparación en tiempo constante: con === se puede adivinar byte a byte.
return a.length === b.length && timingSafeEqual(a, b);
}Contestá 2xx apenas lo recibas y hacé el trabajo después. Si contestás 4xx no reintentamos —damos por hecho que lo rechazaste—; ante un 5xx o un timeout reintentamos a los 1, 5, 15, 60 y 180 minutos, y después lo dejamos. Usá x-pickea-entrega como clave de idempotencia: un reintento nuestro trae el mismo id.
Eventos
| Evento | Cuándo |
|---|---|
| asn.recibido | Terminamos de recibir un envío tuyo. Si hubo diferencias, vienen en el detalle. |
| cuenta.aviso_mora | Tenés una liquidación vencida. A los 14 días se frenan los despachos. |
| cuenta.bloqueo_mora | Se frenaron los despachos por mora. Se destraba solo al acreditarse lo vencido. |
| devolucion.recibida | Llegó una devolución. Todavía no vuelve a stock: primero se inspecciona. |
| liquidacion.emitida | Se cerró la semana y tenés una liquidación nueva, con su vencimiento. |
| orden.cortada | Faltó mercadería al prepararla y sale incompleta. Avisale al comprador antes que él te reclame. |
| orden.despachada | Salió del galpón. Trae el transportista y el seguimiento si el envío ya lo tiene. |
| orden.no_entregada | El transportista no pudo entregarla. |
| orden.repuesta | Entró stock y una orden frenada consiguió reserva. Ya va a preparación. |
| orden.sin_stock | La venta entró pero no alcanzó el stock. Queda frenada y sigue sola cuando entre mercadería. |
| pago.acreditado | Vimos tu transferencia y se imputó. |
| pago.rechazado | No pudimos conciliar un pago informado. Viene el motivo. |
| sistema.aviso | Un aviso nuestro que no entra en las categorías de arriba. |
| stock.bajo | Un SKU bajó del mínimo que configuraste. |
Límites
| Qué | Cuánto |
|---|---|
| Llamadas por minuto | 60, por llave |
| SKU por respuesta de stock | 200 (paginado con `pagina`) |
| Líneas por orden | Sin tope práctico; un SKU no se puede repetir en la misma venta |
El tope es por llave y no por vendedor: una integración desbocada no te frena las otras. Si tenés varios sistemas conectados, dale una llave a cada uno.