Ofertas del Merchant

Crea, lista, actualiza, archiva, restaura y elimina (soft delete) ofertas — los planes de precios asociados a un producto — desde la superficie de Merchant del Tokeflow Dashboard.

Una oferta es un plan comprable asociado a un producto: define el ciclo de cobro, el comportamiento de trial y de setup, los límites de ciclo y uno o más precios específicos por moneda. Un producto puede tener varias ofertas — un plan mensual, un plan anual, una variante promocional — y cada oferta lleva sus propios precios en unidades menores por moneda ISO 4217. Las ofertas son lo que los clientes realmente suscriben o compran en el checkout.

Estos endpoints impulsan las pantallas de gestión de ofertas del Tokeflow Dashboard para un único Merchant. Las ofertas hacen referencia a un producto y, a su vez, son referenciadas por suscripciones, por lo que la eliminación está protegida: una oferta con cualquier historial de suscripción se conserva para los registros de cobro.

Estos endpoints impulsan la interfaz del Tokeflow Dashboard. Están autenticados con una sesión del dashboard (JWT bearer) obtenida al iniciar sesión — no con claves de API sk_/pk_. Cada solicitud también debe enviar el header x-merchant-id que identifica el contexto del Merchant (mrc_…). Consulta Autenticación del Dashboard.

Ciclo de vida de la oferta

Archivar oculta una oferta de los nuevos checkouts manteniéndola totalmente legible; es reversible con unarchive. La eliminación por soft delete quita la oferta (y se propaga en cascada a sus precios), pero se rechaza con 409 mientras cualquier suscripción — en cualquier estado — aún la referencie, y puede revertirse con restore.

El objeto oferta

Derivado de OfferResponseDto, devuelto por cada endpoint de esta página que devuelve un cuerpo.

CampoTipoDescripción
idstringID de la oferta, con el prefijo ofr_.
product_idstringProducto padre, con el prefijo prd_.
namestringNombre visible de la oferta.
slugstringIdentificador en minúsculas, único por producto.
descriptionstring | nullDescripción de texto libre.
billing_cyclestringUno de daily, biweekly, monthly, quarterly, half_yearly, yearly, custom, none.
custom_billing_daysnumber | nullPeríodo en días. Obligatorio cuando billing_cycle = custom.
cycle_limitnumber | nullNúmero fijo de cobros. null = cobrar hasta la cancelación.
free_trialbooleanSi la oferta comienza con un trial gratuito.
trial_daysnumber | nullDuración del trial en días. Obligatorio cuando free_trial = true.
setup_chargebooleanSi el primer ciclo se cobra con un importe de primer cobro distinto.
renew_after_cycle_limitbooleanSi la suscripción se renueva después de alcanzar cycle_limit.
renewal_offer_idstring | nullOferta usada para la renovación posterior a cycle_limit. null = renovar con la misma oferta.
is_defaultbooleanSi esta es la oferta predeterminada de su producto.
statusstringactive o archived.
created_atstringMarca de tiempo de creación (ISO 8601 UTC).
updated_atstringMarca de tiempo de la última actualización (ISO 8601 UTC).
pricesarrayPrecios de la oferta. Se rellena cuando los precios se cargan de forma eager (create, get por ID).

billing_cycle: "none" describe una oferta única, sin recurrencia. Para ciclos recurrentes que no encajan en los presets, usa custom junto con custom_billing_days.


Endpoints

GET/api/v1/merchant/offers

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Devuelve una lista paginada de las ofertas del Merchant, filtrable por producto, estado, ciclo de cobro y nombre.

Parámetros de consulta

CampoTipoObligatorioDescripción
pagenumberNoNúmero de página, indexado desde 1 (predeterminado 1, mín. 1).
limitnumberNoElementos por página (predeterminado 20, mín. 1, máx. 100).
product_idstringNoFiltra las ofertas a un único producto.
statusstringNoFiltra por estado: active o archived.
billing_cyclestringNoFiltra por ciclo de cobro: daily, biweekly, monthly, quarterly, half_yearly, yearly, custom o none.
is_defaultbooleanNoFiltra solo las ofertas predeterminadas.
namestringNoFiltro de coincidencia parcial por el nombre de la oferta.

Ejemplo de solicitud

curl -G https://api.tokeflow.com/api/v1/merchant/offers \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b" \
  --data-urlencode "product_id=prd_a1b2c3d4e5" \
  --data-urlencode "status=active" \
  --data-urlencode "page=1" \
  --data-urlencode "limit=20"

Ejemplo de respuesta — 200 OK

{
  "data": [
    {
      "id": "ofr_a1b2c3d4e5",
      "product_id": "prd_a1b2c3d4e5",
      "name": "Mensal",
      "slug": "mensal",
      "description": "Plano mensal padrão",
      "billing_cycle": "monthly",
      "custom_billing_days": null,
      "cycle_limit": 12,
      "free_trial": false,
      "trial_days": null,
      "setup_charge": false,
      "renew_after_cycle_limit": false,
      "renewal_offer_id": null,
      "is_default": true,
      "status": "active",
      "created_at": "2026-05-19T12:00:00Z",
      "updated_at": "2026-05-19T12:00:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 42,
    "total_pages": 3,
    "has_next": true,
    "has_prev": false
  }
}

POST/api/v1/merchant/offers

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Crea una oferta con sus precios iniciales. Se requiere al menos un precio; cada precio es un importe en unidades menores para una moneda ISO 4217.

Campos de la solicitud

CampoTipoObligatorioDescripción
product_idstringSíProducto padre, con el prefijo prd_.
namestringSíNombre visible (máx. 255 caracteres).
slugstringSíIdentificador en minúsculas, único por producto (máx. 100 caracteres).
descriptionstringNoDescripción de texto libre (máx. 2000 caracteres).
billing_cyclestringSíUno de daily, biweekly, monthly, quarterly, half_yearly, yearly, custom, none.
custom_billing_daysnumberCondicionalPeríodo en días (mín. 1). Obligatorio cuando billing_cycle = custom.
cycle_limitnumberNoNúmero fijo de cobros (mín. 1). Omite o null = cobrar hasta la cancelación.
free_trialbooleanNoSi la oferta comienza con un trial gratuito. Predeterminado false.
trial_daysnumberCondicionalDuración del trial en días (mín. 1). Obligatorio cuando free_trial = true.
setup_chargebooleanNoCobra el primer ciclo por el first_charge_amount de cada precio. Predeterminado false.
renew_after_cycle_limitbooleanNoRenueva la suscripción después de cycle_limit cobros. Predeterminado false.
renewal_offer_idstringNoOferta para la renovación posterior a cycle_limit. Omite = renovar con la misma oferta.
is_defaultbooleanNoConvierte esta en la oferta predeterminada de su producto. Predeterminado false.
statusstringSíactive o archived.
pricesarraySíAl menos un precio (ver abajo).

Campos de precio (prices[])

CampoTipoObligatorioDescripción
currencystringSíCódigo de moneda ISO 4217.
amountnumberSíImporte en unidades menores (mín. 0). Ej.: R$99,00 = 9900.
first_charge_amountnumberNoImporte del primer ciclo en unidades menores. Usado cuando setup_charge = true. 0 = solo validación de tarjeta.
is_defaultbooleanNoMarca esta moneda como la predeterminada de la oferta.

Ejemplo de solicitud

curl -X POST https://api.tokeflow.com/api/v1/merchant/offers \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_a1b2c3d4e5",
    "name": "Mensal",
    "slug": "mensal",
    "description": "Plano mensal padrão",
    "billing_cycle": "monthly",
    "cycle_limit": 12,
    "free_trial": false,
    "setup_charge": false,
    "is_default": true,
    "status": "active",
    "prices": [
      { "currency": "BRL", "amount": 9900, "is_default": true },
      { "currency": "USD", "amount": 1900 }
    ]
  }'

Ejemplo de respuesta — 201 Created

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal",
  "slug": "mensal",
  "description": "Plano mensal padrão",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": true,
  "status": "active",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T12:00:00Z",
  "prices": [
    {
      "currency": "BRL",
      "amount": 9900,
      "is_default": true
    },
    {
      "currency": "USD",
      "amount": 1900,
      "is_default": false
    }
  ]
}

Un trial gratuito no necesita un cobro de setup: free_trial: true con trial_days ya cobra 0 al inicio, y la tarjeta se sigue registrando mediante una validación de tarjeta. Para cobrar una tarifa de alta junto con el trial, añade setup_charge: true con un first_charge_amount mayor que 0 en el precio; first_charge_amount: 0 es la forma explícita de decir "validar la tarjeta, no cobrar nada".


GET/api/v1/merchant/offers/:id

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Recupera una única oferta por ID, incluidos sus precios. Devuelve el objeto oferta.

Ejemplo de solicitud

curl https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5 \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 200 OK

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal",
  "slug": "mensal",
  "description": "Plano mensal padrão",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": true,
  "status": "active",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T12:00:00Z",
  "prices": [
    {
      "currency": "BRL",
      "amount": 9900,
      "is_default": true
    }
  ]
}

PATCH/api/v1/merchant/offers/:id

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Actualiza una oferta. Envía solo los campos que quieras cambiar; se devuelve el objeto oferta actualizado.

Ejemplo de solicitud

curl -X PATCH https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5 \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Mensal Plus", "description": "Plano mensal com upgrade" }'

Ejemplo de respuesta — 200 OK

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal Plus",
  "slug": "mensal",
  "description": "Plano mensal com upgrade",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": true,
  "status": "active",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T14:30:00Z"
}

DELETE/api/v1/merchant/offers/:id

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Elimina una oferta por soft delete, propagándose en cascada a sus precios. La solicitud se rechaza con 409 mientras cualquier suscripción — en cualquier estado — referencie la oferta; las ofertas referenciadas por suscripciones se conservan para el historial de cobro. Una oferta eliminada por soft delete puede recuperarse con restore.

Códigos de respuesta

CódigoCuándo
204 No ContentOferta eliminada por soft delete.
404 Not FoundOferta no encontrada.
409 ConflictLa oferta tiene suscripciones y no puede eliminarse.

Ejemplo de solicitud

curl -X DELETE https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5 \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 204 No Content (cuerpo vacío)

Cuando una oferta no puede eliminarse porque hay suscripciones que la referencian, archívala en su lugar — las ofertas archivadas quedan fuera de los nuevos checkouts mientras su historial de cobro permanece intacto.


POST/api/v1/merchant/offers/:id/archive

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Archiva una oferta, estableciendo status en archived. Devuelve el objeto oferta actualizado.

Ejemplo de solicitud

curl -X POST https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5/archive \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 201 Created

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal",
  "slug": "mensal",
  "description": "Plano mensal padrão",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": false,
  "status": "archived",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T15:00:00Z"
}

POST/api/v1/merchant/offers/:id/unarchive

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Desarchiva una oferta, estableciendo status de nuevo en active. Devuelve el objeto oferta actualizado.

Ejemplo de solicitud

curl -X POST https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5/unarchive \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 201 Created

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal",
  "slug": "mensal",
  "description": "Plano mensal padrão",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": false,
  "status": "active",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T15:10:00Z"
}

POST/api/v1/merchant/offers/:id/restore

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Restaura una oferta eliminada por soft delete y sus precios. Devuelve el objeto oferta restaurado.

Ejemplo de solicitud

curl -X POST https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5/restore \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 201 Created

{
  "id": "ofr_a1b2c3d4e5",
  "product_id": "prd_a1b2c3d4e5",
  "name": "Mensal",
  "slug": "mensal",
  "description": "Plano mensal padrão",
  "billing_cycle": "monthly",
  "custom_billing_days": null,
  "cycle_limit": 12,
  "free_trial": false,
  "trial_days": null,
  "setup_charge": false,
  "renew_after_cycle_limit": false,
  "renewal_offer_id": null,
  "is_default": false,
  "status": "active",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T16:00:00Z"
}

GET/api/v1/merchant/offers/:id/default-price

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Devuelve el precio predeterminado de una oferta para una moneda dada, o null si la oferta no tiene precio predeterminado en esa moneda.

Parámetros de consulta

CampoTipoObligatorioDescripción
currencystringSíCódigo de moneda ISO 4217 para resolver el precio predeterminado.

Ejemplo de solicitud

curl -G https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5/default-price \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b" \
  --data-urlencode "currency=BRL"

Ejemplo de respuesta — 200 OK

{
  "currency": "BRL",
  "amount": 9900,
  "is_default": true
}

GET/api/v1/merchant/offers/:fromId/transitions/:toId/effective-behavior

Merchant

Auth: Dashboard session (JWT bearer). Se requiere membresía del Merchant.

Resuelve el change_charge_behavior efectivo para un par de transición de oferta — cómo se cobrará una suscripción que pasa de la oferta :fromId a la oferta :toId. Úsalo para previsualizar el comportamiento de cobro que aplicará el Dashboard antes de confirmar un cambio de plan.

Ejemplo de solicitud

curl https://api.tokeflow.com/api/v1/merchant/offers/ofr_a1b2c3d4e5/transitions/ofr_f6g7h8i9j0/effective-behavior \
  -H "Authorization: Bearer <session-jwt>" \
  -H "x-merchant-id: mrc_9f8e7d6c5b"

Ejemplo de respuesta — 200 OK


Errores

Respuestas de error comunes para este recurso:

HTTPCausa típica
400Cuerpo inválido — ej.: prices ausente, billing_cycle: "custom" sin custom_billing_days, o free_trial: true sin trial_days.
401Sesión del dashboard ausente o expirada.
403El usuario de la sesión no es miembro del Merchant en x-merchant-id.
404Oferta no encontrada o no perteneciente al Merchant.
409Eliminación rechazada — la oferta es referenciada por al menos una suscripción.

Relacionados

En esta página