> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usesink.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrations, billing, and distribution

> Import provider variables, manage subscriptions, and distribute the CLI.

## Provider imports

Sink reads environment variables out of Railway, Vercel and Render. The provider token is used for the request that needs it and is never stored.

<Info>
  The whole import route group is gated on a paid entitlement — an unentitled call answers `402`.
</Info>

### Discover what a token can reach

```http theme={null}
POST /integrations/providers/{provider}/projects
```

`provider` is `railway`, `vercel` or `render`.

```json theme={null}
{ "token": "provider_token" }
```

The response lists projects with their environments and services, in the provider's own vocabulary.

### Preview and apply

Base path: `/integrations/{workspace_id}/{team_id}/{project_id}/{environment_id}`

| Method | Path       | Purpose                                                         |
| ------ | ---------- | --------------------------------------------------------------- |
| `POST` | `/preview` | Compute the create / update / skip plan. Writes nothing.        |
| `POST` | `/`        | Apply it. Returns `created`, `updated`, `unchanged`, `skipped`. |

```json theme={null}
{
  "provider": "vercel",
  "token": "provider_token",
  "source": { "project_id": "prj_abc", "target": "production" },
  "reveal": false,
  "mode": "skip"
}
```

`reveal` controls whether preview values come back in clear text or masked. `mode` — `skip` or `overwrite` — applies only to the apply call; `overwrite` records the provider's value as a **new version** rather than replacing history.

Source shapes per provider, and the CLI equivalent of all of this, are in [Import from a provider](/guides/importing).

## Plans and payments

| Method | Path                                 | Purpose                                                               |
| ------ | ------------------------------------ | --------------------------------------------------------------------- |
| `GET`  | `/plans/`                            | List the available plans with their prices and limits.                |
| `GET`  | `/plans/{workspace_id}/subscription` | The plan, limits and current usage for one workspace.                 |
| `GET`  | `/payments/subscription`             | The signed-in user's own subscription.                                |
| `POST` | `/payments/checkout`                 | `{ "plan_id": "…" }` — start a checkout and get a URL.                |
| `POST` | `/payments/portal`                   | A billing-portal URL for the current subscriber.                      |
| `POST` | `/payments/subscription/change`      | `{ "plan_id": "…" }` — move between plans.                            |
| `POST` | `/payments/subscription/cancel`      | Cancel; body accepts `cancel_at_period_end` and an optional `reason`. |
| `POST` | `/payments/webhook`                  | Provider webhook. Server-to-server, signature-verified.               |

Subscriptions belong to a user; limits are enforced per workspace against the subscription of the user who owns it. [Plans and limits](/guides/plans) explains the counting rules and what a `402` means.

<Note>
  Creating, editing and delisting plans (`POST`, `PATCH`, `DELETE` on `/plans/`) is administrative and requires a separate operator token, not an ordinary API key.
</Note>

## CLI distribution

These three are unauthenticated by design — you cannot log in before you have a client.

| Method | Path                 | Purpose                                                 |
| ------ | -------------------- | ------------------------------------------------------- |
| `GET`  | `/install.sh`        | The installer, with this deployment's address baked in. |
| `GET`  | `/cli/manifest.json` | Current CLI version and the wheel's checksum.           |
| `GET`  | `/cli/{filename}`    | Download a published wheel.                             |

Because the script is served by the deployment it installs a client for, the version always matches the server. The installer verifies the wheel against the manifest before linking `sink` into `~/.local/bin`. A deployment with no published release answers `503` rather than pretending otherwise.

## Health

| Method | Path           | Purpose                                      |
| ------ | -------------- | -------------------------------------------- |
| `GET`  | `/health/live` | The process is up. Nothing else is claimed.  |
| `GET`  | `/health`      | Probe every dependency and report readiness. |

`/health` answers `200` with `"status": "ok"`, `200` with `"degraded"` when something non-essential is down, and `503` with `"down"` when a critical dependency — the database or the master key — is gone. Degraded is deliberately a `200`: the node still serves the paths that matter, so a monitor watching the body sees the problem without a load balancer evicting a node that works.

```json theme={null}
{
  "status": "ok",
  "service": "sink-api",
  "environment": "production",
  "checks": {
    "postgres": { "status": "ok", "latency_ms": 12.4 },
    "redis":    { "status": "ok", "latency_ms": 1.8 }
  }
}
```
