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

# Programs

> Connect page that opens the VPP flow and lists the programs available to the user.

This page opens the VPP flow and lists the programs and managed tariffs available to the user, with estimates and enrollment state.

> [tab] Overview
>
> ![](https://mintcdn.com/flatpeak-d495c19e/2B6nWUU4-c2pSD3E/images/busbar/connect/vpp-programs.png?fit=max\&auto=format\&n=2B6nWUU4-c2pSD3E\&q=85\&s=7bd2e61d286f7a71795b2c35d650d146)

> [tab] Join Program
>
> ![](https://mintcdn.com/flatpeak-d495c19e/2B6nWUU4-c2pSD3E/images/busbar/connect/vpp-programs-join-program.png?fit=max\&auto=format\&n=2B6nWUU4-c2pSD3E\&q=85\&s=f69bc5506173798d72e1922c4258c8a3)

> [tab] Join Conflict
>
> ![](https://mintcdn.com/flatpeak-d495c19e/2B6nWUU4-c2pSD3E/images/busbar/connect/vpp-programs-already-in-program.png?fit=max\&auto=format\&n=2B6nWUU4-c2pSD3E\&q=85\&s=e888a8077528c5e26668494912e08677)

> [tab] No Programs
>
> ![](https://mintcdn.com/flatpeak-d495c19e/2B6nWUU4-c2pSD3E/images/busbar/connect/vpp-programs-no-programs.png?fit=max\&auto=format\&n=2B6nWUU4-c2pSD3E\&q=85\&s=20cff459867abca9be670135689d2939)

> [tab] Code
>
> ```json Connect response theme={"system"}
> {
>   "connect_session": "cos_6587fa4362341be5b524de3b",
>   "route": "programs",
>   "live_mode": true,
>   "actions": [
>     "BACK",
>     "CLOSE"
>   ],
>   "data": {
>     "device_type": "BATTERY_STORAGE",
>     "tariff_connected": false,
>     "location": {
>       "timezone": "America/Denver",
>       "currency_code": "USD"
>     },
>     "programs": [
>       {
>         "operator": { "id": "opr_8587fa49c7e5297ccc6c57e5", "display_name": "Pick" },
>         "id": "vpr_6a1f8e375db9de605baadd46",
>         "display_name": "Community Powershare",
>         "url": "https://pick.com/programs/community-powershare",
>         "enrollment_state": "NOT_ENROLLED",
>         "managed": false,
>         "currency_code": "USD",
>         "estimate": {
>           "amount": 612,
>           "period": "YEAR",
>           "dispatch_events_per_month": 15
>         },
>         "terms": {
>           "rewards": [
>             { "basis": "FIXED", "rate": 15, "period": "QUARTER" },
>             { "basis": "DELIVERED_KWH", "rate": 0.35 }
>           ],
>           "opt_out_policy": "ALLOWED",
>           "notice_days": 30
>         },
>         "enrollment": {
>           "join_days": 10,
>           "dispatch_test_required": true
>         }
>       },
>       {
>         "operator": { "id": "opr_9c2e1b55d1a8340aa1b23f77", "display_name": "PG&E" },
>         "id": "vpr_7b2f9d486ec0ef716cbbee57",
>         "display_name": "On-demand V2G",
>         "url": "https://pge.com/programs/on-demand-v2g",
>         "enrollment_state": "NOT_ENROLLED",
>         "managed": true,
>         "currency_code": "USD",
>         "estimate": {
>           "amount": 104,
>           "period": "MONTH",
>           "dispatch_events_per_month": 8
>         },
>         "terms": {
>           "rewards": [],
>           "opt_out_policy": "NOT_ALLOWED",
>           "notice_days": 30
>         },
>         "enrollment": {
>           "join_days": 14,
>           "dispatch_test_required": true
>         }
>       }
>     ]
>   }
> }
> ```
>
> ```bash Your POST to Connect (data) theme={"system"}
> curl --request POST \
>   --url https://connect.flatpeak.com \
>   --header 'Content-Type: application/json' \
>   --data '{
>   "connect_session": "cos_6587fa4362341be5b524de3b",
>   "route": "programs",
>   "data": {
>     "program": {
>       "id": "vpr_6a1f8e375db9de605baadd46"
>     }
>   }
> }'
> ```
>
> ```json Connect response (managed tariff) theme={"system"}
> {
>   "connect_session": "cos_6587fa4362341be5b524de3b",
>   "route": "session_redirect",
>   "live_mode": true,
>   "data": {
>     "redirect_type": "OPERATOR_SIGNUP",
>     "redirect_url": "https://pge.com/programs/on-demand-v2g/signup?program_id=vpr_7b2f9d486ec0ef716cbbee57&oem_id=oem_6a3a8dada72cd0a249ff9528&signup_reference=sur_6a7c0e2f9b4d1a3c5e8f7b6d"
>   }
> }
> ```
>
> #### Enrollment state
>
> `NOT_ENROLLED` means the device has never enrolled in the program. Show any other `enrollment_state` as [enrollment states](/docs/energy-api/guides/vpp/enrollment-states.md) describes.
>
> A device can be in one program at a time. If the user picks another, ask them to leave the current one first.
>
> #### Tariff connection
>
> `tariff_connected` is `false` until the location has a connected tariff, and selecting a program before then returns `action_invalid`. A managed tariff can be selected without one, because the VPP operator supplies the tariff.
>
> #### One operator's programs
>
> When the session was [created](/docs/energy-api/reference/connect-sessions/create.md) with an `operator_id`, `programs` lists only that VPP operator's programs the device is eligible for. An enrollment the device holds with another VPP operator is still listed, so the user can see and leave it.
>
> #### Managed tariffs
>
> `managed` is `true` when the VPP operator runs the device and the program replaces the user's tariff. List managed tariffs under their own heading, after the programs where the user keeps their tariff. Every program dispatches through VPP events, and a managed tariff also runs the device with plans.
>
> The user signs up for a managed tariff with the VPP operator, so selecting one creates no enrollment. Connect answers with [`session_redirect`](/docs/energy-api/reference/connect/tariff/redirects#operator-sign-up) and `redirect_type` `OPERATOR_SIGNUP`. Open `redirect_url` in the system browser, unchanged, and close Connect. The VPP operator learns nothing about the device at this point, and `enrollment_state` stays `NOT_ENROLLED`.
>
> After signing up, the user comes back to your app by [universal link](/docs/energy-api/reference/connect/vpp/universal-links.md) with a new Connect session. Connect shows [consent](/docs/energy-api/reference/connect/vpp/consent.md) there, and the enrollment starts once the user allows it.
>
> Hosted Connect reads "Keep your tariff, earn from events" and "Switch to a managed tariff. The operator runs your battery. Replaces your tariff." Its button is "Join" on a program; on a managed tariff it is "Continue with PG\&E", with the operator's `display_name`.
>
> #### Estimates
>
> `estimate` is what the user is told to expect. It is a projection and never binding. The copy follows `managed`:
>
> | `managed` | Copy |
> | :- | :- |
> | `false` | "You earn 612 USD per year" |
> | `true` | "Your bill drops by 104 USD per month" |
>
> | Field | Description |
> | :- | :- |
> | `amount` | Estimated amount for one `period`, in the program's `currency_code`. |
> | `period` | Period the estimate covers: `YEAR` or `MONTH`. The VPP operator sets it per program. |
> | `dispatch_events_per_month` | Approximate number of dispatch events per month the estimate assumes. |
>
> Show the amount with its period, and the assumption next to it. Do not convert between periods, and say that the actual amount varies.
>
> #### Terms
>
> `terms` holds what binds the user and the VPP operator once the user has joined. Show it on the Join screen. The enrollment keeps a copy of the `terms` it joined with, and a later change to the program does not alter that copy.
>
> | Field | Description |
> | :- | :- |
> | `rewards` | What the user is paid, in the program's `currency_code`. Empty when the program pays no rewards, as a managed tariff may. |
> | `opt_out_policy` | Whether the user may skip an event. |
> | `notice_days` | Maximum number of days leaving may take once the user is enrolled. |
>
> Show every entry in `rewards`:
>
> | `basis` | `rate` is paid | Copy |
> | :- | :- | :- |
> | `FIXED` | Once per `period`: `MONTH`, `QUARTER` or `YEAR` | "15 USD per quarter" |
> | `EVENT` | Per event the device delivers in full | "1 USD per event delivered in full" |
> | `DELIVERED_KWH` | Per kWh delivered | "0.35 USD per kWh delivered" |
> | `COMMITTED_KWH` | Per kWh of the device's locked share of an event | "0.20 USD per kWh committed" |
>
> | `opt_out_policy` | The user may skip an event |
> | :- | :- |
> | `ALLOWED` | Always. |
> | `ALLOWED_BEFORE_LOCK` | Until the allocation locks at `time_allocation_locks`. Device shares are then fixed. |
> | `NOT_ALLOWED` | Never. |
>
> #### Joining and leaving
>
> | Field | Description |
> | :- | :- |
> | `enrollment.join_days` | Maximum number of days enrollment may take after the user asks to join. |
> | `enrollment.dispatch_test_required` | `true` when the device must deliver a short `TEST` event before approval. |
> | `terms.notice_days` | Maximum number of days leaving may take once the user is enrolled. |
>
> Show both periods when the user confirms joining: "Enrollment can take up to 10 days. Once enrolled, leaving can take up to 30 days."
>
> #### No programs
>
> When `programs` is empty, `status` is `NONE_AVAILABLE`, so show an empty state. When a program becomes available to the device, your backend receives `device.update`. See [Events](/docs/energy-api/guides/platform/events.md).
>
> #### Actions
>
> | Action | Result |
> | :- | :- |
> | `BACK` | Returns the previous page. If there is none, returns `callback_url`. |
> | `CLOSE` | Returns the `callback_url` set on the Connect session. |
>
> #### Errors
>
> | Error code | Description |
> | :- | :- |
> | `data_json_invalid` | Data does not conform to the JSON schema. |
> | `action_invalid` | Action is not available on this route, or is not permitted in the current state, for example program selection while no tariff is connected. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.