How it works
The iOS client uses Apple’s FinanceKit framework to read Wallet data. It enrolls a publisher connection with Sure, maps each selected source account to a Sure account, and uploads ordered batches of events. Sure’s server-side worker applies each batch and updates your ledger. Both foreground “Sync now” (triggered manually from the app) and optional background delivery use the same enrollment, upload, receipt, and conflict-resolution protocol. Whether Wallet sync is offered to a user is the iOS client’s decision, made through StoreKit. The server does not gate access by family ID or a feature flag — any family administrator can enroll a publisher.Protocol overview
Enrollment and activation
The iOS client enrolls a publisher connection by callingPOST /api/v1/financekit/connections with a consent record and a client-generated enrollment ID. Sure returns a FinancekitPublisherConfiguration that includes the upload URL, protocol version, account limits, and a publisher credential.
Before uploads begin, the client maps each selected source account to a Sure account using PUT /api/v1/financekit/connections/{connection_id}/account_mappings/{source_id}, then activates the connection with POST /api/v1/financekit/connections/{connection_id}/activate.
Uploading batches
The client uploads ordered batches toPOST /api/v1/financekit/publishers/{publisher_id}/batches. Each batch is an immutable, sequenced payload of up to 500 events authenticated with the publisher credential (a bearer token separate from the user’s API key).
Each batch carries:
- A
sequencenumber starting at 1 - A
predecessor_digest(SHA-256 of the previous batch payload) for all sequences after the first - A
capture_idandchunk_index/chunk_countto support multi-chunk captures capture_mode(snapshotordelta) and asnapshot_completeflag- Up to 500 events: account upserts, balance upserts, transaction upserts, transaction tombstones, or account unavailability notices
FinancekitBatchReceipt. The client can retrieve a receipt at any time using GET /api/v1/financekit/publishers/{publisher_id}/batches/{batch_id} to recover from response loss.
Capacity limits
Protocol 2 enforces per-publisher limits:- 20 selected accounts per publisher
- 500 events per batch
- 1 MiB of JSON per batch payload
- 100 accepted or processing batches in the inbox at one time
- 100 chunks per capture (allowing large histories across consecutive captures)
Batch receipt status
Credential rotation and repair
A publisher credential can be rotated withPOST /api/v1/financekit/connections/{connection_id}/credential. After rotation, the previous credential can no longer upload batches or call the batch receipt endpoint.
If a connection enters repair_required — for example, due to an unresolvable conflict or a predecessor digest mismatch — the client must call POST /api/v1/financekit/connections/{connection_id}/repair to open a new generation and stream before uploads resume.
Conflicts
A conflict arises when Sure cannot automatically reconcile a publisher event with existing ledger data. Open conflicts are listed onGET /api/v1/financekit/connections/{connection_id}/conflicts and resolved with PATCH /api/v1/financekit/connections/{connection_id}/conflicts/{id}.
Two resolutions are available:
keep_sure— closes the conflict without modifying the publisher stream. The conflicting source identity is settled permanently so the same record does not re-enter the conflict branch on future captures.retry_after_repair— closes the conflict, moves the connection torepair_required, revokes queued work and credentials, and requires a repair call before uploads resume.
Disconnecting a publisher
Deleting a connection revokes the publisher credential and removes the AccountProvider links. What happens to the imported financial data depends on thedisposition parameter passed to DELETE /api/v1/financekit/connections/{connection_id}.
When
discard is accepted, the connection payload includes purge_requested_at. Poll GET /api/v1/financekit/connections/{connection_id} and check purge_completed_at to confirm the removal has finished.
Which dispositions a build supports is advertised in the connection_dispositions array returned by GET /api/v1/financekit/capabilities. Client code should feature-detect against that list rather than hardcoding the available values.
A discard is irreversible. Imported entries the family reconciled, excluded, split, or edited are removed along with the rest.