Skip to main content
FinanceKit is an Apple framework that lets users share their Apple Wallet accounts — bank accounts, credit cards, and transaction history — directly with Sure from their iPhone. The iOS app reads Wallet data on-device with the user’s consent and uploads it to Sure over HTTPS. No Apple credentials, private keys, or FinanceKit framework components are required on the server. See Transaction history and import limits for initial sync defaults, history limits, and options for older transactions.

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 calling POST /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 to POST /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 sequence number starting at 1
  • A predecessor_digest (SHA-256 of the previous batch payload) for all sequences after the first
  • A capture_id and chunk_index / chunk_count to support multi-chunk captures
  • capture_mode (snapshot or delta) and a snapshot_complete flag
  • Up to 500 events: account upserts, balance upserts, transaction upserts, transaction tombstones, or account unavailability notices
Sure acknowledges each batch immediately with a 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 with POST /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 on GET /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 to repair_required, revokes queued work and credentials, and requires a repair call before uploads resume.
A balance observation that disagrees with a stored value raises a conflict and allows ingestion to continue. The stored observation and canonical balance stay unchanged; the connection keeps applying subsequent batches while the conflict is open.

Disconnecting a publisher

Deleting a connection revokes the publisher credential and removes the AccountProvider links. What happens to the imported financial data depends on the disposition 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.

Data retention

Exact payload bytes are retained for seven days after a batch is applied, permanently failed, or revoked. This supports response-loss recovery and operational investigation. Canonical financial data follows Sure’s normal family retention behavior. A family financial-data reset removes all FinanceKit connections, lineages, observations, identities, conflicts, and batch receipts for that family.

API reference

The FinanceKit endpoints are documented in the API reference.