# Requests and responses

Source: https://heaven.dev/docs/requests

Reads are GETs, changes are POSTs, and every response has the same shape.

## One shape for every endpoint

Each resource has one endpoint, with four ways to use it:

| Request | Does |
| --- | --- |
| `GET /v1/computer/` | Reads every Computer you can see, or one of them with `?computer=NAME` |
| `POST /v1/computer/create` | Creates one |
| `POST /v1/computer/modify` | Changes one. The body's `action` says how, such as `"restart"`, `"rename"` or `"domain add"` |
| `POST /v1/computer/delete` | Deletes it |

Pools, organizations and integrations work the same way. A `/modify` request carries exactly one `action` and that action's fields. A field that belongs to another action is refused (`invalid`).

Some Computer actions, and `/v1/computer/delete`, take `computers` to act on several Computers at once. See [changing Computers](https://heaven.dev/docs/computers#modify).

Request:

```sh
curl https://heaven.dev/v1/computer/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"computer":"my-site","action":"rename","name":"my-shop"}'
```

## Sending fields

- **A `POST`** sends a JSON object with `Content-Type: application/json`, which `curl --json` sets. A body can be up to 512 KiB, or 2 MiB for `exec`.
- **A `GET`** sends the same fields in its query: `?computer=my-site&view=usage&range=7d`. For a list, repeat the field (`?tags=web&tags=prod`). For a switch, write `true` or `false`.
- **Field names** are snake_case. A field that takes several values is plural: `tags`, `users`, `computers`.
- **Sizes and times** are strings: `"30d"`, `"12h"`, `"8GiB"`.

## Naming things

You can name anything by its name or its ID: `"computer":"my-site"` and `"computer":"7cd4a3ec-…"` are the same request. IDs never change, so use them in automation. Otherwise a rename could point a later request at something else.

- **A Computer's name** is unique across Heaven, since it becomes `NAME.heaven.dev`. It has 3 to 63 letters, digits and hyphens, and can't start or end with a hyphen. Case doesn't matter. Some names, such as `www`, `api`, `blog` and `staging`, are reserved.
- **A pool's name** is unique only in its account, so a pool shared with you can have the same name as one of yours. A name that matches two pools is refused, and the error lists each one's ID.

## Which account

You have a personal account and can belong to up to 10 organizations. A request about a Computer or pool acts in the account that owns it, so naming the Computer or pool is enough.

A request about an account itself, such as making a pool, billing, static addresses, integrations or members, takes `"organization": "NAME"`. Without it, the request acts in your personal account. Buying [capacity](https://heaven.dev/docs/pools#capacity), charges, billing details and account deletion act in your personal account only, and take no `organization`.

Reads without `organization` return everything you can reach, in every account, and each item names its account.

## Views

A `GET` of one Computer, of your pools or of your account returns everything about it that you can read. For a Computer, that's its access, domains, ports, mail and snapshots. Parts your key can't read are listed in `withheld`, and parts that couldn't be read at that moment in `unavailable`. The rest is still returned. To read one part instead, add `view`:

Request:

```sh
curl 'https://heaven.dev/v1/computer/?computer=my-site&view=snapshots' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

Each endpoint's reference lists its views. Each view is its own command, so a key can be allowed some views and not others.

## Responses

Success is HTTP 200 with the result in `data`:

200:

```json
{"version": 1, "data": {…}}
```

A refusal or failure has an `error` instead, and an HTTP status that matches the error's [kind](https://heaven.dev/docs/errors):

404:

```json
{
  "version": 1,
  "error": {
    "kind": "not_found",
    "message": "No Computer \"nope\" that you can access. Run `view` to list your Computers."
  }
}
```

- **New fields can appear** in version 1 responses. Ignore ones you don't know.
- **`null` means unknown**, never zero. A measurement nobody took is `null`, and an empty list is `[]`.
- **Times** are RFC 3339. Large counters, such as traffic, are decimal strings.
- **Text instead of JSON.** With `Accept: text/plain`, a command returns what `ssh heaven.dev COMMAND` prints, with the same HTTP status. A snapshot change then waits until it finishes, as it does over SSH.
- **`Heaven-Exit-Status`**, on every JSON or text response, is the exit status the command has over SSH. It's `0`, or `1` for a refusal or for a change where some targets failed. For `exec`, it's the command's own exit status.

## Changes return an operation

Heaven saves a change to a Computer, such as create, start, stop, rename or a snapshot, before it responds. The change finishes on the Computer's server shortly after. The response is an operation:

200:

```json
{
  "version": 1,
  "data": {
    "request_id": "f4515dc8-125c-45d4-9000-fcb344896108",
    "operation": {
      "id": "8540e6f2-9f39-4d39-89b5-eeac80d0ac97",
      "kind": "create",
      "computer_id": "0098166a-9908-43ab-967b-4111c45c3b33",
      "revision": 1,
      "state": "accepted"
    }
  }
}
```

`accepted` means saved, not finished. [Operations and retries](https://heaven.dev/docs/operations) shows how to follow it. Other changes, such as adding a domain or an SSH key, take effect at once. They return what they made, or `{"updated": true}`.
