# Write your first records

Define a collection, write two records on the main branch and read them back.

You will define a collection called `patients`, write two records into it, read one back by id, and run four small queries. Everything goes through two commands: `haematite write` and `haematite query`.

## Before you begin

Have the service running from [Install and run](/haematite/getting-started/install/). Every command below takes `--config` with the file the service was started with.

## Define a collection

A collection is a named home for records. You define it once. A schema is optional, so `null` is fine while you are getting started.

**Terminal**

```bash
haematite write --config service.json --branch main collection.put \
  '{"collection":"patients","schema":null}'
```


The command prints a request id and then a receipt. The receipt carries the version the branch is now at.

## Write two records

Each write names the collection, the record id and the document.

**Terminal**

```bash
haematite write --config service.json --branch main document.put \
  '{"collection":"patients","document_id":"p0","document":{"name":"Ada","ward":"4B","admitted":20260912}}'
haematite write --config service.json --branch main document.put \
  '{"collection":"patients","document_id":"p1","document":{"name":"Bea","ward":"3A","admitted":20260913}}'
```


Writing the same id again adds a new version. The earlier version stays readable at the version it was written.

> Writes that cannot collide
> Pass `--expected` with the version you last read. If anyone wrote in between, your change is refused instead of overwriting theirs. Pass `--request-id` to make a retry safe.


## Read one record back

**Terminal**

```bash
haematite call --config service.json documents.get \
  '{"selection":{"branch":"main"},"collection":"patients","document_id":"p0"}'
```


## Run four queries

The first stage names a collection. Later stages filter, shape or count.

**Terminal**

```bash
haematite query --config service.json --branch main 'collection("patients")'
haematite query --config service.json --branch main 'patients(ward: "4B")'
haematite query --config service.json --branch main 'collection("patients") | { name ward }'
haematite query --config service.json --branch main 'collection("patients") | count'
```


1. Every patient.
2. Only patients in ward 4B.
3. Only the `name` and `ward` fields of every patient.
4. How many patients there are.

Each row prints on its own line. The whole answer is read at the branch head of the moment the first page was read.

## Exit codes you will see

- `0`: Answered or applied. The receipt or the rows are on standard output.
- `1`: Could not prepare or connect before sending the request. Read the command's diagnostic; this is a client-command exit code, not an offline maintenance result.
- `2`: Refused, for codes this client knows. A refusal it doesn't know exits 3, even when nothing was applied; read its receipt. Read-only calls return 2 for service refusals.
- `3`: The outcome is not known to the client. For write only, standard error names the request id to repeat it with. Query standard error instead reports any incomplete row count.


## Next step

Read [Records, collections and versions](/haematite/concepts/records-collections-versions/), then the [query language](/haematite/query-language/).
