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

# Configuration

> All environment variables the service reads

Configuration is loaded from environment variables (and an optional `.env`
file) via pydantic-settings — see `src/scheduling_bridge/config.py`.

## Market setup

| Variable               | Default  | Meaning                                                                                           |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------- |
| `HOME_CONTROL_AREA`    | `TenneT` | Control area whose balancing group receives the EPEX/ECC delivery                                 |
| `ACTIVE_CONTROL_AREAS` | all four | Comma-separated subset, e.g. `TenneT,Amprion`                                                     |
| `INCLUDE_EXCHANGE_LEG` | `true`   | Include the EPEX/ECC leg in the Engrate submission (`false` if ECC auto-nominates)                |
| `UNIT`                 | `MW`     | Input unit: `MW` (average per 15 min) or `MWH`. Engrate always receives MWh; MW is converted (÷4) |

<Warning>
  `HOME_CONTROL_AREA` defaults to `TenneT` as a placeholder. Set it to the
  real home area before any live use — it decides where the physical EPEX
  delivery lands.
</Warning>

## Engrate

| Variable                    | Default                  | Meaning                                                                                                |
| --------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------ |
| `ENGRATE_BASE_URL`          | `https://api.engrate.io` | Engrate API base URL                                                                                   |
| `ENGRATE_API_KEY`           | —                        | API key from the [Engrate console](https://console.engrate.io), sent raw in the `authorization` header |
| `ENGRATE_TEST_MODE`         | `false`                  | Sets Engrate's `test` flag: skips gate-closure validation                                              |
| `AREA_MARKET_IDS`           | see below                | JSON: per-area market identifiers                                                                      |
| `EXCHANGE_COUNTERPARTY_EIC` | unset                    | Party EIC of the ECC counterparty for the exchange leg                                                 |

`AREA_MARKET_IDS` maps each control area to its identifiers:

```json theme={null}
{
  "TenneT": {
    "balancing_group_eic": "<EIC of our TenneT balancing group>",
    "control_area_eic": "10YDE-EON------1",
    "tso": "TENNET_DE_TSO",
    "receiver_eic": "10XDE-EON------1"
  }
}
```

The control-area EIC Y codes default to the public, stable values. The
balancing-group EICs default to **placeholders and must be configured**;
the TSO identifiers and receiver EICs follow Engrate's documented pattern
and need verification — see [Assumptions](/setup/assumptions).

## Trader sFTP

| Variable                  | Default   | Meaning                                  |
| ------------------------- | --------- | ---------------------------------------- |
| `SFTP_HOST` / `SFTP_PORT` | — / `22`  | Trader's sFTP server                     |
| `SFTP_USERNAME`           | —         | Login user                               |
| `SFTP_PASSWORD`           | unset     | Password auth                            |
| `SFTP_PRIVATE_KEY_PATH`   | unset     | Key-file auth (alternative to password)  |
| `SFTP_TARGET_DIR`         | `/upload` | Drop directory for the open-position CSV |

## Inbound API scopes and audit

| Variable                | Default      | Meaning                                                                       |
| ----------------------- | ------------ | ----------------------------------------------------------------------------- |
| `EXTERNAL_API_KEY`      | unset        | The customer's key — grants the data-delivery endpoints                       |
| `PROCESS_API_KEY`       | unset        | Internal key — grants the `/v1/process/*` endpoints (and everything external) |
| `EXTERNAL_API_KEYS`     | unset        | Several named keys: `name:secret,name:secret`                                 |
| `PROCESS_API_KEYS`      | unset        | Same, for the process scope                                                   |
| `ALLOW_UNAUTHENTICATED` | `false`      | Development escape hatch — see below                                          |
| `AUDIT_DIR`             | `data/audit` | Root directory of the [audit trail](/setup/audit-trail)                       |

<Warning>
  With no credential configured the service **refuses** the authenticated
  routes with `503` rather than serving them openly. `/health` stays
  reachable so the platform can still schedule the app. Set
  `ALLOW_UNAUTHENTICATED=true` only on a developer machine; the service
  announces it in the event log every time it starts.
</Warning>

See [Security](/setup/security) for the full model — named callers,
rotation, OIDC and rate limiting.

## Alerting

| Variable                                                            | Default          | Meaning                                                                 |
| ------------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------- |
| `SLACK_WEBHOOK_URL`                                                 | unset            | Slack incoming webhook (the URL is the credential)                      |
| `PUSHOVER_APP_TOKEN` / `PUSHOVER_USER_KEY`                          | unset            | Both required before the channel exists                                 |
| `PUSHOVER_DEVICE`                                                   | unset            | Limit alerts to one device                                              |
| `PUSHOVER_RETRY_SECONDS` / `PUSHOVER_EXPIRE_SECONDS`                | `300` / `3600`   | Emergency repeat interval and give-up time                              |
| `TWILIO_ACCOUNT_SID` / `TWILIO_AUTH_TOKEN`                          | unset            | Twilio credentials for SMS                                              |
| `TWILIO_FROM` / `TWILIO_TO`                                         | unset            | Sender (number or alphanumeric ID) and comma-separated E.164 recipients |
| `SLACK_MIN_PRIORITY` / `PUSHOVER_MIN_PRIORITY` / `SMS_MIN_PRIORITY` | `-2` / `0` / `2` | Priority each channel starts at                                         |
| `GATE_CLOSURE_LOCAL_TIME`                                           | `14:30`          | Day-ahead deadline in local market time                                 |
| `GATE_CLOSURE_WARN_MINUTES`                                         | `60`             | Lead time for the unsubmitted-day alarm                                 |

See [Alerting](/setup/alerting) for what pages and what stays quiet.

<Note>
  In the Azure deployment all of these are wired up by the Bicep template —
  secrets as Container Apps secrets, the audit directory on an Azure Files
  mount, and the orchestrator timer with the process key. See
  [Azure deployment](/setup/azure-deployment).
</Note>
