> ## Documentation Index
> Fetch the complete documentation index at: https://dynamo-csms.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# CPO Commands — Control Chargers as an Operator

> Send commands to one or many charge points as a CPO. Includes single-charger commands, bulk operations, and command history for audit trails.

CPO command endpoints let Charge Point Operators send operational commands to their charge point fleet. Unlike the OCPP 1.6 endpoints that map directly to OCPP protocol actions, CPO commands are higher-level operations that Dynamo CSMS translates to the appropriate OCPP messages automatically.

All CPO command endpoints require an organization API key with the `write:charge_points` scope. History endpoints additionally require `read:charge_points`.

**Base URL:** `https://api.dynamo-csms.com`

***

## Send command to a charge point

`POST /api/v1/cpo/commands/{charge_point_id}`

Sends a command to a single charge point. The command is executed immediately and the response includes the charge point's acknowledgement.

<ParamField path="charge_point_id" type="string" required>
  The unique identifier of the target charge point.
</ParamField>

<ParamField body="command" type="string" required>
  The command to execute. See the supported commands table below for valid values.
</ParamField>

<ParamField body="parameters" type="object">
  Command-specific parameters. Required fields vary by command — see the command reference below.
</ParamField>

<ParamField body="timeout_seconds" type="integer">
  How long to wait for the charge point to acknowledge the command (default: 10, max: 60).
</ParamField>

### Supported commands

| Command             | Description                        | Required parameters                        |
| ------------------- | ---------------------------------- | ------------------------------------------ |
| `start_session`     | Start a charging session           | `connector_id`, `id_tag`                   |
| `stop_session`      | Stop an active session             | `transaction_id`                           |
| `set_available`     | Mark connector as available        | `connector_id`                             |
| `set_unavailable`   | Mark connector as unavailable      | `connector_id`                             |
| `soft_reset`        | Restart after active sessions end  | —                                          |
| `hard_reset`        | Immediate restart                  | —                                          |
| `set_power_limit`   | Cap charging power                 | `connector_id`, `limit_watts`              |
| `clear_power_limit` | Remove power cap                   | `connector_id`                             |
| `unlock_connector`  | Mechanically unlock connector      | `connector_id`                             |
| `update_firmware`   | Trigger firmware update            | `firmware_url`, `retrieve_date`            |
| `get_diagnostics`   | Request diagnostic upload          | `upload_url`                               |
| `send_local_list`   | Push local RFID authorization list | `list_version`, `local_authorization_list` |

<CodeGroup>
  ```bash cURL — start session theme={null}
  curl -X POST https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001 \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "command": "start_session",
      "parameters": {
        "connector_id": 1,
        "id_tag": "RFID-USER-4A2F"
      }
    }'
  ```

  ```bash cURL — set power limit theme={null}
  curl -X POST https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001 \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "command": "set_power_limit",
      "parameters": {
        "connector_id": 1,
        "limit_watts": 7400
      }
    }'
  ```

  ```bash cURL — soft reset theme={null}
  curl -X POST https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001 \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command": "soft_reset"}'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "command": "set_unavailable",
          "parameters": {"connector_id": 2},
      },
  )
  print(response.json())
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        command: "stop_session",
        parameters: { transaction_id: 10042 },
      }),
    }
  );
  const data = await response.json();
  ```
</CodeGroup>

**Response `200 OK`**

```json theme={null}
{
  "command_id": "cmd_8b3f1a9c",
  "charge_point_id": "CP-SITE42-001",
  "command": "start_session",
  "status": "Accepted",
  "parameters": {
    "connector_id": 1,
    "id_tag": "RFID-USER-4A2F"
  },
  "charge_point_response": {
    "status": "Accepted"
  },
  "executed_at": "2024-03-10T15:45:00Z",
  "response_time_ms": 185
}
```

<ResponseField name="command_id" type="string">
  Unique identifier for this command execution. Use it to look up history.
</ResponseField>

<ResponseField name="status" type="string">
  Dynamo CSMS status: `Accepted`, `Rejected`, `Timeout`, `Error`.
</ResponseField>

<ResponseField name="charge_point_response" type="object">
  Raw OCPP response from the charge point.
</ResponseField>

<ResponseField name="response_time_ms" type="integer">
  Milliseconds between sending the command and receiving the charge point acknowledgement.
</ResponseField>

***

## Send bulk command

`POST /api/v1/cpo/commands/bulk`

Sends the same command to multiple charge points simultaneously. Commands are dispatched in parallel. The response includes per-charge-point results.

<ParamField body="charge_point_ids" type="string[]" required>
  List of charge point identifiers to target. Maximum 100 per request.
</ParamField>

<ParamField body="command" type="string" required>
  The command to send to all charge points. Must be the same command for all targets.
</ParamField>

<ParamField body="parameters" type="object">
  Parameters applied uniformly to all charge points.
</ParamField>

<ParamField body="timeout_seconds" type="integer">
  Per-charge-point timeout in seconds (default: 10, max: 60).
</ParamField>

<ParamField body="continue_on_failure" type="boolean">
  If `true`, continues sending to remaining charge points even if some fail. Defaults to `true`.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/cpo/commands/bulk \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "charge_point_ids": [
      "CP-SITE42-001",
      "CP-SITE42-002",
      "CP-SITE42-003"
    ],
    "command": "soft_reset",
    "continue_on_failure": true
  }'
```

**Response `207 Multi-Status`**

```json theme={null}
{
  "bulk_command_id": "bulk_2c7a4f9e",
  "command": "soft_reset",
  "total": 3,
  "succeeded": 2,
  "failed": 1,
  "results": [
    {
      "charge_point_id": "CP-SITE42-001",
      "command_id": "cmd_9a1b3c5d",
      "status": "Accepted",
      "response_time_ms": 142
    },
    {
      "charge_point_id": "CP-SITE42-002",
      "command_id": "cmd_9a1b3c5e",
      "status": "Accepted",
      "response_time_ms": 167
    },
    {
      "charge_point_id": "CP-SITE42-003",
      "command_id": "cmd_9a1b3c5f",
      "status": "Timeout",
      "error": "Charge point did not respond within 10 seconds",
      "response_time_ms": null
    }
  ],
  "executed_at": "2024-03-10T16:00:00Z"
}
```

<ResponseField name="bulk_command_id" type="string">
  Identifier for the bulk operation as a whole.
</ResponseField>

<ResponseField name="succeeded" type="integer">
  Number of charge points that returned `Accepted`.
</ResponseField>

<ResponseField name="failed" type="integer">
  Number of charge points that timed out, rejected, or errored.
</ResponseField>

<ResponseField name="results" type="array">
  Per-charge-point result objects.
</ResponseField>

<ResponseField name="results[].status" type="string">
  Per-charge-point outcome: `Accepted`, `Rejected`, `Timeout`, `Error`, `Offline`.
</ResponseField>

***

## Get command history for a charge point

`GET /api/v1/cpo/commands/{charge_point_id}/history`

Returns the history of commands sent to a specific charge point, ordered by most recent first.

<ParamField path="charge_point_id" type="string" required>
  The charge point to retrieve history for.
</ParamField>

<ParamField query="command" type="string">
  Filter by command type (e.g. `start_session`, `soft_reset`).
</ParamField>

<ParamField query="status" type="string">
  Filter by outcome: `Accepted`, `Rejected`, `Timeout`, `Error`.
</ParamField>

<ParamField query="from" type="string">
  ISO 8601 start of date range (e.g. `"2024-03-01T00:00:00Z"`).
</ParamField>

<ParamField query="to" type="string">
  ISO 8601 end of date range.
</ParamField>

<ParamField query="page" type="integer">
  Page number (default: 1).
</ParamField>

<ParamField query="per_page" type="integer">
  Results per page (default: 20, max: 100).
</ParamField>

```bash theme={null}
curl "https://api.dynamo-csms.com/api/v1/cpo/commands/CP-SITE42-001/history?from=2024-03-01T00:00:00Z&status=Rejected" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response `200 OK`**

```json theme={null}
{
  "charge_point_id": "CP-SITE42-001",
  "commands": [
    {
      "command_id": "cmd_7f2a1b3c",
      "command": "start_session",
      "status": "Rejected",
      "parameters": {
        "connector_id": 2,
        "id_tag": "RFID-USER-UNKNOWN"
      },
      "charge_point_response": {
        "status": "Rejected"
      },
      "executed_at": "2024-03-05T10:22:00Z",
      "executed_by": "api_key:key_abc123",
      "response_time_ms": 203
    },
    {
      "command_id": "cmd_6e1a0b2c",
      "command": "set_unavailable",
      "status": "Rejected",
      "parameters": {
        "connector_id": 1
      },
      "charge_point_response": {
        "status": "Rejected"
      },
      "executed_at": "2024-03-03T08:14:00Z",
      "executed_by": "api_key:key_abc123",
      "response_time_ms": 198
    }
  ],
  "total": 2,
  "page": 1,
  "per_page": 20
}
```

<ResponseField name="commands[].executed_by" type="string">
  The API key or user that triggered the command, in the format `api_key:{key_id}` or `installer:{installer_id}`.
</ResponseField>

***

## Get organization-wide command history

`GET /api/v1/cpo/commands/history`

Returns command history across all charge points in your organization. Useful for audit trails, troubleshooting, and usage reporting.

<ParamField query="charge_point_id" type="string">
  Filter to a specific charge point.
</ParamField>

<ParamField query="command" type="string">
  Filter by command type.
</ParamField>

<ParamField query="status" type="string">
  Filter by outcome.
</ParamField>

<ParamField query="executed_by" type="string">
  Filter by the API key or installer that sent the command.
</ParamField>

<ParamField query="from" type="string">
  ISO 8601 start of date range.
</ParamField>

<ParamField query="to" type="string">
  ISO 8601 end of date range.
</ParamField>

<ParamField query="page" type="integer">
  Page number (default: 1).
</ParamField>

<ParamField query="per_page" type="integer">
  Results per page (default: 20, max: 200).
</ParamField>

```bash theme={null}
curl "https://api.dynamo-csms.com/api/v1/cpo/commands/history?from=2024-03-01T00:00:00Z&to=2024-03-31T23:59:59Z&command=hard_reset" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response `200 OK`**

```json theme={null}
{
  "commands": [
    {
      "command_id": "cmd_1a2b3c4d",
      "charge_point_id": "CP-NORTH-012",
      "command": "hard_reset",
      "status": "Accepted",
      "parameters": {},
      "executed_at": "2024-03-15T02:00:00Z",
      "executed_by": "api_key:key_def456",
      "response_time_ms": 310
    },
    {
      "command_id": "cmd_2b3c4d5e",
      "charge_point_id": "CP-SOUTH-007",
      "command": "hard_reset",
      "status": "Timeout",
      "parameters": {},
      "executed_at": "2024-03-15T02:01:00Z",
      "executed_by": "api_key:key_def456",
      "response_time_ms": null,
      "error": "Charge point did not respond within 10 seconds"
    }
  ],
  "total": 2,
  "page": 1,
  "per_page": 20
}
```

***

## Pagination

All history endpoints use cursor-free page-based pagination. The response always includes `total`, `page`, and `per_page`. To retrieve subsequent pages, increment `page` in your query:

```bash theme={null}
# Page 1
curl "https://api.dynamo-csms.com/api/v1/cpo/commands/history?page=1&per_page=100"

# Page 2
curl "https://api.dynamo-csms.com/api/v1/cpo/commands/history?page=2&per_page=100"
```

***

## Error responses

```json theme={null}
{
  "error": {
    "code": "charge_point_offline",
    "message": "CP-SITE42-003 is not currently connected to the OCPP server.",
    "charge_point_id": "CP-SITE42-003",
    "request_id": "req_9f3a2b1c"
  }
}
```

| Status | Code                   | Meaning                                             |
| ------ | ---------------------- | --------------------------------------------------- |
| `400`  | `validation_error`     | Missing or invalid field in request                 |
| `400`  | `invalid_command`      | Command name is not recognized                      |
| `400`  | `missing_parameters`   | Required parameters for this command are absent     |
| `400`  | `too_many_targets`     | Bulk request exceeds 100 charge points              |
| `401`  | `unauthorized`         | Missing or invalid API key                          |
| `403`  | `forbidden`            | Key lacks `write:charge_points` scope               |
| `404`  | `not_found`            | Charge point does not belong to your organization   |
| `408`  | `timeout`              | Charge point did not respond within the timeout     |
| `422`  | `charge_point_offline` | Charge point is not connected via OCPP              |
| `422`  | `ocpp_rejected`        | Charge point returned `Rejected`                    |
| `429`  | `rate_limited`         | Exceeded command rate limit (10/s per charge point) |
