Documentación para desarrolladores

Smart Sends Express API

Integra envíos multi-carrier en tu plataforma con unas pocas líneas de código

Empezar gratis
Base URLhttps://smartsendsllc.com/api/v1

Quick Start

Obtén una cotización multi-carrier en segundos.

curl -X POST https://smartsendsllc.com/api/v1/quotes \
  -H "Authorization: Bearer ss_live_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "origin": {"city":"Bogota","state":"Cundinamarca","country":"CO","postal_code":"110111"},
    "destination": {"city":"Miami","state":"Florida","country":"US","postal_code":"33101"},
    "package": {"weight_kg":2,"length_cm":30,"width_cm":20,"height_cm":15}
  }'

Características

Todo lo que necesitas para gestionar envíos a escala.

Multi-Carrier

DHL, FedEx, TCC, Coordinadora, ServiEntrega — cotiza y envía con todos desde un solo endpoint.

Webhooks en Tiempo Real

Recibe notificaciones automáticas cada vez que un envío cambie de estado.

Rastreo Unificado

Un solo endpoint para rastrear envíos de cualquier carrier, sin importar quién lo transporte.

Seguridad

HMAC signatures para webhooks, rate limiting configurable y scopes granulares por API key.

Referencia API

Todos los endpoints disponibles. Haz clic para expandir detalles y ejemplos.

Guías de Integración

Conecta Smart Sends con tu plataforma de e-commerce favorita.

  1. 1

    Obtén tu API key en /dashboard/developers

  2. 2

    En tu admin de Shopify, ve a Settings > Shipping

  3. 3

    Agrega "Carrier Service" con URL: https://smartsendsllc.com/api/v1/carrier/shopify/rates

  4. 4

    Las tarifas aparecerán automáticamente en el checkout

Webhooks

Recibe notificaciones en tiempo real cuando cambia el estado de un envío.

Eventos disponibles

shipment.createdEnvío creado y guía generada
shipment.shippedEnvío despachado por el carrier
shipment.in_transitEnvío en tránsito
shipment.deliveredEnvío entregado al destinatario
shipment.cancelledEnvío cancelado
shipment.exceptionProblema con el envío (devolución, dirección incorrecta, etc.)

Verificación de firma

Cada petición webhook incluye un header X-Signature con la firma HMAC-SHA256 del body. Verifica siempre la firma antes de procesar el evento.

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Política de reintentos

Si tu endpoint responde con un código diferente a 2xx, reintentamos hasta 3 veces con backoff exponencial:2s → 4s → 8s.

Autenticación

Cómo autenticarte y los límites de uso de la API.

API Key

Envía tu API key en cada petición usando uno de estos headers:

Authorization: Bearer ss_live_tu_api_key

# o alternativamente:
X-API-Key: ss_live_tu_api_key

Rate Limiting

Por defecto, cada API key tiene un límite de 60 solicitudes por minuto. Los headers de respuesta incluyen información del estado actual:

HeaderDescripción
X-RateLimit-LimitLímite máximo de solicitudes por minuto
X-RateLimit-RemainingSolicitudes restantes en la ventana actual
X-RateLimit-ResetTimestamp Unix cuando se renueva la ventana

Scopes

Cada API key tiene scopes granulares que controlan qué operaciones puede realizar. Los scopes disponibles son:

quotes:readshipments:readshipments:writetracking:readaddresses:readwebhooks:manage

SDK oficial JavaScript

Un archivo, sin dependencias, funciona en Node 18+ y navegadores. Auto-retry con backoff exponencial, Idempotency-Key automático y verificación de webhooks incluida.

Instalación

Descarga directa (recomendado para copy-paste):

# Node.js
curl -o smartsends.js https://smartsendsllc.com/sdk/smartsends.js

# HTML
<script src="https://smartsendsllc.com/sdk/smartsends.js"></script>

Uso mínimo

const { SmartSends } = require('./smartsends');

const client = new SmartSends({ apiKey: process.env.SMARTSENDS_API_KEY });

// Cotizar
const { quotes } = await client.quotes({
  origin:      { city: 'Bogota', country: 'CO', postal_code: '110111' },
  destination: { city: 'Miami',  country: 'US', postal_code: '33101' },
  package:     { weight_kg: 1.5, length_cm: 20, width_cm: 15, height_cm: 10 },
});
console.log(quotes[0]);  // { carrier: 'DHL', service: '...', price: 285000, currency: 'COP', ... }

// Crear envío (Idempotency-Key auto)
const shipment = await client.createShipment({
  service_type: 'dhl_express_worldwide',
  origin, destination, package: pkg, reference: 'ORDER-42',
});

// Descargar guía PDF
const pdfBuffer = await client.downloadLabel(shipment.id);

// Rastrear
const track = await client.track(shipment.tracking_number);

Verificar firma de webhook

const { verifyWebhook } = require('./smartsends');

app.post('/webhooks/smartsends', express.raw({ type: 'application/json' }), async (req, res) => {
  const ok = await verifyWebhook(
    req.body,                                      // Buffer con el body crudo
    req.headers['x-smartsends-signature'],
    process.env.SMARTSENDS_WEBHOOK_SECRET
  );
  if (!ok) return res.status(401).end();

  const event = JSON.parse(req.body.toString());
  // event.event = 'shipment.delivered', event.data = { ...Shipment }
  res.status(200).end();
});

Reglas de Commercial Invoice (envíos internacionales)

DHL exige Commercial Invoice para todo envío internacional. Smart Sends aplica la misma regla que el portal MyDHL: si el valor declarado es mayor a USD 200, debes subir tu factura como PDF; por debajo, DHL la genera automáticamente a partir de los line items.

≤ USD 200 — automático

No envías nada extra. La API pide a DHL que genere la Commercial Invoice y te la devuelve enshipment.invoice.data_url.

source: "dhl_generated"

> USD 200 — obligatorio subir

Debes mandar invoice_pdf_base64con tu factura como PDF. Se anexa vía Paperless Trade. Si falta, la API responde400 INVOICE_REQUIRED.

source: "uploaded"

Ejemplo — envío > USD 200 con factura

const fs = require('fs');
const invoiceB64 = fs.readFileSync('mi-factura.pdf').toString('base64');

const shipment = await client.createShipment({
  service_type: 'dhl_express_worldwide',
  origin:       { name: 'Tienda X', ..., country: 'CO' },
  destination:  { name: 'John Doe',  ..., country: 'US', postal_code: '33101' },
  package:      { weight_kg: 3.5, length_cm: 40, width_cm: 30, height_cm: 20,
                  content: 'Electronics', declared_value: 850 },   // USD
  invoice_pdf_base64: invoiceB64,
  reference: 'ORDER-1042',
});
// shipment.invoice.source === 'uploaded'

Ejemplo — envío ≤ USD 200 (auto-generada)

const shipment = await client.createShipment({
  service_type: 'dhl_express_worldwide',
  origin, destination,
  package: { weight_kg: 1.5, ..., content: 'Sample garment', declared_value: 120 },
  reference: 'ORDER-1043',
});
// shipment.invoice.source     === 'dhl_generated'
// shipment.invoice.data_url   === 'data:application/pdf;base64,JVBERi0xLjQ...'
fs.writeFileSync('invoice.pdf',
  Buffer.from(shipment.invoice.data_url.split(',')[1], 'base64'));

Error de referencia

HTTP/1.1 400 Bad Request
{
  "error": {
    "code": "INVOICE_REQUIRED",
    "message": "Envíos internacionales con valor declarado > USD 200 requieren invoice_pdf_base64. Sube tu Commercial Invoice como PDF base64.",
    "details": {
      "threshold_usd": 200,
      "declared_value": 850,
      "hint": "Envía el campo `invoice_pdf_base64` con el PDF de tu factura codificado en base64 (sin prefijo `data:`)."
    }
  }
}

Cómo construir tu módulo de envío

Guía end-to-end para integrar tu tienda, ERP o plataforma. Si sigues estos 6 pasos tu módulo funciona en producción y respeta las reglas de aduana, idempotencia y reintentos.

  1. 1

    Auth y configuración

    Solicita al comerciante su API key (prefijo ss_live_) desde/dashboard/developers. Guárdala cifrada en tu tienda. Nunca la muestres al cliente final. Envía siempreAuthorization: Bearer ss_live_....

  2. 2

    Cotizar al checkout

    Cuando el comprador llene la dirección de envío, llama a POST /quotescon origen (bodega del comerciante), destino (dirección del comprador) y las dimensiones del carrito. Muestra las opciones ordenadas por precio. Cachea la respuesta 5 min para reducir latencia.

    const { quotes } = await client.quotes({
      origin, destination, package: { weight_kg, length_cm, width_cm, height_cm },
    });
    // Renderiza quotes[0..N] como opciones de shipping method en tu checkout.
  3. 3

    Crear la guía al confirmar la orden

    Cuando el pago se confirma, llama a POST /shipments. Genera y guarda un UUID por orden comoIdempotency-Key: si el request falla por timeout y reintentas, la API devuelve la misma guía sin crear duplicados.

    Reglas de factura: si el envío es internacional ydeclared_value > 200(USD), incluye tu invoice_pdf_base64. Si es ≤ 200, no envíes nada y DHL genera la factura automáticamente.

    const orderUuid = crypto.randomUUID();
    const shipment = await client.createShipment({
      service_type: chosenQuote.service_type,
      origin, destination,
      package: { weight_kg, length_cm, width_cm, height_cm, content, declared_value },
      reference: order.id,                    // ID de tu tienda para reconciliar
      invoice_pdf_base64: needsInvoice        // solo si internacional && > USD 200
        ? fs.readFileSync(invoicePath).toString('base64')
        : undefined,
    }, orderUuid);                            // Idempotency-Key
    // Guarda shipment.tracking_number en tu DB ligado al order.id.
  4. 4

    Imprimir la etiqueta (y la factura si aplica)

    La respuesta incluye shipment.label_url(endpoint que sirve el PDF) y shipment.invoice.data_url(base64 del Commercial Invoice cuando DHL lo generó). Descarga ambos, mándalos a la impresora o guárdalos en el pedido para adjuntarlos al paquete.

    const labelPdf = await client.downloadLabel(shipment.id);   // ArrayBuffer PDF
    fs.writeFileSync(`labels/${shipment.tracking_number}.pdf`, Buffer.from(labelPdf));
    
    if (shipment.invoice?.data_url) {
      const invPdf = Buffer.from(shipment.invoice.data_url.split(',')[1], 'base64');
      fs.writeFileSync(`invoices/${shipment.tracking_number}.pdf`, invPdf);
    }
  5. 5

    Escuchar cambios de estado (webhooks)

    Configura una URL con PUT /webhooks. Recibirás shipment.shipped,shipment.in_transit,shipment.delivered,shipment.exception. Verifica siempre la firma HMAC-SHA256 antes de procesar. Devuelve 2xx rápido — nuestro sistema es idempotente pero tu handler también debería serlo.

    // Express.js — verifica firma y procesa
    app.post('/webhooks/smartsends', express.raw({ type: 'application/json' }), async (req, res) => {
      const ok = await verifyWebhook(req.body, req.headers['x-smartsends-signature'], SECRET);
      if (!ok) return res.status(401).end();
      const evt = JSON.parse(req.body.toString());
      await updateOrderStatus(evt.data.tracking_number, evt.event, evt.data.status);
      res.status(200).end();
    });
  6. 6

    Cancelaciones y rastreo público

    Si el cliente cancela antes del pickup, llama aPOST /shipments/{id}/cancel— reembolsamos al wallet. En la página de estado del pedido en tu tienda enlaza ahttps://smartsendsllc.com/rastreo/{tracking_number}para que el cliente vea eventos en tiempo real sin necesidad de exponer tu API key.

✅ Checklist antes de ir a producción

  • • API key de producción (ss_live_) cifrada en tu backend, no en el frontend.
  • Idempotency-Key generado y persistido por orden.
  • • Reintento automático en 429/5xx con backoff exponencial (el SDK oficial lo hace por ti).
  • • Regla de invoice implementada: subir factura si declared_value > 200 USD internacional.
  • • URL de webhook con verificación HMAC-SHA256 y respuesta 2xx en < 5 s.
  • • Manejo de INSUFFICIENT_BALANCE: notificar al comerciante que recargue su wallet.
  • • Timeout del cliente HTTP ≥ 30 s (creación de guías DHL puede tomar hasta 20 s).
  • • Storage del PDF de etiqueta + factura por al menos 90 días (aduana puede pedir).

Idempotencia

Cualquier POST/PATCH puede reintentarse sin duplicar operaciones enviando el headerIdempotency-Keycon un UUID (o string único ≤255 chars). Reintentos con la misma clave devuelven la misma respuesta sin volver a ejecutar la lógica.

curl -X POST https://smartsendsllc.com/api/v1/shipments \
  -H "Authorization: Bearer ss_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: shp-8f42d7b1-a291-4c6e-9f0d-1b5e77e02c9a" \
  -d '{"service_type":"dhl_express_worldwide","origin":{...},"destination":{...},"package":{...}}'

El SDK oficial JavaScript genera y envía la clave automáticamente en cada POST/PATCH — no tienes que hacer nada. Si integras con fetch/curl a mano, genera un UUID por operación y guárdalo por si necesitas reintentar.

Sandbox y Testing

Genera una API key de prueba desde/dashboard/developersy actívala en modo sandbox. En sandbox no se cobra saldo, no se generan guías reales y los webhooks se disparan a URLs de prueba (RequestBin, webhook.site, ngrok).

Prefijo de API key

Producción: ss_live_...

Sandbox: ss_test_...

Endpoint de salud

Verifica que la API responde antes de integrar:

curl https://smartsendsllc.com/api/v1/openapi | jq '.info.version'