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

# Heroku

> Connect Heroku to CloudThinker for app and dyno inventory, log triage, add-on and pipeline review, and approval-gated platform controls

Connect your Heroku account to enable CloudThinker agents to inventory apps and dynos, read app logs, review add-ons and their plans, and inspect teams, private spaces, and pipeline stages — plus approval-gated changes like restarting dynos, scaling, and promoting a pipeline stage.

Heroku authenticates with an **API token**. The token carries the same access as the Heroku user who created it, so that user's team and app membership defines the agent's reach.

## Prerequisites

* A **Heroku account** with access to the apps, teams, and pipelines you want to investigate.
* The Heroku CLI installed, to create the API token.

There is no way to scope a Heroku token to a subset of apps. Least privilege comes from the account you create the token with, not from the token itself — see [Required permissions](#required-permissions).

## Setup

<Steps>
  <Step title="Create an API token">
    Run this in the Heroku CLI, signed in as the account CloudThinker should use:

    ```bash theme={null}
    heroku authorizations:create -d cloudthinker
    ```

    Copy the value printed as `Token` when the command prints it — it begins with `HRKU-`. The token is created with `global` scope and does not expire unless you set `--expires-in <seconds>`; use `heroku authorizations:revoke <id>` to invalidate it later.

    The Heroku Dashboard also exposes an account-level **API Key** under **Account Settings**, but Heroku revokes that key whenever your account password changes, so prefer the CLI authorization. If your account signs in through SSO, Heroku will not let it create a non-expiring token; Heroku's own guidance is to keep a separate non-SSO user for integration tokens.
  </Step>

  <Step title="Add the connection in CloudThinker">
    Navigate to **Connections → Heroku** and enter:

    * **API token**: the token you just created

    Click **Connect**. CloudThinker verifies the token against Heroku and shows a **Connected** status.
  </Step>
</Steps>

## Connection details

| Field | Description | Example |
| - | - | - |
| **API token** | Heroku API token for the account whose apps, teams, and pipelines CloudThinker should reach | `HRKU-...` |

## Required permissions

Create the token from a Heroku account that belongs to only the teams CloudThinker should reach, then give that account the smallest app role that covers what you want the agent to do.

| Heroku app role | What CloudThinker can do with it |
| - | - |
| **View** | App, dyno, add-on, team, private space, and pipeline inventory |
| **Operate** | Everything above, plus reading app logs, restarting dynos, maintenance mode, scaling, and provisioning paid add-ons |
| **Manage** | Not required by this connection |

<Note>
  Reading app logs requires **Operate**. A **View**-only account connects successfully and can list apps, but every log request fails.
</Note>

Use the `global` token scope. Heroku's narrower scopes — `read`, `write`, `read-protected`, and `write-protected` — all exclude account information, and Heroku cannot resolve the token's own account without it, so app and pipeline lookups fail. Create the token from a dedicated Heroku user rather than an account owner, keep that user out of teams the agent does not need, and rotate the token on your normal schedule.

## Agent capabilities

Once connected, agents have read access to your Heroku apps, dynos, add-ons, teams, and pipelines.

| Capability | Description |
| - | - |
| **Apps** | List apps and inspect a single app's region, stack, and current release state |
| **Logs** | Read recent app logs for error and crash triage |
| **Dynos** | List the dyno formation and the state of each running process |
| **Add-ons** | Inventory the add-ons attached to an app and browse available add-on services and plans |
| **Teams & Private Spaces** | List the teams and private spaces the account can reach |
| **Pipelines** | List pipelines and inspect their stages and the apps in each |
| **Changes** | Restart dynos, toggle maintenance mode, scale, create an add-on or pipeline, and promote a pipeline stage — **requires approval** |

Every Heroku operation that is not a read is approval-gated: CloudThinker states the effect and the exact inputs, then waits for your confirmation. Approving one change is not approval for the next one, or for the same change on a different app.

### Verify the connection

```text theme={null}
Check the Heroku connection and list my apps with their dyno formation
```

### Example prompts

```text theme={null}
My Heroku apps with their stack, region, and current dyno formation as a table
A fix for my Heroku app that is throwing errors, based on its recent logs
Which add-on plans we are paying for across my Heroku apps
```

For accounts with many apps, name the app or the pipeline in your prompt so the agent returns focused results.

## Write access

Restarts and maintenance mode are reversible in one step: a restart replaces dynos with the same formation, and maintenance mode is a switch the paired action clears.

<Warning>
  Scaling, add-on creation, and pipeline promotion are not free or not reversible in one step. Scaling and creating an add-on both change what Heroku bills you, and promoting a pipeline stage is a production release that no single call undoes. Read the inputs before you approve.
</Warning>

Database operations are outside this connection entirely. No agent tool reads Heroku Postgres credentials, runs SQL against your databases, or reads config vars. If you need query access to a Heroku Postgres database, add a [PostgreSQL connection](/guide/connections/postgresql) with its own credentials.

## Troubleshooting

<Accordion title="401 Unauthorized">
  The token is missing, expired, or revoked. Create a fresh authorization with `heroku authorizations:create` and reconnect. If you used the Dashboard API Key, check whether the account password changed — Heroku revokes that key when it does.
</Accordion>

<Accordion title="403 Forbidden on an app or team">
  The token's account is not a member of that app or team, or its app role is too low. Add the account to the team, or raise its app role to **Operate** for logs and dyno actions.
</Accordion>

<Accordion title="404 Couldn't find that user">
  The token cannot read its own account, so Heroku cannot resolve which apps and pipelines it owns. This is what a narrow token scope looks like. Create a new authorization with the default `global` scope and reconnect.
</Accordion>

<Accordion title="404 for a named app or pipeline">
  The name is wrong, or the token's account cannot see that resource. Ask the agent to list apps or pipelines first and use a name from that list.
</Accordion>

<Accordion title="429 Too Many Requests">
  Heroku allows 4,500 API requests per hour per account and refills the pool at roughly 75 per minute. Wait for the pool to refill, and scope requests to a single app so the agent makes fewer calls per run.
</Accordion>

<Accordion title="A change was requested but never ran">
  Writes need explicit approval in the same turn. Approve the action when prompted; a rejected call is final and the agent will not retry it.
</Accordion>

<Accordion title="No private spaces are listed">
  Private Spaces are available only to verified Heroku Teams and to Heroku Enterprise. An account without them has none to list, so an empty result here is not a fault in the connection.
</Accordion>

## Security

* **Least privilege** — grant only the permissions the agents need for your use case; start read-only and widen later.
* **Read-only by default** — use read-only credentials unless you want agents to make changes through this connection.
* **Rotate credentials** — rotate keys and tokens on your normal schedule; CloudThinker picks up the new value when you update the connection.
* **Revoke on offboarding** — remove the credential at the provider when you delete a connection or a teammate leaves.

- **Use a dedicated account** — a Heroku token inherits everything its user can reach and cannot be narrowed to specific apps, so choose the account carefully, pass `--expires-in` to plan rotation, and revoke with `heroku authorizations:revoke <id>` when you are done.
- **Treat logs as sensitive** — an app can print secrets into its own log output, so log triage can surface values you did not intend to share.

## Related

<CardGroup cols={2}>
  <Card title="Vercel Connection" icon="https://mintcdn.com/cloudthinker/R1-llSMEloTP_DJf/images/icons/vercel.svg?fit=max&auto=format&n=R1-llSMEloTP_DJf&q=85&s=84c091b1a241ec5c1eaf822e2f155691" href="/guide/connections/vercel" width="24" height="24" data-path="images/icons/vercel.svg">
    Similar setup for Vercel projects and deployments
  </Card>

  <Card title="PostgreSQL Connection" icon="https://mintcdn.com/cloudthinker/aLd-ttc-SCW-aFky/images/icons/postgresql.svg?fit=max&auto=format&n=aLd-ttc-SCW-aFky&q=85&s=8bb2ac033d0a2ccbef51154a76e1e819" href="/guide/connections/postgresql" width="24" height="24" data-path="images/icons/postgresql.svg">
    Query access to a Heroku Postgres database
  </Card>
</CardGroup>
