# Integrations

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

Integrations let Computers call an outside service without its secret ever being on them.

Give Heaven a service's credential once. Attached Computers then call the service through Heaven's proxy, which adds the credential to each request, so the secret is never on the Computer. Inside a Computer, an integration named `payments` is at `http://payments.int.heaven.dev` (or `https://`):

Inside the Computer:

```sh
curl http://payments.int.heaven.dev/v1/items
# reaches https://api.example.com/v1/items, with the stored credential
```

| Term | Means |
| --- | --- |
| `kind` | `http-proxy` for an HTTPS API, `registry` for a private container registry, `github` for GitHub |
| `target` | The service's HTTPS origin, such as `https://api.example.com` (not for GitHub) |
| `attachments` | Which Computers can use it: `computer:NAME`, `pool:POOL` (the Computers in it, including new ones), `tag:TAG` or `auto:all` |

The account's owner, or an organization's admins, change integrations. Other members see them with secrets masked.

Adding a tag that a `tag:` attachment selects gives a Computer the credential. So only the owner or admins can add such a tag to a Computer, signed in or over SSH. An API key is refused (`denied`). Anyone with root on an attached Computer can use the integration, so attach it only where that's acceptable.

Every account starts with `self`, which returns a Computer's own metadata at `https://self.int.heaven.dev/`.

Read with `GET /v1/integration/`. Change one with `POST /v1/integration/modify`, naming the `integration` and an `action`. The action is the command name without its `integration` prefix.

## Managing integrations

### List integrations

`GET /v1/integration/`

Lists your account's integrations, with their credentials masked.

Stored credentials show as `***`. A GitHub integration that needs to be connected again shows `reconnect`.

#### Query

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

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

Request:

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

200:

```json
{
  "version": 1,
  "data": [
    {
      "id": "aaf026c7-c320-4e46-87fe-e054afa52f93",
      "name": "self",
      "type": "self",
      "attachments": ["auto:all"]
    },
    {
      "id": "0fa26014-a995-4109-80f0-db2136c9303a",
      "name": "payments",
      "type": "http-proxy",
      "target": "https://api.example.com",
      "strip_prefix": "",
      "comment": "",
      "attachments": ["tag:web"],
      "headers": { "Authorization": "Bearer ***" }
    }
  ]
}
```

### Create an integration

`POST /v1/integration/create`

Stores an HTTPS service's credential. Attached Computers use it through Heaven's proxy without ever holding it. Kind `github` connects your GitHub account with a device code instead.

#### Body

- `kind` string *required*: `http-proxy` or `registry`. For GitHub, see [GitHub](https://heaven.dev/docs/integrations#github).
- `name` string: The integration's name: 1 to 63 lowercase letters, digits and hyphens, unique in the account. It becomes `NAME.int.heaven.dev`.
- `target` string: The service's HTTPS origin. It can include a port, but no path.
- `headers` string[]: Other headers to add, as `Name:value`, up to 16.
- `bearer` string: A token sent as `Authorization: Bearer …`.
- `basic_auth` string: `USER:PASSWORD`, sent as basic authentication.
- `strip_prefix` string: A path prefix to remove before forwarding, such as `/api/v3`.
- `attachments` string[]: What uses it: computer:NAME, pool:POOL, tag:TAG or auto:all.
- `comment` string: A note, shown to Computers in their metadata.
- `peer` boolean: The target is another of your Computers, `https://NAME.heaven.dev`, on port 443 or 3000 to 9999. You need ownership or root access on it. Heaven vouches for each request: the target receives `X-Heaven-Source-Vm` with the caller's name, which callers can't forge. The integration keeps working when the target is renamed. Once the target is deleted, `view` shows `target_deleted`.
- `no_auth` boolean: Store no credential, and forward requests as they are. Can't be used with `peer`.
- `read_only` boolean: For GitHub integrations only. With true, the integration's writes are refused.
- `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/integration/create \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{
    "kind": "http-proxy",
    "name": "payments",
    "target": "https://api.example.com",
    "bearer": "sk_live_…",
    "attachments": ["tag:web"]
  }'
```

200:

```json
{"version": 1, "data": {"id": "0fa26014-a995-4109-80f0-db2136c9303a"}}
```

### Change an integration

`POST /v1/integration/modify` with `"action": "edit"`

Changes an integration's target, credential or settings. A credential is replaced only when given.

Changing `target` drops the stored credential, so send it again, or send `no_auth`. A GitHub integration takes only `read_only`, `reconnect` and `comment`.

#### Body

- `integration` string *required*: An integration's name.
- `target` string: The service's HTTPS address.
- `headers` string[]: A header the service needs, NAME: VALUE. Treated as a secret and never included in errors.
- `bearer` string: The service's bearer token. Treated as a secret and never included in errors.
- `basic_auth` string: The service's user:password. Treated as a secret and never included in errors.
- `strip_prefix` string: A path prefix to remove before calling the service.
- `attachments` string[]: Also attach it to computer:NAME, pool:POOL, tag:TAG or auto:all. Its other attachments stay: `integration detach` removes one.
- `comment` string: A comment on it.
- `peer` boolean: Make it a peer integration. `target` is a Computer's website (https://NAME.DOMAIN), which attached Computers call as themselves. Heaven keeps the key that signs their calls.
- `no_auth` boolean: The service needs no credential. Computers reach it through Heaven's proxy with none added, and edit clears the stored one.
- `read_only` boolean: For GitHub integrations only. With true, the integration's writes are refused.
- `reconnect` boolean: Start over with a new device code.
- `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/integration/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "edit", "integration": "INTEGRATION"}'
```

### Attach an integration

`POST /v1/integration/modify` with `"action": "attach"`

Lets a Computer, the Computers with a tag, or every Computer use an integration.

#### Body

- `integration` string *required*: An integration's name.
- `attachment` string *required*: What can use it: computer:NAME, pool:POOL, tag:TAG or auto:all.
- `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/integration/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "attach", "integration": "payments", "attachment": "computer:my-site"}'
```

### Detach an integration

`POST /v1/integration/modify` with `"action": "detach"`

Takes an integration away from a Computer, a tag or every Computer.

#### Body

- `integration` string *required*: An integration's name.
- `attachment` string *required*: What to detach it from: computer:NAME, pool:POOL, tag:TAG or auto:all.
- `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/integration/modify \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"action": "detach", "integration": "INTEGRATION", "attachment": "ATTACHMENT"}'
```

### Delete an integration

`POST /v1/integration/delete`

Deletes an integration and its stored credential. Computers can no longer use it.

For GitHub, this forgets the token. It doesn't uninstall Heaven's app on GitHub.

#### Body

- `integration` string *required*: An integration's name.
- `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/integration/delete \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"integration": "INTEGRATION"}'
```

## GitHub

Connect your own GitHub account, and `git clone` and `gh` work on attached Computers with no token copied there. Send `POST /v1/integration/create` with `"kind": "github"`. The integration acts as you on GitHub: it can do what you can, in the repositories you choose, and no more.

Any member can connect their own GitHub account and attach it to Computers they own. Only the account's owner or an organization's admins can attach one with `pool:`, `tag:` or `auto:all`, or to other members' Computers.

1. ### Ask for a code

   Send `{"kind":"github","name":"github-me"}`. The response has a GitHub device code and two links, valid for an hour. One link authorizes Heaven, and the other picks the repositories it can reach.

2. ### Enter the code

   Enter it at `https://github.com/login/device`, then open the links.

3. ### Send the same request again

   Heaven waits up to 20 seconds for GitHub, then connects. If you send it too early, the response says so and keeps the code.

Request:

```sh
curl https://heaven.dev/v1/integration/create \
  -H "Authorization: Bearer $HEAVEN_API_KEY" \
  --json '{"kind": "github", "name": "github-me", "attachments": ["computer:my-site"]}'
```

On a Computer, `git clone https://github.int.heaven.dev/OWNER/REPO` works. So does `gh`, with `GH_HOST=github.int.heaven.dev` and any `GH_ENTERPRISE_TOKEN` value, which Heaven replaces with your credential. `github.int` uses the attached GitHub integration that reaches the repository's owner. With `read_only: true`, every write is refused. To create a Computer with a repository already cloned, send `github: {"repo": "OWNER/REPO"}` to [create](https://heaven.dev/docs/computers#create).

Then, on the Computer:

```sh
git clone https://github.int.heaven.dev/acme/website
GH_HOST=github.int.heaven.dev GH_ENTERPRISE_TOKEN=x gh pr list
```

When GitHub access is revoked, or after six months without use, the list shows `reconnect`. Send `edit` with `reconnect: true` to get a new code. The attachments stay.

### List a GitHub integration's repositories

`GET /v1/integration/?view=repos`

Lists the repositories a GitHub integration reaches.

#### Query

- `integration` string *required*: An integration's name.
- `organization` string: Act in this organization (its name or ID) instead of your personal account.

- An API key needs `integration repo view` in its commands.

Request:

```sh
curl 'https://heaven.dev/v1/integration/?integration=github-me&view=repos' \
  -H "Authorization: Bearer $HEAVEN_API_KEY"
```
