# Account

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

Your SSH and API keys, billing, static addresses, defaults and invitations, and deleting your account.

Your SSH keys, API keys, invitations and defaults belong to you, whichever account you act in. Billing and static addresses belong to an account. To act in one of your organizations, add `"organization"`; its billing owner and admins manage its billing and addresses. [Capacity](https://heaven.dev/docs/pools#capacity), charges, billing details and account deletion act in your personal account only.

Read with `GET /v1/account/`. Change with `POST /v1/account/modify` and one `action`. Each section below is one read or action.

## Your account

### Read your account

`GET /v1/account/`

Returns your user and account IDs, and every part of your account you can read: keys, invitations, billing, addresses and defaults.

#### Query

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `account view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

200:

```json
{
  "version": 1,
  "data": {
    "user_id": "9e3fe81d-9eb7-4eca-b49d-043b4434de28",
    "account_id": "5e209a1c-a2bf-4dfd-867d-38eab3ae8cf9",
    "ssh_keys": {"keys": […]},
    "api_keys": {"api_keys": […]},
    "invitations": [],
    "billing": {
      "balance_micros": 9945205,
      "per_hour_micros": 54795,
      "card_saved": false,
      "entries": [
        {
          "at": "2026-11-02T13:13:31Z",
          "kind": "minimum",
          "amount_micros": -54795,
          "pool": "cap-4eced550aa534859"
        },
        {
          "at": "2026-11-02T13:13:31Z",
          "kind": "credit",
          "amount_micros": 10000000
        }
      ],
      "can_manage": true
    },
    "addresses": {"addresses": [], "limit": 2}
  }
}
```

### Change your email address

`POST /v1/account/modify` with `"action": "account email"`

Changes the address you sign in with and Heaven writes to. Without `code`, it mails a code to the new address. With the code, it makes the change and tells the old address.

#### Body

- `email` string *required*: The new address, such as ada@example.com.
- `code` string: The code Heaven mailed to the new address. Treated as a secret and never included in errors.
- `old_code` string: The code Heaven mailed to your current address. Treated as a secret and never included in errors.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "account email", "email": "ada@example.com"}'
```

### Set your name

`POST /v1/account/modify` with `"action": "account name"`

Sets the name people see beside your email address. `clear` removes it.

#### Body

- `name` string: Your name, as people should see it.
- `clear` boolean: Remove your name.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "account name", "name": "Ada Lovelace"}'
```

### List the commands a key can run

`GET /v1/account/?view=commands`

Lists every command an API key can name, with its endpoint and fields, and whether you can give it to a key.

Each command comes with its route, fields, flags and usage, and says whether a key with a [scope](https://heaven.dev/docs/authentication#scope) can run it.

#### Query

- `command` string: Read only this command, in full, such as `pool create`.
- `full` boolean: With false, list each command by its name, summary, endpoint and fields only. Defaults to true (MCP tools: false).

- Any API key can run it.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=commands' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

## SSH keys

An SSH key lets `ssh NAME@heaven.dev` reach your Computers and `ssh heaven.dev` run commands as you. Only the public key is sent; the private key never leaves your machine. API keys you create can't add SSH keys, so add your first key on the [dashboard](https://heaven.dev/dashboard/keys).

### List SSH keys

`GET /v1/account/?view=ssh-keys`

Lists your active SSH keys.

- An API key needs `ssh-key view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=ssh-keys' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

200:

```json
{
  "version": 1,
  "data": {
    "keys": [
      {
        "id": "6451b0b7-a069-452f-a433-36dac93ddb9f",
        "fingerprint": "SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU",
        "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA…",
        "label": "laptop"
      }
    ]
  }
}
```

### Add an SSH key

`POST /v1/account/modify` with `"action": "ssh-key add"`

Adds an SSH public key. You can limit it to the Computers with a tag, or to one Computer.

With `tag`, the key reaches only Computers that carry that tag. With `computer`, it reaches only that Computer, and you need ownership or root access on it. Either way, the key can't run commands.

#### Body

- `public_key` string *required*: The public key, as in ~/.ssh/id_ed25519.pub.
- `label` string: A label to recognize it by.
- `tag` string: Let the key reach only Computers with this tag.
- `computer` string: Let the key reach only this Computer.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{
    "action": "ssh-key add",
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… me@laptop",
    "label": "laptop"
  }'
```

200:

```json
{
  "version": 1,
  "data": {
    "id": "6451b0b7-a069-452f-a433-36dac93ddb9f",
    "fingerprint": "SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU",
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA…",
    "label": "laptop"
  }
}
```

### Make a site token

`POST /v1/account/modify` with `"action": "ssh-key create"`

Makes a token a program can use to open one Computer's private site. A new SSH key limited to that Computer signs it, and the token works until you remove that key.

#### Body

- `computer` string *required*: The Computer whose private site the token opens.
- `label` string: A name for its key in `ssh-key view`, such as deploy.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

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

### Rename an SSH key

`POST /v1/account/modify` with `"action": "ssh-key rename"`

Changes an SSH key's label.

#### Body

- `key` string *required*: The key: its ID or exact label.
- `label` string *required*: The new label.

- An API key needs `ssh-key rename` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "ssh-key rename", "key": "KEY", "label": "deploy"}'
```

### Remove an SSH key

`POST /v1/account/modify` with `"action": "ssh-key remove"`

Revokes an SSH key and every token signed with it.

#### Body

- `key` string *required*: The key's ID (see `ssh-key view`).

- An API key needs `ssh-key remove` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "ssh-key remove", "key": "KEY"}'
```

## API keys

### List API keys

`GET /v1/account/?view=api-keys`

Lists your API keys that still work, with their labels, expiry and last use. Their secrets are never shown.

Your sign-ins are listed with them, each with its label, commands, scope and expiry.

#### Query

- `all` boolean: Include finished and canceled ones.

- An API key needs `api-key view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=api-keys' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Create an API key

`POST /v1/account/modify` with `"action": "api-key create"`

Creates a key that can run only the commands it names. You can also limit it to some pools, Computers and tags. The response shows its token once.

See [what a key can run](https://heaven.dev/docs/authentication#permissions) and [what it can reach](https://heaven.dev/docs/authentication#scope).

#### Body

- `label` string: A label to recognize it by.

- `expires` string *required*: How long the key works, such as `30d` or `12h`, up to `365d`, or `never`.

- `commands` string[]: A command the key can run. Without any, the key gets the read-only set.

- `scope` object

  Limit the key to these pools, Computers and Computers with these tags, up to 64 of each.

  - `computers` string[]: Limit the key to this Computer.
  - `pools` string[]: Limit the key to this pool's Computers.
  - `tags` string[]: Limit the key to Computers with this tag.

- An API key needs `api-key create` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "api-key create", "label": "deploy", "expires": "30d", "commands": ["view", "restart"]}'
```

200:

```json
{
  "version": 1,
  "data": {
    "id": "51d8138f-4472-4ec4-b4f8-1ec1d2ba65a2",
    "label": "deploy",
    "cmds": ["view", "restart"],
    "created_at": "2026-11-01T23:18:35Z",
    "expires_at": "2026-12-01T23:18:35Z",
    "last_used_at": null,
    "revoked_at": null,
    "token": "heaven1.…"
  }
}
```

### Remove an API key

`POST /v1/account/modify` with `"action": "api-key remove"`

Revokes an API key at once.

It also ends a sign-in, given the sign-in's ID.

#### Body

- `key` string *required*: The key's ID (see `api-key view`).

- An API key needs `api-key remove` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "api-key remove", "key": "KEY"}'
```

### Edit an API key

`POST /v1/account/modify` with `"action": "api-key edit"`

Changes a key's label, commands, scope or expiry, and keeps its ID and secret. New commands or a new scope replace the old ones, `no_scope` removes the scope, and a new expiry counts from now.

#### Body

- `key` string *required*: The key's ID (see `api-key view`).

- `label` string: A label to recognize it by.

- `expires` string: The key's new expiry, counted from now, such as 30d or 12h (up to 365d), or never.

- `commands` string[]: A command the key can run, replacing its list.

- `no_scope` boolean: Remove the key's scope, so it reaches everything its commands allow.

- `scope` object

  Limit the key to these pools, Computers and Computers with these tags, up to 64 of each.

  - `computers` string[]: Limit the key to this Computer.
  - `pools` string[]: Limit the key to this pool's Computers.
  - `tags` string[]: Limit the key to Computers with this tag.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "api-key edit", "key": "KEY_ID", "expires": "never", "commands": ["view", "restart"]}'
```

### Rotate an API key

`POST /v1/account/modify` with `"action": "api-key rotate"`

Gives an API key a new secret, shown once, and keeps its ID, commands, scope and expiry. The old secret keeps working for `overlap`.

#### Body

- `key` string *required*: The key's ID (see `api-key view`).
- `overlap` string: How long the old secret keeps working: 0 to 7d (default 24h).

- An API key needs `api-key rotate` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "api-key rotate", "key": "KEY_ID", "overlap": "1h"}'
```

## Billing

Each account has one subscription for its monthly [capacity](https://heaven.dev/docs/pools#capacity). Hourly capacity, and egress above the allowance, are paid from the account's wallet. Card numbers never pass through Heaven. People enter them on a Stripe page, and these actions return that page's address as `url`.

### Read billing

`GET /v1/account/?view=billing`

Returns what needs attention, the next renewal, what each purchase costs, the wallet and how long it will last, automatic top-up, recent charges and this month's egress.

#### Query

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `billing view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=billing' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### List charges

`GET /v1/account/?view=charges`

Lists every top-up, credit and charge on your account, newest first, one page at a time.

#### Query

- `before` string: The `next` value from the previous page, or an RFC 3339 time, to read older entries.
- `limit` string: How many entries to return: 50 by default, up to 500.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `billing history` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=charges' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

200 With `limit=2`:

```json
{
  "version": 1,
  "data": {
    "entries": [
      {
        "id": "67320cf5-09e6-4f87-bc66-4ae3149b8f96",
        "at": "2026-11-02T13:13:31Z",
        "kind": "minimum",
        "amount_micros": -54795,
        "pool": "cap-4eced550aa534859",
        "period_start": "2026-11-02T13:13:31Z",
        "period_end": "2026-11-02T14:13:31Z"
      },
      {
        "id": "3322e98e-f3fc-407d-9d2c-681fe8960de6",
        "at": "2026-11-02T13:13:31Z",
        "kind": "credit",
        "amount_micros": 10000000
      }
    ]
  }
}
```

### List invoices

`GET /v1/account/?view=invoices`

Lists every invoice, for monthly plans, prorations and top-ups, newest first, each with its Stripe page.

#### Query

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `billing invoices` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=invoices' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Top up the wallet

`POST /v1/account/modify` with `"action": "billing top-up"`

Returns a Stripe page where you add $5 to $1,000 to your wallet, and get an invoice for it.

In an account's first 30 days, each top-up is at most $250. The first top-up saves the card and turns on automatic top-ups of $20, unless you send `no_auto_top_up`.

#### Body

- `amount` string: The amount in whole dollars, from 5 to 1000.
- `auto_top_up` string: With the first top-up, the amount of each automatic top-up, in whole dollars (default 20).
- `no_auto_top_up` boolean: Don't save the card for automatic top-ups.
- `invoice` boolean: Get a bank-transfer invoice instead of Stripe's card page. Only for accounts approved for it.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing top-up", "amount": "20"}'
```

200:

```json
{
  "version": 1,
  "data": {
    "url": "https://checkout.stripe.com/c/pay/…",
    "purpose": "Add money to your balance on Stripe's page ($5 or more); your card is saved for automatic top-ups of $20.00 when less than a day of use is left"
  }
}
```

### Charge your saved card

`POST /v1/account/modify` with `"action": "billing charge"`

Adds $5 to $1,000 to your wallet from your saved card, at once.

If the card needs you to confirm the payment, the request returns `payment_required` with Stripe's page in `url`. If the response is `unknown`, Heaven settles the charge with Stripe within minutes and never makes it twice. To find out what happened, send the same `Idempotency-Key` again, or [list your charges](https://heaven.dev/docs/account#billing-history).

#### Body

- `amount` string *required*: How much to add, whole dollars from 5 to 1000.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- A key whose commands allow it must also allow `billing top-up`.
- Retry it safely with an `Idempotency-Key` header.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  -H "Idempotency-Key: billing-charge-20" \
  --json '{"action": "billing charge", "amount": "20"}'
```

### Set automatic top-up

`POST /v1/account/modify` with `"action": "billing auto-top-up"`

Tops up the wallet from your saved card when less than a day of use is left, up to a monthly limit, or turns this off.

It tops up at most 5 times a day.

#### Body

- `amount` string: The amount in whole dollars, from 5 to 1000.
- `monthly_limit` string: The most automatic top-ups can add in a month, in whole dollars: $500 unless you set it, up to $5,000.
- `off` boolean: Turn it off.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- A key whose commands allow it must also allow `billing top-up`.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing auto-top-up", "amount": "20"}'
```

### Refund the wallet

`POST /v1/account/modify` with `"action": "billing refund"`

Refunds the wallet's unspent money from top-ups in the last 180 days to the cards it came from.

Heaven refunds the newest top-ups first. Promotional credit is never refunded. For money older than 180 days, contact support.

#### Body

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing refund"}'
```

### Pay an invoice

`POST /v1/account/modify` with `"action": "billing pay"`

Pays an open invoice with your card. Without an invoice, it pays the failed renewal.

If the card needs you to confirm the payment, the response is Stripe's page for doing so.

#### Body

- `invoice` string: An invoice's ID (see `billing invoices`).
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing pay"}'
```

### Redeem an offer

`POST /v1/account/modify` with `"action": "billing redeem"`

Redeems an offer code. Credit goes into the wallet at once, and a discount, trial or boost applies to your next purchase it fits.

Credit is spent before money you paid. It's never refunded, and it can expire. A discount, trial or boost waits for the account's next purchase it fits, and its time starts then.

The request is refused, with the reason, if the offer is unknown, paused, ended or fully redeemed, if this account already redeemed it, or if it isn't for this account.

#### Body

- `code` string *required*: The offer code.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `billing redeem` in its commands.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing redeem", "code": "WELCOME"}'
```

### Read or set the egress cap

`POST /v1/account/modify` with `"action": "billing egress-cap"`

Returns this month's egress and its spending cap, or sets, removes or resets the cap.

The response has this month's egress, the pooled allowance, projected use, the overage so far and what it cost, and the cap. While egress charging is switched off, it says what would be charged instead.

`default` sets the cap to what the account's plans cost for the month. At the cap, egress charges stop, and internet egress slows to 5 Mbit/s per pool until the month ends or you raise the cap. Only the account's owner, or an organization's billing owner and admins, can change it.

#### Body

- `amount` string: The amount in whole dollars, from 5 to 1000.
- `off` boolean: Turn it off.
- `default` boolean: Go back to the default cap, which is what your plans cost for the month.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing egress-cap"}'
```

### List billing contacts

`GET /v1/account/?view=billing-contacts`

Lists the extra addresses that get invoices and billing emails.

#### Query

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `billing contacts` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=billing-contacts' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Add a billing contact

`POST /v1/account/modify` with `"action": "billing contacts add"`

Also sends invoices and billing emails to another address, such as your accounting team's.

#### Body

- `email` string *required*: The address to add.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing contacts add", "email": "accounting@example.com"}'
```

### Remove a billing contact

`POST /v1/account/modify` with `"action": "billing contacts remove"`

Stops sending billing emails to an extra address.

#### Body

- `email` string *required*: The address to remove.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing contacts remove", "email": "ada@example.com"}'
```

### Set the billing time zone

`POST /v1/account/modify` with `"action": "billing time-zone"`

Sets a time zone for deadlines in billing emails, shown beside UTC.

#### Body

- `zone` string *required*: An IANA time zone, such as Europe/Berlin.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing time-zone", "zone": "Europe/Paris"}'
```

### Turn usage notices on or off

`POST /v1/account/modify` with `"action": "billing usage-emails"`

Turns usage notices, about egress nearing its allowance or cap, on or off.

Usage notices are sent when egress reaches 80% and 100% of the allowance, and 80% of the cap. Billing emails, about payments, the wallet and deletions, are always sent.

#### Body

- `on` boolean: Send usage notices again.
- `off` boolean: Stop usage notices. Billing emails are still sent.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing usage-emails"}'
```

### Set invoice details

`POST /v1/account/modify` with `"action": "billing details"`

Sets the email, company, tax ID and postal address on your invoices and receipts. With none of them, returns the current details.

#### Body

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- `email` string: The email invoices go to.

- `company` string: The company name on invoices.

- `tax_id` string: A tax ID as `TYPE:NUMBER`, such as `eu_vat:DE123456789`. Send `""` to remove it.

- `postal_address` object

  The postal address on invoices. `line1` and `country` are required.

  - `line1` string *required*: The address's first line.
  - `line2` string: The address's second line.
  - `city` string: The city.
  - `state` string: The state or region.
  - `postal_code` string: The postal code.
  - `country` string: The country, as a two-letter code (such as DE).

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing details"}'
```

### Start saving a card

`POST /v1/account/modify` with `"action": "billing card setup"`

Returns what Stripe's card fields need to take a card for your account with no payment: a setup, its client secret and Heaven's publishable key. The dashboard's Add card dialog uses it.

#### Body

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing card setup"}'
```

### Save a card

`POST /v1/account/modify` with `"action": "billing card save"`

Makes the card a setup saved your account's card, once Stripe has confirmed it: the one charges, automatic top-ups and monthly plans use.

#### Body

- `setup` string *required*: The setup `billing card setup` answered (seti_…), once Stripe has confirmed its card.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing card save", "setup": "seti_1Q2w3E4r5T6y7U8i"}'
```

### Open the billing portal

`POST /v1/account/modify` with `"action": "billing portal"`

Returns a link to Stripe's page for your card, billing address, tax IDs and invoices.

You change plans in Heaven, not in the portal.

#### Body

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "billing portal"}'
```

## Capacity

Capacity is a plan's memory, vCPUs and storage on one server. You divide it into [pools](https://heaven.dev/docs/pools). [How capacity works](https://heaven.dev/docs/pools#capacity) covers billing and limits.

### Buy capacity

`POST /v1/account/modify` with `"action": "capacity buy"`

Buys a plan's capacity on one server without making a pool. Pay monthly on your account's subscription, or by the hour from your wallet.

- **Monthly** (the default) adds a line to your account's subscription. Your first purchase returns a `checkout_url`: pay there by card within 30 minutes. Later purchases charge the prorated amount up to your renewal date, and return an `invoice_url` when the card needs you to confirm.
- **Hourly** is paid from your wallet by the minute, for at least an hour. The wallet must cover the first hour.

#### Body

- `plan` string: The plan's number, 1 to 6 (see `plan view`).
- `monthly` boolean: Pay monthly, on your account's subscription (the default).
- `hourly` boolean: Pay by the minute from your wallet, for at least an hour.
- `offer` string: An offer's code or ID.
- `dry_run` boolean: Change nothing, and show what it would do and charge.
- `server` string: The server to buy on. Defaults to the one with the most room.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- Retry it safely with an `Idempotency-Key` header.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  -H "Idempotency-Key: capacity-buy-2" \
  --json '{"action": "capacity buy", "plan": "2", "hourly": true}'
```

200:

```json
{
  "version": 1,
  "data": {
    "id": "cap-5e809142ece64cc3",
    "server": "h-ff6cf959-8d63-463c-8bd8-ef48c9dedc0b",
    "plan": 2,
    "kind": "hourly",
    "charged_micros": 109589,
    "balance_micros": 9835616
  }
}
```

### Change a purchase's plan

`POST /v1/account/modify` with `"action": "capacity resize"`

Moves a purchase to another plan. A monthly upgrade applies once the prorated difference is paid, and a downgrade at the end of the period. An hourly purchase changes at once.

`dry_run` returns Stripe's preview of the prorated difference and changes nothing.

#### Body

- `capacity` string *required*: The purchase's ID (see `capacity view`).
- `plan` string: The plan's number, 1 to 6 (see `plan view`).
- `dry_run` boolean: Change nothing, and show what it would do and charge.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "capacity resize", "capacity": "CAPACITY", "plan": "3"}'
```

### Switch monthly or hourly

`POST /v1/account/modify` with `"action": "capacity switch"`

Switches a purchase to monthly as soon as the first month is paid, or to hourly at the end of the paid period.

Until the first month is paid, you pay the hourly rate. No hour is paid twice.

#### Body

- `capacity` string *required*: The purchase's ID (see `capacity view`).
- `monthly` boolean: Switch to monthly once the first month is paid.
- `hourly` boolean: Switch to hourly at the end of the paid period.
- `dry_run` boolean: Change nothing, and show what it would do and charge.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "capacity switch", "capacity": "CAPACITY", "hourly": true}'
```

### Cancel a scheduled change

`POST /v1/account/modify` with `"action": "capacity cancel-change"`

Cancels a purchase's scheduled downgrade, release or switch to hourly. The purchase keeps its plan and renews as before.

#### Body

- `capacity` string *required*: The purchase's ID (see `capacity view`).
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "capacity cancel-change", "capacity": "CAPACITY"}'
```

### Release capacity

`POST /v1/account/modify` with `"action": "capacity release"`

Ends a purchase. Hourly capacity ends at once, and a monthly plan at the end of the period paid for.

If the purchase is already released, the response has its `released_at`.

- **Hourly:** you pay for at least its first hour.
- **Monthly:** it ends at `releases_at`, and you can use it until then. `capacity cancel-change` undoes the release. If you release your first monthly purchase within 48 hours, it ends at once and is refunded. This applies once.

You can't release capacity while pools on its server still need its memory. You also can't release it while your pools there, stopped ones included, store more than 120% of the storage that would be left. The error names the pools and what each stores.

#### Body

- `capacity` string *required*: The purchase's ID (see `capacity view`).
- `yes` boolean: Confirm. Without it nothing changes, and the response says what would happen.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "capacity release", "capacity": "CAPACITY"}'
```

## Static addresses

> **Not offered yet.** Static addresses are built but not offered yet. Until they are, the `ip` actions return `unavailable`, and they aren't listed in `help`, the MCP tools or `?view=commands`. These sections describe how they will work.

A static IPv4 address belongs to your account, whether it's attached or not. You can attach it to one of three things:

- **A Computer** (`computer`): every TCP and UDP port reaches the Computer at this address, and its outgoing connections leave from it.
- **A pool** (`pool`): the pool's Computers that have no address of their own send from it, and the pool's public ports are on it. No other port reaches them.
- **Your account on one server** (`account: true`, plus `server` when your pools are on several servers): the same, for your pools on that server that have no address.

A Computer uses the first address it has, in this order: its own, its pool's, your account's on its server, then the server's shared address. Its public ports follow whichever address is in use and keep their numbers.

When a request names several addresses and one is refused, none of them changes. Each address counts against the [rate limit](https://heaven.dev/docs/errors#rate-limits). An account can hold 2 addresses unless Heaven raises its limit.

### List static addresses

`GET /v1/account/?view=addresses`

Lists your account's static IPv4 addresses, what each is attached to, and your limit.

#### Query

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `ip view` in its commands.
- Not available yet: it returns `unavailable` until static addresses are offered.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=addresses' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Buy static addresses

`POST /v1/account/modify` with `"action": "ip buy"`

Buys static IPv4 addresses for your account, or takes back one you released in the last 7 days.

Heaven buys all `count` addresses or none.

#### Body

- `region` string: Where the address is routed (default the only one).
- `count` string: How many to buy (default 1).
- `address` string: An address you released in the last 7 days, to take back.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- Retry it safely with an `Idempotency-Key` header.
- Not available yet: it returns `unavailable` until static addresses are offered.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  -H "Idempotency-Key: ip-buy-1" \
  --json '{"action": "ip buy"}'
```

200:

```json
{
  "version": 1,
  "data": {
    "bought": [
      {
        "address": "203.0.113.24",
        "region": "us-east",
        "bought_at": "2026-11-01T23:30:00Z"
      }
    ]
  }
}
```

### Attach static addresses

`POST /v1/account/modify` with `"action": "ip attach"`

Attaches a static address to a Computer, a pool, or your account on one server.

Attaching moves the address off anything it was attached to. To attach several at once, use `attachments`.

#### Body

- `address` string: The address to attach.

- `computer` string: The Computer to attach it to.

- `pool` string: Attach it to this pool instead.

- `account` boolean: Attach it to your account on one server instead.

- `server` string: With `account`: the server, when your pools are on several.

- `attachments` object[]

  Each address and what it attaches to: {address, computer}, {address, pool} or {address, account: true}.

  - `account` boolean: true attaches it to your account on one server.
  - `address` string *required*: The address to attach.
  - `computer` string: The Computer to attach it to.
  - `pool` string: The pool to attach it to.
  - `server` string: With account, the server, when your pools are on several servers.

- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- Also on `/v1/pool/modify` and `/v1/computer/modify`, for one pool or Computer.
- Not available yet: it returns `unavailable` until static addresses are offered.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "ip attach", "address": "203.0.113.24", "pool": "web"}'
```

### Detach static addresses

`POST /v1/account/modify` with `"action": "ip detach"`

Detaches static addresses from their Computer, pool or server. Your account keeps them.

With `computer` or `pool`, each address must be attached there, or the request is refused.

#### Body

- `addresses` string[] *required*: Static IPv4 addresses of your account.
- `computer` string: The Computer they must be attached to.
- `pool` string: The pool they must be attached to.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `ip detach` in its commands.
- Also on `/v1/pool/modify` and `/v1/computer/modify`, for one pool or Computer.
- Not available yet: it returns `unavailable` until static addresses are offered.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "ip detach", "addresses": ["203.0.113.7"]}'
```

### Release static addresses

`POST /v1/account/modify` with `"action": "ip release"`

Gives static addresses back to Heaven.

For 7 days no other account can get them, and you can take each one back with `ip buy` and its `address`.

#### Body

- `addresses` string[] *required*: Static IPv4 addresses of your account.
- `yes` boolean: Confirm. Without it nothing changes, and the response says what would happen.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- API keys you create can't run it. Use a sign-in key or SSH.
- Not available yet: it returns `unavailable` until static addresses are offered.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "ip release", "addresses": ["203.0.113.7"]}'
```

## Defaults

### Read your default setup script

`GET /v1/account/?view=defaults`

Returns the setup script a new Computer runs when it's created without one.

- An API key needs `defaults view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=defaults' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Set your default setup script

`POST /v1/account/modify` with `"action": "defaults set"`

Sets the setup script a new Computer runs when it's created without one.

The script can be up to 10 KiB. Heaven stores it encrypted.

#### Body

- `setup_script` string *required*: The script. Treated as a secret and never included in errors.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "defaults set", "setup_script": "SETUP_SCRIPT"}'
```

### Clear your default setup script

`POST /v1/account/modify` with `"action": "defaults clear"`

Removes your default setup script.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "defaults clear"}'
```

## Sign-in

### Read your sign-in lifetime

`GET /v1/account/?view=sign-in`

Returns how long your sign-ins last, on this website and on private websites.

- An API key needs `sign-in view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=sign-in' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Set your sign-in lifetime

`POST /v1/account/modify` with `"action": "sign-in lifetime"`

Sets how long your sign-ins last: 7d, 14d, 28d, 90d (the default) or never.

#### Body

- `lifetime` string *required*: How long sign-ins last: 7d, 14d, 28d, 90d or never.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "sign-in lifetime", "lifetime": "28d"}'
```

### Sign out everywhere

`POST /v1/account/modify` with `"action": "sign-in end-all"`

Ends every sign-in to this website, in every browser, and to private websites. SSH and API keys stay.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "sign-in end-all"}'
```

## Invitations

### List your invitations

`GET /v1/account/?view=invitations`

Lists invitations to you from organizations and teams.

- An API key needs `invitation view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/account/?view=invitations' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```

### Accept an invitation

`POST /v1/account/modify` with `"action": "invitation accept"`

Joins the organization or team that invited you.

#### Body

- `invitation` string *required*: The invitation's ID, the organization's name, or `ORGANIZATION@TEAM` for a team.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "invitation accept", "invitation": "acme"}'
```

### Decline an invitation

`POST /v1/account/modify` with `"action": "invitation decline"`

Declines an invitation to an organization or team.

#### Body

- `invitation` string *required*: The invitation: its ID, the organization's name, or ORGANIZATION@TEAM.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "invitation decline", "invitation": "INVITATION"}'
```

## Account deletion

### Delete your account

`POST /v1/account/delete`

Deletes your account in two steps. The first request emails you a code and returns what will be deleted. The second, with the code and `yes`, deletes it.

The code is 8 digits. It lasts 15 minutes or 5 tries, and Heaven sends at most one a minute.

The second step leaves your organizations, deletes your Computers, pools and capacity, and erases your identity. It returns an [operation group](https://heaven.dev/docs/operations#groups). From then on your account is suspended: every other request is refused until deletion finishes, except reading that operation group.

The first step's `balance_micros` is your personal balance. Deleting your account forfeits it, since balances aren't refunded.

If you're the last member of an organization, it closes. If you're an organization's billing owner, your cards stop paying for it, and Heaven offers billing ownership to its first admin, or to its first member if it has no admins. Nobody becomes billing owner without accepting. Until someone does:

- the organization runs on its balance;
- its admins get its billing emails, or all its members if it has no admins;
- paying by card and buying monthly capacity are refused, until an admin offers billing ownership and a member accepts it.

#### Body

- `yes` boolean: Confirm. Without it nothing changes, and the response says what would happen.

- `transfer_computers_to` object

  Who in each organization gets your Computers there. Without it, each organization keeps them.

  - `user` string *required*: A member of your organizations who gets your Computers there.

- `code` string: The code the first request mailed you. Treated as a secret and never included in errors.

- API keys you create can't run it. Use a sign-in key or SSH.

Request:

```sh
curl https://heaven.dev/v1/account/delete \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{}'
```

200 The first step:

```json
{
  "version": 1,
  "data": {
    "code_sent_to": "you@example.com",
    "code_expires_at": "2026-11-02T13:28:31Z",
    "organizations": [
      {
        "id": "b429e8c1-7328-4c73-a919-292bc9ed7a08",
        "name": "acme",
        "computers": [],
        "computers_to": "",
        "billing_owner": true,
        "closes": true
      }
    ],
    "computers": ["my-site"],
    "pools": ["web"],
    "capacity": ["cap-4eced550aa534859"],
    "addresses": [],
    "balance_micros": 0
  }
}
```
