> ## Documentation Index
> Fetch the complete documentation index at: https://evsim.synergyboat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Author a custom scenario

> The scenario JSON shape, the knobs that matter, and how to import, run, and save a scenario you wrote by hand or generated from CI.

A **custom scenario** is a charging journey described as JSON: the same thing the
Charging Journeys builder produces, written down so a human or an agent can version
it, diff it, and replay it from CI. Import one and it opens in the builder with every
knob restored; run it and it streams evidence and lands a report exactly like a
catalogue journey.

The fastest way to get a valid file is **Download sample** on the Charging Journeys
page. It exports a ready-to-run scenario for your selected target. Edit that, or write
one from the shape below.

## The shape

```json theme={null}
{
  "schemaVersion": 1,
  "journey": "first-successful-charge",
  "roleUnderTest": "EMSP",
  "journeyPack": "core-charging",
  "ocpiVersion": "2.2.1",
  "coverageDepth": "happy-path",
  "clock": { "mode": "accelerated", "durationSeconds": 3000 },
  "session": {
    "cadenceSeconds": 300,
    "jitterSeconds": 0,
    "strategy": "put-and-patch",
    "updates": ["kwh", "total_cost", "status", "charging_periods"]
  },
  "catalogue": { "locationUpdates": true, "tariffUpdates": true },
  "completion": { "cdrDelaySeconds": 300 },
  "contract": { "cdrWithinSeconds": 600 },
  "disturbances": [],
  "seed": "204"
}
```

## The knobs that matter

* **`journey`**: the template the scenario starts from (e.g. `first-successful-charge`).
  It selects the story; an unknown id falls back to the recommended journey.
* **`ocpiVersion`** and **`targetId`** are advisory in the file. On import the builder
  runs the scenario against whichever target you have selected, so a sample from one
  target still runs against another, and you do not need a real `targetId` to share a
  file.
* **`clock.mode`**: `accelerated` compresses a session into seconds; `real` runs it at
  wall-clock cadence for long-session testing.
* **`session.cadenceSeconds`** and **`jitterSeconds`**: how often meter updates are
  pushed, and how irregular they are (`jitterSeconds` above 0 means irregular).
* **`session.updates`**: which fields each update carries (`kwh`, `total_cost`,
  `status`, `charging_periods`).
* **`disturbances`**: faults injected mid-journey to prove the endpoint fails safely
  (e.g. `skip_intermediate_update`, `duplicate_full_put`, `delay_cdr`).
* **`coverageDepth`**: `happy-path`, `edge-cases`, or `adversarial`.
* **`seed`**: makes a run reproducible; keep it stable to replay the same story.

Unknown or malformed fields fall back to sensible defaults, so a partial file still
imports and simply uses the defaults for anything you left out.

## Import, run, and save

1. On **Charging Journeys**, choose **Import scenario JSON** and pick your file, or
   **Download sample** to start from a working one.
2. The scenario opens in the builder on the **Configure** step with your knobs applied.
   Adjust anything, then **Preview** to compile the plan.
3. **Start the run.** It streams live and lands a graded report in **Runs**, stored on
   your account, replayable and runnable from CI with the same JSON.

See also [Run a charging journey](/docs/guide/run-a-charging-journey) for the run, follow,
and recovery flow.
