# FHIR and paging

Canonical page: https://docs.ovok.com/flutter-sdk/fhir

`ovok.fhir` reads and writes FHIR R4 resources as decoded JSON (`JsonMap`).

```dart
final patient = await ovok.fhir.read('Patient', id);

final page = await ovok.fhir.search('Observation', {
  'patient': 'Patient/$id',
  '_count': 50,
});

await ovok.fhir.create(observation, ifNoneExist: 'identifier=urn:device|42');
await ovok.fhir.update(patient);
await ovok.fhir.patch('Patient', id, [PatchOperation.replace('/active', false)]);
await ovok.fhir.delete('Patient', id);
final first = await ovok.fhir.searchOne('Patient', {'identifier': 'urn:mrn|123'});
```

- **AND and OR:** a list value repeats its parameter, which FHIR reads as AND, as in
  `'date': ['ge2026-01-01', 'le2026-02-01']`. For OR, pass one comma-separated string.
- **Conditional create:** with `ifNoneExist`, a retry cannot create a duplicate, so the
  request is retried like a GET.
- **Batches:** `batch(bundle)` sends a FHIR batch or transaction Bundle.

## Paging [#paging]

Every list returns `Future<Page<T>>` with `data`, `hasMore` and `total` (null when the
server does not count). `autoPaging()` streams every item from that page on, fetching
the next page only when it is needed:

```dart
await for (final observation in page.autoPaging()) {
  // every page, fetched as you go
}
```

The same `Page` works for every list in the SDK, whichever pagination the server uses.

## Questionnaire responses [#questionnaire-responses]

`ovok.questionnaires.populate` requests a prefilled FHIR Questionnaire. Submit the
completed resource with `ovok.questionnaireResponses.submit`; the SDK sends it through
the existing FHIR transaction endpoint. Flutter apps can render the same resource with
[`QuestionnaireForm`](/flutter-sdk/questionnaire-forms).
