> ## 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.

# Organizations API — Members, Roles, and Settings

> Create organizations, invite team members with scoped roles, manage site owner onboarding, and configure org-wide billing and timezone settings.

Organizations are the top-level tenants in Dynamo CSMS. Every charge point, project, and billing record belongs to an organization. You can invite team members with scoped roles, manage site owner onboarding, and configure organization-wide settings from these endpoints.

## Authentication

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
# or
X-API-Key: YOUR_API_KEY
```

***

## Organizations

### Create an organization

`POST /api/v1/organizations`

<ParamField body="name" type="string" required>
  Display name for the organization.
</ParamField>

<ParamField body="country" type="string" required>
  ISO 3166-1 alpha-2 country code (e.g., `"GB"`, `"DE"`, `"US"`).
</ParamField>

<ParamField body="contact_email" type="string" required>
  Primary contact email address for the organization.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/organizations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Greenway Charging Ltd",
    "country": "GB",
    "contact_email": "ops@greenway.example.com"
  }'
```

```json theme={null}
{
  "id": "org_01HX7A3B2C4D5E6F",
  "name": "Greenway Charging Ltd",
  "country": "GB",
  "contact_email": "ops@greenway.example.com",
  "created_at": "2024-01-20T09:00:00Z"
}
```

### Get an organization

`GET /api/v1/organizations/{org_id}`

<ParamField path="org_id" type="string" required>
  The ID of the organization to retrieve.
</ParamField>

### Update an organization

`PUT /api/v1/organizations/{org_id}`

Replaces the organization's mutable fields. Include all fields you want to retain, not just the ones you are changing.

<ParamField path="org_id" type="string" required>
  The ID of the organization to update.
</ParamField>

<ParamField body="name" type="string" required>
  Updated display name.
</ParamField>

<ParamField body="country" type="string" required>
  Updated ISO 3166-1 alpha-2 country code.
</ParamField>

<ParamField body="contact_email" type="string" required>
  Updated contact email address.
</ParamField>

***

## Members

### List members

`GET /api/v1/organizations/{org_id}/members`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

```bash theme={null}
curl https://api.dynamo-csms.com/api/v1/organizations/org_01HX7A3B2C4D5E6F/members \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "user_id": "usr_01HX8B4C3D5E6F7G",
      "email": "alice@greenway.example.com",
      "name": "Alice Chen",
      "role": "admin",
      "joined_at": "2024-01-20T09:15:00Z"
    },
    {
      "user_id": "usr_01HX8B4C3D5E6F8H",
      "email": "bob@greenway.example.com",
      "name": "Bob Singh",
      "role": "viewer",
      "joined_at": "2024-01-21T11:00:00Z"
    }
  ],
  "total": 2
}
```

### Update a member's role

`PUT /api/v1/organizations/{org_id}/members/{user_id}/role`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

<ParamField path="user_id" type="string" required>
  The ID of the member whose role you are changing.
</ParamField>

<ParamField body="role" type="string" required>
  The new role. One of `"admin"`, `"member"`, or `"viewer"`.
</ParamField>

```bash theme={null}
curl -X PUT https://api.dynamo-csms.com/api/v1/organizations/org_01HX7A3B2C4D5E6F/members/usr_01HX8B4C3D5E6F8H/role \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role": "member"}'
```

### Remove a member

`DELETE /api/v1/organizations/{org_id}/members/{user_id}`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

<ParamField path="user_id" type="string" required>
  The ID of the member to remove.
</ParamField>

Returns `204 No Content` on success.

***

## Invitations

### Invite a member

`POST /api/v1/organizations/{org_id}/invitations`

Sends an email invitation to join your organization with the specified role.

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

<ParamField body="email" type="string" required>
  Email address of the person to invite.
</ParamField>

<ParamField body="role" type="string" required>
  Role to assign on acceptance: `"admin"`, `"member"`, or `"viewer"`.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/organizations/org_01HX7A3B2C4D5E6F/invitations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "charlie@example.com",
    "role": "member"
  }'
```

```json theme={null}
{
  "id": "inv_01HXC5D4E3F2G1H0",
  "email": "charlie@example.com",
  "role": "member",
  "expires_at": "2024-01-27T09:00:00Z",
  "created_at": "2024-01-20T09:00:00Z"
}
```

### Accept an invitation

`POST /api/v1/organizations/invitations/accept`

The invited user calls this endpoint with the token from their invitation email.

<ParamField body="token" type="string" required>
  The invitation token from the invitation email.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/organizations/invitations/accept \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token": "inv_tok_abc123xyz"}'
```

### Cancel an invitation

`DELETE /api/v1/organizations/{org_id}/invitations/{invitation_id}`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

<ParamField path="invitation_id" type="string" required>
  The ID of the invitation to cancel.
</ParamField>

Returns `204 No Content` on success.

***

## Organization settings

### Get settings

`GET /api/v1/organizations/{org_id}/settings`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

```bash theme={null}
curl https://api.dynamo-csms.com/api/v1/organizations/org_01HX7A3B2C4D5E6F/settings \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "org_id": "org_01HX7A3B2C4D5E6F",
  "default_currency": "GBP",
  "timezone": "Europe/London",
  "billing_email": "billing@greenway.example.com",
  "notification_preferences": {
    "alert_emails": true,
    "weekly_report": true
  }
}
```

### Update settings

`PUT /api/v1/organizations/{org_id}/settings`

<ParamField path="org_id" type="string" required>
  The organization ID.
</ParamField>

<ParamField body="default_currency" type="string">
  ISO 4217 currency code (e.g., `"GBP"`, `"EUR"`, `"USD"`).
</ParamField>

<ParamField body="timezone" type="string">
  IANA timezone name (e.g., `"Europe/London"`).
</ParamField>

<ParamField body="billing_email" type="string">
  Email address for billing-related notifications.
</ParamField>

<ParamField body="notification_preferences" type="object">
  Object controlling which notifications the organization receives.
</ParamField>

***

## Site owner

Site owners are external partners or property managers who host charge points on your network. These endpoints manage their onboarding flow and profile.

### Accept a site owner invitation

`POST /api/v1/site-owner/accept-invitation/{token}`

<ParamField path="token" type="string" required>
  The site owner invitation token from the invitation email.
</ParamField>

### Get onboarding status

`GET /api/v1/site-owner/onboarding/status`

Returns the current stage of the site owner onboarding process.

```bash theme={null}
curl https://api.dynamo-csms.com/api/v1/site-owner/onboarding/status \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "stage": "documents_pending",
  "completed_steps": ["profile", "bank_details"],
  "pending_steps": ["documents", "approval"]
}
```

### Complete onboarding

`POST /api/v1/site-owner/onboarding/complete`

Signals that the site owner has submitted all required information.

### Get site owner profile

`GET /api/v1/site-owner/profile`

Returns profile and account details for the authenticated site owner.

### List site owner projects

`GET /api/v1/site-owner/projects`

Returns all charging projects associated with this site owner.

```bash theme={null}
curl https://api.dynamo-csms.com/api/v1/site-owner/projects \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "proj_01HXD6E5F4G3H2I1",
      "name": "Canary Wharf Car Park",
      "charge_point_count": 12,
      "status": "active"
    }
  ],
  "total": 1
}
```

***

## Driver portal

The driver portal lets EV drivers view their own session history and manage billing disputes without needing access to the operator API.

### List driver sessions

`GET /api/v1/portal/sessions`

Returns all charging sessions for the authenticated driver.

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

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

<ParamField query="limit" type="number" default="20">
  Number of sessions to return (max 100).
</ParamField>

```bash theme={null}
curl "https://api.dynamo-csms.com/api/v1/portal/sessions?from=2024-01-01&to=2024-01-31" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "session_id": "sess_01HXE7F6G5H4I3J2",
      "charge_point_id": "cp_001",
      "started_at": "2024-01-15T08:30:00Z",
      "ended_at": "2024-01-15T09:45:00Z",
      "energy_kwh": 22.4,
      "cost": 7.84,
      "currency": "GBP"
    }
  ],
  "total": 1
}
```

### Get session cost breakdown

`GET /api/v1/portal/sessions/{session_id}/cost-breakdown`

<ParamField path="session_id" type="string" required>
  The session ID.
</ParamField>

Returns an itemised breakdown of session charges including energy, time, and any applicable fees.

### Download session receipt

`GET /api/v1/portal/sessions/{session_id}/receipt`

<ParamField path="session_id" type="string" required>
  The session ID.
</ParamField>

Returns a PDF receipt for the session. The response `Content-Type` is `application/pdf`.

### Submit a billing dispute

`POST /api/v1/portal/sessions/{session_id}/dispute`

<ParamField path="session_id" type="string" required>
  The session ID to dispute.
</ParamField>

<ParamField body="reason" type="string" required>
  Description of the issue with the charge.
</ParamField>

<ParamField body="expected_cost" type="number">
  What the driver believes the correct cost should be.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/portal/sessions/sess_01HXE7F6G5H4I3J2/dispute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Session ended prematurely but full session duration was charged.",
    "expected_cost": 3.50
  }'
```

```json theme={null}
{
  "dispute_id": "disp_01HXF8G7H6I5J4K3",
  "session_id": "sess_01HXE7F6G5H4I3J2",
  "status": "open",
  "created_at": "2024-01-20T14:00:00Z"
}
```

***

## Reservations

Reservations let drivers hold a connector before they arrive, reducing the chance of finding no available charger.

### Create a reservation

`POST /api/v1/reservations`

<ParamField body="charge_point_id" type="string" required>
  The charge point to reserve a connector on.
</ParamField>

<ParamField body="connector_id" type="number" required>
  The connector number to reserve.
</ParamField>

<ParamField body="expiry_date" type="string" required>
  ISO 8601 datetime at which the reservation expires if unused.
</ParamField>

<ParamField body="id_tag" type="string" required>
  The driver's ID tag (RFID UID or email). Only this tag can use the reservation.
</ParamField>

```bash theme={null}
curl -X POST https://api.dynamo-csms.com/api/v1/reservations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "charge_point_id": "cp_001",
    "connector_id": 1,
    "expiry_date": "2024-01-20T16:00:00Z",
    "id_tag": "driver@example.com"
  }'
```

```json theme={null}
{
  "reservation_id": "res_01HXG9H8I7J6K5L4",
  "charge_point_id": "cp_001",
  "connector_id": 1,
  "id_tag": "driver@example.com",
  "expiry_date": "2024-01-20T16:00:00Z",
  "status": "active",
  "created_at": "2024-01-20T14:30:00Z"
}
```

### List reservations

`GET /api/v1/reservations`

<ParamField query="charge_point_id" type="string">
  Filter reservations by charge point.
</ParamField>

<ParamField query="status" type="string">
  Filter by status: `active`, `used`, `expired`, or `cancelled`.
</ParamField>

### Cancel a reservation

`DELETE /api/v1/reservations/{reservation_id}`

<ParamField path="reservation_id" type="string" required>
  The ID of the reservation to cancel.
</ParamField>

Returns `204 No Content` on success. Cancellation sends a `CancelReservation` command to the charge point via OCPP.
