Skip to content

Agent workflows

The DuitMyself Public API is designed to be safe for agent-driven bookkeeping, sync, and reconciliation work.

  1. Call GET /v1/agent/context first.
  2. Cache the returned accounts, categories, and payees by id and externalId.
  3. Use the .../upsert endpoints with stable externalId values for agent-managed writes.
  4. Reuse an Idempotency-Key only when retrying the exact same request body.
  5. Watch X-RateLimit-* and Retry-After before retrying aggressively.
  • Positive amounts are expenses.
  • Negative amounts are income.
  • Transfers should use isTransfer: true and transferToAccountId.
  • System categories are readable but not writable.
  • Public IDs such as acct_..., txn_..., and cat_... are stable API identifiers. Never rely on Convex internals.
  • Prefer safe writes rules whenever an agent may retry automatically.
  import { createDuitMyselfApiClient } from "@duitmyself/api-client";

const client = createDuitMyselfApiClient({
apiKey: process.env.DUITMYSELF_API_KEY!,
baseUrl: "https://api.duitmyself.app",
});

const context = await client.getAgentContext({
recentTransactionLimit: 50,
});

const meta = client.getLastResponseMeta();
  await client.upsertTransaction(
{
  externalId: "openclaw:txn:2026-04-14:salary",
  accountId: "acct_...",
  amount: -2500,
  date: "2026-04-14",
  note: "April salary",
},
{
  idempotencyKey: "txn-openclaw-2026-04-14-salary",
}
);

Use upsert when the agent owns the source identifier and may retry later. Good examples:

  • importing from another ledger
  • syncing a spreadsheet
  • reconciling receipts from an inbox
  • running scheduled bookkeeping agents

Use plain POST when you truly want a brand-new object and do not have a stable external identity.