xip
  • Personas
  • Negocios
  • Desarrolladores
EntrarAgenda una demo
Desarrolladores

API de Xip para couriers y comercios (v1)

Todo lo que hace el panel de negocio, desde tu sistema: listas de confirmación, pedidos de dirección desde un checkout, entregas reportadas con GPS y avisos por webhook.

En esta guía

  • Autenticación
  • Errores
  • Crear una lista
  • Ver una lista
  • Descargar el CSV
  • Reportar una entrega
  • Pedir la dirección desde un checkout
  • Webhooks
  • Límites

Con esta API tu sistema (ruteador, tienda, ERP) hace lo mismo que el panel de Xip, pero solo:

  1. Crea una lista de confirmación y recibe un link por persona para mandarle por WhatsApp.
  2. Se entera al momento de cada confirmación, por webhook, con el pin exacto, cómo entrar y el día elegido.
  3. Descarga la lista en CSV para cargarla en el ruteador.
  4. Reporta qué pasó en la puerta. Una entrega hecha cerca del pin sube el XipScore de esa dirección.
  5. Pide la dirección desde tu checkout y recibe la aprobación de la persona al momento.

La dirección siempre es de la persona. Tu sistema la lee solo mientras el permiso que ella dio siga vigente (hasta 7 días después del día de entrega) y cada lectura queda en la bitácora de acceso.

Autenticación

Crea una clave en Panel de negocio → Conectar tu sistema → Claves de API. La clave completa se muestra una sola vez; guárdala en tu sistema como secreto.

Cada pedido la lleva en la cabecera:

Authorization: Bearer xip_live_…

Dirección base: https://api.xip.com.pa/v1.

La dirección anterior, https://xip.com.pa/api/v1, sigue funcionando igual: no hace falta cambiarla si ya la usas.

Errores

Todas las respuestas de error tienen la misma forma:

JSON

{ "error": { "code": "not_found", "message": "No existe esa lista." } }
HTTPcodeCuándo
400invalid_jsonEl cuerpo no es JSON válido
401unauthorizedFalta la clave, no existe o está desactivada
403no_accessNo tienes permiso vigente sobre esa dirección
404not_foundLa lista, la persona o el código Xip no existen (o no son tuyos)
409not_confirmedReportaste una entrega de alguien que todavía no confirmó
410address_goneLa persona eliminó esa dirección
413payload_too_largeEl cuerpo pasa del límite
422variosDatos incompletos o inválidos; el mensaje dice qué falta

Crear una lista

POST /confirmations

Una persona es un teléfono: si mandas varios pedidos con el mismo teléfono, van juntos en un solo link. Los teléfonos de 7 u 8 dígitos se toman como de Panamá (+507).

Terminal

curl -X POST https://api.xip.com.pa/v1/confirmations \
  -H "Authorization: Bearer $XIP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ruta-2026-11-03-am" \
  -d '{
    "label": "Ruta martes AM",
    "recipients": [
      { "name": "Ana Pérez", "phone": "6123-4567", "address": "Edif. Vista Mar, apto 12B", "order_ref": "PF-1001", "packages": 2 },
      { "name": "Luis Gómez", "phone": "+50769876543", "order_ref": "PF-1002", "notes": "Frágil" }
    ],
    "delivery_options": ["2026-11-03", "2026-11-04"]
  }'
CampoTipo
labeltextoOpcional. Nombre de la lista
recipients[]listaMáximo 1 000 filas
recipients[].nametextoObligatorio
recipients[].phonetextoObligatorio
recipients[].addresstextoOpcional. La dirección que tienes hoy, tal cual
recipients[].order_reftextoOpcional. Tu número de pedido o guía
recipients[].packagesnúmeroOpcional, 1 por defecto
recipients[].notestextoOpcional
delivery_optionslista de fechas AAAA-MM-DDOpcional. Los días que ofreces a esta lista (hora de Panamá, hasta 7, de hoy a 30 días). Si no lo mandas, Xip usa la regla fija de tu negocio (hora de corte, anticipación y días sin entrega). Si todos los días ya pasaron cuando la persona abre el link, le pide uno nuevo

También puedes mandar el mismo CSV que subes en el panel, con Content-Type: text/csv y el nombre en ?label=.

Idempotencia. Con la cabecera Idempotency-Key, repetir el pedido devuelve la misma lista (HTTP 200 y "reused": true) en vez de crear otra. Úsala si tu sistema reintenta.

Respuesta 201:

JSON

{
  "id": "5b0c…",
  "reused": false,
  "recipients": [
    { "id": "9e1a…", "name": "Ana Pérez", "phone": "+50761234567", "confirm_url": "https://xip.com.pa/c/Kp3…" }
  ],
  "skipped": ["Fila 7: el teléfono \"12\" no parece válido."]
}

Mándale a cada persona su confirm_url, o pide que Xip se lo mande por su WhatsApp con "send_whatsapp": true al crear la lista (hasta 200 en esa llamada) y POST /confirmations/{id}/send para el resto (o con ?retry_failed=true, para reintentar los que no llegaron). Cada persona trae whatsapp.status: sent, delivered, read o failed.

Si no usas el WhatsApp de Xip, mándale tú el confirm_url. Ahí pone su pin, cómo entrar y elige el día. No necesita cuenta.

Cada link vale 30 días. Si la persona ya le confirmó una dirección a tu negocio antes, el link le ofrece reusarla; nunca le muestra direcciones que no te haya compartido a ti. Las personas salen en el mismo orden de tu lista, y una lista admite hasta 1 000 filas.

Ver una lista

GET /confirmations/{id}

JSON

{
  "id": "5b0c…",
  "label": "Ruta martes AM",
  "created_at": "2026-11-02T14:03:11Z",
  "summary": { "total": 2, "confirmed": 1, "pending": 1 },
  "recipients": [
    {
      "id": "9e1a…",
      "name": "Ana Pérez",
      "phone": "+50761234567",
      "orders": [{ "order_ref": "PF-1001", "packages": 2, "notes": null }],
      "original_address": "Edif. Vista Mar, apto 12B",
      "status": "confirmed",
      "delivery_choice": { "type": "home", "date": "2026-11-03" },
      "address": {
        "xip_code": "XIP-7KQ2",
        "location": { "lat": 8.9824, "lng": -79.5199 },
        "address_line": "Calle 50, Edif. Vista Mar",
        "how_to_enter": "Torre B, piso 12. Avisar al portero.",
        "notes": "Si no contesto, dejar en recepción",
        "navigate_url": "https://xip.com.pa/t/4f…",
        "access_expires_at": "2026-11-11T04:59:59Z"
      },
      "confirm_url": "https://xip.com.pa/c/Kp3…",
      "sent_at": null,
      "opened_at": "2026-11-02T15:20:00Z",
      "confirmed_at": "2026-11-02T15:22:41Z"
    }
  ]
}

status puede ser pending, confirmed, cancelled o access_revoked (confirmó, pero luego quitó el permiso o venció). address solo viene mientras el permiso esté vigente.

navigate_url es la pantalla de llegada para el motorizado (Google Maps, Waze o Apple Maps, y cómo entrar). Vence al final del día de entrega.

Descargar el CSV

GET /confirmations/{id}/export.csv

Una fila por pedido, con estas columnas: orden, fecha_entrega, nombre, telefono, direccion, latitud, longitud, como_entrar, notas, paquetes, codigo_xip, link_llegada, estado, direccion_original. Las pendientes traen la dirección original de tu lista. Si una celda empieza con =, +, - o @ y no es un número, sale con un apóstrofo delante para que Excel no la ejecute como fórmula.

Reportar una entrega

POST /delivery-events

Terminal

curl -X POST https://api.xip.com.pa/v1/delivery-events \
  -H "Authorization: Bearer $XIP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_id": "9e1a…",
    "event": "delivered",
    "location": { "lat": 8.98245, "lng": -79.51987, "accuracy_m": 12 },
    "operator_id": "moto-07"
  }'
Campo
recipient_id o xip_codeUno de los dos. recipient_id es el id de la persona en la lista
eventdelivered, failed_absent (no había nadie), failed_address (no se encontró) o call_needed
locationOpcional, pero sin ubicación la entrega no verifica el pin. lat, lng y accuracy_m del GPS
operator_idOpcional. Tu identificador del motorizado
notesOpcional

Solo puedes reportar sobre direcciones a las que tienes permiso vigente.

El link de llegada (navigate_url) sirve para llegar; no confirma la entrega ni suma al XipScore. La entrega se reporta aquí, con GPS.

Cuándo una entrega sube el XipScore. Si event es delivered, el GPS está a 150 m o menos del pin y su precisión es de 100 m o mejor, cuenta como evidencia real (+15 al XipScore, una vez por tipo de evento). Si quedó más lejos, se registra la desviación del pin y no suma.

Respuesta 201:

JSON

{
  "id": "c41d…",
  "event": "delivered",
  "created_at": "2026-11-03T16:40:02Z",
  "location_check": { "distance_m": 6, "max_distance_m": 150, "verified": true, "reason": null },
  "xip_score": 65
}

Pedir la dirección desde un checkout

POST /address-requests

Para tiendas y pasarelas de pago: pides la dirección de un número para una compra y la persona decide si la comparte. Si el WhatsApp de Xip está encendido, le llega el link al momento; si no, se lo mandas tú con approve_url.

Terminal

curl -X POST https://api.xip.com.pa/v1/address-requests \
  -H "Authorization: Bearer $XIP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: orden-88123" \
  -d '{ "phone": "6123-4567", "name": "Ana Pérez", "order_ref": "88123" }'
Campo
phoneObligatorio
nameOpcional. Para saludar a la persona
order_refOpcional. Tu número de orden
delivery_optionsOpcional. Si mandas fechas, la persona también elige el día
send_whatsappOpcional, true por defecto. Con false, Xip no le escribe y tú le mandas el link

Respuesta 201:

JSON

{ "id": "a09d…", "status": "pending", "approve_url": "https://xip.com.pa/c/Kp3…", "expires_in_hours": 24, "whatsapp": { "enabled": true, "sent": true } }

GET /address-requests/{id} devuelve status:

  • pending: todavía no responde.
  • approved: compartió su dirección; viene en address, igual que en las listas, durante 14 días si no hubo día de entrega.
  • declined: decidió no compartirla.
  • expired: pasaron 24 horas sin respuesta.
  • revoked: la compartió y después te quitó el permiso.

Si la persona ya entró a Xip con su celular, en el link ve todas sus direcciones guardadas y solo elige una.


Webhooks

En Conectar tu sistema → Webhook pones la URL de tu sistema (https, puerto 443, en un servidor público). Xip crea un secreto (whsec_…) para firmar cada aviso. Con Enviar prueba llega un evento ping.

Cada aviso es un POST con JSON:

JSON

{
  "id": "0f6a…",
  "event": "confirmation.confirmed",
  "created_at": "2026-11-02T15:22:42Z",
  "data": {
    "confirmation_id": "5b0c…",
    "recipient": { "...": "la misma forma que en GET /confirmations/{id}" }
  }
}
EventoCuándo
confirmation.confirmedUna persona confirmó su dirección y su día
confirmation.revokedLa persona te quitó el permiso desde su link. data trae confirmation_id y recipient_id; desde ese momento la dirección ya no viene en la lista ni en el CSV
address_request.approvedUn pedido de dirección de checkout fue aprobado. data trae address_request_id y request con la misma forma de cada persona de una lista
address_request.declinedLa persona decidió no compartir su dirección. data trae address_request_id
address_request.revokedLa persona te quitó el permiso después de aprobar. data trae address_request_id
pingPrueba desde el panel

Verifica la firma. La cabecera Xip-Signature trae t=<segundos unix>,v1=<firma>. La firma es el HMAC-SHA256, en hexadecimal, de <t>.<cuerpo tal cual llegó> con tu secreto. Rechaza el aviso si la firma no coincide o si t tiene más de 5 minutos.

JavaScript

import { createHmac, timingSafeEqual } from "node:crypto";

function verifyXip(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const given = Buffer.from(parts.v1 ?? "", "hex");
  return given.length === 32 && timingSafeEqual(given, Buffer.from(expected, "hex"));
}

Responde con un 2xx en menos de 5 segundos. Si tu sistema no responde, Xip reintenta a los 1, 5 y 30 minutos, y a las 2 y 6 horas; cada aviso trae el mismo id en todos los intentos, así que puedes descartar repetidos. Los avisos y su estado salen en Últimos avisos del panel, donde también puedes reintentar a mano.

Límites

  • 120 pedidos por minuto por clave de API. Si pasas el límite, la respuesta es 429 con code: "rate_limited"; espera un minuto.
  • 1 000 filas por lista.
xip

La dirección entregable de Panamá. Gratis para las personas, siempre con su permiso.

Xip

  • Personas
  • Negocios
  • Desarrolladores

Tu cuenta

  • Crear mi dirección
  • Entrar

Documentación

  • API
  • Botón para checkouts
  • Privacidad

© 2026 Xip