Skip to main content
En vez de consultar cada pedido cada tanto, podés recibir un aviso en tu servidor cuando algo cambia: se pagó, entró a producción, se despachó, se entregó o se canceló.

Dar de alta un destino

Los destinos se administran sólo desde tu panel, en Integraciones > API > Avisos. No se pueden crear por API, a propósito: así una clave filtrada no puede sumar un destino para llevarse datos. Gudink no puede mandar avisos a localhost, a una IP ni a un puerto que no sea 443. Para probar en tu máquina, ver Probar tu destino sin publicarlo.

Eventos

  • Sólo se avisan los pedidos creados por la API.
  • ready_to_ship, delivery_failed y la vuelta de on_hold a pending_payment no tienen evento propio: los ves en el status del próximo aviso o con GET /orders/:id.
  • No hay avisos de productos: un evento product.updated todavía no existe.
  • Volver a entrar al mismo estado no se avisa dos veces. Si un pedido se pausa, se reanuda y se vuelve a pausar por el mismo motivo, recibís un solo order.on_hold. Si necesitás el estado exacto de ahora, pedilo con GET /orders/:id.

El cuerpo del aviso

Un aviso de pedido:
El aviso no trae el nombre, el teléfono ni la dirección de tu comprador. Si los necesitás, consultá el pedido con tu clave.

El aviso de prueba

El aviso de “Mandar prueba” es un evento propio, sin order. En la especificación es el esquema WebhookTestEvent. Llega con las mismas tres cabeceras y la misma firma que cualquier aviso:
Trae sólo id, type y created_at. Verificá la firma igual que en cualquier aviso, respondé 2xx y no busques ningún pedido.

Cómo tiene que responder tu servidor

  1. Verificá la firma antes de hacer nada con el contenido (ver Verificar la firma).
  2. Respondé cualquier 2xx en menos de 10 segundos. Guardá el aviso, respondé, y procesalo después. No hagas el trabajo pesado antes de contestar.
  3. Deduplicá por webhook-id. El mismo aviso puede llegar más de una vez.
  4. No dependas del orden de llegada, ni entre pedidos distintos ni dentro de un mismo pedido: order.in_production puede llegar antes que order.paid. El campo status del aviso, o GET /orders/:id, dice dónde está el pedido. Quedate con el último que procesaste por created_at.
Qué status devolver en cada caso: Si recibís avisos reales con firma inválida, tu secreto está mal cargado: corregilo antes de que el destino se desactive.

Reintentos de un aviso

Además, tus destinos se desactivan junto con tus claves cuando cambia quién controla la cuenta. Ver Cuándo se revocan solas.

Cómo ponerte al día después de una caída

Si tu servidor estuvo caído, o un destino se desactivó, no hace falta esperar avisos: reconstruí el estado consultando.
  1. Guardá siempre el created_at del último pedido que tenés.
  2. Pedí GET /orders?created_after=<ese instante> y seguí con next_cursor hasta que sea null. Son los pedidos que te faltan.
  3. Para los pedidos que ya tenías, pedí GET /orders?updated_after=<la última vez que te pusiste al día> y seguí con next_cursor hasta que sea null. Actualizá los que tengan un updated_at más nuevo que el tuyo. Es una sola consulta paginada, en vez de un GET /orders/:id por pedido.

Verificar la firma

Cada aviso trae tres cabeceras, con el formato Standard Webhooks: La firma es un HMAC-SHA256 del texto <webhook-id>.<webhook-timestamp>.<cuerpo crudo>. La clave del HMAC es tu secreto, sin el prefijo whsec_ y decodificado de base64. Tres reglas:
  • Usá el cuerpo crudo, tal como llegó. Si lo convertís a objeto y lo volvés a serializar, la firma no coincide.
  • Rechazá el aviso si la firma no coincide.
  • Rechazá el aviso si webhook-timestamp difiere en más de 5 minutos de tu reloj.
Ejemplo en Node.js. También sirve cualquier librería de Standard Webhooks. Devuelve true o false y nunca tira una excepción, así un encabezado raro termina en 401 y no en 500:
Dos detalles que el ejemplo ya cubre y que conviene copiar en cualquier lenguaje:
  • El timestamp tiene que ser sólo dígitos antes de compararlo con tu reloj.
  • La firma se compara como bytes decodificados de base64, con el mismo largo, en tiempo constante. Nunca como texto.

Vector de prueba

Con estos valores tu verificación tiene que dar true. Si tu código mira la hora, fijá el reloj en ese timestamp; con la hora real, la ventana de 5 minutos lo rechaza, y eso también está bien. Es el mismo aviso de prueba de arriba. El secreto es sólo de ejemplo: no sirve para ningún destino real. Cambiá un carácter del cuerpo y tiene que dar false.

Probar tu destino sin publicarlo

Dos formas, y conviene usar las dos:
  1. Sin red, firmando vos los avisos. Tu verificación no sabe quién firmó: firmá un cuerpo de aviso con el secreto del vector de prueba (o con el de tu destino) y mandáselo a tu ruta local con cualquier cliente HTTP. Así probás la firma, el 401, la deduplicación por webhook-id, un timestamp viejo y cada type, en tus tests y sin internet:
    Con el cuerpo, el id y el timestamp del vector, webhook-signature tiene que dar exactamente la del vector.
  2. Con avisos reales. Exponé tu servidor local con cualquier túnel https que te dé un nombre de host público en el puerto 443, dá de alta esa URL como destino en el panel de pruebas y tocá “Mandar prueba”. Para ver los avisos de cada estado, hacé avanzar un pedido de prueba con la simulación del entorno de pruebas. Cuando termines, borrá ese destino: un túnel apagado acumula fallas y el destino se desactiva.

Si no querés usar avisos

No son obligatorios. Podés consultar cada cierto tiempo GET /orders?updated_after=<tu última consulta>, que trae en una sola consulta paginada los pedidos que cambiaron, o GET /orders/:id para los pedidos que todavía no terminaron. Respetá los límites de uso y dejá de consultar un pedido cuando llega a delivered o cancelled.