Vender la eSIM es solo la mitad del producto; la otra mitad es lo que ocurre después: mostrar a los clientes los datos que les quedan, vender recargas en el momento oportuno y gestionar el único proveedor (KDDI Japón) que entrega las eSIM de forma asíncrona por webhook. Todo lo demás se resuelve con simples consultas de sondeo. Esta guía cubre las tres cosas.
¿Acabas de llegar? Empieza por la primera parte: Cómo vender eSIM en tu app con Node.js; allí se construye el helper hmacHeaders() que se usa a continuación.
Consulta cualquier eSIM por su ICCID para conocer el consumo en tiempo real. La lógica de negocio interesante se construye encima: avisar al llegar al 80 % de uso, mostrar los datos restantes en tu app o lanzar una oferta de recarga automática antes de que el cliente se quede sin datos a mitad del viaje.
// hmacHeaders() from part one of this tutorial
async function getUsage(iccid) {
const query = '?iccid=' + encodeURIComponent(iccid);
const res = await fetch(
BASE_URL + '/api/v1/business/esims/usage/query' + query,
{ headers: hmacHeaders() }
);
return res.json();
}
const usage = await getUsage('8910300001234567890');
console.log(usage.data.data);
// { total_mb: 1024, used_mb: 256, remaining_mb: 768,
// usage_percentage: 25, is_unlimited: false }
// Perfect for "80% used - top up now?" push notificationsLas recargas son la venta recurrente con mayor margen del negocio de las eSIM: el cliente ya tiene el perfil instalado, así que no hay ninguna fricción de alta. Consulta siempre primero los paquetes compatibles por ICCID: no todos los paquetes pueden recargar todas las eSIM.
// 1. Which packages can THIS eSIM be topped up with?
async function getTopupPackages(iccid) {
const query = '?iccid=' + encodeURIComponent(iccid);
const res = await fetch(
BASE_URL + '/api/v1/business/topup/packages' + query,
{ headers: hmacHeaders() }
);
const data = await res.json();
return data.data.packages;
}
// 2. Apply a top-up - charged from your balance, active immediately
async function topUp(iccid, packageCode) {
const body = JSON.stringify({ iccid, packageCode });
const res = await fetch(BASE_URL + '/api/v1/business/topup/order', {
method: 'POST',
headers: hmacHeaders(body),
body
});
return res.json();
}Algunos proveedores (como KDDI Japón) aprovisionan de forma asíncrona: tu pedido devuelve status: "pending_details" y los datos de la eSIM llegan por webhook entre 1 y 5 minutos después. Registra una URL de webhook global una sola vez o pasa callbackUrl en cada pedido.
// One-time setup: register your webhook endpoint
const body = JSON.stringify({
webhook_url: 'https://your-server.com/api/esim-callback',
events: ['esim.provisioned']
});
const res = await fetch(BASE_URL + '/api/v1/business/webhooks', {
method: 'PUT',
headers: hmacHeaders(body),
body
});
const { webhook } = await res.json();
// SAVE webhook.secret (whsec_...) - you need it to verify signatures.
// Alternative: pass callbackUrl per-order in the order request instead.Cada entrega va firmada con HMAC-SHA256 (cabecera X-Webhook-Signature). Verifícala contra el cuerpo en bruto de la petición con una comparación de tiempo constante: nunca proceses una carga sin firmar ni verifiques contra un JSON reserializado.
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signatureHeader, webhookSecret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
// Express: use the RAW body for verification, not the parsed JSON
app.post('/api/esim-callback',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-webhook-signature'];
const rawBody = req.body.toString();
if (!verifyWebhookSignature(rawBody, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(rawBody);
if (event.event === 'esim.provisioned') {
const { order_reference, iccid, qr_code_url, lpa_string } = event.data;
// The eSIM is ready - deliver it to your customer now
}
res.status(200).send('ok'); // always ack fast, process async
});X-Webhook-Id para que los reintentos nunca entreguen una eSIM dos veces.Suspender, cancelar, entrega por SMS, eventos de red y mucho más: la referencia completa de endpoints está en la documentación.