> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sure.am/llms.txt
> Use this file to discover all available pages before exploring further.

# FinanceKit

> Sync Apple Wallet data directly from iOS devices

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](/providers/transaction-history) 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

| Status | Meaning |
| - | - |
| `accepted` | Durably stored, awaiting processing |
| `processing` | Worker has started applying the batch |
| `applied` | Ledger updated successfully |
| `failed` | Permanent processing failure; see `error_code` |
| `revoked` | Batch invalidated by a credential rotation or repair |

### 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}`.

| Disposition | Behavior | Response |
| - | - | - |
| `retain` (default) | Keeps every account, balance, and transaction | `204 No Content` |
| `discard` | Removes imported accounts, entries, identities, and lineage data in the background | `202 Accepted` |

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.

> [!NOTE]
>
> 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](/api-reference).

| Endpoint | Description |
| - | - |
| `GET /api/v1/financekit/capabilities` | Discover supported protocol versions, limits, and connection dispositions |
| `POST /api/v1/financekit/connections` | Enroll a new publisher |
| `GET /api/v1/financekit/connections/{id}` | Read connection status and paginated account mappings |
| `PUT /api/v1/financekit/connections/{connection_id}/account_mappings/{source_id}` | Map a source account |
| `POST /api/v1/financekit/connections/{connection_id}/activate` | Activate the publisher |
| `POST /api/v1/financekit/connections/{connection_id}/credential` | Rotate the publisher credential |
| `POST /api/v1/financekit/connections/{connection_id}/repair` | Open a new generation after repair\_required |
| `DELETE /api/v1/financekit/connections/{connection_id}` | Disconnect a publisher, retaining or discarding imported history |
| `POST /api/v1/financekit/publishers/{publisher_id}/batches` | Upload a batch |
| `GET /api/v1/financekit/publishers/{publisher_id}/batches/{batch_id}` | Read a batch receipt |
| `GET /api/v1/financekit/connections/{connection_id}/conflicts` | List open conflicts |
| `PATCH /api/v1/financekit/connections/{connection_id}/conflicts/{id}` | Resolve a conflict |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.