Deploying a Project
POST /projects/deploy
Submit a ProjectDescriptor to create or update a project. The endpoint is idempotent: deploying the same descriptor twice produces all noop actions and returns immediately with the unchanged project status.
curl -X POST https://api.foundrydb.com/projects/deploy \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"descriptor": {
"name": "my-todo-app",
"resources": [
{
"logical_name": "db",
"kind": "postgres",
"spec": { "plan": "tier-2", "storage_gb": 50 }
},
{
"logical_name": "web",
"kind": "app",
"spec": {
"image": "ghcr.io/myorg/todo:latest",
"port": 3000
}
}
],
"dependencies": {
"web": ["db"]
}
}
}'
The response is 202 Accepted with the initial deploy state and the computed plan:
{
"project_id": "a1b2c3d4-...",
"deployment_id": "e5f6a7b8-...",
"status": "Pending",
"plan": [
{ "logical_name": "db", "kind": "postgres", "action": "create" },
{ "logical_name": "web", "kind": "app", "action": "create" }
]
}
Provisioning is asynchronous. Use project_id and deployment_id to poll for the final outcome.
Plan actions
The engine computes one action per resource before touching anything:
| Action | When |
|---|---|
create | Resource does not yet exist |
update | Resource exists and its spec changed (app image or env only in Phase 1) |
noop | Resource is unchanged and Running |
unmanaged | Resource was previously provisioned but is absent from the new descriptor |
The plan array in the response reflects these decisions before any resource is created. You can inspect it to confirm what the engine will do.
Dependency ordering and concurrency
The engine topologically sorts the resource graph and provisions resources in order: a resource is started only after all of its declared (and inferred) dependencies reach Running. Resources with no mutual dependency provision concurrently.
For the example above, the engine provisions db first. Once db is Running it provisions web, at which point it also wires the database attachment and injects DATABASE_URL into the web container.
What gets injected
The engine injects connection credentials into the app container automatically when it wires attachments. You do not need to set these variables yourself.
From a postgres attachment
When exactly one database is attached:
| Variable | Value |
|---|---|
DATABASE_URL | Full connection string including TLS parameters |
When multiple databases are attached each gets a set of prefixed variables. The prefix is derived from the attached service's name.
From a files attachment
When exactly one files service is attached:
| Variable | Value |
|---|---|
S3_ENDPOINT | HTTPS endpoint of the object storage service |
S3_BUCKET | Bucket name |
S3_ACCESS_KEY | Attachment-scoped access key ID |
S3_SECRET | Attachment-scoped secret access key |
When multiple files services are attached each gets a prefixed set: {NAME}_S3_ENDPOINT, {NAME}_S3_BUCKET, {NAME}_S3_ACCESS_KEY_ID, {NAME}_S3_SECRET_ACCESS_KEY.
Always injected
| Variable | Value |
|---|---|
FOUNDRY_API_TOKEN | A scoped platform token with services:read and files:read permissions |
FOUNDRY_API_URL | https://api.foundrydb.com |
The FOUNDRY_API_TOKEN is minted once at app creation and preserved across re-deploys. Re-deploying with a changed image or env never re-mints or drops the token.
Polling for completion
Poll GET /projects/{name} until status is Running:
curl https://api.foundrydb.com/projects/my-todo-app \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
The response carries the project's aggregate status and a resources array with per-resource status and status_detail.
To inspect the computed plan and track a specific deploy attempt, poll the deployment endpoint:
curl https://api.foundrydb.com/projects/my-todo-app/deployments/$DEPLOYMENT_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
This returns the deployment record (including plan, status, and error), the live project_status, and a per-resource status snapshot.
Project lifecycle
Pending -> Provisioning -> Wiring -> Running
RollingBack -> Failed (first-deploy failure or abort; no orphans)
Failed (re-deploy failure; healthy resources retained)
Deleting -> Deleted (explicit teardown)
| Status | Meaning |
|---|---|
Pending | Deploy accepted; queued |
Provisioning | One or more resources are being created or updated |
Wiring | All resources are running; cross-resource credentials are being injected |
Running | All resources are provisioned and wired |
RollingBack | A terminal first-deploy failure triggered atomic teardown |
Failed | Terminal after rollback, or after a re-deploy failure (healthy resources retained) |
Deleting | Explicit teardown in progress |
Deleted | Terminal after a clean teardown |
Re-deploy semantics
A project can only be re-deployed when its status is terminal (Running, Failed, or Deleted). Submitting a deploy while one is already in progress or while the project is being torn down returns 409 Conflict.
On a re-deploy the engine diffs the new descriptor against current state:
- Changed app spec (image or env): a
PatchAppServiceis applied in place. - Changed non-app spec: the change is recorded; in-place mutation of a running database or files service is not performed in Phase 1.
- Unchanged resource: no action.
- Resource removed from descriptor: flagged
unmanaged, never touched.
A re-deploy failure never tears down previously-provisioned healthy resources.
Teardown
Explicit teardown deletes every provisioned resource in the project and revokes the project's scoped platform token. Resources that were never provisioned are removed immediately from the project record.
curl -X DELETE https://api.foundrydb.com/projects/my-todo-app \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
Returns 202 Accepted. Poll GET /projects/my-todo-app until status is Deleted. This operation is irreversible for any provisioned resource.
Listing and inspecting projects
# List all projects
curl https://api.foundrydb.com/projects \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
# Get a specific project with per-resource status
curl https://api.foundrydb.com/projects/my-todo-app \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"
Next steps
- Project descriptor reference — every field and kind the descriptor accepts.
- App Hosting guide — detailed documentation on hosted application services.
- Authentication — how to obtain a bearer token.
- Full API reference — the complete Projects API specification.