Famílias de Produtos
Agrupe produtos e planos relacionados sob uma única entidade de catálogo e defina um comportamento padrão de cobrança na mudança para transições de ofertas dentro do grupo.
Uma família de produtos agrupa produtos e planos relacionados em uma única entidade de catálogo — por exemplo, os níveis de uma mesma assinatura (Light, Pro, Premium) ou um conjunto de complementos avulsos vendidos em conjunto. As famílias dão estrutura ao seu catálogo: em vez de uma lista plana de produtos, você modela as relações entre eles.
Uma família também carrega um comportamento padrão de cobrança na mudança — a regra aplicada quando uma assinatura passa de uma oferta para outra pertencente a produtos da mesma família (um upgrade, downgrade ou troca de plano). Defina-o uma vez na família, e toda transição dentro dessa família o herda, a menos que seja sobrescrito.
A Tokeflow orquestra pagamentos; ela não processa nem liquida fundos. As famílias de produtos são pura modelagem de catálogo — elas descrevem o que você vende e como as mudanças de plano são cobradas, nunca quem movimenta o dinheiro.
As famílias de produtos fazem parte do catálogo, que tem escopo de Merchant. Com uma chave de Merchant, o merchant é inferido. Com uma chave de Organization, direcione a um merchant com o parâmetro de query merchant_id (em list/get) ou o campo de corpo (em create). Consulte Autenticação.
Onde as famílias se encaixam
Uma família fica no topo da hierarquia do catálogo. Os produtos pertencem a uma família; ofertas e preços derivam dos produtos; assinaturas se apoiam em ofertas.
Quando um assinante faz a transição de uma oferta em um produto para uma oferta em outro produto da mesma família, o change_charge_behavior da família decide como a mudança é cobrada.
O comportamento de cobrança na mudança
change_charge_behavior define o tratamento de cobrança padrão para transições de ofertas dentro da família.
| Value | Meaning |
|---|---|
next_renew | Aplica a mudança na próxima renovação — o novo preço passa a valer no ciclo de faturamento seguinte. |
prorated | Rateia a diferença para o ciclo atual. |
override | Substitui a cobrança atual pelos termos da nova oferta imediatamente. |
Se você omitir change_charge_behavior na criação, a família assume o padrão next_renew.
O mecanismo de transição executa os três comportamentos — next_renew, prorated e override. O change_charge_behavior padrão armazenado na família é aplicado a cada mudança dentro dela, a menos que uma transição de oferta substitua um par específico.
O objeto de família de produtos
| Field | Type | Description |
|---|---|---|
id | string | Identificador único, prefixado com pfa_. |
merchant_id | string | Merchant proprietário, prefixado com mrc_. |
name | string | Nome legível para humanos, por exemplo Streaming Plans. |
slug | string | Identificador em minúsculas, único por merchant. |
description | string | null | Descrição opcional em texto livre. |
custom_plan_id | string | null | Referência opcional a um plano externo, apenas para exibição. Único por merchant quando definido. |
change_charge_behavior | enum | Comportamento de transição padrão: next_renew, prorated ou override. |
created_at | string | Timestamp de criação em ISO 8601 UTC. |
updated_at | string | Timestamp da última atualização em ISO 8601 UTC. |
deleted_at | string | null | Timestamp de exclusão lógica em ISO 8601 UTC, ou null quando ativo. Presente apenas em registros com exclusão 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"
}Criar uma família de produtos
POST/api/v1/product-families
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:write.
Cria uma nova família no catálogo do merchant de destino.
Parâmetros de corpo
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Sim | Nome legível para humanos. |
slug | string | Sim | Identificador em minúsculas, único por merchant (entre famílias ativas). |
description | string | Não | Descrição em texto livre. |
custom_plan_id | string | Não | Referência a um plano externo (apenas para exibição), única por merchant quando definida. |
change_charge_behavior | enum | Não | next_renew (padrão), prorated ou override. |
merchant_id | string | Condicional | Obrigatório apenas com uma chave de Organization, para direcionar a um merchant. Inferido a partir de uma chave 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"
}'Resposta 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"
}Envie um cabeçalho Idempotency-Key na criação. Repetir a mesma chave retorna o resultado original (HTTP 200 no replay vs 201 na primeira criação) em vez de criar uma duplicata. Consulte Idempotência e limites de taxa.
slug deve ser único por merchant entre as famílias ativas. Uma duplicata retorna 409 (conflict_error). O mesmo se aplica a custom_plan_id quando definido.
Listar famílias de produtos
GET/api/v1/product-families
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:read.
Retorna uma lista paginada de famílias do merchant, das mais recentes para as mais antigas.
Parâmetros de query
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Não | Filtro de correspondência parcial (sem diferenciar maiúsculas de minúsculas) no nome da família. |
slug | string | Não | Filtra por slug exato. |
change_charge_behavior | enum | Não | Filtra por next_renew, prorated ou override. |
page | integer | Não | Número da página, padrão 1, mínimo 1. |
limit | integer | Não | Itens por página, padrão 20, máximo 100. |
merchant_id | string | Condicional | Obrigatório apenas com uma chave 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"Resposta 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"
}Obter uma família de produtos
GET/api/v1/product-families/:id
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:read.
Recupera uma única família pelo ID.
curl https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…"Resposta 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"
}Um ID desconhecido retorna 404 (not_found_error).
Atualizar uma família de produtos
PATCH/api/v1/product-families/:id
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:write.
Atualiza parcialmente uma família. Envie apenas os campos que deseja alterar. Todos os campos de criação são atualizáveis: name, slug, description, custom_plan_id e 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"
}'Resposta 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"
}Alterar slug ou custom_plan_id para um valor já usado por outra família ativa no mesmo merchant retorna 409 (conflict_error).
Excluir logicamente uma família de produtos
DELETE/api/v1/product-families/:id
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:write.
Faz a exclusão lógica da família. O registro é mantido com um timestamp deleted_at e excluído dos resultados de list e get, preservando a auditabilidade. As posições de slug e custom_plan_id são liberadas para reutilização por novas famílias ativas.
curl -X DELETE https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5 \
-H "Authorization: Bearer sk_live_mer_…"Resposta 204 No Content
O corpo da resposta está vazio. Um ID desconhecido retorna 404 (not_found_error).
Esta é uma exclusão lógica — a família pode ser recuperada com o endpoint de restauração abaixo.
Restaurar uma família de produtos
POST/api/v1/product-families/:id/restore
Auth: chave de Organization (com merchant_id) ou chave de Merchant. Requer o escopo products:write.
Restaura uma família com exclusão lógica, limpando seu deleted_at. A restauração recupera o slug e o custom_plan_id originais somente se nenhuma família ativa os tiver assumido nesse meio-tempo.
curl -X POST https://api.tokeflow.com/api/v1/product-families/pfa_a1b2c3d4e5/restore \
-H "Authorization: Bearer sk_live_mer_…"Resposta 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 erro
| Condition | HTTP | Type |
|---|---|---|
| A família já está ativa (sem exclusão lógica) | 400 | validation_error |
Uma família ativa agora detém o mesmo slug | 409 | conflict_error |
Uma família ativa agora detém o mesmo custom_plan_id | 409 | conflict_error |
| Família não encontrada | 404 | not_found_error |
Se a restauração falhar com um conflito de slug ou custom_plan_id, renomeie ou arquive a família ativa que detém a posição e, em seguida, tente a restauração novamente.
Erros
Todos os erros usam o envelope padrão. Consulte Erros para o 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"
}
}Relacionados
- Produtos — os níveis que pertencem a uma família.
- Conceitos centrais — como catálogo, ofertas e assinaturas se encaixam.
- Visão geral da referência da API — envelopes, paginação, dinheiro e IDs.