Encore Platform API Reference
The Encore platform provides an API for programmatic access to control certain parts of the platform.
We're working on expanding the set of features available over the API. Please reach out to us on Discord if you have use cases where additional API functionality would be useful.
The Base URL for the Encore platform API is https://api.encore.dev.
Authentication
All API calls require valid authentication, which is provided by sending an access token in the Authorization header,
in the format Authorization: Bearer ${ACCESS_TOKEN}.
You can retrieve an API access token from the OAuth Token endpoint, using an OAuth Client. An API access token expires after one hour. For continuous access, shortly before an API access token expires, request a new API access token from the Encore platform's OAuth token endpoint.
OAuth client libraries in popular programming languages can handle the API access token generation and renewal.
See the OAuth Clients for more information on creating OAuth Clients.
OAuth
Method: POST
Path: /api/oauth/token
Query Parameters
Response
The API responds with a 2xx status code on successful creation of an API access token.
type Token = {
// The access token itself.
"access_token": string;
// The access token expires after 1 hour (3600 seconds).
"expires_in": 3600;
// The actor the token belongs to, in this case the OAuth2 client id.
actor: string;
// Indicates the access token should be passed as a "Bearer" token in the Authorization header.
"token_type": "Bearer";
}
Response Format
Every endpoint except the OAuth token endpoint wraps its payload in an envelope:
{
"ok": true,
"data": { }
}
Errors use the same envelope:
{
"ok": false,
"error": {
// The error code, for example "validation" or "not_found".
"code": "validation",
// Extra information about the error, when there is any.
// For validation errors it names the field at fault.
"detail": { "field": "services", "type": "empty" },
// A human readable description, when there is one.
"detailed_error": ""
}
}
Where this reference says an endpoint returns an object, that object is the value of data.
Rollouts
The Encore platform's deployment system consists of several phases:
- A build phase
- An infrastructure provisioning phase
- A deployment phase
These phases are combined into a unified entity called a Rollout. A rollout represents the coordinated process of rolling out a specific version of an Encore application.
We use the term rollout to disambiguate from the deployment phase, which specifically refers to the last phase of the rollout process (where the version is being deployed onto the provisioned infrastructure).
The Rollout Object
The Rollout object represents the state of a rollout.
// The representation of a rollout.
type Rollout = {
// Unique id of the rollout.
id: string;
// The current status of the rollout.
status: "pending" | "queued" | "running" | "completed";
// What the conclusion was of the rollout (when status is "completed").
// If the status is not "completed" the conclusion is "pending".
conclusion: "pending" | "canceled" | "failure" | "success";
// When the rollout was queued, started, and completed.
queued_at: Date | null;
started_at: Date | null;
completed_at: Date | null;
// Information about the various rollout phases.
// A phase is null until the rollout reaches it, and the infra phase
// is null when the rollout has no infrastructure change.
// See type definitions below.
build: RolloutPhase<BuildStatus, BuildConclusion> | null;
infra: RolloutPhase<InfraStatus, InfraConclusion> | null;
deploy: RolloutPhase<DeployStatus, DeployConclusion> | null;
}
// Common structure of the various rollout phases.
type RolloutPhase<Status, Conclusion> = {
// Unique id of the phase.
id: string;
// The current status of the rollout phase.
status: Status;
// What the conclusion was of the phase.
conclusion: Conclusion;
// When the phase was queued, started, and completed.
queued_at: Date | null;
started_at: Date | null;
completed_at: Date | null;
}
// The current status and conclusion of a build.
// If the status is not "completed" the conclusion is "unknown".
type BuildStatus = "queued" | "running" | "completed";
type BuildConclusion = "unknown" | "canceled" | "failure" | "success";
// The current status and conclusion of an infra change.
// The "proposed" status means the change is awaiting human approval.
// The "rejected" conclusion means a human rejected the proposed infra change.
type InfraStatus = "pending" | "proposed" | "queued" | "running" | "completed";
type InfraConclusion = "unknown" | "canceled" | "failure" | "rejected" | "success";
// The current status and conclusion of a deploy.
// If the status is not "completed" the conclusion is "unknown".
type DeployStatus = "pending" | "queued" | "running" | "completed";
type DeployConclusion = "unknown" | "canceled" | "failure" | "success";
Triggering a rollout
Method: POST
Path: /api/apps/${APP_ID}/envs/${ENV_NAME}/rollouts
Path Parameters
JSON Request Body
{
// Which commit to roll out. Provide exactly one of the three.
// The order of precedence is latest_deploy, then sha, then branch.
//
// The commit hash to roll out.
"sha": "abc123...",
// The name of the branch to roll out the latest commit from.
"branch": "main",
// Roll out the commit currently deployed to the environment, again.
"latest_deploy": false,
// Optional. Set to skip running tests during build.
"skip_tests": false,
// Optional. Set to force a rebuild instead of reusing a cached build.
"force_rebuild": false,
// Optional. Deploy only these services, leaving the rest of the
// environment on the revision it is already running.
"services": ["users", "billing"],
// Optional. Leave the gateways on the revision they are running.
// Only valid together with "services".
"skip_gateways": false,
// Optional. Deploy what the rollout covers even if the platform
// considers it already up to date.
"force_redeploy": false
}
Exactly one of sha, branch and latest_deploy must be provided; if more than one is given,
latest_deploy takes precedence over sha, which takes precedence over branch. All other fields
are optional: the booleans default to false, and an omitted services deploys the whole
environment.
Naming the commit. latest_deploy resolves the commit of the environment's current deploy and
starts a new rollout from it, on the same path as a commit or branch rollout. It is the deployed
commit, not the most recent rollout's, which may have failed or may still be in flight. If nothing is
deployed to the environment the request fails with a 400.
Partial deploys. services restricts the deploy phase only: infrastructure is still provisioned
for the whole environment and database migrations still run. Services that are not named keep running
the revision they are already on.
Two restrictions apply to the set of services:
- Services that share a process must be deployed together, since a container runs one image. Naming
some but not all of the services in a group fails the rollout during planning, with an error naming
the ones left out. Set
process_per_serviceon the environment to be able to deploy them apart. - Service names are not checked when the rollout is created — the build is what says which services exist — so an unknown name also fails the rollout during planning rather than being rejected here.
skip_gateways only means something alongside services, and sending it without a non-empty
services is rejected with a 400. Gateways are deployed by default, because a gateway left behind does
not know about the endpoints the new revision adds. Holding them back instead avoids applying the
new revision's view of routes to services that are still serving the old one.
force_redeploy overrides the platform's record of what is already current, and nothing else. In
particular it does not widen the scope: a rollout restricted with services still redeploys only
those.
Deduplication. If an active rollout already exists for the same environment and commit, it is
returned instead of a new one being created. Rollouts count as the same request only if they also
agree on services, skip_gateways and force_redeploy, so a narrower redeploy of the same commit
is not folded into an earlier one.
Response
The API responds with a 2xx status code on successful creation of a new rollout.
On success it returns a Rollout object as its JSON response payload, representing the current state of the newly created rollout.
Retrieving a rollout
Method: GET
Path: /api/apps/${APP_ID}/rollouts/${ROLLOUT_ID}
Path Parameters
Response
The API responds with a 2xx status code on successful retrieval of the rollout. On success it returns a Rollout object as its JSON response payload, representing the current state of the requested rollout.
Approving infrastructure changes
Approves the proposed infrastructure changes for a rollout, allowing infrastructure provisioning to proceed.
Method: POST
Path: /api/apps/${APP_ID}/rollouts/${ROLLOUT_ID}/approve-infra
Path Parameters
Response
The API responds with a 2xx status code when the request is successful. On success it returns a Rollout object as its JSON response payload, representing the rollout after the approval attempt.
When the infrastructure change is awaiting approval, its status changes from proposed to queued.
Rejecting infrastructure changes
Rejects the proposed infrastructure changes for a rollout and cancels the rollout.
Method: POST
Path: /api/apps/${APP_ID}/rollouts/${ROLLOUT_ID}/reject-infra
Path Parameters
Response
The API responds with a 2xx status code when the request is successful. On success it returns a Rollout object as its JSON response payload, representing the rollout after the rejection attempt.
When the infrastructure change is awaiting approval, its status changes to completed with the rejected conclusion.
Rejecting the infrastructure changes causes the rollout to be canceled.
Describing infrastructure changes
Describes the infrastructure changes a rollout proposes: the same plan the dashboard shows when
asking for approval. The id to pass is the id of the rollout's infra phase.
Method: GET
Path: /api/apps/${APP_ID}/infra-changes/${INFRA_CHANGE_ID}
Path Parameters
Response
The API responds with a 2xx status code on successful retrieval, and with 404 if the change does not exist or belongs to another application.
type InfraChange = {
// Unique id of the infrastructure change.
id: string;
// The status and conclusion of the change, as on a rollout's infra phase.
status: InfraStatus;
conclusion: InfraConclusion;
// When the change was queued, started, and completed.
queued_at: Date | null;
started_at: Date | null;
completed_at: Date | null;
// The environment the change applies to, in the form "env_...".
env_id: string;
// The rollout the change belongs to, in the form "roll_...".
// Null for a change that was not made as part of a rollout.
rollout_id: string | null;
// What kind of change this is.
type: "provision" | "deploy" | "cleanup" | "delete" | "restore" | "custom" | "fetch";
// The commit the change was planned from.
commit_hash: string;
// Whether any of the changes below restarts a running resource.
requires_restart: boolean;
// The individual resource changes making up the plan.
changes: ResourceChange[];
}
type ResourceChange = {
// What is happening to the resource.
action: "create" | "modify" | "delete" | "deploy" | "other";
// Whether applying this change restarts the resource.
requires_restart: boolean;
// Whether the change has to be applied at the cloud provider.
provider_update: boolean;
// The resource fields that are changing, for example "MemoryMiB".
changed_fields: string[];
// The resource being changed. See below.
resource: object;
}
Only changes that have to be applied at the cloud provider are listed; bookkeeping-only changes are left out, the same way the approval screen leaves them out.
The resource object uses the dashboard's resource schema, so its field names are camelCase rather
than snake_case, and a configuration value that is changing is reported as a
{"current": ..., "requested": ...} pair — the requested value, not a snapshot of a change that has
already been applied. Costs are not included.
Member Management
The Encore platform provides APIs for managing application members, including inviting users, listing members, and updating member roles.
Member Object
type Member = {
// The user's email address
email: string;
// The member's role in the application
role: "owner" | "reader" | "writer" | "none";
// When the member was invited to the application
invited: timestamp;
// When the member accepted the invitation
accepted: timestamp;
// When the membership expires
expires: timestamp;
// The member's username
username: string;
// The member's full name
full_name: string;
// The member's picture URL
picture_url: string;
}
Available Roles
- owner: Full control over the application
- writer: Can write application resources
- reader: Can read application resources
- none: Used to revoke access to an application
Invite Member
Invite a new member to an Encore application.
Method: POST
Path: /api/apps/${APP_ID}/member
Path Parameters
JSON Request Body
{
// The email address of the user to invite
"email": string;
// The role to assign to the invited member
"role": "owner" | "reader" | "writer" | "none";
}
Response
The API responds with a 2xx status code on successful invitation.
On success it returns a Member object as its JSON response payload, representing the newly invited member.
List Members
Retrieve a list of all members for an Encore application.
Method: GET
Path: /api/apps/${APP_ID}/members
Path Parameters
Response
The API responds with a 2xx status code on success.
On success it returns an array of Member objects as its JSON response payload, representing all current members and pending invites for the application.
type Response = Member[];
Update Member Role
Update the role of an existing member.
Method: PUT
Path: /api/apps/${APP_ID}/members
Path Parameters
JSON Request Body
{
// The email address of the member to update
"email": string;
// The new role to assign to the member
"role": "owner" | "reader" | "writer" | "none";
}
Response
The API responds with a 2xx status code on successful update.
Error Cases
- 403 Forbidden: Insufficient permissions to manage members
- 409 Conflict: Attempting to remove the last owner (error detail: "last_owner")
- 404 Not Found: Member not found