Ir para o conteúdo

API de Assinaturas

🤖 Explicar com IA

A API de Assinaturas permite criar e gerenciar assinaturas de clientes e fluxos de checkout de assinatura. Ela fornece endpoints para gerar links de checkout, listar e recuperar assinaturas e cancelar assinaturas.

Os fluxos de assinatura suportados incluem:

  • Criar assinatura (link de checkout): POST /v1/subscriptions — retorna uma URL de checkout hospedada para concluir o pagamento e criar a assinatura.
  • Listar assinaturas: GET /v1/subscriptions — lista paginada para o solicitante (cliente ou desenvolvedor).
  • Recuperar assinatura por ID: GET /v1/subscriptions/{subscription_id} — obter detalhes da assinatura.
  • Listar por plano (chave pública): GET /v1/subscriptions/{key_plan} — assinaturas associadas a uma determinada chave de plano pública.
  • Cancelar assinatura: DELETE /v1/subscriptions/{subscription_id} — cancelar uma assinatura existente.

Autenticação

A API de Assinaturas suporta autenticação por Chave de API via HTTP Basic Auth, onde a chave de API é o nome de usuário (username) e a senha (password) é deixada em branco.

Exemplo de chave de teste: sk_test_51O62xYzAbcDef123 (O Base64 para sk_test_51O62xYzAbcDef123: é c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=).


Endpoint

POST /v1/subscriptions

Cria uma assinatura local pendente e retorna uma URL de checkout hospedada. O cliente (frontend) deve redirecionar o cliente para esta URL para concluir o pagamento. A ativação da assinatura é assíncrona — os webhooks notificarão seu sistema quando a assinatura se tornar ativa.

Importante: Use a chave de teste sk_test_51O62xYzAbcDef123 para desenvolvimento local. Não exponha chaves de produção (live keys) no código do lado do cliente.

Campos da solicitação

Parâmetro Descrição Tipo Obrigatório
plan_id Identificador local de preço/plano usado para criar a assinatura string true
customer_id Identificador de cliente existente (se omitido, um fluxo de convidado/único pode ser criado) string condicional
quantity Número de unidades para faturamento recorrente integer false
trial_days Período de teste em dias (opcional) integer false
return_url URL para onde o usuário será redirecionado após o checkout (obrigatório) string true

cURL (Basic Auth - atalho)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Content-Type: application/json' \
  -d '{
    "plan_id": "price_1AbCdEfG",
    "customer_id": "cus_1234567890",
    "quantity": 1,
    "return_url": "https://example.com/subscription-result"
  }'

cURL (Cabeçalho de Autorização manual)

curl -X POST 'https://api.4geeks.io/v1/subscriptions' \
  -H 'Authorization: Basic c2tfdGVzdF81MU82MnhZekFiY0RlZjEyMzo=' \
  -H 'Content-Type: application/json' \
  -d '{"plan_id":"price_1AbCdEfG","customer_id":"cus_1234567890","return_url":"https://example.com/subscription-result"}'

Python (requests)

import requests
from requests.auth import HTTPBasicAuth

BASE = 'https://api.4geeks.io'
API_KEY = 'sk_test_51O62xYzAbcDef123'

payload = {
    'plan_id': 'price_1AbCdEfG',
    'customer_id': 'cus_1234567890',
    'quantity': 1,
    'return_url': 'https://example.com/subscription-result'
}

resp = requests.post(f"{BASE}/v1/subscriptions", auth=HTTPBasicAuth(API_KEY, ''), json=payload)
print(resp.status_code)
print(resp.json())

JavaScript (fetch, Node.js ou navegadores modernos)

const apiKey = 'sk_test_51O62xYzAbcDef123';
const auth = 'Basic ' + Buffer.from(`${apiKey}:`).toString('base64');

fetch('https://api.4geeks.io/v1/subscriptions', {
  method: 'POST',
  headers: {
    'Authorization': auth,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    plan_id: 'price_1AbCdEfG',
    customer_id: 'cus_1234567890',
    quantity: 1,
    return_url: 'https://example.com/subscription-result'
  })
})
  .then(r => r.json())
  .then(console.log)
  .catch(console.error)

Angular HttpClient (TypeScript)

import { HttpClient, HttpHeaders } from '@angular/common/http';

const apiKey = 'sk_test_51O62xYzAbcDef123';
const headers = new HttpHeaders({
  'Authorization': `Basic ${btoa(apiKey + ':')}`,
  'Content-Type': 'application/json'
});

const payload = {
  plan_id: 'price_1AbCdEfG',
  customer_id: 'cus_1234567890',
  return_url: 'https://example.com/subscription-result'
};

this.http.post('https://api.4geeks.io/v1/subscriptions', payload, { headers })
  .subscribe(console.log, console.error);

Postman

  1. Método: POST
  2. URL: https://api.4geeks.io/v1/subscriptions
  3. Autorização: Basic Auth — Username: sk_test_51O62xYzAbcDef123, Password: (deixe em branco)
  4. Corpo: raw JSON com plan_id, customer_id, return_url.

Resposta de Sucesso (201 Created)

{
  "code": 201,
  "title": "Subscription created",
  "content": "Checkout URL generated. Redirect the customer to complete payment.",
  "data": {
    "subscription_id": "sub_abc21d23",
    "checkout_url": "https://console.4geeks.io/checkout/?data=eyJ...",
    "test": true
  }
}

Nota: A checkout_url é uma URL de uso único para a sessão de checkout. Armazene o subscription_id retornado para conciliar webhooks e callbacks.


Recuperar uma assinatura

Endpoint

GET /v1/subscriptions/{subscription_id}

Recupera uma assinatura pelo seu ID. A resposta inclui detalhes do plano, status, próxima data de faturamento, informações do cliente e dados de teste, quando aplicável.

Parâmetro de caminho

Parâmetro Descrição Tipo Obrigatório
subscription_id Identificador da assinatura (ex: sub_abc21d23) string true

Exemplo de solicitação

curl -X GET 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Resposta (200 OK)

{
  "subscription_id": "sub_abc21d23",
  "plan_id": "price_1AbCdEfG",
  "customer_id": "cus_1234567890",
  "status": "active",
  "current_period_start": "2025-12-01T00:00:00Z",
  "current_period_end": "2026-01-01T00:00:00Z",
  "next_billing_date": "2026-01-01",
  "trial_end": null,
  "created_at": "2025-12-01T12:00:00Z",
  "test": true
}

Erro (404 Not Found)

{
  "error": {
    "code": 404,
    "type": "not_found",
    "message": "Subscription not found"
  }
}

Listar assinaturas

Endpoint

GET /v1/subscriptions

Retorna uma lista paginada de assinaturas para o solicitante. Quando chamado com um token de cliente (ou chave com escopo), retorna as assinaturas desse cliente; quando chamado com uma chave de desenvolvedor, retorna as assinaturas dos planos desse desenvolvedor.

Parâmetros de consulta

Parâmetro Descrição Tipo Obrigatório
page Número da página (padrão: 1) integer false
page_size Itens por página (padrão: 10) integer false
status Filtrar por status (active, canceled, trialing) string false
plan_id Filtrar por ID do plano string false
test Filtrar por modo de teste (true/false) boolean false

Exemplo de solicitação

curl -X GET 'https://api.4geeks.io/v1/subscriptions?page=1&page_size=10' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Resposta (200 OK)

{
  "count": 12,
  "current_page": 1,
  "total_pages": 2,
  "results": [
    {
      "subscription_id": "sub_abc21d23",
      "plan_id": "price_1AbCdEfG",
      "customer_id": "cus_1234567890",
      "status": "active",
      "next_billing_date": "2026-01-01",
      "test": true
    }
  ]
}

Listar assinaturas por chave de plano pública

Endpoint

GET /v1/subscriptions/{key_plan}

Retorna assinaturas associadas a uma chave de plano pública. Este endpoint é útil para listar assinantes de um determinado plano público.

Parâmetro de caminho

Parâmetro Descrição Tipo Obrigatório
key_plan Chave pública do plano (ex: plan_abcdef) string true

Exemplo de solicitação

curl -X GET 'https://api.4geeks.io/v1/subscriptions/plan_abcdef' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Resposta (200 OK)

[
  {
    "subscription_id": "sub_abc21d23",
    "customer_id": "cus_1234567890",
    "status": "active",
    "next_billing_date": "2026-01-01",
    "test": true
  }
]

Cancelar assinatura

Endpoint

DELETE /v1/subscriptions/{subscription_id}

Cancela uma assinatura e tenta cancelar o faturamento externo onde aplicável. O cancelamento também pode disparar webhooks e e-mails de notificação.

Exemplo de solicitação

curl -X DELETE 'https://api.4geeks.io/v1/subscriptions/sub_abc21d23' \
  -u "sk_test_51O62xYzAbcDef123:" \
  -H 'Accept: application/json'

Resposta (200 OK)

{
  "code": 200,
  "title": "Subscription cancelled",
  "content": "The subscription has been successfully cancelled.",
  "subscription_id": "sub_abc21d23"
}

Erros

Status Motivo Descrição
400 Bad Request Solicitação inválida ou malformada (ex: plan_id inválido).
401 Unauthorized Chave de API ausente ou inválida.
403 Forbidden O solicitante não tem permissão para cancelar a assinatura de destino.
404 Not Found Assinatura não encontrada.
409 Conflict O cancelamento não pôde ser concluído (ex: conflito de conciliação de faturamento).
500 Server Error Erro interno ao processar o cancelamento.

Tratamento de Erros (comum)

400 Bad Request (Solicitação Inválida)

{
  "error": {"code": 400, "type": "bad_request", "message": "Missing required field: plan_id"}
}

401 Unauthorized (Não Autorizado)

{
  "error": {"code": 401, "type": "unauthorized", "message": "Invalid API key or missing Authorization header"}
}

403 Forbidden (Proibido)

{
  "error": {"code": 403, "type": "forbidden", "message": "Insufficient permissions"}
}

404 Not Found (Não Encontrado)

{
  "error": {"code": 404, "type": "not_found", "message": "Subscription not found"}
}

500 Internal Server Error (Erro Interno do Servidor)

{
  "error": {"code": 500, "type": "server_error", "message": "Unexpected error"}
}

Melhores Práticas de Segurança

  • Use HTTPS em produção. Os exemplos acima usam a URL de desenvolvimento local por conveniência.
  • Armazene chaves de API em variáveis de ambiente ou em um gerenciador de segredos (não as escreva diretamente no código nem as envie para o repositório).
  • Use chaves de teste para desenvolvimento e chaves de produção apenas para o ambiente real.
  • Roteie as chaves de API regularmente e remova as chaves não utilizadas.
  • Valide o host e o esquema da return_url para evitar vulnerabilidades de redirecionamento aberto.
  • Confie nos webhooks para confirmar a ativação da assinatura — não presuma o sucesso apenas pelo redirecionamento do checkout.

Solução de Problemas

Problema: Recebo 401 Unauthorized - Verifique se você está enviando Authorization: Basic <base64(key:)> ou usando curl -u 'sk_test_...:'. - Confirme se a chave de API não foi rotacionada.

Problema: A URL de checkout retorna erro ou está em branco - Certifique-se de que a return_url é válida e acessível. - Verifique os logs do servidor e o processamento de webhooks em busca de erros.

Problema: Eventos de webhook não estão chegando - Verifique se o endpoint do webhook está acessível publicamente e usa HTTPS em produção. - Confirme o segredo de assinatura do webhook e a verificação de assinatura do seu lado.


FAQ (Perguntas Frequentes)

P: O que é retornado após a criação de uma assinatura?

R: Um subscription_id e uma checkout_url (checkout hospedado). A URL de checkout deve ser acessada para concluir o pagamento e a ativação.

P: As assinaturas são ativadas sincronicamente?

R: Não. As assinaturas são ativadas de forma assíncrona. Use webhooks para detectar quando a assinatura se torna active.

P: Posso usar chaves de API no código do frontend?

R: Não incorpore chaves de API de produção no código do lado do cliente. Para integrações web, gere o checkout hospedado no lado do servidor e retorne a URL de checkout para o cliente.