# 04 · Visit

  Opening a visit touches no payer. It is an encounter and its account, written together in
  one atomic step, so the clinical record can start even while every payer is down.

## Why this stop exists

The visit is the container everything else attaches to. It is an **encounter first** —
conditions, observations, CDSS and generated documents hang off it — so it has to be
clinically native before it is ever billable.

Opening it is **local**. The rail writes an `Encounter` and an `Account` to its own clinical
store in a single atomic write and calls no payer. A visit with no covered lines is a purely
clinical visit and stays that way until one is added. Everything that touches a payer — the
authorization, the claim — happens on the lines you attach afterwards, and each is its own
answer that never un-opens the visit.

## Open the visit

<ApiRef method="POST" path="/api/v2/visits" to="/rail-api/04-visit" keep="visit_ref">
  Open an encounter and its account. `service_type` — OUTPATIENT or INPATIENT — is the only
  required field; it becomes the encounter's class and the service type every later
  authorization carries.
</ApiRef>

Identity and a service type are the whole of a clinical visit:

<Wireframe
  title="Open visit"
  actor="Front desk · Example Medical Centre (FID-47-105963-0)"
  rows={[
    [
      { label: "Patient", kind: "text", span: 2, from: "unique_patient_id", note: "Resolved at Identify" },
      { label: "Service type", kind: "field", span: 1, from: "service_type", note: "Outpatient · Inpatient" },
      { label: "Open visit", kind: "action", span: 1 },
    ],
    [
      { label: "Visit open — clinical", kind: "text", span: 4, tone: "positive", from: "visit_ref", note: "No cover attached yet. Conditions, observations and documents can start now; billing waits for a line." },
    ],
  ]}
  caption={<>A visit with no <code>service_lines</code> is clinical only. It needs no cover and no consent — nothing is being spent.</>}
/>

To open **against a cover**, send the committed `selection_ref` from [02 · Verify
cover](/rail/stops/Entitle), the `consent_ref` the consent ceremony minted (below), and one
or more `service_lines`, each naming its cover:

```json
{
  "unique_patient_id": "SIL-UPI-0091774",
  "service_type": "OUTPATIENT",
  "selection_ref": "4428ab22-…",
  "consent_ref": "1af5b95e-…",
  "service_lines": [
    { "code": "SHA-18-005", "cover": "SHA:zBxhrTRZ5_hYaO36" }
  ]
}
```

`selection_ref` is required once `service_lines` is present; `consent_ref` is required once a
selection is in scope. A clinical visit sends none of them.

## The consent it spends is a reference, not a proof

The consent ceremony happens end to end in the consent surface at [03 ·
Consent](/rail/stops/Consent) — the decision, the OTP or biometric, the verification. What
opening a visit receives is the **`consent_ref`** that ceremony produced: a redeemable
reference to a verified consent, not the raw proof. Open spends it once, by binding it to the
encounter.

  A point-of-care proof is single-use — its issuer admits exactly one redeemer. The ceremony
  is that redeemer; it mints a `visit_start` consent record and hands back a reference. Open
  redeems the *reference*, so a second open presenting the same one is refused
  `CONSENT_ALREADY_REDEEMED`. The proof itself is spent before it ever crosses this boundary.

## Service lines — the authorization unit

A service line is one intervention plus the cover it draws on. It is the unit a payer
authorizes and reserves balance against, and it is **payer-first**: the rail writes the line
as pending, asks the payer, and moves it to the answer the payer gave.

<ApiRef method="POST" path="/api/v2/visits/{visit_ref}/service-lines" to="/rail-api/04-visit" keep="service_line_ref">
  Authorize a cover for a named intervention. The same thing a line at open does, available
  after the fact — a visit opened clinical becomes billable here.
</ApiRef>

<Wireframe
  title="Authorize a service"
  actor="Front desk"
  rows={[
    [
      { label: "Intervention", kind: "field", span: 2, from: "code", note: "e.g. SHA-18-005" },
      { label: "Cover", kind: "field", span: 1, from: "cover", note: "One the selection names" },
      { label: "Authorize", kind: "action", span: 1 },
    ],
    [
      { label: "Authorized — KES 3,000 reserved", kind: "text", span: 4, tone: "positive", from: "the payer's answer", note: "The reserved amount is the payer's, never computed here." },
    ],
    [
      { label: "Refused — BENEFIT_EXHAUSTED", kind: "text", span: 4, tone: "negative", note: "The payer's own verdict, relayed word for word. The visit stays open; fix or drop this line." },
    ],
  ]}
  caption={<>Two outcomes worth designing for. A third — the payer being unreachable — leaves the line <em>pending</em> and is safe to retry; it is not a rejection.</>}
/>

Three outcomes, and only one is an error you resolve by changing the line:

<Wire
  rows={[
    { call: "authorized", does: "The payer reserved balance against the intervention", keep: "service_line_ref → add bill lines under it" },
    { call: "refused", does: "The payer declined; its machine code and reason are relayed verbatim", keep: "read the verdict, then fix or drop the line" },
    { call: "pending", does: "The payer did not answer; the line is kept durably and is retryable", keep: "PAYER_UNREACHABLE (502) → retry the same request" },
  ]}
/>

A refused or unreachable payer **never un-opens the visit**. The line carries the outcome;
the encounter and everything clinical proceed regardless.

## Record the practitioner

Who performed a service is stated once on the visit and referenced by every bill line, rather
than re-typed per line. The identification is checked against the Health Worker Registry when
it is added, so a bad registration number is refused at the desk — not when the payer's claim
bounces a week later.

<ApiRef method="POST" path="/api/v2/visits/{visit_ref}/practitioners" to="/rail-api/04-visit" keep="practitioner_ref">
  Record a performer. Verified against the registry under its regulator before it is stored.
</ApiRef>

It can happen at any time after open — nothing about opening a visit or authorizing a service
line waits on a clinician being known.

## Record a diagnosis

A diagnosis is a **clinical fact first** and a claim field second: it exists on visits that
never bill, it is recorded by a clinician rather than the desk, and it changes over a visit.
It is written to the clinical record — a `Condition` on the encounter — so CDSS, document
generation and the claim builder all read the same one.

<ApiRef method="POST" path="/api/v2/visits/{visit_ref}/diagnoses" to="/rail-api/05-treat" keep="diagnosis_ref">
  Record a diagnosis against the encounter. No cover appears here — a clinical diagnosis needs
  none, and a payer that requires one enforces that on the claim.
</ApiRef>

  Record the diagnosis in whatever system the clinician works in — ICD-11, ICD-10. Where a
  payer's claim wants the other system, the claim builder translates it at claim time. The
  desk never re-codes.

## What breaks here

<CostTable
  rows={[
    {
      where: "Visit",
      symptom: "\"It says consent required\"",
      cause: "The visit named a selection but no consent_ref. Run the consent ceremony first and pass the reference it returns.",
    },
    {
      where: "Visit",
      symptom: "\"Consent not redeemable\"",
      cause: "The consent expired, was already spent, or was taken for a different purpose. It is a fresh ceremony, not a retry — the redemption policy decides.",
    },
    {
      where: "Visit",
      symptom: "\"That cover is not in the selection\"",
      cause: "A service line named a cover the committed selection does not carry. A cover outside the selection needs its own selection and its own consent.",
    },
    {
      where: "Bill",
      symptom: "\"No authorized service line for this charge\"",
      cause: "A bill line drew on a service line that is pending or refused. There is no authorization for the charge to draw down until the line is authorized.",
    },
    {
      where: "Bill",
      symptom: "\"Practitioner not on the visit\"",
      cause: "The bill line referenced a practitioner_ref that was never added. Record the practitioner first; it is validated once, there.",
    },
  ]}
/>

### Errors

The rail's own refusals, before any payer is asked, carry a stable `error` code. Everything
else is the payer's verdict, relayed with its status intact.

| HTTP | `error` | When |
|------|---------|------|
| 404 | `PATIENT_NOT_FOUND` | The clinical store holds no patient under that identity. |
| 400 | `SERVICE_TYPE_INVALID` | `service_type` was not OUTPATIENT or INPATIENT. |
| 400 | `CONSENT_REQUIRED` | A selection is in scope but no `consent_ref` was sent. |
| 404 | `CONSENT_NOT_FOUND` | `consent_ref` resolves to nothing. |
| 409 | `CONSENT_NOT_REDEEMABLE` | Expired, consumed, or wrong purpose — the policy's own code is in `detail`. |
| 409 | `SELECTION_UNUSABLE` | The selection is unknown, inactive, or belongs to another patient. |
| 409 | `COVER_NOT_IN_SELECTION` | A line named a cover the selection does not carry. |
| 409 | `VISIT_NOT_OPEN` | The visit exists but no longer admits changes. |
| 409 | `SERVICE_LINE_MISSING` | A bill line named no authorized service line. |
| 409 | `SERVICE_LINE_NOT_AUTHORIZED` | The service line is pending or refused. |
| 409 | `PRACTITIONER_NOT_ON_VISIT` | The referenced practitioner was never added. |
| 422 | `PRACTITIONER_INVALID` | The registry did not resolve the identification under its regulator. |
| 502 | `PAYER_UNREACHABLE` | The payer did not answer; the line stays pending and the call may be retried. |

## Next

**Next:** [05 · Treat](/rail/stops/Treat) — the clinical record on the open encounter, then
[07 · Bill](/rail/stops/Bill) to charge under an authorized line.
