API reference
The Depllo REST API. Every route below is mounted under
/api/v1 and rides the family { data, error, meta } envelope.
Base URL
https://depllo.forjio.com/api/v1
Authentication
Send a workspace API key as a Bearer token — create one at Dashboard → API Keys:
Authorization: Bearer sk_live_<your API key>
A key acts in the workspace it was created in. A Huudis access token (what
depllo auth login stores) works the same way; browser sessions
authenticate by cookie; the runner protocol uses a separate runner token.
Full details, with curl, SDK and CLI examples:
API authentication.
Every route, with its parameters and body fields, is in the generated route reference.
Response envelope
{
"data": { },
"error": null,
"meta": { "requestId": "req_...", "timestamp": "2026-01-01T00:00:00Z" }
}
On error, data is null and error carries an UPPER_SNAKE_CASE code
(NOT_FOUND, VALIDATION_ERROR, CONFLICT, AUTH_REQUIRED,
FORBIDDEN, PIPELINE_NOT_CREATED, UPSTREAM_ERROR, …) plus a
human-readable message.
Idempotency
Mutating requests accept an Idempotency-Key header. Re-sending the same
key returns the original result instead of creating a duplicate.
Pagination
List endpoints that paginate use an opaque cursor query param and
return meta.cursor (the next cursor) and meta.hasMore.
Projects
List projects
GET /projects — every project in your workspace, each with its latest
pipeline for the dashboard chip.
Create a project
POST /projects
{
"repoFullName": "your-org/your-repo",
"name": "your-repo",
"defaultBranch": "main",
"configPath": ".depllo-ci.yml",
"cloneToken": "ghp_… (optional, for private repos)"
}
Creating a project also registers the GitHub webhook. The response
includes a webhook field indicating whether that succeeded.
Get / delete a project
GET /projects/:idDELETE /projects/:id— removes the project and all its pipelines, jobs, variables, and schedules.
Re-create the webhook
POST /projects/:id/webhook — idempotent; the settings-page "re-create"
action.
Pipelines
List a project's pipelines
GET /projects/:id/pipelines?cursor=<cursor> — newest first,
cursor-paginated.
Run a pipeline manually
POST /projects/:id/pipelines
{ "ref": "main", "variables": { "DEPLOY_ENV": "staging" } }
Depllo fetches .depllo-ci.yml at the ref and creates the pipeline.
Returns 422 PIPELINE_NOT_CREATED if workflow: rules excludes it.
To run an earlier commit of the branch (a roll back), add its sha. It must be on
the branch (its head or an ancestor), and the pipeline still runs as that branch,
so branch rules such as "deploy only from master" apply as usual:
{ "ref": "master", "sha": "9c41d02" }
Get a pipeline (with jobs)
GET /projects/:id/pipelines/:iid — by the display iid (42). Returns
the pipeline plus its jobs and stage order (the DAG page shape). The same
detail is available by id at GET /pipelines/:id.
Cancel / retry
POST /projects/:id/pipelines/:iid/cancel(orPOST /pipelines/:id/cancel)POST /projects/:id/pipelines/:iid/retry(orPOST /pipelines/:id/retry)
Jobs
Get a job (with artifacts)
GET /jobs/:id
Job actions
POST /jobs/:id/retryPOST /jobs/:id/play— start amanualjob.POST /jobs/:id/cancel
Logs
GET /jobs/:id/log?from=<seq>— paged log chunks from a sequence number; the response includescompleteandlastSeq.GET /jobs/:id/log/stream?from=<seq>— SSE tail. Emitschunkevents,: pingheartbeats, and a finaldoneevent with the terminal status.
Artifact download
GET /jobs/:id/artifacts/:artId/download — streams the .tar.gz.
Variables
GET /projects/:id/variables— values are never returned in full, only a last-4 preview.POST /projects/:id/variables
{ "key": "NPM_TOKEN", "value": "…", "masked": true, "protected": false, "fileType": false }
PATCH /projects/:id/variables/:varIdDELETE /projects/:id/variables/:varId
Schedules
GET /projects/:id/schedulesPOST /projects/:id/schedules
{ "cron": "0 3 * * *", "ref": "main", "active": true, "variables": { "NIGHTLY": "1" } }
PATCH /projects/:id/schedules/:schedIdDELETE /projects/:id/schedules/:schedIdGET /schedules— all schedules across your workspace.
Cron is a 5-field expression evaluated in WIB (Asia/Jakarta).
Runners
GET /runners— shared plus workspace runners.POST /runners/:id/pausePOST /runners/:id/resume
API keys
Managed by a signed-in person only — a request authenticated by an API
key gets 403 FORBIDDEN here.
GET /api-keys— the workspace's active keys (prefix only, never the key).POST /api-keys—{ "name": "deploy script" }; the response'skeyis the only time the full key is shown.DELETE /api-keys/:id— revoke; requests with the key get401at once.
Webhooks
Endpoints that receive depllo.pipeline.finished.v1, depllo.job.finished.v1 and
depllo.webhook_endpoint.disabled.v1 — signed, retried, logged. A session or an API
key. The whole story (payloads, signature, retries) is in Webhooks.
GET /webhook-endpoints/event-types— the event catalogue.GET /webhook-endpoints— the workspace's endpoints (never the secret:secretPreview).POST /webhook-endpoints—{ "url": "https://…", "events": ["depllo.job.*"], "description": "…" };eventsdefaults to["*"]. The response'ssecretis the only time it is shown.GET /webhook-endpoints/:id,PATCH /webhook-endpoints/:id(url,events,description,active),DELETE /webhook-endpoints/:id.GET /webhook-deliveries(endpointId,status,type,limit,cursor),GET /webhook-deliveries/:id,POST /webhook-deliveries/:id/retry(202).
Usage
GET /usage — compute minutes used this calendar month for your
workspace, plus the tier limit:
{
"accountId": "acc_…",
"periodStart": "2026-07-01T00:00:00.000Z",
"minutesUsed": 128,
"tier": "growth",
"minutesLimit": 6000,
"softWarn": false,
"exhausted": false
}
Public
Status badge
GET /public/badges/:badgeToken/pipeline.svg — no auth; the latest
default-branch pipeline status as an SVG. See
Status badges.
GitHub webhook intake
POST /webhooks/github/:projectId — called by GitHub, not you. HMAC-verified
with the per-project secret. push and pull_request events create
pipelines.