# APIv4 Reference
Clever Cloud provides a public REST API used by its own services and customers, known as [`/v2`](/api/v2/).
As our platform evolves, we're progressively moving to `/v4` endpoints, adding functionalities, with a more modern approach:
```
https://api.clever-cloud.com/v4/
```

While the documentation moves towards completion, this page presents the most useful endpoints and example requests available now.

{{< callout type="info" >}}
Each query response contains a `Sozu-Id`. If you need help from our support team, it can help to provide it.
{{< /callout>}}

## Billing
- `/v4/billing/organisations/{orgid}/invoices`
- `/v4/billing/organisations/{orgid}/invoices/{invoiceid}`
- `/v4/billing/organisations/{orgid}/invoices/{invoiceid}.html`
- `/v4/billing/organisations/{orgid}/invoices/{invoiceid}.pdf`
- Type: `GET`

You can use optional parameters to filter it:
| Parameter                   | Type     | Comment                                                                        |
| :---                        | :---     | :---                                                                           |
| `limit`                     | `int`    |                                                                                |
| `since`                     | `string` | ISO 8601 formatted                                                             |
| `until`                     | `string` | ISO 8601 formatted                                                             |

Example response, for each invoice:
```bash
[
    {
    "invoice_number": "",
    "kind": "",
    "owner_id": "",
    "address": {
      "address_id": "",
      "owner_id": "",
      "name": "",
      "company": "",
      "address": "",
      "city": "",
      "zipcode": "",
      "country_alpha2": "",
      "vat_number": "",
      "vat_percent": float,
      "customer_cost_center": "",
      "customer_purchase_order": ""
    },
    "emission_date": "",
    "pay_date": "",
    "status": "",
    "currency": "",
    "price_factor": float,
    "discount": float,
    "vat_percent": float,
    "total_tax_excluded": {
      "currency": "",
      "amount": float,
      "amount_formatted": "",
      "default_display": ""
    },
    "total_tax": {
      "currency": "",
      "amount": float,
      "amount_formatted": "",
      "default_display": ""
    },
    "category": "",
    "payment_provider": "",
    "transaction_id": "",
    "customer_order_id": ""
  },
  {…}
]
```

## Deployments
- `/v4/orchestration/organisations/{ownerId}/applications/{applicationId}/deployments`
- `/v4/orchestration/organisations/{ownerId}/applications/{applicationId}/deployments/{deploymentId}`
- Type: `GET`

Example response, for each deployment:
```bash
[
  {
    "id": "",
    "ownerId": "",
    "applicationId": "",
    "startDate": "",
    "state": "",
    "steps": [
      {
        "state": "",
        "date": ""
      },
      {
        "state": "",
        "date": ""
      },
      {
        "state": "",
        "date": ""
      }
    ],
    "version": {
      "commitId": ""
    },
    "origin": {
      "action": "",
      "cause": "",
      "source": "",
      "authorId": "",
      "constraints": [
        ""
      ],
      "priority": ""
    },
    "hasDedicatedBuild": boolean
  },
  {…}
]
```

## Instances
- `/v4/orchestration/organisations/{ownerId}/applications/{applicationId}/instances`
- Type: `GET`

You can use optional parameters to filter it:
| Parameter                   | Type     | Comment                                                                        |
| :---                        | :---     | :---                                                                           |
| `deploymentId`              | `string` |                                                                                |
| `limit`                     | `int`    |                                                                                |
| `excludeDeleted`            | `boolean`|                                                                                |
| `since`                     | `string` | ISO 8601 formatted                                                             |
| `until`                     | `string` | ISO 8601 formatted                                                             |
| `order`                     | `string` | `ASC` or `DESC`                                                                |
| `includeState`              | `string` | case sensitive, repeated                                                       |
| `excludeState`              | `string` | case sensitive, repeated                                                       |

Example response, for each instance:
```bash
[
  {
    "id": "",
    "ownerId": "",
    "applicationId": "",
    "deploymentId": "",
    "name": "",
    "flavor": "",
    "index": int,
    "state": "",
    "creationDate": "",
    "deletionDate": "",
    "network": {
      "ip": "",
      "port": int
    },
    "isBuildVm": boolean
  },
  {…}
]
```

## Load Balancers
- `/v4/load-balancers/organisations/{ownerId}/applications/{applicationId}/load-balancers/default`
- Type: `GET`

Example response:
```bash
[
  {
    "id": "",
    "name": "",
    "zoneId": "",
    "dns": {
      "cname": "",
      "a": []
    }
  }
]
```

## Logs

### Get logs stream

- `/v4/logs/organisations/{ownerId}/applications/{applicationId}/logs`
- Type: `GET`

Answers with logs in a SSE (Server-Sent Events) stream. You can use optional parameters to filter it:

| Parameter                   | Type     | Comment                                                                        |
| :---                        | :---     | :---                                                                           |
| `deploymentId`              | `string` |                                                                                |
| `instanceId`                | `string` |                                                                                |
| `since`                     | `string` | ISO 8601 formatted                                                             |
| `until`                     | `string` | ISO 8601 formatted                                                             |
| `field`                     | `string` | Allow to get only asked fields, repeated                                       |
| `filter`                    | `string` | Case insensitive `contains` type search                                        |
| `limit`                     | `int64 ` | Minimum: `1`                                                                   |
| `service`                   | `string` | systemd service name, repeated (default: `bas` and `bas-deploy`, can be `all`) |
| `throttleElements`          | `int`    | Maximum elements read per `throttlePerInMilliseconds`, default `100`           |
| `throttlePerInMilliseconds` | `long`   | Default `300`                                                                  |

### Create a logs drain

- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains`
- Type: `POST`

```json
{
  "kind": "ACCESSLOG|LOG",
  "recipient": {
    "type": "<recipient_type>",
    "url": "<endpoint>"
    // Additional fields, depending on recipient_type
  }
}
```

The `recipient.type` discriminates the payload shape. Allowed values and their fields:

| `type`          | Required (besides `type` and `url`) | Optional                                                              |
| :---            | :---                                | :---                                                                  |
| `DATADOG`       | —                                   | —                                                                     |
| `ELASTICSEARCH` | `index`                             | `username`, `password`, `tlsVerification` (`DEFAULT` or `TRUSTFUL`)   |
| `NEWRELIC`      | `apiKey`                            | —                                                                     |
| `OVH_TCP`       | —                                   | `token`, `rfc5424StructuredDataParameters`                            |
| `RAW_HTTP`      | —                                   | `username`, `password`                                                |
| `SYSLOG_TCP`    | —                                   | `rfc5424StructuredDataParameters`                                     |
| `SYSLOG_UDP`    | —                                   | `rfc5424StructuredDataParameters`                                     |

Field reference:

| Field                             | Type     | Comment                                                                                              |
| :---                              | :---     | :---                                                                                                 |
| `username`                        | `string` | Basic Auth username (`ELASTICSEARCH`, `RAW_HTTP`)                                                    |
| `password`                        | `string` | Basic Auth password (`ELASTICSEARCH`, `RAW_HTTP`)                                                    |
| `index`                           | `string` | Elasticsearch index name                                                                             |
| `tlsVerification`                 | `string` | Elasticsearch TLS mode, `DEFAULT` (verify) or `TRUSTFUL` (skip verification)                         |
| `apiKey`                          | `string` | New Relic API key                                                                                    |
| `token`                           | `string` | OVHcloud Logs Data Platform token                                                                    |
| `rfc5424StructuredDataParameters` | `string` | RFC 5424 structured data, e.g. `X-OVH-TOKEN="…"`                                                     |

### List logs drains

- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains`
- Type: `GET`

Optional query parameters: `status`, `executionStatus`, `executionStatusNotIn`.

### Manage a logs drain

- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains/{drainId}`
- Type: `GET`/`DELETE`

### Enable/disable a logs drain

- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains/{drainId}/enable`
- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains/{drainId}/disable`
- Type: `PUT`

### Test or reset a logs drain

- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains/{drainId}/test-command`
- Type: `GET` — returns a `curl` command to test connectivity to the drain endpoint.
- `/v4/drains/organisations/{ownerId}/resources/{resourceId}/drains/{drainId}/reset-cursor`
- Type: `PATCH` — restarts log forwarding from the latest position.

## Operators
A Clever Cloud Operator deploys and manage resources for a given service. Available operators are: `keycloak`, `matomo`, `metabase`, `otoroshi`.

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}`
- Type: `GET`

Example response (Otoroshi — the richest payload):
```json
{
  "resourceId": "otoroshi_<uuid>",
  "addonId": "addon_<uuid>",
  "name": "resource_name",
  "ownerId": "user_or_org_id",
  "plan": "PLAN_NAME",
  "version": "x.y.z",
  "javaVersion": "X",
  "accessUrl": "https://service-web-ui-id.services.clever-cloud.com",
  "availableVersions": ["x.y.z", "…"],
  "initialCredentials": {
    "user": "user_name",
    "password": "user_password"
  },
  "api": {
    "url": "https://service-api-id.services.clever-cloud.com",
    "user": "api_user",
    "secret": "api_secret",
    "openapi": "https://service-api-id.services.clever-cloud.com/api/openapi.json",
    "swaggerUrl": "https://service-api-id.services.clever-cloud.com/api/openapi/ui"
  },
  "resources": {
    "entrypoint": "app_<uuid>",
    "redisId": "redis_<uuid>",
    "pulsarId": "pulsar_<uuid>",
    "elasticId": "elasticsearch_<uuid>",
    "cellarId": "cellar_<uuid>"
  },
  "features": {
    "networkGroup": { "id": "ng_<uuid>" }
  }
}
```

Field availability per operator:

All operators always return: `resourceId`, `addonId`, `name`, `ownerId`, `plan`, `version`, `accessUrl`, `availableVersions`, `resources`.

Other fields depend on the operator (`✓` = always returned, `—` = not returned, `?` = returned when set):

| Field                   | `otoroshi` | `keycloak` | `matomo` | `metabase` |
| :---                    | :---:      | :---:      | :---:    | :---:      |
| `javaVersion`           | ✓          | ✓          | —        | ✓          |
| `phpVersion`            | —          | —          | ✓        | —          |
| `initialCredentials`    | ✓          | ✓          | —        | —          |
| `api`                   | ✓          | —          | —        | —          |
| `features.networkGroup` | ?          | ?          | —        | —          |

For Otoroshi, `resources.entrypoint` and `resources.redisId` are always returned; `pulsarId`, `elasticId` and `cellarId` only appear when the corresponding resource exists. When the Network Group feature is enabled, `features.networkGroup` returns `{ "id": "ng_<uuid>" }`; otherwise it is `null`.

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/reboot`
- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/rebuild`
- Type: `POST`
- Response code: `204`

### Version management

Available for `keycloak`, `metabase` and `otoroshi`.

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/version/check`
- Type: `GET`

```json
{
  "installed": "x.y.z",
  "latest": "x.y.z",
  "available": ["x.y.z", "…"],
  "needUpdate": boolean
}
```

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/version/update`
- Type: `POST`

```json
{
  "targetVersion": "x.y.z"
}
```

### Otoroshi configuration export

- `/v4/addon-providers/addon-otoroshi/addons/{operator_id}/config.yaml`
- Type: `GET`
- Response: `application/yaml` — the full `otoroshictl`-compatible configuration of the instance.

### Network Groups
You can add the deployed service main application in a [Network Group](/doc/develop/network-groups/) to activate some enhanced features:
- `keycloak`: [Secured Multi Instances feature](/doc/addons/keycloak/#secured-multi-instances)
- `otoroshi`: once in a Network Group, an Otoroshi instance can be used in front of Clever Cloud applications

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/networkgroup`
- Type: `POST`
- Response code: `202`

Response contains the full operator object with `networkGroup` feature enabled:
```bash
"features": {
  "networkGroup": {
    "id": "ng_id"
  }
}
```

- `/v4/addon-providers/addon-{operator_name}/addons/{operator_id}/networkgroup`
- Type: `DELETE`
- Response code: `204`
If no Network Group is found, the `networkGroup` feature value is `null`:

```bash
"features": {
  "networkGroup": null
}
```

## Products zones
- `/v4/products/zones`
- `/v4/products/zones/{name}`
- Type: `GET`

You can use optional query parameters to filter the results:

| Parameter | Type     | Comment                                        |
| :---      | :---     | :---                                           |
| `tag`     | `string` | Filter zones on tags (e.g. `infra:clever-cloud`) |
| `ownerId` | `string` | Restrict to zones the given owner has access to |

Example response, for each zone:
```bash
[
  {
    "id": "",
    "name": "",
    "country": "",
    "countryCode": "",
    "city": "",
    "displayName": "",
    "lat": float,
    "lon": float,
    "outboundIPs": [],
    "tags": []
  },
  {…}
]
```

## Pulsar policies
- `/v4/addon-providers/addon-pulsar/addons/{addon-id}/storage-policies`
- Type: `GET`/`PATCH`

Define or get offload/retention policies of a [Pulsar add-on](/doc/addons/pulsar). Retention is how long messages are kept in the topic. Offload is how long messages are kept in the hot storage (NVMe SSD) before being moved to Cellar object storage (S3 compatible, HDD).

Example query/response:
```json
{
  "retentionPolicies": {
    "sizeInBytes": number,
    "durationInMinutes": number
  },
  "offloadPolicies": {
    "sizeInBytes": number,
    "durationInMinutes": number
  }
}
```

| Field               | Type    | Comment                                                                |
| :---                | :---    | :---                                                                   |
| `sizeInBytes`       | `int64` | Size threshold in bytes. Optional. A negative value means no limit.    |
| `durationInMinutes` | `int64` | Duration threshold in minutes. Optional. A negative value means no limit. |

When both fields are omitted (or `null`), retention is infinite and offload is disabled.

