Ciclos de cobrança
Cada assinatura é cobrada em ciclos: períodos de cobrança recorrentes (por exemplo, um mês) com data de início, fim, vencimento e status próprios. A Selectwin gera e cobra os ciclos automaticamente; e
Cada assinatura é cobrada em ciclos: períodos de cobrança recorrentes (por exemplo, um mês) com data de início, fim, vencimento e status próprios. A Selectwin gera e cobra os ciclos automaticamente; estes endpoints permitem listar o histórico de ciclos, consultar um ciclo específico e disparar a renovação do ciclo de uma assinatura.
| Operação | Método | Endpoint |
|---|---|---|
| Listar ciclos | GET | /v1/subscriptions/{subscriptionId}/cycles |
| Consultar ciclo | GET | /v1/subscriptions/{subscriptionId}/cycles/{cycleId} |
| Renovar ciclo | POST | /v1/subscriptions/{subscriptionId}/cycles |
Autenticação por header SelectKey em todas as chamadas; base URL https://api.selectwin.io/v1. Dinheiro em centavos (inteiro) e datas em ISO 8601 UTC. Veja Convenções.
Como funciona
Um ciclo (objeto com prefixo cyc_) é a unidade de faturamento de uma assinatura. Quando você cria uma assinatura, a Selectwin gera o primeiro ciclo; ao final de cada período, gera o próximo, seguindo a frequência do plano (billing.frequency / billing.frequencyCount). Cada ciclo carrega:
- um número sequencial (
cycle: 1, 2, 3, …); - uma janela de vigência (
startDate→endDate); - a data de vencimento da cobrança (
dueDate); - um
statusque evolui conforme a cobrança é gerada e paga.
O objeto currentCycle, retornado em Consultar assinatura, reflete sempre o ciclo vigente. Cada mudança de status do ciclo dispara um webhook de assinatura — não fique consultando estes endpoints em laço; veja Proibição de polling.
Valores de status do ciclo
O campo status descreve em que ponto da cobrança o ciclo está. No contrato ele é tipado apenas como string (sem enum fixo). Os valores que aparecem nos exemplos do contrato são:
status | Significado |
|---|---|
billed | Cobrança do ciclo já emitida (transação gerada), aguardando confirmação. |
paid | Ciclo pago — pagamento confirmado para o período. |
canceled | Ciclo cancelado (por exemplo, ao cancelar a assinatura). |
Nota
Como o contrato não fixa um enum, trate status de forma defensiva: aceite valores além destes sem quebrar e sempre reaja ao webhook de assinatura, não a um conjunto fechado de estados.
O fluxo típico (inferido a partir dos exemplos) é: a cobrança é emitida (billed), depois confirmada (paid); um ciclo pode terminar como canceled se a assinatura for cancelada.
Trate os IDs (
cyc_…,subs_…) como opacos: armazene a string inteira e não faça parsing do prefixo.
Listar ciclos
GET /v1/subscriptions/{subscriptionId}/cycles
Retorna o histórico paginado de ciclos da assinatura — útil para montar uma timeline de faturas/renovações ou conciliar cobranças. A lista traz uma projeção leve de cada ciclo (sem amount); para o detalhe completo, use Consultar ciclo.
Quando usar
- Exibir o histórico de cobranças de uma assinatura ao cliente ou no painel.
- Conciliar quantos ciclos já foram gerados/pagos.
- Não use em laço para "esperar" um pagamento — reaja ao webhook correspondente.
Requisição
Headers
| Header | Valor |
|---|---|
SelectKey | sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ (produção; em sandbox começa com sl_test_) |
Parâmetros de caminho
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | sim | ID da assinatura (ex.: subs_01hqzvabc). |
Parâmetros de query
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
limit | number (1–100) | não | Máximo de itens por página (ex.: 20). |
offset | number (≥ 0) | não | Quantos itens pular (paginação). |
sort | string | não | Ordenação: ascending ou descending. |
Veja Paginação para o padrão offset/limit/hasMore.
curl -X GET "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles?limit=20&sort=descending" \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"Resposta
200 OK — envelope paginado com os ciclos em data:
{
"offset": 0,
"limit": 20,
"total": 3,
"hasMore": false,
"page": {
"current": 1,
"total": 1,
"offset": { "first": 0, "prev": null, "next": null, "last": 0 }
},
"data": [
{
"id": "cyc_01hqzvabc",
"status": "paid",
"cycle": 1,
"startDate": "2026-04-01T00:00:00.000Z",
"endDate": "2026-05-01T00:00:00.000Z",
"dueDate": "2026-04-01T00:00:00.000Z",
"billedAt": "2026-04-01T10:15:00.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"createdAt": "2026-04-12T17:56:33.000Z"
}
],
"merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
"_links": {
"self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles", "method": "GET" }
}
}Campos de cada item em data[]:
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID do ciclo (cyc_…). |
status | string | Status do ciclo (ex.: billed, paid, canceled). |
cycle | integer | Número sequencial do ciclo (1, 2, 3, …). |
startDate | string (date-time) | Início da vigência do período. |
endDate | string (date-time) | Fim da vigência do período. |
dueDate | string (date-time) | Data de vencimento da cobrança. |
billedAt | string (date-time) | Quando a cobrança do ciclo foi emitida. |
updatedAt | string (date-time) | Última atualização. |
createdAt | string (date-time) | Criação do registro do ciclo. |
O item de lista não inclui
amount. Para obter o valor do ciclo, consulte o ciclo individualmente.
Consultar ciclo
GET /v1/subscriptions/{subscriptionId}/cycles/{cycleId}
Retorna o detalhe de um único ciclo.
Requisição
Parâmetros de caminho
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | sim | ID da assinatura (ex.: subs_01hqzvabc). |
cycleId | string | sim | ID do ciclo (ex.: cyc_01hqzvabc). |
curl -X GET "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles/cyc_01hqzvabc" \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"Resposta
200 OK:
{
"id": "cyc_01hqzvabc",
"cycle": 1,
"status": "billed",
"startDate": "2026-04-01T00:00:00.000Z",
"endDate": "2026-05-01T00:00:00.000Z",
"dueDate": "2026-05-01T00:00:00.000Z",
"billedAt": "2026-04-01T10:15:00.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"createdAt": "2026-04-12T17:56:33.000Z",
"merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
"_links": {
"self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles/cyc_01hqzvabc", "method": "GET", "description": "Read a cycle." },
"list": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles", "method": "GET", "description": "List cycles of a subscription." },
"create": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles", "method": "POST", "description": "Renew cycle of subscription." }
}
}Campos da resposta:
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID do ciclo (cyc_…). |
cycle | integer | Número sequencial do ciclo. |
status | string | Status (ex.: billed, paid, canceled). |
startDate | string (date-time) | Início do período. |
endDate | string (date-time) | Fim do período. |
dueDate | string (date-time) | Vencimento da cobrança. |
billedAt | string (date-time) | Quando a cobrança foi emitida. |
updatedAt | string (date-time) | Última atualização. |
createdAt | string (date-time) | Criação do registro. |
merchant | object | Identificação do vendedor (name, merchantId, isSubAccount). |
_links | object | Links HATEOAS para self, list e create (renovar). |
Renovar ciclo
POST /v1/subscriptions/{subscriptionId}/cycles
Dispara a renovação do ciclo da assinatura. A operação não recebe corpo: o servidor avança o ciclo de cobrança da assinatura conforme a regra de negócio do plano e retorna o ciclo resultante.
Atenção
A resposta desta operação é um objeto de ciclo (cyc_…), não uma transação. Use-a para acionar o avanço do ciclo de cobrança da assinatura — não como forma de capturar um pagamento avulso. A cobrança em si segue o fluxo normal de cobrança da assinatura e é refletida pelo status do ciclo e pelos webhooks correspondentes.
Quando usar (e quando não)
- Use para forçar o avanço/renovação do ciclo de uma assinatura quando seu fluxo de negócio exigir antecipar a próxima cobrança.
- Não use para cobrar um valor pontual fora da assinatura — para isso, crie uma transação avulsa.
- Não use em laço para "garantir" pagamento; reaja aos webhooks de assinatura.
Requisição
Headers
| Header | Valor |
|---|---|
SelectKey | sua chave de API (sl_live_… em produção). |
X-Idempotency-Key | recomendado: garante que repetições da chamada (timeout/retry) não disparem duas renovações. Veja Idempotência. |
Parâmetros de caminho
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | sim | ID da assinatura (ex.: subs_01hqzvabc). |
Esta operação não tem corpo de requisição nem parâmetros de query.
curl -X POST "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles" \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
-H "X-Idempotency-Key: 8f1c2e7a-1b9d-4a3e-9c6f-2b7a1d0e5c44"Resposta
200 OK — o ciclo resultante:
{
"id": "cyc_01hqzvabc",
"subscriptionId": "subs_01hqzvabc",
"status": "paid",
"amount": 9900,
"dueDate": "2026-04-01T00:00:00.000Z",
"paidAt": "2026-04-01T10:15:00.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"createdAt": "2026-04-12T17:56:33.000Z",
"merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
"_links": {
"self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/cycles/cyc_01hqzvabc", "method": "GET" }
}
}Campos da resposta:
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID do ciclo (cyc_…). |
subscriptionId | string | ID da assinatura à qual o ciclo pertence. |
status | string | Status do ciclo (ex.: billed, paid, canceled). |
amount | integer | Valor do ciclo, em centavos (9900 = R$ 99,00). |
dueDate | string (date-time) | Vencimento da cobrança do ciclo. |
paidAt | string (date-time) | Quando o ciclo foi pago (quando aplicável). |
updatedAt | string (date-time) | Última atualização. |
createdAt | string (date-time) | Criação do registro. |
merchant | object | Identificação do vendedor. |
_links | object | Link self para consultar o ciclo. |
Note a diferença de projeção: a renovação e a consulta individual retornam
amount; o item de lista não retornaamount.
Erros
Trate sempre pelo error.code (estável), nunca pela message. Veja Tratamento de Erros e o Catálogo de Códigos de Erro.
error.code | HTTP | Quando ocorre |
|---|---|---|
invalidParameters | 400 | Parâmetro de caminho/query malformado (ex.: limit fora de 1–100). |
unauthorized | 401 | SelectKey ausente, inválida ou revogada. |
forbidden | 403 | Chave sem permissão para a assinatura. |
notFound | 404 | Assinatura (subscriptionId) ou ciclo (cycleId) inexistente. |
insufficientFundsError | 402 | Renovação requer saldo/fundos e a cobrança não pôde ser concluída (só em POST). |
unprocessableEntity | 422 | Estado da assinatura incompatível com a operação (regra de negócio). |
tooManyRequests | 429 | Limite de requisições excedido — respeite error.retryAfterMinutes e use backoff. |
serverError | 500 | Erro interno — repita com backoff; se persistir, contate o suporte. |
O
402 insufficientFundsErroraplica-se à renovação (POST), que envolve cobrança; jáGET(listar/consultar) não retorna402.
Boas práticas
- Use
X-Idempotency-KeynoPOSTpara que retries de rede não disparem renovações duplicadas. - Reaja a webhooks, não a polling: acompanhe a mudança de
statusdo ciclo (billed→paid) pelos eventos de assinatura em vez de reconsultar em laço. - Mostre
amountda consulta/renovação, não da lista — o item paginado omiteamountde propósito. - Trate
paidAt/billedAtcomo possivelmente ausentes enquanto o ciclo ainda não foi cobrado ou pago. - Pagine o histórico com
limit/offsete ordene comsort=descendingpara mostrar o ciclo mais recente primeiro. - Converta dinheiro e datas só na exibição: guarde centavos e ISO 8601 UTC internamente.
- Não confunda renovar ciclo com cobrança avulsa: para um pagamento fora do plano, use uma transação.
Veja também
- Visão geral de Assinaturas — modelo do objeto, status e ciclo de vida.
- Consultar assinatura — onde aparece o
currentCycle. - Listar assinaturas · Criar assinatura · Cancelar assinatura
- Itens da assinatura · Splits da assinatura
- Paginação · Idempotência · Proibição de polling · Convenções
How is this guide?