Skip to content

Safe writes

The safest DuitMyself integrations treat every write as retryable. That means combining idempotency keys with the right create or upsert route.

Every POST and PATCH request requires an Idempotency-Key header.

  • Reuse the same key only when retrying the exact same request body.
  • Same key plus same body replays the stored response.
  • Same key plus different body returns a conflict error.

Use .../upsert endpoints when your integration or agent already has a stable identifier for the object it is writing.

Good fits:

  • spreadsheet or CSV sync jobs
  • imports from another ledger
  • receipt processing pipelines
  • recurring bookkeeping agents

Use plain create when you want a new object every time

Section titled “Use plain create when you want a new object every time”

Use a normal POST create route when:

  • you do not have a stable upstream identifier
  • every submission should create a new record
  • the API object is user-authored and not mirrored from another system
  curl -X POST "https://api.duitmyself.com/v1/accounts/upsert" \
-H "Authorization: Bearer key_..." \
-H "Idempotency-Key: acct-wallet-demo-001" \
-H "Content-Type: application/json" \
-d '{
  "externalId": "demo:wallet:cash",
  "name": "Cash Wallet",
  "type": "physical",
  "currency": "MYR"
}'

Good externalId values are:

  • stable across retries
  • unique inside your source system
  • descriptive enough to debug later

Examples:

  • bankfeed:txn:2026-04-14:8842
  • receiptbot:merchant:tealive
  • spreadsheet:account:cash-wallet
  • Generate Idempotency-Key per logical write attempt.
  • Keep request bodies deterministic while retrying.
  • Prefer upsert for integration-owned objects.
  • Log X-Request-Id for debugging.
  • Respect Retry-After and X-RateLimit-* headers before retrying aggressively.