Commet
  • Precios
Iniciar SesiónRegistrarse

Migrar de Paddle a Commet

Guía práctica para mover subscriptions, checkouts y webhooks de Paddle Billing a Commet, con código lado a lado y una comparación honesta de fees.


Introducción

Elegiste Paddle para dejar de lidiar con impuestos globales, y esa parte funcionó. Pero tu producto se está volviendo usage-based, tus clientes están en mercados que Paddle cobra en USD, y cada checkout pasa por un overlay que no controlás desde el backend.

Commet también es Merchant of Record, así que mantenés la cobertura de impuestos y compliance por la que migraste a Paddle. Lo que cambia es la experiencia de desarrollo: planes, subscriptions y medición de uso son primitivas de API, no objetos de dashboard cableados a un overlay de JavaScript.

Saltá directo a cualquier sección:

  • Historia
  • Conceptos
  • SDKs oficiales
  • Crear customers y subscriptions vía API
  • Medir uso / metering
  • Webhooks
  • Impuestos y compliance
  • Precios
  • Conclusión

Historia

Paddle fue fundada en Londres en 2012 por Christian Owens y Harrison Rose. Fue pionera del modelo Merchant of Record para empresas de software: Paddle le vende a tu cliente, así que el registro, la presentación y la remisión de impuestos en cada jurisdicción son trabajo de Paddle, no tuyo. En 2022 adquirió ProfitWell, sumando analytics de subscriptions, y su generación actual de API es Paddle Billing.

Commet aplica el mismo modelo de Merchant of Record a un problema más acotado: billing para productos SaaS y de IA que cobran por consumo. Los planes son la fuente de verdad, los eventos de uso alimentan los cobros medidos, y el pricing en moneda local cubre mercados — Latinoamérica en particular — donde el checkout en USD lastima la conversión.

Como las dos plataformas son Merchant of Record, esta es una migración entre equivalentes en impuestos: la comparación que importa es superficie de API, metering y fees. De eso trata el resto de esta guía.

Conceptos

Las dos plataformas son Merchant of Record, así que los conceptos de vendedor de registro coinciden. Los objetos de billing difieren:

PaddleCommet
Product + PricePlan (precio, features e intervalos en un solo objeto)
Transaction + checkout de Paddle.jscheckoutUrl que devuelve subscriptions.create
SubscriptionSubscription
CustomerCustomer
DiscountsCódigos promocionales
Uso trackeado en tu propia base de datosFeatures medidas + eventos de uso
Notifications (webhooks)Webhooks (opcionales — el estado es consultable)

La diferencia estructural es dónde empieza el billing. En Paddle, una subscription nace del lado del cliente: creás una transaction o pasás price IDs al overlay de Paddle.js, y la subscription se materializa después del checkout. En Commet, una subscription nace del lado del servidor: una llamada a la API la crea y devuelve la URL de checkout.

Estados de subscription

Los ciclos de vida se traducen limpio:

Estado en Commet¿Da acceso?Estado más cercano en Paddle
pending_paymentNo— (transaction aún no completada)
trialingSítrialing
activeSíactive
past_dueSí (período de gracia)past_due
pausedNopaused
canceledNocanceled
expiredNo—

Dale acceso con active o trialing, y tratá past_due como período de gracia mientras corren los reintentos de pago.

Modelos de consumo

Cada plan de Commet usa exactamente un modelo de consumo — son mutuamente excluyentes por plan:

  • metered: pago por uso, agregado y facturado a fin de período.
  • credits: los clientes compran paquetes de créditos por adelantado; el uso los consume.
  • balance: un balance monetario prepago que se debita por evento, incluyendo pricing por token de IA.

Ninguno de los tres tiene equivalente en Paddle — esta es la capa que los equipos sobre Paddle construyen en su propia base de datos.

SDKs oficiales

SDK / herramientaPaddleCommet
Node.js / TypeScript@paddle/paddle-node-sdk@commet/node
Pythonpaddle-python-sdkcommet
Gopaddle-go-sdkcommet-go
Java—commet-java
PHPpaddle-php-sdkcommet-php
Browser / checkoutPaddle.js (requerido para checkout)No hace falta — el checkout es una URL de redirect
Helpers para Next.js—@commet/next (handler de webhooks, helpers de rutas)
Integración con AI SDK—commet-ai-sdk (tracking de tokens)
Integración de auth—commet-better-auth
CLI—CLI commet (commet listen para webhooks locales)

Instalá el SDK de Node.js:

npm install @commet/node

Inicializá el cliente:

lib/commet.ts
import { Commet } from '@commet/node'

export const commet = new Commet({
  apiKey: process.env.COMMET_API_KEY!,
})

Las API keys están separadas por entorno: las keys ck_sandbox_xxx pegan contra tu organización sandbox, así que el mismo código corre en sandbox y producción cambiando solo la key.

Crear customers y subscriptions vía API

En Paddle, creás el customer y una transaction del lado del servidor, y después abrís el checkout con Paddle.js en el navegador:

Paddle — servidor
import { Paddle } from '@paddle/paddle-node-sdk'

const paddle = new Paddle(process.env.PADDLE_API_KEY!)

const customer = await paddle.customers.create({
  email: 'billing@acme.com',
})

const transaction = await paddle.transactions.create({
  customerId: customer.id,
  items: [{ priceId: 'pri_01gsz8x8sawmvhz1pv30nge1ke', quantity: 1 }],
})
Paddle — navegador
Paddle.Checkout.open({
  transactionId: transaction.id,
})

En Commet, todo el flujo es del lado del servidor. Los planes se referencian por un código legible, y la respuesta incluye la URL de checkout:

Commet
const customer = await commet.customers.create({
  email: 'billing@acme.com',
  id: 'user_123',
})

const subscription = await commet.subscriptions.create({
  customerId: 'user_123',
  planCode: 'pro',
})

// redirigir a subscription.data.checkoutUrl

customers.create es idempotente: si ya existe un customer con el mismo id, devuelve el registro existente. Usás tu propio ID de usuario en todos lados; sin tabla de mapeo de IDs.

Los parámetros que acepta subscriptions.create:

ParámetroTipoDescripción
customerIdstringID de customer de Commet (cus_xxx) o tu ID externo
planCodestringCódigo del plan (alternativa a planId)
planIdstringUUID del plan (alternativa a planCode)
billingIntervalstringweekly, monthly, quarterly, yearly o one_time
initialSeatsobjectCódigos de tipo de seat mapeados a cantidades
skipTrialbooleanSaltear el período de trial del plan
successUrlstringURL de redirect después del pago exitoso

Verificar acceso es una consulta directa, no un lookup alimentado por webhooks:

Commet
const sub = await commet.subscriptions.getActive({ customerId: 'user_123' })

if (sub.data?.status === 'active') {
  // El usuario pagó
}

Cambios de plan y proration

Donde Paddle expone modos de proration que elegís por update (prorated_immediately, full_next_billing_period, etcétera), Commet trae una sola política por defecto: los cambios que benefician al cliente aplican inmediatamente; los que lo perjudican aplican en la renovación.

Los upgrades proratean y toman efecto al instante; los downgrades se programan para el próximo período. Los clientes también pueden cambiar de plan solos a través del Customer Portal, creado automáticamente por cliente.

Trials

Los trials se definen en el plan, y skipTrial: true los saltea por subscription. Durante un trial la tarjeta se captura pero no se cobra, y Commet emite trial.started, trial.will_end (3 días antes del vencimiento) y trial.converted o trial.expired al final.

Medir uso / metering

Paddle no tiene metering de uso nativo. Los equipos que corren pricing usage-based sobre Paddle suelen trackear el consumo en su propia base de datos y facturarlo ajustando cantidades de los items de la subscription o emitiendo cargos one-time a fin de período: el pipeline de medición lo construís y reconciliás vos.

En Commet, el billing medido es una feature del plan. Tu aplicación envía eventos; Commet agrega y factura a fin de período:

Commet
await commet.usage.track({
  customerId: 'user_123',
  feature: 'api_calls',
  value: 1,
  idempotencyKey: 'req_abc123',
})

La lista completa de parámetros:

ParámetroTipoRequeridoDescripción
featurestringSíCódigo de evento de una feature medida (a-z0-9_)
customerIdstringSíID de customer de Commet o tu ID externo
valuenumberNoCantidad consumida. Default 1
idempotencyKeystringNoEvita eventos duplicados
timestampstringNoDatetime ISO 8601. Default: ahora
propertiesobjectNoMetadata clave-valor para debugging

La idempotencyKey evita eventos duplicados: Commet rechaza eventos con una key ya registrada para el mismo customer.

Los chequeos de entitlements en tiempo real salen de la misma definición del plan, así que el gating pasa antes de la factura, no después:

Commet
const { data } = await commet.featureAccess.get({
  code: 'api_calls',
  customerId: 'user_123',
})

if (data.allowed) {
  // Servir el request
}

Billing de tokens de IA

Si cobrás por uso de IA, Commet mantiene un catálogo de precios de más de 180 modelos. Pasá model, inputTokens y outputTokens al mismo método track, y Commet calcula el costo, aplica tu margen configurado y debita el balance del cliente:

Commet
await commet.usage.track({
  customerId: 'user_123',
  feature: 'ai_chat',
  model: 'gpt-4o',
  inputTokens: 1500,
  outputTokens: 300,
})

En Paddle, todo este pipeline — lookup de precio por modelo, margen, débito de balance, facturación de overage — vive en tu codebase.

Los planes también soportan créditos y balance prepago como modelos de consumo de primera clase. Mirá usage-based billing para comparar los tres modelos.

Las features medidas también pueden llevar cuotas y límites de seats: Commet emite quota.threshold_reached y quota.exceeded cuando los clientes se acercan a sus límites, y seats.updated / seats.limit_reached para features basadas en seats — señales que de otra forma calcularías desde tus propias tablas de uso.

Webhooks

Paddle entrega notificaciones firmadas con el header Paddle-Signature, y el SDK las verifica y parsea:

Paddle
const event = await paddle.webhooks.unmarshal(
  rawBody,
  process.env.PADDLE_WEBHOOK_SECRET!,
  signature,
)

switch (event.eventType) {
  case 'subscription.activated':
    // Dar acceso
    break
  case 'subscription.canceled':
    // Quitar acceso
    break
}

La forma en Commet es parecida, y en Next.js el handler de @commet/next elimina el boilerplate: verifica firmas y rutea eventos a callbacks tipados:

app/api/webhooks/commet/route.ts
import { Webhooks } from '@commet/next'

export const POST = Webhooks({
  webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,

  onSubscriptionActivated: async (payload) => {
    // Dar acceso
  },

  onSubscriptionCanceled: async (payload) => {
    // Quitar acceso
  },
})

Fuera de Next.js, verificá la firma HMAC-SHA256 con commet.webhooks.verifyAndParse({ rawBody, signature, secret }); la firma llega en el header X-Commet-Signature.

Los eventos que manejás hoy mapean casi uno a uno:

Evento de PaddleEvento de Commet
subscription.createdsubscription.created
subscription.activatedsubscription.activated
subscription.updatedsubscription.updated / subscription.plan_changed
subscription.canceledsubscription.canceled
subscription.past_duesubscription.past_due
transaction.completedpayment.received
transaction.payment_failedpayment.failed
adjustment.created (refund)payment.refunded

Dos detalles operativos que valen la pena:

  • Commet reintenta entregas fallidas con backoff exponencial — 8 intentos, de 1 minuto a 6 horas — y después te manda por email el endpoint, el evento y la última respuesta.
  • Para desarrollo local, commet listen localhost:3000/api/webhooks/commet reenvía eventos en vivo a tu máquina, sin herramientas de tunneling.
  • Si tres entregas seguidas fallan, Commet desactiva el endpoint automáticamente y te manda un email de confirmación; reactivalo desde Settings → Webhooks cuando tu receptor esté arreglado.

Y como el estado de la subscription es consultable vía subscriptions.getActive, los webhooks son notificaciones — no el mecanismo que mantiene tu base de datos correcta.

Impuestos y compliance

Acá las plataformas coinciden: las dos son Merchant of Record. Paddle y Commet le venden a tu cliente, calculan y remiten impuestos, y absorben el trabajo de compliance. Si migraste a Paddle por eso, no perdés nada al moverte a Commet.

Las diferencias están en cobertura y superficie de pagos:

  • Monedas locales en Latinoamérica. Commet cobra planes en ARS, BRL, CLP, COP, PEN, UYU, PYG, BOB, MXN, CAD y EUR, con un precio canónico en USD y la moneda auto-detectada según el país de facturación del cliente. Si vendés en LatAm, cobrar en moneda local afecta directamente la conversión y las tasas de aprobación.
  • Métodos de pago. Paddle soporta tarjetas más wallets y PayPal. El checkout de Commet hoy es solo con tarjeta: si el volumen por wallets o PayPal importa en tu revenue, tenelo en cuenta al planificar la migración.
  • Refunds y disputas los maneja el Merchant of Record en ambas plataformas. En Commet, los refunds son gratis y las disputas cuestan $15.
  • Payouts son parte del trato de Merchant of Record en los dos lados: la plataforma cobra a tus clientes y te liquida tu revenue neto.

El pricing es regional por diseño. Definís un precio canónico en USD por plan, agregás precios locales solo para las monedas que te importan, y la contabilidad interna queda en USD.

Precios

Las dos plataformas cobran un único fee todo-incluido: procesamiento, impuestos y responsabilidad de Merchant of Record:

PaddleCommet
Por transacción exitosa5% + $0.504.5% + $0.40
Procesamiento de pagosIncluidoIncluido
Cálculo y remisión de impuestosIncluidoIncluido
Tarjetas internacionalesIncluidas en el fee base+1.5% (tarjetas no estadounidenses)
DisputasSegún la política vigente de Paddle$15 por disputa
Refunds—Gratis

Sobre $1M de revenue anual con tarjeta y una transacción promedio de $50, la diferencia de cabecera — 0.5% más $0.10 por transacción — son $7,000 por año. Corré los números con tu propia distribución; la brecha crece con la cantidad de transacciones.

Ninguna de las dos plataformas cobra fees mensuales de plataforma — las dos son take-rate puro, así que el costo escala con el revenue desde la primera transacción.

Detalles completos en la página de precios.

Conclusión

Moverse de un Merchant of Record a otro es una migración más chica que abandonar el modelo: tu historia de impuestos no cambia, y el trabajo se concentra en los objetos de billing.

Hay una cosa que no migra automáticamente, así que planificala: las facturas históricas. Mantené acceso a Paddle para las facturas viejas; Commet genera facturas desde el primer ciclo migrado en adelante.

  1. Modelá tus Products y Prices de Paddle como planes de Commet con features explícitas.
  2. Reemplazá el flujo de transaction + overlay de Paddle.js por subscriptions.create → redirect al checkoutUrl.
  3. Mové tu tracking de uso casero a commet.usage.track y borrá el código de reconciliación.
  4. Portá los handlers de webhooks: los eventos mapean casi uno a uno.
  5. Hacé el corte en la renovación, corriendo un ciclo en paralelo para comparar facturas.

La ganancia se concentra en el paso 3: las tablas de uso, los jobs de agregación y los scripts de facturación de fin de período que mantenés alrededor de Paddle dejan de existir.

Probá el flujo completo antes de tocar producción: cada cuenta de Commet incluye un entorno sandbox aislado con tarjetas de prueba y un test clock, así que podés simular un ciclo de billing completo — checkout, uso, renovación — en minutos.

Arrancá con el quickstart, o leé primero la comparación completa entre Paddle y Commet.

Desarrolladores

  • Documentación
  • Templates
  • GitHub

Frameworks

  • Next.js
  • Remix
  • Nuxt
  • SvelteKit
  • Astro
  • Express
  • Hono
  • Django
  • FastAPI

Recursos

  • Blog
  • Changelog
  • Precios

IA

  • Agentes
  • Servidor MCP
  • Agent Skills
  • Claude Code
  • Codex
  • Cursor

Aprender

  • Guías
  • Glosario
  • Soluciones
  • Facturación por Modelo de IA
  • Commet VS otros

Comparar

  • Alternativa a Stripe
  • Alternativa a Orb
  • Alternativa a Recurly
  • Alternativa a Paddle
  • Alternativa a Chargebee
  • Alternativa a Lago

Nosotros

  • Nosotros
  • Open Source
  • Términos y condiciones
  • Política de privacidad

Países

  • México
  • Argentina
  • Colombia
  • Chile
  • Perú
  • Ecuador
  • Uruguay
  • Paraguay
  • Bolivia
  • Panamá
  • El Salvador
  • Brasil
XLinkedInGitHub