# Referrals, samples and one authentication

  A patient authenticated at the dispensary that referred them should not have to authenticate
  again at the hospital they were referred to. The proof travels with the referral.

  No `/referrals` prefix is registered in the service, and there is no referral surface behind the
  gateway at all — every call on this page answers 404 today, the specimen routing included.

  What follows is the design the rail is being built to, and it is worth reading before you model
  referrals yourself. It is not something you can integrate against yet.

## Hub and spoke, without building hub and spoke

A referral network is normally a project: agreements between facilities, an integration per
partner, a shared directory, a way to move documents. Every new spoke is new work.

On the rail it is a call. Both facilities are already connected, both are already resolved
against the facility registry, and the clinical record is already in a form the other side can
read. Referral is what those things add up to.

<Wire
  rows={[
    { call: "You refer", does: "Name the receiving facility and the service you want. The clinical record goes with it. A referral is not a letter asking them to start again.", keep: "referral_id" },
    { call: "They see it before the patient arrives", does: "An inbound referral is in their queue with the diagnosis, the investigations already done and the results already back.", keep: "their inbox" },
    { call: "They accept, and the visit opens", does: "Acceptance opens the receiving visit against the authorisation the source took. The patient walks in already known.", keep: "visit_id" },
  ]}
/>

## Refer

<ApiRef method="POST" path="/api/v1/visits/{visit_id}/referrals" to="/rail-api/05-treat">
  Refer onward, carrying the record and the authorisation taken here.
</ApiRef>

`include_clinical: true` is the field that decides whether this is a referral or a note. With
it, the receiving clinician opens the patient and sees the encounter, the conditions, the
observations and any results already returned. That is the difference between a hub that
repeats the workup and one that continues it.

<ApiRef method="GET" path="/api/v1/referrals?direction=inbound" to="/rail-api/05-treat">
  Referrals sent to this facility, with the record and the authorisation attached.
</ApiRef>

<ApiRef method="POST" path="/api/v1/referrals/{referral_id}/accept" to="/rail-api/05-treat">
  Accept or decline, and open the receiving visit against the source authorisation.
</ApiRef>

Accept the referral before you open a visit. A visit opened against an unaccepted referral is
refused with `REFERRAL_NOT_ACCEPTED`. Acceptance is what binds the source authorisation to the
new encounter, so skipping it sends the patient back to authenticate.

## One authentication, at the facility they were standing in

Build the workflow around this feature, because it is the one patients notice.

Consent on the rail is proof that a member was present and willing. Ordinarily it is taken
where the care happens. On a referral that rule would mean a patient authenticates at the
dispensary, travels to the county hospital, and authenticates again for the same episode,
often returning a second day because the biometric device was down or the phone that receives
the code was left at home.

<BuildSequence
  steps={[
    {
      do: "Take the authorisation once, at the source",
      detail:
        "The patient is standing in front of you. Whatever modality the payer requires (a one-time code, biometrics, a guardian) is collected here, at [03 · Consent](/rail/stops/Consent), and produces an authorization_ref.",
    },
    {
      do: "Send it with the referral",
      detail:
        "authorization_ref travels on the referral. The response echoes back where it was authenticated, whether the destination will honour it, and when it expires.",
    },
    {
      do: "The destination opens against it",
      detail:
        "Accepting the referral opens the receiving visit bound to that authorisation. The patient does not give consent a second time, on a second device, at the end of a second journey.",
    },
    {
      do: "Show the patient the window, at the source",
      detail:
        "The authorisation has an expiry. Tell the patient when they are referred, not when they arrive. This is the one failure mode the design does not remove.",
    },
  ]}
/>

  Read `authorization.honoured_at_destination` from the referral response rather than assuming
  it. Where a payer requires re-authentication at the point of service for a benefit, it comes
  back false, and the receiving facility must capture consent as normal. If you build only for
  the happy path, the patient gets turned away at a desk that cannot explain why.

If the patient arrives after the window has closed, the destination gets
`REFERRAL_AUTH_EXPIRED`. That is a prompt to re-authenticate there, rather than a rejected
referral. The clinical record and the acceptance both stand.

## Samples travel the same way

A specimen sent to a hub laboratory is an order with a journey attached. The order says what
to do; the sample record says what physically moved, and lets both ends see where it is.

<ApiRef method="POST" path="/api/v1/referrals/{referral_id}/samples" to="/rail-api/05-treat">
  Send a specimen against the order that asked for it.
</ApiRef>

<Wire
  rows={[
    { call: "The sample is tied to the order", does: "Not to a courier manifest. The result comes back against the order, so the requesting clinician sees it in the patient's record rather than in an email.", keep: "order_id" },
    { call: "Cold chain is declared, not assumed", does: "A specimen that must stay cold says so, and a hub that cannot honour it declines on receipt rather than running a test on a degraded sample.", keep: "cold_chain" },
    { call: "Rejection is a state with a reason", does: "The reason reaches the sender (haemolysed, insufficient, unlabelled), who can recollect while the patient may still be reachable.", keep: "the reason" },
  ]}
/>

A spoke that can send samples can offer tests it cannot perform. That is the commercial
argument for the referral feature, and it is the same three calls as everything else on this
stop.

## What breaks here

<CostTable
  rows={[
    {
      where: "Treat",
      symptom: "\"The patient was sent back to authenticate again\"",
      cause: "The receiving visit was opened directly instead of through referral acceptance, so nothing bound the source authorisation to it.",
    },
    {
      where: "Treat",
      symptom: "\"They arrived and the authorisation had expired\"",
      cause: "The window was never shown at the source. Surface the expiry when the referral is written, on the patient's copy.",
    },
    {
      where: "Treat",
      symptom: "\"The hospital started the workup from scratch\"",
      cause: "include_clinical was false, so the referral carried a reason and nothing else.",
    },
    {
      where: "Treat",
      symptom: "\"The result went to the hub, not to us\"",
      cause: "The sample was sent without the order it belongs to. Results route by order, not by facility.",
    },
  ]}
/>

### Errors

| HTTP | `error` | When |
|------|---------|------|
| 409 | `REFERRAL_NOT_ACCEPTED` | A visit was opened against a referral nobody accepted. |
| 409 | `REFERRAL_AUTH_EXPIRED` | The source authorisation's window closed before arrival. |
| 403 | `CLINICAL_CONSENT_MISSING` | The patient's proof does not cover sharing the record onward. |

  Everything a referral carries was recorded once, as clinical data. The same recording is what
  lets the rail generate the documents a claim needs, instead of somebody typing them.
