REST API
Reference for the pipedash-web REST API and WebSocket. Covers auth, every route by group and curl examples.
The pipedash-web server exposes every Pipedash operation under /api/v1 and streams events on /api/v1/ws. The web UI calls the same routes. This page lists all of them.
All paths below are relative to /api/v1. The router registers paths that end in / as written, so they keep the slash, for example /api/v1/providers/. Request and response bodies are JSON.
Authentication
The server compares the Authorization header with the current value of PIPEDASH_VAULT_PASSWORD. If the variable is not set, every request passes. If it is set, protected routes need this header:
Authorization: Bearer <vault-password>The comparison runs in constant time. A missing or wrong header returns status 401. The server reads the variable on every request, so opening or closing the vault changes the rule at once.
These paths skip the check:
- Outside the API: any path that does not start with
/api/v1/, such as the embedded frontend. - Prefixes:
/api/v1/health,/api/v1/setupand/api/v1/vault. - Exact paths:
/api/v1/wsand/api/v1/plugins. The subpath/api/v1/plugins/metadataneeds the header.
/api/v1/factory-reset needs the header like every other route.
Errors
Handled errors return a JSON body with code, message and an optional details.
| Status | code | Cause |
|---|---|---|
| 400 | BAD_REQUEST | Invalid config or provider type |
| 401 | UNAUTHORIZED | Provider authentication failed |
| 404 | NOT_FOUND | Unknown provider or pipeline |
| 409 | CONFLICT | Setup already done |
| 501 | NOT_SUPPORTED | The provider does not support the action |
| 503 | NOT_INITIALIZED | Setup is still required |
| 500 | INTERNAL_ERROR | Any other failure |
A 401 from the auth check has no body.
Health and setup
Both groups skip authentication.
| Method | Path | Purpose |
|---|---|---|
| GET | /health | Server status, version and provider count |
| GET | /setup/status | Config and setup state |
| POST | /setup/config | Saves the first config and starts services |
POST /setup/config takes { "config": { ... }, "vault_password": "<optional>" }. It returns 409 when the instance is already configured.
Providers
| Method | Path | Purpose |
|---|---|---|
| GET | /providers/ | Lists providers |
| POST | /providers/ | Creates a provider |
| GET | /providers/{id} | Reads a provider config |
| PUT | /providers/{id} | Updates a provider |
| DELETE | /providers/{id} | Removes a provider |
| POST | /providers/{id}/validate | Checks the saved credentials |
| PUT | /providers/{id}/refresh-interval | Changes the stored refresh interval |
| GET | /providers/{id}/organizations | Lists organizations |
| GET | /providers/{id}/permissions | Reads saved permissions |
| GET | /providers/{id}/features | Reads feature availability |
| GET | /providers/{id}/table-schema | Reads the table schema |
| POST | /providers/validate | Checks supplied credentials |
| POST | /providers/organizations | Discovers organizations |
| POST | /providers/permissions/check | Checks token permissions |
| POST | /providers/preview | Previews discoverable pipelines |
| POST | /providers/field-options | Loads dynamic config choices |
POST /providers/ takes these fields:
| Field | Type | Default |
|---|---|---|
name | string | Required |
provider_type | string | Required |
token | string | Required |
config | object of strings | {} |
refresh_interval | integer | 60 |
PUT /providers/{id} takes the same body without provider_type.
curl -X POST http://localhost:8080/api/v1/providers/ \
-H "Authorization: Bearer <vault-password>" \
-H "Content-Type: application/json" \
-d '{
"name": "GitHub OSS",
"provider_type": "github",
"token": "<github-token>",
"config": { "selected_items": "hcavarsan/pipedash" }
}'{
"id": 1,
"name": "GitHub OSS",
"provider_type": "github",
"config": { "selected_items": "hcavarsan/pipedash" },
"refresh_interval": 60
}The response never includes the token. The validate, organizations, permissions and field-options routes take provider_type and config. The preview route also takes org, search, page and page_size. See the provider pages for each config key.
Pipelines
| Method | Path | Purpose |
|---|---|---|
| GET | /pipelines/ | Lists pipelines |
| GET | /pipelines/cached | Lists cached pipelines |
| GET | /pipelines/fresh | Fetches pipelines from the providers |
| GET | /pipelines/lazy | Lists pipelines page by page |
| GET | /pipelines/{id}/runs | Run history |
| GET | /pipelines/{id}/runs/{run_number} | One run in detail |
| POST | /pipelines/{id}/trigger | Starts a run |
| POST | /pipelines/{id}/runs/{run_number}/cancel | Cancels a run |
| GET | /pipelines/{id}/workflow-params | Trigger form parameters |
The list routes take an optional provider_id query. /pipelines/lazy also takes page (default 1) and page_size (default 20). /pipelines/{id}/runs takes the same page and page_size.
POST /pipelines/{id}/trigger takes workflow_id (required) and inputs (optional JSON). The server reads the target from workflow_id and ignores the {id} in the path, so the pipeline ID goes in both places. The response holds run_id, a string the provider returns.
curl -X POST "http://localhost:8080/api/v1/pipelines/<pipeline-id>/trigger" \
-H "Authorization: Bearer <vault-password>" \
-H "Content-Type: application/json" \
-d '{ "workflow_id": "<pipeline-id>", "inputs": { "ref": "main" } }'{ "run_id": "<run-id>" }GET /pipelines/{id}/workflow-params lists the inputs a pipeline accepts. See trigger and cancel for the UI flow.
Plugins
| Method | Path | Purpose |
|---|---|---|
| GET | /plugins/ | Lists plugins (no auth) |
| GET | /plugins/metadata | Plugin metadata |
Cache
| Method | Path | Purpose |
|---|---|---|
| GET | /cache/stats | Cache statistics |
| DELETE | /cache/run-history/{pipeline_id} | Clears one history cache |
| DELETE | /cache/run-history | Clears all history caches |
| DELETE | /cache/pipelines | Clears the pipeline cache |
| DELETE | /cache/workflow-params | Clears the parameter cache |
| DELETE | /cache/ | Clears every cache |
Metrics
| Method | Path | Purpose |
|---|---|---|
| GET | /metrics/config | Reads the global metrics config |
| PUT | /metrics/config | Updates it |
| GET | /metrics/pipelines/{id}/config | Reads a pipeline metrics config |
| PUT | /metrics/pipelines/{id}/config | Updates it |
| POST | /metrics/pipelines/{id}/query | Queries raw metrics |
| POST | /metrics/aggregated | Queries aggregated metrics |
| GET | /metrics/storage/stats | Metric storage statistics |
| POST | /metrics/flush | Deletes metrics |
PUT /metrics/config takes enabled and default_retention_days. The pipeline route takes enabled and retention_days. POST /metrics/flush takes an optional pipeline_id. See metrics.
Preferences
| Method | Path | Purpose |
|---|---|---|
| GET | /preferences/table/{provider_id}/{table_id} | Reads table preferences |
| PUT | /preferences/table/{provider_id}/{table_id} | Saves table preferences |
| GET | /preferences/table/{provider_id}/{table_id}/default | Reads the defaults |
Refresh
| Method | Path | Purpose |
|---|---|---|
| GET | /refresh/mode | Reads the refresh mode |
| PUT | /refresh/mode | Sets the mode with { "mode": "<mode>" } |
| POST | /refresh/all | Refreshes all pipelines now |
See refresh for the modes and intervals.
Storage
| Method | Path | Purpose |
|---|---|---|
| GET | /storage/config | Reads the storage config |
| PUT | /storage/config | Updates it |
| GET | /storage/config/content | Reads the TOML text |
| PUT | /storage/config/content | Saves TOML from { "content": "..." } |
| POST | /storage/config/analyze | Analyzes a change from { "new_content": "..." } |
| GET | /storage/paths | Effective file paths |
| POST | /storage/validate | Validates a storage config |
| POST | /storage/test-connection | Tests a storage connection |
| GET | /storage/vault-password-status | Reports whether the password variable is set |
| POST | /storage/migration/plan | Builds a migration plan |
| POST | /storage/migration/execute | Runs a migration |
See storage backends for what a migration moves.
Vault
The vault routes skip authentication.
| Method | Path | Purpose |
|---|---|---|
| GET | /vault/status | Lock state and password source |
| POST | /vault/unlock | Opens the vault with a password |
| POST | /vault/lock | Closes the session |
GET /vault/status returns is_unlocked, password_source (env_var, session or none), backend, requires_password and is_first_time.
POST /vault/unlock takes password and returns success and message.
curl -X POST http://localhost:8080/api/v1/vault/unlock \
-H "Content-Type: application/json" \
-d '{ "password": "<vault-password>" }'{ "success": true, "message": "Vault unlocked successfully" }A failed attempt still returns status 200, with "success": false and a message such as Invalid password or storage error: .... If the vault is already open, the message is Vault is already unlocked.
A successful call sets PIPEDASH_VAULT_PASSWORD in the server process, so later requests must send that password as the bearer token. POST /vault/lock removes the variable. Its message says a restart is needed to clear the token cache fully.
System
| Method | Path | Purpose |
|---|---|---|
| POST | /factory-reset | Removes all providers and metrics |
The response holds providers_removed, caches_cleared, tokens_cleared and metrics_cleared.
WebSocket
Live events stream on /api/v1/ws. When PIPEDASH_VAULT_PASSWORD is set, the first message from the client must be:
{ "type": "auth", "token": "<vault-password>" }The server closes the socket if the first message is missing, is not valid JSON, has another type or carries a wrong token. The server sends no reply on success. Without a password there is no handshake. After that, every event arrives as a text frame with this envelope:
{ "type": "pipeline-status-changed", "payload": {} }type is the event name and payload is the event data. The server ignores text frames that the client sends after the handshake. The event names are:
| Group | Events |
|---|---|
| Providers | providers-changed, provider-added, provider-updated, provider-removed, provider-status-updated |
| Pipelines | pipelines-fetched, pipelines-fetch-error, pipelines-updated, pipeline-status-changed |
| Runs | run-triggered, run-cancelled |
| Refresh | refresh-error |
| Metrics | metrics-generated, metrics-global-config-changed, metrics-config-changed, metrics-flushed |
| Migration | migration-progress, migration-complete |
| Cache | pipeline-cache-invalidated, run-history-cache-invalidated |
| Vault | vault-unlocked |