@economizee/sdk
v0.1.0
Published
Typed TypeScript client for the Economizee public API.
Maintainers
Readme
@economizee/sdk
Typed TypeScript client for the Economizee public API (048). Node-first (18+), browser
best-effort. No runtime dependencies — uses the platform-native fetch.
Install (in-repo, via the workspace)
pnpm add @economizee/sdk --workspace(Publishing to the public npm registry is a separate ops step — the package is publish-ready.)
Construct
import { Economizee } from '@economizee/sdk';
const sdk = new Economizee({
apiKey: process.env.ECONOMIZEE_API_KEY!, // eco_<prefix>_<secret>, from Configurações → API
baseUrl: 'https://your-app.tld', // optional; /api/v1 appended/normalized
// retry: { enabled: true, maxRetries: 3 },
});Read
const accounts = await sdk.accounts.list();
// [{ id, name, type, currency, balance: { amountCents: 1234567, currency: 'BRL' }, institutionId }]
const page = await sdk.transactions.list({ from: '2026-06-01', to: '2026-06-30', limit: 50 });
// { data: [...], meta: { nextCursor } }
const budget = await sdk.budgets.get({ month: '2026-06' });
const categories = await sdk.categories.list();Iterate everything (auto-pagination)
for await (const tx of sdk.transactions.listAll({ from: '2026-01-01', to: '2026-12-31' })) {
console.log(tx.date, tx.amount.amountCents, tx.amount.currency);
}Write (needs a transactions:write key)
const created = await sdk.transactions.create({
type: 'EXPENSE',
accountId: '...',
amount: { amountCents: 2500, currency: 'BRL' }, // integer cents — NEVER a float
categoryId: '...',
description: 'Café',
date: '2026-06-09',
});
await sdk.transactions.pay(pendingId); // mark a scheduled tx paidHandle errors
import { ApiError } from '@economizee/sdk';
try {
await sdk.transactions.create(input);
} catch (e) {
if (e instanceof ApiError) {
switch (e.code) {
case 'insufficient_scope':
/* key lacks transactions:write */ break;
case 'currency_mismatch':
/* amount currency must match the account */ break;
case 'validation_error':
console.error(e.fields);
break;
case 'not_found':
/* hidden/cross-household resource */ break;
case 'rate_limited':
/* only after retries are exhausted */ break;
case 'network_error':
/* transport failure (status 0) */ break;
}
}
}- Rate limits (
429) are retried automatically (honoringRetry-After, capped). Business 4xx errors are never retried. - Money is always
{ amountCents: integer, currency: 'ISO4217' }— the SDK never converts to a float. - Timestamps are ISO 8601 UTC strings, passed through untouched.
Methods
| Method | Endpoint | Scope |
| -------------------------------- | ----------------------------- | -------------------- |
| accounts.list() | GET /accounts | accounts:read |
| transactions.list(filters?) | GET /transactions | transactions:read |
| transactions.listAll(filters?) | GET /transactions (paged) | transactions:read |
| transactions.create(input) | POST /transactions | transactions:write |
| transactions.pay(id, body?) | POST /transactions/{id}/pay | transactions:write |
| categories.list() | GET /categories | categories:read |
| budgets.get(query?) | GET /budgets | budgets:read |
goals / dashboard methods are not in v1 (those 048 endpoints are deferred); they will be added
additively when the API ships them.
Regenerating types
Types are generated from the committed 048 OpenAPI snapshot:
pnpm -F @economizee/sdk gen # from openapi.snapshot.json
OPENAPI_URL=https://app/api/v1/openapi.json pnpm -F @economizee/sdk gen # refresh from liveA test asserts the committed types match a fresh generation, so a 048 contract change is caught.
