215 lines
6.5 KiB
Markdown
215 lines
6.5 KiB
Markdown
---
|
|
title: Hub public API
|
|
description: Use organization API keys to install configuration, dispatch manual runs, and enroll daemons.
|
|
nav: Public API
|
|
order: 78
|
|
category: Hub
|
|
---
|
|
|
|
# Hub public API
|
|
|
|
The Hub public API lets automation operate on projects and daemons in one
|
|
organization. Set the Hub origin in `HUB_URL` below, for example
|
|
`https://hub.example.com`.
|
|
|
|
## Authentication
|
|
|
|
Create an organization API key from the Hub dashboard under **API keys**. Send
|
|
it as a bearer token on every API request:
|
|
|
|
```http
|
|
Authorization: Bearer paseo_pk_...
|
|
Content-Type: application/json
|
|
```
|
|
|
|
API keys are organization-scoped. The organization that owns the key determines
|
|
which projects and daemon enrollment tokens it can reach; there is no
|
|
organization ID to add to these requests. A project slug from another
|
|
organization is not accessible through the key.
|
|
|
|
Each key has one or more selectable scopes:
|
|
|
|
| Scope | Operation |
|
|
| ----------------------- | --------------------------------------------------- |
|
|
| `configuration:install` | Replace and activate a project's configuration. |
|
|
| `runs:dispatch` | Dispatch a configured manual trigger for a project. |
|
|
| `daemons:enroll` | Issue a short-lived daemon enrollment token. |
|
|
|
|
API keys do not grant dashboard access. They cannot manage connections,
|
|
projects, or organization members.
|
|
|
|
Missing, invalid, or revoked credentials return `401`:
|
|
|
|
```json
|
|
{ "error": "unauthorized" }
|
|
```
|
|
|
|
A valid key without the scope required by an endpoint returns `403`:
|
|
|
|
```json
|
|
{ "error": "forbidden" }
|
|
```
|
|
|
|
## Configuration install
|
|
|
|
`configuration:install` replaces the project's current configuration with the
|
|
supplied YAML after Hub validates and compiles it, then activates the new
|
|
revision.
|
|
|
|
```http
|
|
POST /api/configurations/install
|
|
```
|
|
|
|
Request body:
|
|
|
|
```json
|
|
{
|
|
"projectSlug": "my-project",
|
|
"yaml": "environments:\n - name: production\n kind: daemon\n daemon: build-server\n cwd: /workspace\ntriggers:\n - name: deploy\n on: manual.run\n environment: production\n filters:\n from_users: [automation]\n agent:\n provider: opencode\n mode: full-access\n prompt: Deploy the project"
|
|
}
|
|
```
|
|
|
|
The YAML must describe a valid Hub configuration. Replace the example daemon,
|
|
working directory, and trigger values with resources in your organization.
|
|
|
|
On success, Hub returns `201`:
|
|
|
|
```json
|
|
{
|
|
"projectSlug": "my-project",
|
|
"versionId": "00000000-0000-4000-8000-000000000000",
|
|
"version": 3,
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
Common responses are `400 {"error":"invalid_request"}` for a missing or
|
|
malformed body, `404 {"error":"project_not_found"}` for an inactive or
|
|
unknown project in the key's organization, and `422` for invalid YAML or an
|
|
invalid configuration. An invalid configuration includes the provisional
|
|
`versionId` in its response.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
curl --fail-with-body -sS -X POST "$HUB_URL/api/configurations/install" \
|
|
-H "Authorization: Bearer $PASEO_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
--data @configuration-install.json
|
|
```
|
|
|
|
## Manual run dispatch
|
|
|
|
`runs:dispatch` dispatches a configured `manual.run` trigger for a project.
|
|
The trigger must exist in the active configuration, and `actor` must be listed
|
|
in that trigger's `filters.from_users` allowlist.
|
|
|
|
```http
|
|
POST /api/manual-runs
|
|
```
|
|
|
|
Request body:
|
|
|
|
```json
|
|
{
|
|
"projectSlug": "my-project",
|
|
"expectedVersionId": "00000000-0000-4000-8000-000000000000",
|
|
"trigger": "deploy",
|
|
"actor": "automation",
|
|
"deliveryKey": "deploy-2026-08-04-001",
|
|
"input": {
|
|
"ref": "main"
|
|
}
|
|
}
|
|
```
|
|
|
|
`expectedVersionId` is optional. When supplied, Hub rejects the dispatch if
|
|
that configuration revision is no longer active. `input` is application data
|
|
made available to the trigger; it may be any JSON value. Use a unique,
|
|
stable `deliveryKey` for each dispatch. Reusing it makes the request resolve to
|
|
the existing trigger instead of starting a duplicate run.
|
|
|
|
On success, Hub returns `200`:
|
|
|
|
```json
|
|
{
|
|
"deliveryKey": "deploy-2026-08-04-001",
|
|
"triggerId": "00000000-0000-4000-8000-000000000000",
|
|
"executionId": "00000000-0000-4000-8000-000000000000",
|
|
"status": "spawning",
|
|
"daemonId": "00000000-0000-4000-8000-000000000000",
|
|
"agentId": "agent-id"
|
|
}
|
|
```
|
|
|
|
Common responses are `400 {"error":"invalid_request"}`, `404` for an
|
|
unknown project, missing configuration, or missing trigger, `403
|
|
{"error":"actor_forbidden"}` when the actor is not allowed by the trigger,
|
|
and `409` when the daemon is offline, the expected configuration is no longer
|
|
current, or the run could not be dispatched.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
curl --fail-with-body -sS -X POST "$HUB_URL/api/manual-runs" \
|
|
-H "Authorization: Bearer $PASEO_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
--data '{
|
|
"projectSlug": "my-project",
|
|
"trigger": "deploy",
|
|
"actor": "automation",
|
|
"deliveryKey": "deploy-2026-08-04-001",
|
|
"input": {"ref": "main"}
|
|
}'
|
|
```
|
|
|
|
## Daemon enrollment
|
|
|
|
`daemons:enroll` issues a short-lived enrollment token for a daemon. The API
|
|
key mints this token; it is not the daemon's long-lived credential and must not
|
|
be used as one.
|
|
|
|
```http
|
|
POST /api/daemons/enrollment-tokens
|
|
```
|
|
|
|
Send an empty JSON object as the request body. On success, Hub returns `201`:
|
|
|
|
```json
|
|
{
|
|
"token": "short-lived-enrollment-token",
|
|
"expiresAt": "2026-08-04T12:10:00.000Z"
|
|
}
|
|
```
|
|
|
|
The token expires after 10 minutes and is consumed when the daemon enrolls.
|
|
Pass it to the Paseo CLI, which exchanges it for the daemon's connection
|
|
credential:
|
|
|
|
```bash
|
|
ENROLLMENT_TOKEN="$(curl --fail-with-body -sS -X POST \
|
|
"$HUB_URL/api/daemons/enrollment-tokens" \
|
|
-H "Authorization: Bearer $PASEO_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
--data '{}' | jq -r .token)"
|
|
|
|
paseo hub connect "$HUB_URL" --token "$ENROLLMENT_TOKEN"
|
|
```
|
|
|
|
An enrollment token cannot be reused. Revoking the API key immediately rejects
|
|
future API requests and expires any unconsumed enrollment tokens that key
|
|
issued. A race between revocation and issuance is resolved by Hub before a new
|
|
token is stored.
|
|
|
|
## Keys, scopes, and audit information
|
|
|
|
The complete API-key secret is shown once, immediately after creation. Store it
|
|
in your deployment's secret manager; Hub does not show it again. The dashboard
|
|
retains only the key's prefix and shows its selected scopes, creation time,
|
|
last-used time, and status.
|
|
|
|
Hub updates `last used` after a key successfully authenticates for a scoped API
|
|
operation. API operations retain the key attribution in Hub's audit evidence,
|
|
so configuration revisions, manual dispatches, and daemon enrollment tokens
|
|
can be traced to the organization key that created them.
|