Familias de productos
Agrupa productos y planes relacionados bajo una única entidad de catálogo y define un comportamiento de cobro de cambios predeterminado para las transiciones de oferta dentro del grupo.
Una familia de productos agrupa productos y planes relacionados en una única entidad de catálogo — por ejemplo, los niveles de una misma suscripción (Light, Pro, Premium) o un conjunto de complementos de pago único vendidos en conjunto. Las familias dan estructura a tu catálogo: en lugar de una lista plana de productos, modelas las relaciones entre ellos.
Una familia también lleva un comportamiento de cobro de cambios predeterminado — la regla que se aplica cuando una suscripción se mueve entre ofertas pertenecientes a productos de la misma familia (una mejora, una degradación o un cambio de plan). Defínelo una sola vez en la familia, y cada transición dentro de esa familia lo hereda a menos que se anule.
Tokeflow orquesta pagos; no procesa ni liquida fondos. Las familias de productos son puro modelado de catálogo — describen qué vendes y cómo se cobran los cambios de plan, nunca quién mueve el dinero.
Las familias de productos forman parte del catálogo, que tiene alcance de Merchant. Con una clave de Merchant, el merchant se infiere. Con una clave de Organization, apunta a un merchant con el parámetro de consulta merchant_id (en list/get) o el campo del cuerpo (en create). Consulta Authentication.
Dónde encajan las familias
Una familia está en la cima de la jerarquía del catálogo. Los productos pertenecen a una familia; las ofertas y los precios cuelgan de los productos; las suscripciones se apoyan en las ofertas.
Cuando un suscriptor pasa de una oferta de un producto a una oferta de otro producto en la misma familia, el change_charge_behavior de la familia decide cómo se factura el cambio.
El comportamiento de cobro de cambios
change_charge_behavior define el tratamiento de facturación predeterminado para las transiciones de oferta dentro de la familia.
| Value | Meaning |
|---|---|
next_renew | Aplica el cambio en la siguiente renovación — el nuevo precio entra en vigor en el ciclo de facturación siguiente. |
prorated | Prorratea la diferencia para el ciclo actual. |
override | Reemplaza el cargo actual con los términos de la nueva oferta de inmediato. |
Si omites change_charge_behavior al crear, la familia usa next_renew de forma predeterminada.
El motor de transiciones ejecuta los tres comportamientos — next_renew, prorated y override. El change_charge_behavior predeterminado almacenado en la familia se aplica a cada cambio dentro de ella, salvo que una transición de oferta anule un par específico.
El objeto de familia de productos
| Field | Type | Description |
|---|---|---|
id | string | Identificador único, prefijado con pfa_. |
merchant_id | string | Merchant propietario, prefijado con mrc_. |
name | string | Nombre legible para humanos, p. ej. Streaming Plans. |
slug | string | Identificador en minúsculas, único por merchant. |
description | string | null | Descripción opcional de texto libre. |
custom_plan_id | string | null | Referencia opcional de plan externo, solo para visualización. Único por merchant cuando se define. |
change_charge_behavior | enum | Comportamiento de transición predeterminado: next_renew, prorated u override. |
created_at | string | Marca de tiempo de creación en UTC ISO 8601. |
updated_at | string | Marca de tiempo de última actualización en UTC ISO 8601. |
deleted_at | string | null | Marca de tiempo de eliminación lógica en UTC ISO 8601, o null cuando está activo. Presente solo en registros eliminados de forma lógica. |
{
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "Family of streaming subscription plans",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "next_renew",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z"
}Crear una familia de productos
POST/api/v1/product-families
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:write.
Crea una nueva familia en el catálogo del merchant de destino.
Parámetros del cuerpo
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Sí | Nombre legible para humanos. |
slug | string | Sí | Identificador en minúsculas, único por merchant (entre las familias activas). |
description | string | No | Descripción de texto libre. |
custom_plan_id | string | No | Referencia de plan externo (solo para visualización), única por merchant cuando se define. |
change_charge_behavior | enum | No | next_renew (predeterminado), prorated u override. |
merchant_id | string | Condicional | Requerido solo con una clave de Organization, para apuntar a un merchant. Se infiere de una clave de Merchant. |
curl -X POST https://api.tokeflow.com/api/v1/product-families \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f3c1d20-9b4a-4e2c-9f6a-2c1d0e7b5a44" \
-d '{
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "Family of streaming subscription plans",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "next_renew"
}'Respuesta 201 Created
{
"success": true,
"data": {
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "Family of streaming subscription plans",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "next_renew",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z"
},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-19T12:00:00.000Z"
}Envía un encabezado Idempotency-Key al crear. Reenviar la misma clave devuelve el resultado original (HTTP 200 al reintentar frente a 201 en la primera creación) en lugar de crear un duplicado. Consulta Idempotency and rate limits.
slug debe ser único por merchant entre las familias activas. Un duplicado devuelve 409 (conflict_error). Lo mismo aplica a custom_plan_id cuando se define.
Listar familias de productos
GET/api/v1/product-families
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:read.
Devuelve una lista paginada de familias del merchant, de la más reciente a la más antigua.
Parámetros de consulta
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Filtro de coincidencia parcial (sin distinción de mayúsculas y minúsculas) sobre el nombre de la familia. |
slug | string | No | Filtra por slug exacto. |
change_charge_behavior | enum | No | Filtra por next_renew, prorated u override. |
page | integer | No | Número de página, predeterminado 1, mínimo 1. |
limit | integer | No | Elementos por página, predeterminado 20, máximo 100. |
merchant_id | string | Condicional | Requerido solo con una clave de Organization. |
curl -G https://api.tokeflow.com/api/v1/product-families \
-H "Authorization: Bearer sk_live_mer_…" \
--data-urlencode "page=1" \
--data-urlencode "limit=20" \
--data-urlencode "name=Streaming" \
--data-urlencode "change_charge_behavior=next_renew"Respuesta 200 OK
{
"success": true,
"data": [
{
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "Family of streaming subscription plans",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "next_renew",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z"
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-19T12:00:00.000Z"
}Obtener una familia de productos
GET/api/v1/product-families/:id
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:read.
Recupera una única familia por su ID.
curl https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…"Respuesta 200 OK
{
"success": true,
"data": {
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "Family of streaming subscription plans",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "next_renew",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-19T12:00:00.000Z"
},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-19T12:00:00.000Z"
}Un ID desconocido devuelve 404 (not_found_error).
Actualizar una familia de productos
PATCH/api/v1/product-families/:id
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:write.
Actualiza parcialmente una familia. Envía solo los campos que quieras cambiar. Todos los campos de creación son actualizables: name, slug, description, custom_plan_id y change_charge_behavior.
curl -X PATCH https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-d '{
"description": "All streaming subscription tiers",
"change_charge_behavior": "prorated"
}'Respuesta 200 OK
{
"success": true,
"data": {
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "All streaming subscription tiers",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "prorated",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-20T09:15:00.000Z"
},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-20T09:15:00.000Z"
}Cambiar slug o custom_plan_id a un valor que ya tenga otra familia activa en el mismo merchant devuelve 409 (conflict_error).
Eliminar de forma lógica una familia de productos
DELETE/api/v1/product-families/:id
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:write.
Elimina de forma lógica la familia. El registro se conserva con una marca de tiempo deleted_at y se excluye de los resultados de list y get, preservando la auditabilidad. Los espacios de slug y custom_plan_id quedan liberados para su reutilización por nuevas familias activas.
curl -X DELETE https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…"Respuesta 204 No Content
El cuerpo de la respuesta está vacío. Un ID desconocido devuelve 404 (not_found_error).
Esta es una eliminación lógica — la familia puede recuperarse con el endpoint de restauración que aparece más abajo.
Restaurar una familia de productos
POST/api/v1/product-families/:id/restore
Auth: clave de Organization (con merchant_id) o clave de Merchant. Requiere el scope products:write.
Restaura una familia eliminada de forma lógica, borrando su deleted_at. La restauración recupera el slug y el custom_plan_id originales solo si ninguna familia activa los ha tomado en el ínterin.
curl -X POST https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5/restore \
-H "Authorization: Bearer sk_live_mer_…"Respuesta 201 Created
{
"success": true,
"data": {
"id": "pfa_a1b2c3d4e5",
"merchant_id": "mrc_a1b2c3d4e5",
"name": "Streaming Plans",
"slug": "streaming-plans",
"description": "All streaming subscription tiers",
"custom_plan_id": "plan_external_42",
"change_charge_behavior": "prorated",
"created_at": "2026-05-19T12:00:00.000Z",
"updated_at": "2026-05-21T11:00:00.000Z"
},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-21T11:00:00.000Z"
}Casos de error
| Condition | HTTP | Type |
|---|---|---|
| La familia ya está activa (no eliminada de forma lógica) | 400 | validation_error |
Una familia activa ahora tiene el mismo slug | 409 | conflict_error |
Una familia activa ahora tiene el mismo custom_plan_id | 409 | conflict_error |
| Familia no encontrada | 404 | not_found_error |
Si la restauración falla por un conflicto de slug o custom_plan_id, renombra o archiva la familia activa que ocupa el espacio y luego reintenta la restauración.
Errores
Todos los errores usan el envelope estándar. Consulta Errors para ver el catálogo completo.
{
"error": {
"type": "conflict_error",
"code": "PRODUCT_FAMILY_SLUG_TAKEN",
"message": "Product family with slug 'streaming-plans' already exists",
"details": {},
"request_id": "req_8f3c1d20",
"timestamp": "2026-05-19T12:00:00.000Z"
}
}Relacionado
- Products — los niveles que pertenecen a una familia.
- Core concepts — cómo encajan el catálogo, las ofertas y las suscripciones.
- API reference overview — envelopes, paginación, dinero e IDs.