Accounting Connections
Connect an accounting platform via OAuth2 to deliver converted files or post accounting transactions — with an honest statement of what platforms allow.
What connections do — honestly
/v1/connections links transmute to your accounting platform so batch results are delivered there on completion: the generated CSV/OFX/XML file lands in the platform's file library for one-click import by a user.
The honest scope: no accounting platform exposes a public API that writes bank statement lines directly. Delivery-to-file-library is what their public APIs actually permit, and transmute never claims otherwise.
| Platform | File delivery | Posting transactions (opt-in, when enabled for your account) |
|---|---|---|
| Xero | Automatic — file lands in the Xero file library via its Files API | BankTransaction (SPEND / RECEIVE) |
| QuickBooks Online | Manual import runbook — we generate the right file, you import it | Deposit / Purchase |
| Sage | Manual import runbook — same | bank_transaction (OTHER_RECEIPT / OTHER_PAYMENT) |
Posting is a different capability from file delivery: a posted transaction is an accounting entry, not a bank statement line, and your platform's own reconciliation still matches it. transmute posts what your mapping says — it does not reconcile, match contacts or compute tax.
Set up a connection (Xero)
Requires the opt-in connections:manage scope:
curl -sS -X POST https://api.transmute.403fin.io/v1/connections \
-H "Authorization: Bearer $TRANSMUTE_KEY" \
-H "Content-Type: application/json" \
-d '{"provider": "xero"}'
# → {"id": "...", "authorizeUrl": "https://login.xero.com/..."}
Open authorizeUrl in a browser and approve access; the OAuth callback completes the connection. Then reference the connection when enqueuing a batch job with a file target (to: "csv", "ofx", ...), and each result file is pushed on completion.
GET /v1/connections lists connections; DELETE /v1/connections/{id} disconnects (revoking our access).
Post transactions into your books
Posting needs three things, in order. It is available once posting is enabled for your account.
- A connection granted with posting. For Xero, reconnect with the posting permission; QuickBooks Online and Sage connect for posting only:
curl -sS -X POST https://api.transmute.403fin.io/v1/connections \
-H "Authorization: Bearer $TRANSMUTE_KEY" -H "Content-Type: application/json" \
-d '{"provider": "xero", "capabilities": ["post"], "replaces": "conn_..."}'
A new connection is created; the replaced one is revoked once you approve. transmute uses the permissions the platform says it granted — a file-delivery connection can never post (connection-reconsent-required).
-
A ledger mapping per bank account (
connections:manage): pick the bank account and the money-in / money-out accounts fromGET /v1/connections/{id}/accounts(fetched live, never stored), thenPUT /v1/connections/{id}/mappings. Optional rules — "if the memo contains rent, book to 469" — are typed by you and must carry"source": "user"; transmute never suggests or learns rules from your messages. -
A preview (
transactions:post):POST /v1/connections/{id}/transactions/dry-runshows the account each transaction books to and the exact object that would be sent, and posts nothing. A preview is required before the first post and after every mapping edit (dry-run-required).
Then post with POST /v1/connections/{id}/transactions — or convert to the accounting-transaction target in a batch with "delivery": {"connection": "conn_...", "deliverAs": "transactions"}. Each transaction gets a stable reference (for statement lines, the same reference an OFX export would carry), and transmute records it before sending, so re-sending the same statement never double-books. If the platform does not answer clearly, the result is unconfirmed and the next attempt reads the transaction back before deciding to resend. Each plan has a monthly post allowance (post-quota-exceeded).
A correct-but-wrong mapping cannot be detected by us — we post exactly what the mapping says. Review the preview.
Failure modes
connection-failed422 — the connection is broken (revoked/expired authorization). Re-connect.provider-error502 — the platform's API failed on delivery. Retryable; the file remains fetchable viaGET /v1/jobs/{id}for the job TTL.
Privacy
Posting keeps only a record per transaction: a SHA-256 key, a status, the platform's transaction id and timestamps — never the transaction itself, never the chart of accounts, never a platform error body. Records expire after 45 days and are deleted when you disconnect.
Delivery is payload transit at your explicit instruction — it extends no retention (the normal batch TTL and purge apply unchanged). Provider tokens are stored encrypted (AES-256-GCM), never appear in any response or log, and delivery errors never echo provider payloads.