A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Heroku API is how an app or AI agent works with a Heroku account: creating and updating apps, scaling and restarting the dynos that run them, deploying releases and rolling them back, and provisioning add-ons like databases. Access is granted through a token sent as a Bearer credential and an OAuth scope that decides how far it reaches, where reading config vars needs a protected scope because they hold runtime secrets. The Platform API is selected by a version header, and Heroku can also push events to a webhook when something happens on an app.
How an app or AI agent connects to Heroku determines what it can reach. There is a route for making calls and a route for receiving events, each governed by the token behind it and the OAuth scope that token carries.
The Platform API answers at https://api.heroku.com and returns JSON. Every request sends the header Accept: application/vnd.heroku+json; version=3 to select the API version, and most resources are addressed by either a UUID or a human-friendly name.
Heroku posts an event to a registered receiver URL when something happens on an app, such as a release or a dyno starting. The webhooks API uses the header Accept: application/vnd.heroku+json; version=3.webhooks, and each delivery is retried for up to 72 hours if the receiver does not accept it.
A personal API token is sent in the Authorization header as a Bearer credential. It carries the account's full access and suits personal scripts and server-side calls. A token can be generated with the CLI or rotated from the account dashboard.
OAuth lets a third-party service request scoped access on behalf of a Heroku user through the authorization-code flow at id.heroku.com. The resulting access token is prefixed HRKU- and carries the scopes granted. Web-flow tokens expire after eight hours and can be refreshed, while a direct-authorization token does not expire.
The Heroku API is split into areas an agent can act on, like apps, dynos, config vars, releases, and add-ons. Each area has its own methods, and writes in some areas restart running processes, change which code is live, or expose runtime secrets.
List, read, create, update, and delete apps, and read the authenticated account.
List and read dynos, run a one-off dyno, and restart or stop dynos.
Read the dyno formation for an app and change how many dynos of each process type run, and their size.
Read and update an app's config vars, the environment variables that hold its settings and secrets.
List and read releases, and create a release to deploy a slug or roll back to a previous one.
List and read builds, and create a build from source to produce a deployable slug.
List, read, provision, and remove add-ons, the attached services like databases and queues.
List, add, and remove the custom domains pointed at an app.
List, add, and remove the people who can access an app.
List, read, and create pipelines, which group an app's staging and production environments.
Create a log session to stream or read an app's recent log output.
Read the authenticated account and the current rate-limit allowance.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
AppsList, read, create, update, and delete apps, and read the authenticated account.5 | ||||||
| GET | /apps | List the apps the account can access. | read | read | Current | |
The global scope also covers this. Identity scope is account-only and does not reach apps. Acts onapp Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /apps/{app_id_or_name} | Get the details of a single app by its id or name. | read | read | Current | |
An app is addressed by its UUID or its human-friendly name. Acts onapp Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps | Create a new app. | write | write | Current | |
Needs the write scope, which pairs with read. The global scope also covers this. Acts onapp Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-appRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /apps/{app_id_or_name} | Update an app, such as renaming it or changing its maintenance mode. | write | write | Current | |
Needs the write scope, which pairs with read. Acts onapp Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-appRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name} | Delete an app and everything running on it. | write | write | Current | |
Irreversible. Needs the write scope, which pairs with read. Acts onapp Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-appRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
DynosList and read dynos, run a one-off dyno, and restart or stop dynos.5 | ||||||
| GET | /apps/{app_id_or_name}/dynos | List the dynos running for an app. | read | read | Current | |
Read-only. Acts ondyno Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /apps/{app_id_or_name}/dynos/{dyno_id_or_name} | Get the details of a single dyno. | read | read | Current | |
Read-only. Acts ondyno Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/dynos | Run a one-off dyno, such as a command or a console. | write | write | Current | |
Runs a process with the app's config vars, so it can reach runtime secrets. Needs the write scope. Acts ondyno Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-dynoRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name}/dynos/{dyno_id_or_name} | Restart or stop a single dyno. | write | write | Current | |
A managed dyno restarts; a one-off dyno stops. Needs the write scope. Acts ondyno Permission (capability) writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name}/dynos | Restart all dynos on an app. | write | write | Current | |
Restarts every running process at once. Needs the write scope. Acts ondyno Permission (capability) writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Formation (scale)Read the dyno formation for an app and change how many dynos of each process type run, and their size.3 | ||||||
| GET | /apps/{app_id_or_name}/formation | List the dyno formation, the process types and how many of each run. | read | read | Current | |
Read-only. Acts onformation Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /apps/{app_id_or_name}/formation/{formation_id_or_type} | Scale a single process type, changing its dyno count or size. | write | write | Current | |
Changing quantity or size affects capacity and cost. Needs the write scope. Acts onformation Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-formationRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /apps/{app_id_or_name}/formation | Scale several process types at once in a single batch update. | write | write | Current | |
Updates the quantity and size of multiple process types in one call. Needs the write scope. Acts onformation Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-formationRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Config varsRead and update an app's config vars, the environment variables that hold its settings and secrets.2 | ||||||
| GET | /apps/{app_id_or_name}/config-vars | Get an app's config vars, its environment variables. | read | read-protected | Current | |
The read scope excludes config vars on purpose, since they hold runtime secrets; reading them needs read-protected or global. Acts onconfig-var Permission (capability) read-protectedVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /apps/{app_id_or_name}/config-vars | Set, change, or remove an app's config vars. | write | write-protected | Current | |
Setting null removes a key. Writing config vars needs write-protected or global, not the plain write scope. Acts onconfig-var Permission (capability) write-protectedVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ReleasesList and read releases, and create a release to deploy a slug or roll back to a previous one.3 | ||||||
| GET | /apps/{app_id_or_name}/releases | List an app's releases, the history of what has gone live. | read | read | Current | |
Read-only. Acts onrelease Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /apps/{app_id_or_name}/releases/{release_id_or_version} | Get the details of a single release. | read | read | Current | |
Read-only. Acts onrelease Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/releases | Create a release by deploying a slug, or roll back by releasing a previous slug. | write | write | Current | |
Takes a slug id; releasing an earlier slug is how a rollback is performed. Needs the write scope. Acts onrelease Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-releaseRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
BuildsList and read builds, and create a build from source to produce a deployable slug.3 | ||||||
| GET | /apps/{app_id_or_name}/builds | List an app's builds. | read | read | Current | |
Read-only. Acts onbuild Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /apps/{app_id_or_name}/builds/{build_id} | Get the details and status of a single build. | read | read | Current | |
Read-only. Acts onbuild Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/builds | Create a build from a source blob to produce a deployable slug. | write | write | Current | |
Takes a source_blob pointing at the code to build. Needs the write scope. Acts onbuild Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-buildRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Add-onsList, read, provision, and remove add-ons, the attached services like databases and queues.4 | ||||||
| GET | /apps/{app_id_or_name}/addons | List the add-ons provisioned for an app. | read | read | Current | |
Read-only. Acts onadd-on Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /apps/{app_id_or_name}/addons/{add_on_id_or_name} | Get the details of a single add-on on an app. | read | read | Current | |
Read-only. Acts onadd-on Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/addons | Provision an add-on, such as a database or queue, on an app. | write | write | Current | |
A paid plan starts billing as soon as it is provisioned. Needs the write scope. Acts onadd-on Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-addonRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name}/addons/{add_on_id_or_name} | Remove an add-on from an app. | write | write | Current | |
Destroys the add-on and its data, such as a database. Needs the write scope. Acts onadd-on Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-addonRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
DomainsList, add, and remove the custom domains pointed at an app.3 | ||||||
| GET | /apps/{app_id_or_name}/domains | List the custom domains on an app. | read | read | Current | |
Read-only. Acts ondomain Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/domains | Add a custom domain to an app. | write | write | Current | |
Needs the write scope, which pairs with read. Acts ondomain Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-domainRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name}/domains/{domain_id_or_hostname} | Remove a custom domain from an app. | write | write | Current | |
The app stops serving that hostname. Needs the write scope. Acts ondomain Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-domainRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
CollaboratorsList, add, and remove the people who can access an app.3 | ||||||
| GET | /apps/{app_id_or_name}/collaborators | List the collaborators on an app. | read | read | Current | |
Read-only. Acts oncollaborator Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /apps/{app_id_or_name}/collaborators | Add a collaborator to an app by email. | write | write | Current | |
Grants another person access to the app. Needs the write scope. Acts oncollaborator Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-collaboratorRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /apps/{app_id_or_name}/collaborators/{collaborator_id_or_email} | Remove a collaborator from an app. | write | write | Current | |
Revokes that person's access. Needs the write scope. Acts oncollaborator Permission (capability) writeVersionAvailable since the API’s base version Webhook event api-collaboratorRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
PipelinesList, read, and create pipelines, which group an app's staging and production environments.3 | ||||||
| GET | /pipelines | List the pipelines the account can access. | read | read | Current | |
Read-only. Acts onpipeline Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /pipelines/{pipeline_id_or_name} | Get the details of a single pipeline. | read | read | Current | |
Read-only. Acts onpipeline Permission (capability) readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /pipelines | Create a pipeline to group an app's environments. | write | write | Current | |
Needs the write scope, which pairs with read. Acts onpipeline Permission (capability) writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
LogsCreate a log session to stream or read an app's recent log output.1 | ||||||
| POST | /apps/{app_id_or_name}/log-sessions | Create a log session to stream or read an app's recent logs. | write | write | Current | |
Returns a temporary URL to fetch the log output. Needs the write scope. Acts onlog-session Permission (capability) writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Account & limitsRead the authenticated account and the current rate-limit allowance.2 | ||||||
| GET | /account | Get the authenticated account's profile. | read | identity | Current | |
The identity scope reaches account information; the app-level read scope does not. Acts onaccount Permission (capability) identityVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /account/rate-limits | Get the account's current rate-limit allowance, the number of request tokens left. | read | identity | Current | |
This call does not consume a request token of its own. Acts onrate-limit Permission (capability) identityVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Heroku can notify an app or AI agent when something happens to an app, like a release being created or a dyno starting, instead of the app repeatedly asking. Heroku posts the event to a webhook URL that has been registered on the app for the chosen entities.
| Event | What it signals | Triggered by |
|---|---|---|
api:app | Fires when an app is created, updated, or destroyed. | /apps/apps/{app_id_or_name}/apps/{app_id_or_name} |
api:dyno | Fires when a new dyno has begun running. | /apps/{app_id_or_name}/dynos |
api:formation | Fires when the dyno formation for a process type is updated or destroyed. | /apps/{app_id_or_name}/formation/{formation_id_or_type}/apps/{app_id_or_name}/formation |
api:release | Fires when a new release is initiated and again when its status changes, such as from pending to succeeded or failed. | /apps/{app_id_or_name}/releases |
api:build | Fires when a new build is initiated and again when the build status changes. | /apps/{app_id_or_name}/builds |
api:addon | Fires when an add-on is provisioned, updated, or removed. | /apps/{app_id_or_name}/addons/apps/{app_id_or_name}/addons/{add_on_id_or_name} |
api:domain | Fires when a custom domain is added to or removed from an app. | /apps/{app_id_or_name}/domains/apps/{app_id_or_name}/domains/{domain_id_or_hostname} |
api:collaborator | Fires when a collaborator is added, updated, or removed on an app. | /apps/{app_id_or_name}/collaborators/apps/{app_id_or_name}/collaborators/{collaborator_id_or_email} |
Heroku limits how fast an app or AI agent can call, through a per-account pool of request tokens that refills over time, and reports the remaining count on every response.
Heroku meters calls with a per-account pool of request tokens that holds at most 4,500. Each API call spends one token, and tokens refill at roughly 75 per minute, which is 4,500 per hour, up to the 4,500 ceiling. Every response carries a RateLimit-Remaining header with the tokens left, and the dedicated rate-limit endpoint reports the same figure without spending a token. When the pool is empty a call returns 429 with an id of rate_limit.
List endpoints page through the Range header rather than query parameters. The default page size is 200 and the maximum is 1,000. A truncated list returns 206 Partial Content with a Next-Range header, and the next page is fetched by repeating the request with Range set to that value. The page size is set with a max key in the header, such as Range: id ..; max=10, and the sort property and direction are set the same way, such as order=desc.
Responses are JSON. A single list page returns at most 1,000 values, the maximum the Range header allows, and larger result sets are walked one page at a time through the Next-Range header.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 401 | unauthorized | The request had no valid token, or the token was invalid or expired. | Send a valid API token or OAuth access token in the Authorization header. |
| 403 | forbidden | The token is valid but its scope or the account's access does not cover this resource. | Use a token whose OAuth scope reaches the resource, such as read-protected for config vars. |
| 404 | not_found | The requested resource does not exist, or the token cannot see it. | Confirm the app id or name and the path, and that the token has access. |
| 422 | invalid_params | The request was understood but the parameters were invalid, or extra verification is required. | Read the message field, correct the parameters, and resend. |
| 429 | rate_limit | The account ran out of request tokens in its hourly pool. | Wait for the pool to refill, around 75 tokens per minute, and check RateLimit-Remaining before retrying. |
| 503 | service_unavailable | The API is temporarily unavailable. | Retry after a short, backed-off delay. |
Heroku versions its Platform API by a number sent in the Accept header. The current version is 3, and each resource also carries a stability level that signals how settled it is.
Version 3 is the current Platform API, selected by sending Accept: application/vnd.heroku+json; version=3 on every request. It is the stable, supported version, and each resource within it carries a stability level of prototype, development, or production that governs how much notice any change to that resource gets. Heroku ships dated, additive changes to version 3 through its changelog rather than minting a new major version for each one.
Before version 3, Heroku exposed earlier API generations that have since been superseded. Version 3 is the one Heroku documents and supports for new integrations, and the version is pinned explicitly in the Accept header so an integration is never moved between generations without changing that header.
An integration pins version 3 in the Accept header on every request.
Heroku changelog ↗Bollard AI sits between a team's AI agents and Heroku. Grant each agent exactly the access it needs, read or write, resource by resource, and every call is checked and logged.