docs: add Hub public API reference
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user