Members
The people in a project, each holding one role: `viewer`, `developer`, `admin` or `owner`. Viewers are read-only across the API. Only an owner can grant the owner role, change an owner's role or remove an owner. Exactly one member is the **biller**, responsible for paying for the project. The biller cannot be removed, or leave, while they hold that responsibility — the attempt is refused with `409 BILLER_CANNOT_LEAVE` — so transfer it to another member first. Inviting, removing and changing the role of a member are done from the control panel by a signed-in owner or admin, never with an API key: a key is refused with `401 API_KEY_NOT_ALLOWED`. A pending invitation can be cancelled through the API.
Every member of the project in the order they joined, the invitations still waiting for an answer, and who holds billing responsibility — including a transfer that is waiting to be accepted.
Auth: a project API key carrying members:read.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthResponse Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/projects/string/members"{ "success": true, "data": { "orgId": "string", "currentUserId": "string", "billerUserId": "string", "pendingBillerUserId": "string", "members": [ { "id": "string", "organizationId": "string", "userId": "string", "role": "viewer", "createdAt": "2019-08-24T14:15:22Z", "user": { "name": "string", "email": "[email protected]", "image": "string" } } ], "pendingInvitations": [ { "id": "string", "email": "[email protected]", "role": "viewer", "expiresAt": "2019-08-24T14:15:22Z" } ] }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}Clears the pending billing transfer. The nominee calls this to decline it, and the current
biller to withdraw it; each notifies the other. Anyone else is refused with
403 FORBIDDEN. For an API key, the caller is the member who created the key, so the key has to belong to the right person.
Auth: a project API key carrying all of members:read and members:write.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthResponse Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/projects/string/members/biller/decline"{ "success": true, "data": null}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}Nominates another member, by their userId, to take over paying for the project. Only the
current biller can start a transfer; anyone else is refused with 403 FORBIDDEN. For an API key, the caller is the member who created the key, so the key has to belong to the right person.
Nothing changes until the nominee accepts. They are notified by email and in the control panel, and accept there by adding a card, which becomes the project's payment method; the previous biller's card is then removed from the project. Accepting or declining notifies the outgoing biller. Nominating someone while a transfer is pending replaces that nomination.
Before transferring, the outgoing biller can have any remaining project credit refunded to their payment method with Refund Credit Balance; otherwise the credit stays with the project for the incoming biller. Payment-processing fees cannot be recovered, so the amount refunded is less than the credit balance.
Any role may hold billing responsibility, so a viewer who is the biller can transfer it too.
Auth: a project API key carrying all of members:read and members:write.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/projects/string/members/biller/transfer" \ -H "Content-Type: application/json" \ -d '{ "targetUserId": "string" }'{ "success": true, "data": null}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}Withdraws an invitation that has not been answered yet, so its link stops working. The ids of pending invitations are in List members.
Only owners and admins can cancel an invitation, as only they can send one. Inviting, removing and changing the role of a member are done from the control panel; API keys cannot change who is in a project.
Auth: a project API key carrying all of members:read and members:write.
Role: the caller must be an owner or admin of the project.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= length1 <= lengthResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X DELETE "https://example.com/v1/projects/string/members/invitations/string"{ "success": true, "data": null}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}The caller's own role in the project. For an API key, that is the role of the member who created it.
Auth: a project API key carrying members:read.
Authorization
apiKey A project API key. X-API-Key: <key> is accepted as an alternative to the Authorization header.
In: header
Path Parameters
1 <= lengthResponse Body
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/projects/string/members/me"{ "success": true, "data": { "role": "viewer" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}{ "success": false, "error": { "code": "string", "message": "string", "docsUrl": "http://example.com" }}Resource groups
Named boxes drawn around resources on the project overview's resource graph. Groups nest, a resource sits in at most one, and they change only how the project is drawn — nothing a group holds behaves any differently for being in it.
Apps
Managed app hosting. An app is either built from a git repository or runs a container image, and is created in two steps: save its configuration as a draft, then create the app from the draft, which charges the project's payment method and starts the first deployment. For an app running an image from one of the project's registries, `imageDeployPolicy` decides what a push to its repository does: `TAG` (the default) redeploys the app when the tag it uses is pushed again, and leaves other tags and an app pinned to a digest alone; `NEWEST` deploys whatever tag was pushed and switches the app to it; `MANUAL` does nothing, and the app moves only through Deploy image. **Environment variables at build time.** An app built from a repository gets its environment variables in the build as well as in the running container, so a value a framework inlines while building — `NEXT_PUBLIC_*`, `VITE_*` — is there. A plain variable is a build argument: a Dockerfile reads it with `ARG NAME`, and an auto-detected build or a static site's build command sees it in its environment without declaring anything. A variable marked secret is a BuildKit secret: it is mounted for the command that reads it and never written to an image layer, the image history or the build cache. A Dockerfile opts in per step with `RUN --mount=type=secret,id=NAME,env=NAME <command>`; auto-detected and static builds see it in the command's environment like a plain one. Names must be identifiers (`[A-Za-z_][A-Za-z0-9_]*`) — a variable named otherwise still reaches the container but is left out of the build. A changed variable is picked up by the next build: a push to the tracked branch, or Redeploy. Variables prefixed `RAILPACK_` also configure an auto-detected build; see the [Railpack reference](https://railpack.com/config/environment-variables). **Configuration file.** An app created from a repository's [configuration file](/docs/guides/app-templates) remembers which file and service it came from, and what the file applied. That is what lets Check configuration file tell the repository moving on apart from a setting changed in the control panel since; whether the file is then ignored, watched or applied on every push is the app's configuration file mode. Every call that changes an app is refused to members with the viewer role, and to a project blocked over an unpaid invoice (`403 ACCOUNT_BLOCKED`). Reading an app's network settings and its recent activity currently sits behind the same gate, and needs `apps:write` as well as `apps:read`. Four calls work with an API key but are not described operation by operation yet, because they answer with the app's full internal record, which is not a stable contract: listing apps (`GET /v1/projects/{projectId}/apps`, `apps:read`), reading one (`GET /v1/projects/{projectId}/apps/{appId}`, `apps:read`), updating its settings and environment variables (`PATCH /v1/projects/{projectId}/apps/{appId}`, `apps:write`) and changing its domain (`PATCH /v1/projects/{projectId}/apps/{appId}/domain`, `apps:write`). Rely only on the fields you also see in the control panel — `id`, `name`, `status`, `url`, the source and build settings, `envVars` — and expect the rest to change. Secret environment variable values come back masked, and a registry credential comes back without its password. Following an app's logs live and opening a console are available in the control panel; the latest log lines are available here.