Hetzner Cloud API 1.0.0
Added: 01/02/2021
Updated at: 06/03/2023
This is the official API documentation for the Public Hetzner Cloud.
## Introduction
The Hetzner Cloud API operates over HTTPS and uses JSON as its data format. The API is a RESTful API and utilizes HTTP methods and HTTP status codes to specify requests and responses.
As an alternative to working directly with our API you may also consider to use:
* Our CLI program [hcloud](https://github.com/hetznercloud/cli)
* Our [library for Go](https://github.com/hetznercloud/hcloud-go)
* Our [library for Python](https://github.com/hetznercloud/hcloud-python)
Also you can find a [list of libraries, tools, and integrations on GitHub](https://github.com/hetznercloud/awesome-hcloud).
If you are developing integrations based on our API and your product is Open Source you may be eligible for a free one time €50 (excl. VAT) credit on your account. Please contact us via the the support page on your Cloud Console and let us know the following:
* The type of integration you would like to develop
* Link to the GitHub repo you will use for the Project
* Link to some other Open Source work you have already done (if you have done so)
## Getting Started
To get started using the API you first need an API token. Sign in into the [Hetzner Cloud Console](https://console.hetzner.cloud/) choose a Project, go to `Security` → `API Tokens`, and generate a new token. Make sure to copy the token because it won’t be shown to you again. A token is bound to a Project, to interact with the API of another Project you have to create a new token inside the Project. Let’s say your new token is `jEheVytlAoFl7F8MqUQ7jAo2hOXASztX`.
You’re now ready to do your first request against the API. To get a list of all Servers in your Project, issue the example request on the right side using [curl](https://curl.haxx.se/).
Make sure to replace the token in the example command with the token you have just created. Since your Project probably does not contain any Servers yet, the example response will look like the response on the right side. We will almost always provide a resource root like `servers` inside the example response. A response can also contain a `meta` object with information like [Pagination](https://docs.hetzner.cloud/#overview-pagination).
**Example Request**
```bash
curl -H "Authorization: Bearer jEheVytlAoFl7F8MqUQ7jAo2hOXASztX" \
https://api.hetzner.cloud/v1/servers
```
**Example Response**
```json
{
"servers": [],
"meta": {
"pagination": {
"page": 1,
"per_page": 25,
"previous_page": null,
"next_page": null,
"last_page": 1,
"total_entries": 0
}
}
}
```
## Authentication
All requests to the Hetzner Cloud API must be authenticated via a API token. Include your secret API token in every request you send to the API with the `Authorization` HTTP header.
To create a new API token for your Project, switch into the [Hetzner Cloud Console](https://console.hetzner.cloud/) choose a Project, go to `Security` → `API Tokens`, and generate a new token.
**Example Authorization header**
```html
Authorization: Bearer LRK9DAWQ1ZAEFSrCNEEzLCUwhYX1U3g7wMg4dTlkkDC96fyDuyJ39nVbVjCKSDfj
```
## Errors
Errors are indicated by HTTP status codes. Further, the response of the request which generated the error contains an error code, an error message, and, optionally, error details. The schema of the error details object depends on the error code.
The error response contains the following keys:
| Keys | Meaning |
|-----------|-----------------------------------------------------------------------|
| `code` | Short string indicating the type of error (machine-parsable) |
| `message` | Textual description on what has gone wrong |
| `details` | An object providing for details on the error (schema depends on code) |
**Example response**
```json
{
"error": {
"code": "invalid_input",
"message": "invalid input in field 'broken_field': is too long",
"details": {
"fields": [
{
"name": "broken_field",
"messages": ["is too long"]
}
]
}
}
}
```
### Error Codes
| Code | Description |
|---------------------------|----------------------------------------------------------------------------------|
| `forbidden` | Insufficient permissions for this request |
| `invalid_input` | Error while parsing or processing the input |
| `json_error` | Invalid JSON input in your request |
| `locked` | The item you are trying to access is locked (there is already an Action running) |
| `not_found` | Entity not found |
| `rate_limit_exceeded` | Error when sending too many requests |
| `resource_limit_exceeded` | Error when exceeding the maximum quantity of a resource for an account |
| `resource_unavailable` | The requested resource is currently unavailable |
| `service_error` | Error within a service |
| `uniqueness_error` | One or more of the objects fields must be unique |
| `protected` | The Action you are trying to start is protected for this resource |
| `maintenance` | Cannot perform operation due to maintenance |
| `conflict` | The resource has changed during the request, please retry |
| `unsupported_error` | The corresponding resource does not support the Action |
| `token_readonly` | The token is only allowed to perform GET requests |
| `unavailable` | A service or product is currently not available |
**invalid_input**
```json
{
"error": {
"code": "invalid_input",
"message": "invalid input in field 'broken_field': is too long",
"details": {
"fields": [
{
"name": "broken_field",
"messages": ["is too long"]
}
]
}
}
}
```
**uniqueness_error**
```json
{
"error": {
"code": "uniqueness_error",
"message": "SSH key with the same fingerprint already exists",
"details": {
"fields": [
{
"name": "public_key"
}
]
}
}
}
```
**resource_limit_exceeded**
```json
{
"error": {
"code": "resource_limit_exceeded",
"message": "project limit exceeded",
"details": {
"limits": [
{
"name": "project_limit"
}
]
}
}
}
```
## Labels
Labels are `key/value` pairs that can be attached to all resources.
Valid label keys have two segments: an optional prefix and name, separated by a slash (`/`). The name segment is required and must be a string of 63 characters or less, beginning and ending with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (`.`), not longer than 253 characters in total, followed by a slash (`/`).
Valid label values must be a string of 63 characters or less and must be empty or begin and end with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between.
The `hetzner.cloud/` prefix is reserved and cannot be used.
**Example Labels**
```json
{
"labels": {
"environment":"development",
"service":"backend",
"example.com/my":"label",
"just-a-key":""
}
}
```
## Label Selector
For resources with labels, you can filter resources by their labels using the label selector query language.
| Expression | Meaning |
|----------------------|---------------------------------------------------------------------|
| `k==v` / `k=v` | Value of key `k` does equal value `v` |
| `k!=v` | Value of key `k` does not equal value `v` |
| `k` | Key `k` is present |
| `!k` | Key `k` is not present |
| `k in (v1,v2,v3)` | Value of key `k` is `v1`, `v2`, or `v3` |
| `k notin (v1,v2,v3)` | Value of key `k` is neither `v1`, nor `v2`, nor `v3` |
| `k1==v,!k2` | Value of key `k1` is `v` and key `k2` is not present |
### Examples
* Returns all resources that have a `env=production` label and that don't have a `type=database` label:
`env=production,type!=database`
* Returns all resources that have a `env=testing` or `env=staging` label:
`env in (testing,staging)`
* Returns all resources that don't have a `type` label:
`!type`
## Pagination
Responses which return multiple items support pagination. If they do support pagination, it can be controlled with following query string parameters:
* A `page` parameter specifies the page to fetch. The number of the first page is 1.
* A `per_page` parameter specifies the number of items returned per page. The default value is 25, the maximum value is 50 except otherwise specified in the documentation.
Responses contain a `Link` header with pagination information.
Additionally, if the response body is JSON and the root object is an object, that object has a `pagination` object inside the `meta` object with pagination information:
**Example Pagination**
```json
{
"servers": [...],
"meta": {
"pagination": {
"page": 2,
"per_page": 25,
"previous_page": 1,
"next_page": 3,
"last_page": 4,
"total_entries": 100
}
}
}
```
The keys `previous_page`, `next_page`, `last_page`, and `total_entries` may be `null` when on the first page, last page, or when the total number of entries is unknown.
**Example Pagination Link header**
```bash
Link: