Smart Sends Express API
Integra envíos multi-carrier en tu plataforma con unas pocas líneas de código
https://smartsendsllc.com/api/v1Quick 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
Obtén tu API key en /dashboard/developers
- 2
En tu admin de Shopify, ve a Settings > Shipping
- 3
Agrega "Carrier Service" con URL:
https://smartsendsllc.com/api/v1/carrier/shopify/rates - 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 generadashipment.shippedEnvío despachado por el carriershipment.in_transitEnvío en tránsitoshipment.deliveredEnvío entregado al destinatarioshipment.cancelledEnvío canceladoshipment.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_keyRate 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:
| Header | Descripción |
|---|---|
X-RateLimit-Limit | Límite máximo de solicitudes por minuto |
X-RateLimit-Remaining | Solicitudes restantes en la ventana actual |
X-RateLimit-Reset | Timestamp Unix cuando se renueva la ventana |
Scopes
Cada API key tiene scopes granulares que controlan qué operaciones puede realizar. Los scopes disponibles son:
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.
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"
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
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
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
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 y
declared_value > 200(USD), incluye tuinvoice_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
Imprimir la etiqueta (y la factura si aplica)
La respuesta incluye
shipment.label_url(endpoint que sirve el PDF) yshipment.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
Escuchar cambios de estado (webhooks)
Configura una URL con
PUT /webhooks. Recibirásshipment.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
Cancelaciones y rastreo público
Si el cliente cancela antes del pickup, llama a
POST /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-Keygenerado 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 USDinternacional. - • 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'