# Retrieve a journey's metrics step by step

Source: https://kirora.io/docs/api/reference/getJourneyStepMetrics

`GET /v1/journeys/{id}/step-metrics`

Requires an API key with the `journeys:read` scope. [About keys and scopes](https://kirora.io/docs/api/reference/authentication)

Works with integration, agent and partner keys.

Where people are and what each step did, by step id across every version of the journey, so a step keeps its counts when others are added or moved. It counts the enrollments that **entered** the journey in the window (all time by default), wherever they are now; `GET /v1/journeys/{id}/metrics` counts by when each thing happened instead. Send steps carry their messages (`email` or `push`) and conversions; a random split, each path and how it converted. Deleting a contact deletes their runs of the journey and those messages, so a past window can later show less than it did.

## Path parameters

- `id` (string, required, uuid) — The journey's id.

## Query parameters

- `from` (string, optional) — Count only the enrollments that entered from then, inclusive: a date-time, or a date meaning the start of that day in the workspace timezone. Give with `to`; omit both for all time.
- `to` (string, optional) — Count only the enrollments that entered before then, exclusive, in the same forms. To include a whole last day, pass the day after it. No later than the end of today; a window touches at most 366 days. Give with `from`.
- `includeRemovedSteps` (string, optional, one of `true`, `false`) — `true`: also the steps no longer in the journey that enrollments passed through, with `removed: true`.

## Header parameters

- `Kirora-Workspace` (string, optional, pattern `^[A-Za-z0-9._:-]{1,128}$`) — Partner keys only: the child workspace to act in, by the external id the partner gave it. Without it, a partner key acts in its own workspace. Any other key that sends it is refused with 403, and an unknown workspace is 404.

## Returns

Returns `200 OK` with a `JourneyStepMetrics` in `data`. Otherwise returns an error; [Errors](https://kirora.io/docs/api/reference/errors) lists every code and which to retry.

- `generatedAt` (string, required, date-time) — When the counters were read.
- `from` (string | null, required, date-time) — Start of the window whose entering enrollments count; `null` for all time.
- `to` (string | null, required, date-time) — End of that window, exclusive.
- `steps` (object[], required) — The journey's steps in order, by id across every version of the journey, then any removed ones asked for.
  - `stepId` (string, required) — The step's id.
  - `name` (string | null, required) — The step's name, if it has one.
  - `type` (string, required, one of `wait`, `wait_until`, `digest`, `send`, `branch`, `filter`, `split`, `random_split`, `action`) — The step type.
  - `removed` (boolean, required) — Whether the step is no longer in the journey (with `includeRemovedSteps`).
  - `entered` (integer, required, min 0) — Enrollments that reached this step, counted once each.
  - `passed` (integer, required, min 0) — Enrollments that reached this step and went on from it.
  - `currentlyHere` (integer, required, min 0) — Enrollments on this step now.
  - `waitingHere` (integer, required, min 0) — Of `currentlyHere`, those waiting out a timer or a due send.
  - `completedHere` (integer, required, min 0) — Enrollments that finished the journey at this step.
  - `exitedHere` (integer, required, min 0) — Enrollments that were ended early while on this step.
  - `nextSteps` (object[], required) — Where enrollments went on to from this step: a decision step's paths, each by the step it leads to.
    - `nextStepId` (string, required) — The id of the step they went on to.
    - `count` (integer, required, min 0) — Enrollments that went there, counted once each.
  - `email` (JourneyEmailCounts, optional) — On an email send step: the messages it created.
    - `created` (integer, required, min 0) — Messages created.
    - `queued` (integer, required, min 0) — Waiting to be sent.
    - `sending` (integer, required, min 0) — Being handed to the provider.
    - `failed` (integer, required, min 0) — Could not be sent.
    - `skipped` (integer, required, min 0) — Not sent, such as for a missing consent or a limit.
    - `sent` (integer, required, min 0) — Handed to the provider, whatever happened after.
    - `delivered` (integer, required, min 0) — Confirmed delivered, whatever happened after; test sends to `delivered@example.com` included (see `simulated`).
    - `bounced` (integer, required, min 0) — Rejected by the recipient server; a test send to `bounce@example.com` is not counted.
    - `complained` (integer, required, min 0) — Marked as spam by the recipient; a test send to `complaint@example.com` is not counted.
    - `opened` (integer, required, min 0) — Opened at least once.
    - `openedByMachine` (integer, required, min 0) — Of `opened`, those only a machine opened: a mail app fetched its images with no reader (Apple Mail Privacy Protection, Gmail's prefetch on delivery) or a mail security scanner checked it.
    - `clicked` (integer, required, min 0) — With a link clicked at least once, by a person.
    - `clickedByMachine` (integer, required, min 0) — Whose links a machine followed, such as a mail security scanner; counted in neither `clicked` nor `opened`.
    - `unsubscribed` (integer, required, min 0) — Whose recipient opted out through the email's link.
    - `simulated` (integer, required, min 0) — Of `sent`, test sends whose outcome was acted out: those to `delivered@`, `bounce@` or `complaint@example.com` (the transactional guide's "Test addresses"). The bounce and complaint rates leave them out.
  - `push` (JourneyPushCounts, optional) — On a push send step: the messages it created.
    - `created` (integer, required, min 0) — Messages created.
    - `queued` (integer, required, min 0) — Waiting to be sent.
    - `sending` (integer, required, min 0) — Being handed to the provider.
    - `failed` (integer, required, min 0) — Could not be sent.
    - `skipped` (integer, required, min 0) — Not sent, such as for a missing consent or a limit.
    - `sent` (integer, required, min 0) — Handed to the provider, whatever happened after.
    - `opened` (integer, required, min 0) — Opened at least once.
    - `clicked` (integer, required, min 0) — With a link clicked at least once, by a person.
  - `conversions` (JourneyConversions[], optional) — On a send step: conversions credited to its messages, per conversion goal.
    - `conversionGoal` (object, required) — The conversion goal.
      - `id` (string, required, uuid)
      - `eventName` (string, required) — The event the conversion goal counts.
    - `count` (integer, required, min 0) — Conversions credited to the journey's messages.
    - `revenue` (object | null, required) — The total of the goal's value; `null` when it reads no value, or when withheld.
      - `currency` (string | null, required) — The goal's currency; `null` when it names none.
      - `value` (number, required, min 0) — Gross, before refunds.
    - `revenueWithheld` (boolean, required) — True when the goal's value property is a masked attribute this viewer may not see, so `revenue` is null.
  - `randomSplit` (object, optional) — On a random split step: each path and how it converted.
    - `paths` (object[], required)
      - `percent` (integer, required, min 0) — The path's share of enrollments, as set.
      - `nextStepId` (string | null, required) — The id of the step it leads to; `null` is the holdout.
      - `count` (integer, required, min 0) — Enrollments that took it.
      - `conversionGoals` (object[], required) — One entry per journey conversion goal; reached by an event it counts, sent or not.
        - `conversionGoalId` (string, required, uuid)
        - `contacts` (integer, required, min 0) — Of those enrollments' contacts, how many did an event the conversion goal counts within its window after the split.
        - `rate` (number | null, required) — `contacts / count`; `null` with no enrollments. Against the holdout, the lift.

## Example

```bash
curl https://api.kirora.io/v1/journeys/018f2a4e-6b1c-7d3e-9f40-37386ae05a6b/step-metrics \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": {
    "generatedAt": "2026-10-02T14:05:00.000Z",
    "from": null,
    "to": null,
    "steps": [
      {
        "stepId": "wait-an-hour",
        "name": "Wait an hour",
        "type": "wait",
        "removed": false,
        "entered": 128,
        "passed": 114,
        "currentlyHere": 12,
        "waitingHere": 12,
        "completedHere": 0,
        "exitedHere": 2,
        "nextSteps": [
          {
            "nextStepId": "welcome-email",
            "count": 114
          }
        ]
      },
      {
        "stepId": "welcome-email",
        "name": "Welcome email",
        "type": "send",
        "removed": false,
        "entered": 114,
        "passed": 0,
        "currentlyHere": 0,
        "waitingHere": 0,
        "completedHere": 114,
        "exitedHere": 0,
        "nextSteps": [],
        "email": {
          "created": 128,
          "queued": 0,
          "sending": 0,
          "failed": 1,
          "skipped": 3,
          "sent": 124,
          "delivered": 121,
          "bounced": 3,
          "complained": 0,
          "opened": 64,
          "openedByMachine": 18,
          "clicked": 19,
          "clickedByMachine": 2,
          "unsubscribed": 1,
          "simulated": 0
        },
        "conversions": [
          {
            "conversionGoal": {
              "id": "0192f3d0-7a1b-7c2d-8e3f-4a5b6c7d8e9f",
              "eventName": "Order Completed"
            },
            "count": 9,
            "revenue": {
              "currency": "USD",
              "value": 450
            },
            "revenueWithheld": false
          }
        ]
      }
    ]
  }
}
```
