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 reaccionar al instante cuando una eSIM se instala, se activa o se queda sin datos, sin sondear. 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 configura el cliente esimfly que se usa a continuación.
Consulta cualquier eSIM por su ICCID para conocer su consumo y validez. Úsalo cuando el cliente abra su eSIM en tu app; para los avisos de "te quedan pocos datos" deja que el webhook esim.usage.threshold (paso 3) te lo diga en lugar de sondear todas las eSIM.
// esimfly = the client from part one
const { data, validity } = await esimfly.esims.usage({ iccid: '8910300001234567890' });
console.log(data);
// { total_mb: 1024, used_mb: 256, remaining_mb: 768,
// usage_percentage: 25, is_unlimited: false }
console.log(validity.expires_at); // 2026-02-05T10:30:00Z
// Call it when the customer opens their eSIM and cache it for 5-15 minutes.
// For "running low" alerts you don't need to poll at all - see webhooks below.Las 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? (they depend on the eSIM)
const { packages } = await esimfly.topups.packages({ iccid, limit: 100 });
// 2. Apply a top-up - charged from your balance, active immediately
const topup = await esimfly.topups.create({ iccid, packageCode: packages[0].package_code });
console.log(topup.esimData); // { newTotalVolumeGB: 8, newRemainingVolumeGB: 8, expiredTime: ... }
console.log(topup.newBalance);
// Top-ups are not idempotent: on a network timeout, check
// esimfly.esims.usage({ iccid }) before trying again.eSIMfly envía un POST HTTP firmado a tu servidor cuando algo cambia en una eSIM: el perfil se instala en un teléfono (esim.installed, en segundos), el plan se activa o caduca (esim.status.changed) o los datos restantes bajan de 500 / 200 / 100 / 50 MB (esim.usage.threshold). Registra tu URL una sola vez y elige los eventos que quieres recibir.
// One-time setup: register your endpoint and pick the events you want
const { webhook } = await esimfly.webhooks.set({
webhookUrl: 'https://your-server.com/api/esimfly-webhook',
events: ['esim.installed', 'esim.status.changed', 'esim.usage.threshold'],
});
// SAVE webhook.secret (whsec_...) - shown once, needed to verify deliveries.
// Events you can subscribe to:
// esim.installed profile enabled on a phone for the first time (seconds)
// esim.status.changed NEW -> ACTIVE -> DEPLETED / EXPIRED (<= 30 min)
// esim.usage.threshold 500 / 200 / 100 / 50 MB remaining (seconds)
// esim.profile.updated every SM-DP+ state change (chatty - usually skip)
// esim.provisioned an asynchronously provisioned order is readyCada 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.
import { constructWebhookEvent, ESIMflyError } from '@esimfly/sdk';
// Express: keep the RAW body - the signature covers the exact bytes
app.post('/api/esimfly-webhook',
express.raw({ type: 'application/json' }),
async (req, res) => {
let event;
try {
event = constructWebhookEvent(
req.body, // raw Buffer
req.header('X-Webhook-Signature'), // sha256=<hex>
process.env.ESIMFLY_WEBHOOK_SECRET,
);
} catch (err) {
const badSignature = err instanceof ESIMflyError && err.code === 'INVALID_SIGNATURE';
return res.status(badSignature ? 401 : 400).end();
}
// Deduplicate: retries reuse the same X-Webhook-Id
const deliveryId = req.header('X-Webhook-Id');
if (await db.webhookDeliveries.exists(deliveryId)) return res.json({ received: true });
await db.webhookDeliveries.insert({ id: deliveryId, event: event.event, data: event.data });
res.json({ received: true }); // ack within 10 s, then do the work
switch (event.event) {
case 'esim.installed':
await db.esims.update({ iccid: event.data.iccid }, { installedAt: event.data.installed_at });
break;
case 'esim.status.changed':
await db.esims.update({ iccid: event.data.iccid }, { status: event.data.new_status });
break;
case 'esim.usage.threshold':
if (event.data.threshold_remaining_mb <= 200) await sendLowDataPush(event.data.iccid);
break;
}
});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.