🔄 Webhooks

StandBy ofrece soporte para webhooks, permitiendo a los desarrolladores recibir notificaciones en tiempo real sobre eventos importantes, como la creación, actualización o cancelación de envíos.

Configuración

Para configurar webhooks, los desarrolladores deben registrar una URL de callback en el Sitio Oficial de StandBy. A continuación se describen los pasos para configurar webhooks:

  1. Registrarse o iniciar sesión en el Sitio Oficial de StandBy.
  2. Navegar a la sección de “Perfil” en la barra superior.
  3. Deslizar a la sección de “Webhooks” y clicar en “Administrar webhooks”.
  4. Crear una nueva llave de acceso clicando en “Agregar webhook” y llenar los campos requeridos, incluyendo el nombre y la URL de callback.
  5. Crea el webhook.

Ejemplo de Payload

Ejemplo de payload enviado a la URL de callback:

{
  "event": "order_completed",
  "payload": {
    "order": {
      "id": "00000000-0000-0000-0000-000000000000",
      "orderNumber": 1234,
      "dayToDeliver": "2025-12-08T20:14:15.000Z",
      "km": 3.043,
      "totalPrice": 76.26,
      "weight": 20,
      "payment": "CASH",
      "requiresSign": true,
      "requiresEvidences": true,
      "deliveredAt": "2025-12-08T20:14:16.236Z",
      "metadata": { "externalOrderId": "ABC123" },
      "deliveryPoints": [
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "position": 1,
          "type": "PICKUP",
          "coords": { "x": 25.5544728, "y": -103.4479596 },
          "address": "Calle Ejemplo 123, Colonia Centro, Ciudad, Estado, México",
          "whoReceives": "Restaurante Ejemplo",
          "whoReceivesPhone": "1234567890",
          "comments": "Pedido de: Cliente Ejemplo - 0987654321",
          "statuses": [
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "TRANSIT",
              "comment": "El operador se dirige al pickup",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:15.921Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "DRIVER_IN_BRANCH",
              "comment": "El operador llegó al pickup",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:15.975Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "LOADED",
              "comment": "El operador cargó los productos",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.009Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "SUPPLIED",
              "comment": "Ya han despachado al operador",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.042Z"
            }
          ],
          "items": [
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "product": "Producto A",
              "quantity": 2
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "product": "Producto B",
              "quantity": 1
            }
          ]
        },
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "position": 2,
          "type": "DROPOFF",
          "coords": { "x": 25.5378952, "y": -103.4404738 },
          "address": "Avenida Principal 456, Colonia Ejemplo, Ciudad, Estado, México",
          "whoReceives": "Juan Pérez",
          "whoReceivesPhone": "5551234567",
          "comments": "Departamento 101. Edificio azul.",
          "statuses": [
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "TRANSIT",
              "comment": "El operador se dirige al dropoff",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.077Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "ON_SITE",
              "comment": "El operador llegó al dropoff",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.112Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "UNLOADED",
              "comment": "El operador descargó los artículos",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.146Z"
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "status": "COMPLETED",
              "comment": "Entrega completada exitosamente",
              "coords": {
                "latitude": 25.5667509,
                "longitude": -103.4394889
              },
              "createdAt": "2025-12-08T20:14:16.185Z"
            }
          ],
          "items": [
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "product": "Producto A",
              "quantity": -2
            },
            {
              "id": "00000000-0000-0000-0000-000000000000",
              "product": "Producto B",
              "quantity": -1
            }
          ]
        }
      ],
      "operator": {
        "name": "John",
        "lastName": "Doe",
        "phone": "5559876543",
        "vehicle": {
          "serial": "VEH001",
          "plate": "ABC1234",
          "type": "MOTORCYCLE",
          "brand": "Honda",
          "model": "CB190",
          "year": 2023
        },
        "location": { "latitude": 25.5615760, "longitude": -103.4341099 }
      },
      "statuses": [
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "status": "PENDING",
          "comment": "Orden creada",
          "coords": null,
          "createdAt": "2025-12-08T20:14:15.535Z"
        },
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "status": "ACCEPTED",
          "comment": "Orden aceptada",
          "coords": {
            "latitude": 25.5558537,
            "longitude": -103.4490823
          },
          "createdAt": "2025-12-08T20:14:15.888Z"
        },
        {
          "id": "00000000-0000-0000-0000-000000000000",
          "status": "COMPLETED",
          "comment": "Orden completada",
          "coords": {
            "latitude": 25.5378952,
            "longitude": -103.4404738
          },
          "createdAt": "2025-12-08T20:14:16.232Z"
        }
      ],
      "createdAt": "2025-12-08T20:14:15.405Z",
      "deletedAt": null
    }
  }
}

Eventos Disponibles

Lista completa de eventos disponibles para webhooks:

  • order_created: Se dispara cuando se crea un nuevo pedido.
  • order_updated: Se dispara cuando se actualiza un pedido existente. (Incluye todo tipo de eventos del envío).
  • order_accepted: Se dispara cuando un pedido es aceptado por un operador.
  • order_cancelled: Se dispara cuando se cancela un pedido.
  • order_completed: Se dispara cuando se completa un pedido.
  • order_operator_accepted: Se dispara cuando un operador acepta un pedido.
  • order_operator_cancelled: Se dispara cuando un operador cancela un pedido.

🔒 Autenticación de Webhooks

Al crear un webhook, se te proporcionará una Llave de Firma (Signing Key) dedicada. Esta llave confidencial actúa como un secreto compartido entre tu aplicación y StandBy, garantizando la autenticidad y la integridad de los mensajes que llegan a tu endpoint.

Para obtener la llave de firma de un webhook específico, dirígete al panel de Webhooks en tu cuenta de StandBy, ubica el webhook correspondiente y selecciona la opción Editar en el menú de tres puntos.


Proceso de verificación

Cada vez que StandBy envía un mensaje POST a tu endpoint, incluye un encabezado HTTP llamado x-standby-signature. Este encabezado contiene un hash SHA-256 generado a partir del cuerpo del mensaje (payload) utilizando tu llave de firma.

Puedes verificar la autenticidad del mensaje siguiendo estos pasos:

  1. Calcula el hash SHA-256 del cuerpo del mensaje (payload) usando tu llave de firma como clave HMAC. Se recomienda utilizar la función HMAC estándar que provea tu lenguaje de programación.

  2. Compara el valor obtenido con el hash recibido en el encabezado x-standby-signature. Si ambos valores coinciden, el mensaje es legítimo y puedes procesarlo. Si no coinciden, rechaza el mensaje y no lo proceses.

Esta verificación asegura que:

  • El mensaje fue enviado realmente por StandBy.
  • Su contenido no fue modificado en tránsito.

Ejemplo de verificación (Python)

import hashlib, hmac

signing_key = 'tu-llave-de-firma'

# Ejemplo de cuerpo abreviado
payload = '{"event": "order_completed", "order": {"id": "123"}}'

computed_signature = hmac.new(
    signing_key.encode('utf-8'),
    payload.encode('utf-8'),
    hashlib.sha256
).hexdigest()

print(computed_signature)
# → 'cdff8133fb065f8d37a2c1c94c3331b6a82766d14e7ea4faacc4886558cedd65'

Ejemplo de verificación (JavaScript/Node.js)

const crypto = require('crypto');
const signingKey = 'tu-llave-de-firma';

const payload = '{"event": "order_completed", "order": {"id": "123"}}';

const computedSignature = crypto.createHmac('sha256', signingKey)
    .update(payload)
    .digest('hex');

console.log(computedSignature);
// → 'cdff8133fb065f8d37a2c1c94c3331b6a82766d14e7ea4faacc4886558cedd65'