Smart Finance API
Hey dev, have fun! ✨
Documentation index — get the full index at https://docs.finance.kobana.com.br/llms.txt. Use this file to discover every available page before you start exploring.
Authentication
Every request needs two things: the token, which says which organization you are, and the X-Workspace-Id header, which says which of its workspaces to act on.
Authorization: Bearer <token>
X-Workspace-Id: <workspace uuid>
The token
A Bearer JWT signed RS256 by the Kobana authorization server (HS512 only against a local development server).
| Claim | Role |
|---|---|
org | The tenant. The organization's public_id — what decides which data the token reaches. |
sub | The person who consented. It is there for audit and scopes nothing. |
scope | Space-separated list (e.g. finance.payables finance.people.write). A .write scope also grants read. |
jti | Token identifier, used for revocation. |
iss / aud / exp | Issuer, audience and expiry. |
⚠️ The tenant is org, never sub. They are different identifier spaces: a person id never matches an organization, so a token built from the wrong one fails on every request.
The X-Workspace-Id header
An organization can own several workspaces, and every route in this API answers for exactly one. The token alone does not say which — which is why the header is required on every operation.
It is a selector, never a grant: the workspace you name is checked against the token's organization. A workspace owned by another organization answers exactly like one that does not exist — deliberately, so the response never reveals that the id is real somewhere else.
| Situation | Response |
|---|---|
| Header absent | 400 WORKSPACE_REQUIRED |
| Workspace of another organization, nonexistent, or malformed id | 403 UNKNOWN_WORKSPACE |
org matches no organization | 403 UNKNOWN_ORGANIZATION |
| Scope insufficient for the operation | 403 INSUFFICIENT_SCOPE |
A workspace Security rule blocked the operation (details.reason says which) | 403 SECURITY_BLOCKED |
Example
curl https://api.finance.kobana.com.br/v1/payables \
-H "Authorization: Bearer $KOBANA_TOKEN" \
-H "X-Workspace-Id: $KOBANA_WORKSPACE_ID"
For command-line testing, export both: export KOBANA_TOKEN=xxxxxxxx and export KOBANA_WORKSPACE_ID=xxxxxxxx, then paste the commands from the docs straight into your terminal.
Format
The API accepts JSON only. Every request must use Content-Type: application/json. Every response uses snake_case.
| Field Type | Format |
|---|---|
| DateTime | ISO8601 format. Examples — Date: 2026-01-24. Date and time: 2026-01-24T10:07:00.000Z |
| Money | Decimal as a string with 2 places ("150.00"). Always positive — the direction is given by the type field (debit/credit) or by context (payable/receivable). |
| UUID | Resource identifiers in UUID v4 format |
Conventions
Conventions used throughout this documentation:
| Convention | Description |
|---|---|
:id | Path parameter to be replaced with the resource's UUID. |
#{variable} | A value from your account to be substituted in the example. |
... | Response content truncated for readability. |
$KOBANA_TOKEN | JWT access token. Export it with export KOBANA_TOKEN=xxxxxxxx. |
$KOBANA_WORKSPACE_ID | Workspace UUID, sent in X-Workspace-Id. Export it with export KOBANA_WORKSPACE_ID=xxxxxxxx. |
Environments
| Environment | Base URL |
|---|---|
| Production | https://api.finance.kobana.com.br/v1 |
| Sandbox | https://api.finance.sandbox.kobana.com.br/v1 |
Status Codes
The API returns standard HTTP status codes:
| Code | Description | |
|---|---|---|
| ✅ | 200 OK | Successful request with a response body. |
| ✅ | 201 Created | Resource created successfully. |
| ✅ | 204 No Content | Successful request with no response body. |
| ❌ | 400 Bad Request | Invalid request — malformed body, filter not allowed, or X-Workspace-Id missing. |
| ❌ | 401 Unauthorized | Missing, invalid, or expired token. |
| ❌ | 403 Forbidden | Insufficient scope, unknown organization, or a workspace outside it. |
| ❌ | 404 Not Found | Resource not found or outside the workspace. |
| ❌ | 422 Unprocessable Entity | Valid request, but the submitted data is not. |
| ❌ | 429 Too Many Requests | Rate limit reached. |
| ❌ | 500 Internal Server Error | Internal processing error. Check the server status. |
Listing and Pagination
Every listing endpoint uses cursor-based pagination:
GET /v1/payables?cursor=<opaque_cursor>&limit=25
The response includes meta.next_cursor — pass it as ?cursor= on the next request to fetch the following page. When meta.next_cursor is null, there are no more pages.
Idempotency
Creation operations (POST) accept the X-Idempotency-Key header. Retries with the same key return the original result without creating duplicates — safe to retry on network failure.
X-Idempotency-Key: <client-generated-uuid-v4>
Request ID
Every request has an associated identifier, available in the Request-Id response header. This value helps with debugging and auditing. The request log is kept for 30 days. When opening a support ticket about a specific request, provide the Request-Id to speed up the investigation.
Security
The API uses 2048-bit SSL certificates. Every request must go over HTTPS — calls to port 80 are redirected to 443.
Clients must support TLSv1.2 or TLSv1.3 with one of the following ciphers: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-CHACHA20-POLY1305, ECDHE-RSA-AES256-SHA384. TLSv1 and TLSv1.1 are not supported.
HTTP Cache
Use HTTP cache headers to reduce load and gain speed. Most responses include ETag and/or Last-Modified — store these values and send them back on subsequent requests via If-None-Match and If-Modified-Since. If the resource has not changed, the response is 304 Not Modified, with no body and no reprocessing.
Error Handling
5xx errors indicate server failures: 500 Internal Server Error (application unavailable), 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout (transient infrastructure failures). Your application should detect these codes and reschedule the request after a few minutes with exponential backoff. Server status: https://status.kobana.com.br.
OpenAPI Spec
Import the spec into Postman or Insomnia for a ready-to-use collection that always reflects the current API:
- YAML:
/api/v1/openapi.yaml - JSON:
/api/v1/openapi.json