Kobana

REST endpoints, signed webhooks, native idempotency.

2 isolated environments (production and sandbox). HMAC-SHA256 on all webhooks. Idempotency via X-Idempotency-Key. Authentication with a Conta Kobana access token.

Feature
Dashboard API screen
300+
REST endpoints
2
isolated environments
HMAC-SHA256
signed webhooks
X-Idempotency-Key
native

Environments for safe integration flow

Production
Real environment. Real charges. Audited logs.
  • https://api.billing.kobana.com.br
  • Real charges
  • Audited logs
Sandbox
Isolated from production. Same API, no real transactions.
  • https://api.billing.sandbox.kobana.com.br
  • No real transactions
  • Environment-specific token

What is available to integrate

Complete REST API
300+ endpoints covering all resources: subscriptions, invoices, payments, customers, plans, NFe, proposals, events.
  • Standardized JSON request/response
  • Semantic HTTP status codes
  • Cursor + offset pagination
  • URL versioning (/v1)
Signed Webhooks
WebhookEndpoint per organization. Events selected via events array. Each delivery in WebhookDelivery with retry and backoff.
  • HMAC-SHA256 via X-Kobana-Signature header
  • Secret encrypted at rest (AES-256-GCM)
  • 40+ event types
  • Exponential retry, up to 7 attempts
Native Idempotency
X-Idempotency-Key header accepted on POST, PUT and PATCH. The same key returns the original response for 24 hours.
  • UUID v4 recommended
  • Scoped per organization
  • X-Idempotent-Replay header on replays
  • 24-hour retention
Conta Kobana Tokens
The API authenticates with a JWT access token issued by Conta Kobana (account.kobana.com.br). Keys created in the dashboard no longer authenticate the API.
  • Mandatory expiration
  • Separate token per environment
  • Immediate revocation
Rate Limiting
Separate limits for reads (GET) and writes. ratelimit-* headers on responses.
  • Reads and writes with their own limits
  • Higher limits on request
  • 429 with Retry-After
Internal Events
Event model records every state change. Useful for audit, replay and debug. EventDispatch worker fires webhooks.
  • Type + resource + JSON data
  • Filters by type and period
  • Manual redelivery from the dashboard
Isolated Sandbox
Environment separate from production, with the same API and no real transactions.
  • https://api.billing.sandbox.kobana.com.br
  • Webhooks delivered to the endpoint you register (ngrok recommended)
  • Same API as production
OpenAPI Spec
OpenAPI 3.1 specification for client generation and interactive documentation.
  • Published at /v1/openapi.json
  • Postman collection
  • kobana CLI generated from the spec
Gateway Callbacks
Public endpoints /api/callbacks/{provider} receive webhooks from Pagar.me, Kobana Banking Gateway, NFe.io. Processed via worker with dedicated handlers.
  • Idempotency by payload
  • Signature validation
  • Logs in Callback model

Verify HMAC webhook signature

javascript
const crypto = require('crypto');

// Raw body: the signature covers the exact bytes received
app.post('/webhooks/kobana', express.raw({ type: 'application/json' }), (req, res) => {
  const id = req.headers['webhook-id'];
  const timestamp = req.headers['webhook-timestamp'];
  const signature = req.headers['webhook-signature'] ?? '';

  // Secret whsec_<base64>: the HMAC key is the decoded base64
  const key = Buffer.from(process.env.KOBANA_WEBHOOK_SECRET.slice(6), 'base64');
  const expected = crypto
    .createHmac('sha256', key)
    .update(`${id}.${timestamp}.${req.body}`)
    .digest();

  const valid = signature.split(' ').some((token) => {
    const received = Buffer.from(token.replace(/^v1,/, ''), 'base64');
    return received.length === expected.length && crypto.timingSafeEqual(received, expected);
  });
  if (!valid || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body);
  switch (event.type) {
    case 'invoice.paid':
      // mark order as paid
      break;
    case 'subscription.canceled':
      // remove access
      break;
  }
  res.sendStatus(200);
});

Perguntas frequentes

Integration that holds up in production