Ofertas do Merchant

Crie, liste, atualize, arquive, restaure e exclua (soft delete) ofertas — os planos de preços vinculados a um produto — a partir da superfície de Merchant do Tokeflow Dashboard.

Uma oferta é um plano comprável vinculado a um produto: ela define o ciclo de cobrança, o comportamento de trial e de setup, os limites de ciclo e um ou mais preços específicos por moeda. Um produto pode ter várias ofertas — um plano mensal, um plano anual, uma variante promocional — e cada oferta carrega seus próprios preços em unidades menores por moeda ISO 4217. As ofertas são o que os clientes de fato assinam ou compram no checkout.

Esses endpoints alimentam as telas de gerenciamento de ofertas do Tokeflow Dashboard para um único Merchant. As ofertas referenciam um produto e, por sua vez, são referenciadas por assinaturas, razão pela qual a exclusão é protegida: uma oferta com qualquer histórico de assinatura é preservada para os registros de cobrança.

Esses endpoints alimentam a interface do Tokeflow Dashboard. Eles são autenticados com uma sessão do dashboard (JWT bearer) obtida ao fazer login — não com chaves de API sk_/pk_. Toda solicitação também deve enviar o header x-merchant-id identificando o contexto do Merchant (mrc_…). Veja Autenticação do Dashboard.

Ciclo de vida da oferta

Arquivar oculta uma oferta de novos checkouts mantendo-a totalmente legível; é reversível com unarchive. A exclusão por soft delete remove a oferta (e propaga em cascata para seus preços), mas é recusada com 409 enquanto qualquer assinatura — em qualquer status — ainda a referenciar, e pode ser revertida com restore.

O objeto oferta

Derivado de OfferResponseDto, retornado por todos os endpoints desta página que retornam um corpo.

CampoTipoDescrição
idstringID da oferta, prefixado com ofr_.
product_idstringProduto pai, prefixado com prd_.
namestringNome de exibição da oferta.
slugstringIdentificador em minúsculas, único por produto.
descriptionstring | nullDescrição em texto livre.
billing_cyclestringUm de daily, biweekly, monthly, quarterly, half_yearly, yearly, custom, none.
custom_billing_daysnumber | nullPeríodo em dias. Obrigatório quando billing_cycle = custom.
cycle_limitnumber | nullNúmero fixo de cobranças. null = cobrar até o cancelamento.
free_trialbooleanSe a oferta começa com um trial gratuito.
trial_daysnumber | nullDuração do trial em dias. Obrigatório quando free_trial = true.
setup_chargebooleanSe o primeiro ciclo é cobrado com um valor de primeira cobrança distinto.
renew_after_cycle_limitbooleanSe a assinatura renova após atingir cycle_limit.
renewal_offer_idstring | nullOferta usada para renovação após cycle_limit. null = renovar com a mesma oferta.
is_defaultbooleanSe esta é a oferta padrão do seu produto.
statusstringactive ou archived.
created_atstringTimestamp de criação (ISO 8601 UTC).
updated_atstringTimestamp da última atualização (ISO 8601 UTC).
pricesarrayPreços da oferta. Preenchido quando os preços são carregados de forma eager (create, get por ID).

billing_cycle: "none" descreve uma oferta avulsa, sem recorrência. Para ciclos recorrentes que não se encaixam nos presets, use custom junto com custom_billing_days.


Endpoints

GET/api/v1/merchant/offers

Merchant

Auth: Dashboard session (JWT bearer). É necessário ser membro do Merchant.

Retorna uma lista paginada das ofertas do Merchant, filtrável por produto, status, ciclo de cobrança e nome.

Parâmetros de consulta

CampoTipoObrigatórioDescrição
pagenumberNãoNúmero da página, indexado a partir de 1 (padrão 1, mín. 1).
limitnumberNãoItens por página (padrão 20, mín. 1, máx. 100).
product_idstringNãoFiltra as ofertas para um único produto.
statusstringNãoFiltra por status: active ou archived.
billing_cyclestringNãoFiltra por ciclo de cobrança: daily, biweekly, monthly, quarterly, half_yearly, yearly, custom ou none.
is_defaultbooleanNãoFiltra apenas as ofertas padrão.
namestringNãoFiltro de correspondência parcial pelo nome da oferta.

Exemplo de requisição

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"

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Cria uma oferta com seus preços iniciais. Pelo menos um preço é obrigatório; cada preço é um valor em unidades menores para uma moeda ISO 4217.

Campos da requisição

CampoTipoObrigatórioDescrição
product_idstringSimProduto pai, prefixado com prd_.
namestringSimNome de exibição (máx. 255 caracteres).
slugstringSimIdentificador em minúsculas, único por produto (máx. 100 caracteres).
descriptionstringNãoDescrição em texto livre (máx. 2000 caracteres).
billing_cyclestringSimUm de daily, biweekly, monthly, quarterly, half_yearly, yearly, custom, none.
custom_billing_daysnumberCondicionalPeríodo em dias (mín. 1). Obrigatório quando billing_cycle = custom.
cycle_limitnumberNãoNúmero fixo de cobranças (mín. 1). Omita ou null = cobrar até o cancelamento.
free_trialbooleanNãoSe a oferta começa com um trial gratuito. Padrão false.
trial_daysnumberCondicionalDuração do trial em dias (mín. 1). Obrigatório quando free_trial = true.
setup_chargebooleanNãoCobra o primeiro ciclo pelo first_charge_amount de cada preço. Padrão false.
renew_after_cycle_limitbooleanNãoRenova a assinatura após cycle_limit cobranças. Padrão false.
renewal_offer_idstringNãoOferta para renovação após cycle_limit. Omita = renovar com a mesma oferta.
is_defaultbooleanNãoTorna esta a oferta padrão do seu produto. Padrão false.
statusstringSimactive ou archived.
pricesarraySimPelo menos um preço (veja abaixo).

Campos de preço (prices[])

CampoTipoObrigatórioDescrição
currencystringSimCódigo de moeda ISO 4217.
amountnumberSimValor em unidades menores (mín. 0). Ex.: R$99,00 = 9900.
first_charge_amountnumberNãoValor do primeiro ciclo em unidades menores. Usado quando setup_charge = true. 0 = apenas validação de cartão.
is_defaultbooleanNãoMarca esta moeda como a padrão da oferta.

Exemplo de requisição

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 }
    ]
  }'

Exemplo de resposta — 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
    }
  ]
}

Um trial gratuito não precisa de uma cobrança de setup: free_trial: true com trial_days já cobra 0 no início, e o cartão continua sendo cadastrado por uma validação de cartão. Para cobrar uma taxa de adesão junto com o trial, adicione setup_charge: true com um first_charge_amount acima de 0 no preço; first_charge_amount: 0 é a forma explícita de dizer "validar o cartão, não cobrar nada".


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

Merchant

Auth: Dashboard session (JWT bearer). É necessário ser membro do Merchant.

Recupera uma única oferta pelo ID, incluindo seus preços. Retorna o objeto oferta.

Exemplo de requisição

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

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Atualiza uma oferta. Envie apenas os campos que deseja alterar; o objeto oferta atualizado é retornado.

Exemplo de requisição

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" }'

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Exclui uma oferta por soft delete, propagando em cascata para seus preços. A solicitação é recusada com 409 enquanto qualquer assinatura — em qualquer status — referenciar a oferta; ofertas referenciadas por assinaturas são mantidas para o histórico de cobrança. Uma oferta excluída por soft delete pode ser recuperada com restore.

Códigos de resposta

CódigoQuando
204 No ContentOferta excluída por soft delete.
404 Not FoundOferta não encontrada.
409 ConflictA oferta tem assinaturas e não pode ser excluída.

Exemplo de requisição

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

Exemplo de resposta — 204 No Content (corpo vazio)

Quando uma oferta não pode ser excluída porque assinaturas a referenciam, arquive-a em vez disso — ofertas arquivadas ficam fora de novos checkouts enquanto seu histórico de cobrança permanece intacto.


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

Merchant

Auth: Dashboard session (JWT bearer). É necessário ser membro do Merchant.

Arquiva uma oferta, definindo status como archived. Retorna o objeto oferta atualizado.

Exemplo de requisição

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"

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Desarquiva uma oferta, definindo status de volta como active. Retorna o objeto oferta atualizado.

Exemplo de requisição

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"

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Restaura uma oferta excluída por soft delete e seus preços. Retorna o objeto oferta restaurado.

Exemplo de requisição

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"

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Retorna o preço padrão de uma oferta para uma dada moeda, ou null se a oferta não tiver preço padrão nessa moeda.

Parâmetros de consulta

CampoTipoObrigatórioDescrição
currencystringSimCódigo de moeda ISO 4217 para resolver o preço padrão.

Exemplo de requisição

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"

Exemplo de resposta — 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). É necessário ser membro do Merchant.

Resolve o change_charge_behavior efetivo para um par de transição de oferta — como uma assinatura movendo-se da oferta :fromId para a oferta :toId será cobrada. Use-o para pré-visualizar o comportamento de cobrança que o Dashboard aplicará antes de confirmar uma mudança de plano.

Exemplo de requisição

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"

Exemplo de resposta — 200 OK


Erros

Respostas de erro comuns para este recurso:

HTTPCausa típica
400Corpo inválido — ex.: prices ausente, billing_cycle: "custom" sem custom_billing_days, ou free_trial: true sem trial_days.
401Sessão do dashboard ausente ou expirada.
403O usuário da sessão não é membro do Merchant em x-merchant-id.
404Oferta não encontrada ou não pertencente ao Merchant.
409Exclusão recusada — a oferta é referenciada por pelo menos uma assinatura.

Relacionados

Nesta página