# Journeys

A journey is a short, linear automation. It is not a full graph builder.

## Triggers

| Trigger | When |
| --- | --- |
| `contact.created` | A CRM contact is upserted (for example a new subscriber) |
| `doi_confirmed` | Double opt-in succeeds |
| `message_kind` | A successful send with that `message_kind` (for example `termin`) |

Each contact email enrolls **once** per journey.

## Steps

Each step sends a template after `delay_hours`. Merge tags and conditionals apply. Journey sends use the step’s `message_kind` (or the template kind) so consent and tracking stay correct.

The worker ticks due enrollments about every 45 seconds.

## API

| Method | Path |
| --- | --- |
| `GET` | `/api/practices/{id}/journeys` |
| `POST` | `/api/practices/{id}/journeys` |
| `GET` / `PATCH` / `DELETE` | `/api/practices/{id}/journeys/{journeyID}` |
| `POST` | `/api/practices/{id}/journeys/seed-termin-recall` |

Create payload:

```json
{
  "name": "Termin → Recall",
  "status": "draft",
  "trigger": "message_kind",
  "trigger_kind": "termin",
  "steps": [
    {
      "delay_hours": 2160,
      "action": "send_template",
      "template_id": "…",
      "message_kind": "recall"
    }
  ]
}
```

Leave status `draft` until you activate. Journey sends tagged `journey:{id}` do not re-enroll themselves.
