Référence API
Schémas publics des endpoints, authentification, scopes et exemples de requêtes.
Sur cette page
Les descriptions des endpoints et les noms des schémas sont communs aux deux langues.
Health & Workers
Service health checks and connected worker status monitoring.
GET/healthHealth checkSans authentification
Returns a plain-text OK response. Use this to verify the backend is running and reachable.
# GET /healthCorps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
body | string | Obligatoire | Plain-text "ok" response. |
Types de contenu: application/json → application/json
Exemple cURL
curl http://localhost:8080/healthExemple de réponse
"ok"GET/api/workers/statusGet connected workersJeton utilisateur
Returns project-scoped worker availability. Busy workers are only included when they are running an execution for the requested project; idle workers are anonymized.
# GET /api/workers/statusParamètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_id | uuid | Obligatoire | Project whose worker availability should be returned. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
connected | number | Obligatoire | Number of workers visible for the requested project. |
workers | WorkerInfo[] | Obligatoire | Array of project-visible worker details. |
workers[].worker_id | string | Obligatoire | Unique worker identifier for project-busy workers, or an anonymized availability identifier for idle workers. |
workers[].status | string | Obligatoire | Worker status: "idle" or "busy". |
workers[].connected_at | string | Facultatif | ISO 8601 timestamp of connection time for project-busy workers. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
"http://localhost:8080/api/workers/status?project_id=PROJECT_ID"Exemple de réponse
{
"connected": 2,
"workers": [
{
"worker_id": "available-1",
"worker_name": "Available worker",
"status": "idle"
},
{
"worker_id": "worker-2",
"worker_name": "Project worker",
"status": "busy",
"connected_at": "2026-04-04T09:45:00Z"
}
]
}Workspaces
Manage workspaces. Users can start with no workspaces; each workspace owns its projects and workers.
GET/api/workspacesList workspacesJeton utilisateur
Returns workspace_members rows for the authenticated user, with each workspace embedded under the workspaces field.
# GET /api/workspacesCorps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspace_id | string | Obligatoire | Workspace UUID from workspace_members. |
role | string | Obligatoire | User role in the workspace. |
workspaces | object | Obligatoire | Embedded workspace: id, name, slug, plan, max_concurrent_executions, created_at. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/workspacesExemple de réponse
[
{
"workspace_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"role": "owner",
"workspaces": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Acme Corp",
"slug": "acme-corp",
"plan": "free",
"max_concurrent_executions": 10,
"created_at": "2026-01-15T08:30:00Z"
}
}
]POST/api/workspacesCreate workspaceJeton utilisateur
Creates a new workspace, inserts the caller as owner, and optionally sets an workspace execution concurrency limit.
# POST /api/workspacesCorps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Display name for the new workspace. |
max_concurrent_executions | number | Facultatif | Optional workspace-wide running execution limit. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created workspace. |
name | string | Obligatoire | Workspace name. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"New Workspace","max_concurrent_executions":5}' \
http://localhost:8080/api/workspacesExemple de réponse
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "New Workspace",
"slug": "new-workspace-1a2b3c4d",
"plan": "free",
"max_concurrent_executions": 5,
"created_at": "2026-04-04T12:00:00Z"
}PUT/api/workspaces/{workspaceId}Update workspaceJeton utilisateur
Updates workspace metadata and workspace-wide execution concurrency for an owner/admin JWT session.
# PUT /api/workspaces/{workspaceId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspaceId | string | Obligatoire | UUID of the workspace. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New display name. |
max_concurrent_executions | number | Facultatif | Workspace-wide running execution limit. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Workspace UUID. |
name | string | Obligatoire | Workspace name. |
max_concurrent_executions | number | Obligatoire | Workspace-wide running execution limit. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_concurrent_executions":5}' \
http://localhost:8080/api/workspaces/b2c3d4e5-f6a7-8901-bcde-f12345678901Exemple de réponse
[
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "New Workspace",
"max_concurrent_executions": 5
}
]GET/api/workspaces/{workspaceId}/statsGet workspace statsJeton utilisateur
Returns aggregate execution and job stats across all projects in a workspace.
# GET /api/workspaces/{workspaceId}/statsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspaceId | string | Obligatoire | UUID of the workspace. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_count | number | Obligatoire | Projects in the workspace. |
total_runs | number | Obligatoire | Total executions. |
passed | number | Obligatoire | Passed executions. |
failed | number | Obligatoire | Failed executions. |
errors | number | Obligatoire | Errored executions. |
running | number | Obligatoire | Running or pending executions. |
avg_duration_ms | number | Obligatoire | Average completed run duration. |
last_run_at | string | null | Obligatoire | Most recent execution creation time. |
pass_rate | number | Obligatoire | Pass percentage across terminal runs. |
job_count | number | Obligatoire | Saved jobs in the workspace. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/workspaces/b2c3d4e5-f6a7-8901-bcde-f12345678901/statsExemple de réponse
{
"project_count": 3,
"total_runs": 128,
"passed": 118,
"failed": 7,
"errors": 3,
"running": 1,
"avg_duration_ms": 2410,
"last_run_at": "2026-05-02T15:30:00Z",
"pass_rate": 92.2,
"job_count": 14
}GET/api/workspaces/{workspaceId}/project-healthGet workspace project healthJeton utilisateur
Returns the latest 12 execution outcomes and current active-run count for every project the authenticated workspace member can access.
# GET /api/workspaces/{workspaceId}/project-healthParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspaceId | string | Obligatoire | UUID of the workspace. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_id | string | Obligatoire | Accessible project UUID. |
recent_runs | array | Obligatoire | Up to 12 recent status and creation-time records, oldest first. |
recent_pass_rate | number | Obligatoire | Pass percentage across recent terminal runs. |
running | number | Obligatoire | All currently pending or running executions. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/workspaces/b2c3d4e5-f6a7-8901-bcde-f12345678901/project-healthExemple de réponse
[
{
"project_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"recent_runs": [
{
"status": "failed",
"created_at": "2026-08-19T10:00:00Z"
},
{
"status": "passed",
"created_at": "2026-08-19T11:00:00Z"
}
],
"recent_pass_rate": 50,
"running": 0
}
]Projects
Manage projects within workspaces. Projects group jobs, test runs, triggers, and queues.
GET/api/workspaces/{workspaceId}/projectsList workspace projectsJeton utilisateur
Returns all projects in the workspace for a browser-authenticated workspace member.
# GET /api/workspaces/{workspaceId}/projectsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspaceId | string | Obligatoire | UUID of the workspace. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Project UUID. |
name | string | Obligatoire | Project name. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/projectsExemple de réponse
[
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "Website QA",
"created_at": "2026-02-01T09:00:00Z"
}
]POST/api/workspaces/{workspaceId}/projectsCreate projectJeton utilisateur
Creates a new project within the specified workspace for an owner/admin JWT session.
# POST /api/workspaces/{workspaceId}/projectsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
workspaceId | string | Obligatoire | UUID of the workspace. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Project name. |
max_concurrent_executions | number | Facultatif | Optional project-level running execution limit. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created project. |
name | string | Obligatoire | Project name. |
workspace_id | string | Obligatoire | UUID of the owning workspace. |
max_concurrent_executions | number | null | Facultatif | Project-level running execution limit, if set. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Checkout Flow RPA","max_concurrent_executions":3}' \
http://localhost:8080/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/projectsExemple de réponse
[
{
"id": "d4e5f6a7-b8c9-0123-defa-234567890123",
"workspace_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Checkout Flow RPA",
"max_concurrent_executions": 3,
"created_at": "2026-04-04T12:30:00Z"
}
]GET/api/projectsList all user projectsJeton utilisateur ou clé API
Returns all projects the authenticated user has access to, across all workspaces.
# GET /api/projectsCorps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Project UUID. |
name | string | Obligatoire | Project name. |
project_type | string | Obligatoire | Project type. |
workspace_id | string | Obligatoire | UUID of the owning workspace. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projectsExemple de réponse
[
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "Website QA",
"project_type": "qa",
"workspace_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"created_at": "2026-02-01T09:00:00Z"
}
]PUT/api/projects/{projectId}Update projectJeton utilisateur
Updates project metadata and clears or sets project-level execution concurrency for an owner/admin JWT session.
# PUT /api/projects/{projectId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New project name. |
max_concurrent_executions | number | null | Facultatif | Project running execution limit, or null to inherit from the workspace. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Project UUID. |
name | string | Obligatoire | Project name. |
max_concurrent_executions | number | null | Facultatif | Project-level running execution limit. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"max_concurrent_executions":null}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012Exemple de réponse
[
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "Website QA",
"max_concurrent_executions": null
}
]GitHub
Connect a project to a GitHub App installation, browse repository state, and export BernOps-managed tests as draft pull requests.
GET/api/github/setupComplete GitHub setupSans authentification
GitHub redirects to this endpoint during OAuth authorization and again after installation. It validates the signed setup state, verifies the installing user can access the returned installation, records the installation, and redirects back to the frontend project GitHub page.
# GET /api/github/setupParamètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
state | string | Obligatoire | Signed setup state returned by GitHub from the authorization or installation URL. |
code | string | Facultatif | GitHub OAuth code returned before installation so BernOps can obtain a user access token for setup verification. |
installation_id | number | Facultatif | GitHub App installation ID assigned by GitHub after OAuth authorization completes. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Location | string | Obligatoire | Frontend redirect URL containing the setup result query parameters. |
Types de contenu: application/json → application/json
Exemple cURL
# Browser redirect endpoint. Start setup through:
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:8080/api/projects/PROJECT_ID/github/install-urlExemple de réponse
HTTP/1.1 302 Found
Location: http://app.bernops-dev/projects/github?projectId=PROJECT_ID&github=installedPOST/api/github/webhooksReceive GitHub webhookSans authentification
Receives GitHub App webhook deliveries, validates the X-Hub-Signature-256 HMAC signature, deduplicates deliveries, and syncs installation, repository, and pull request state. Processing failures are recorded and returned as non-2xx responses so GitHub can retry.
# POST /api/github/webhooksCorps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
payload | GitHub webhook JSON | Obligatoire | Raw GitHub webhook payload. The exact shape depends on the X-GitHub-Event header. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
accepted | boolean | Obligatoire | Whether the delivery was accepted for processing. |
delivery_id | string | Obligatoire | GitHub delivery ID from X-GitHub-Delivery. |
status | string | Facultatif | Processing status recorded for the delivery. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "X-GitHub-Event: installation" \
-H "X-GitHub-Delivery: delivery-001" \
-H "X-Hub-Signature-256: sha256=CALCULATED_SIGNATURE" \
-H "Content-Type: application/json" \
-d '{"action":"created"}' \
http://localhost:8080/api/github/webhooksExemple de réponse
{
"accepted": true,
"delivery_id": "delivery-001",
"status": "processed"
}POST/api/projects/{projectId}/github/install-urlCreate install URLJeton utilisateur
Creates a short-lived signed setup state and returns the GitHub App user authorization URL for a workspace owner/admin. The OAuth step is required before installation so BernOps can verify the returned installation belongs to the installing GitHub user.
# POST /api/projects/{projectId}/github/install-urlParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project to connect. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
url | string | Obligatoire | GitHub App user authorization URL containing the signed state. |
expires_at | string | Obligatoire | ISO 8601 expiry timestamp for the setup state. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/github/install-urlExemple de réponse
{
"url": "https://github.com/login/oauth/authorize?client_id=Iv1.example&redirect_uri=https%3A%2F%2Fapi.bernops.example%2Fapi%2Fgithub%2Fsetup&state=SIGNED_STATE",
"expires_at": "2026-05-03T12:10:00Z"
}GET/api/projects/{projectId}/github/statusGet GitHub statusJeton utilisateur
Returns the project GitHub connection state, available workspace installations, selected repository, pull request sync state, whether the current user can manage the project connection, and whether they can install the workspace GitHub App.
# GET /api/projects/{projectId}/github/statusParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
installed | boolean | Obligatoire | Whether the workspace has at least one GitHub App installation. |
connected | boolean | Obligatoire | Whether the project has a selected repository. |
installations | GitHubInstallation[] | Obligatoire | Workspace installations visible to the project. |
repository | GitHubRepository | null | Facultatif | Selected project repository, if connected. |
pull_requests | GitHubPullRequest[] | Obligatoire | Tracked BernOps export pull requests for the selected repository. |
can_manage | boolean | Obligatoire | Whether the current user can manage the GitHub connection. |
can_install | boolean | Obligatoire | Whether the current user can create workspace-level GitHub App install URLs. |
default_folder | string | Obligatoire | Default folder used when selecting a repository. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/github/statusExemple de réponse
{
"installed": true,
"connected": true,
"installations": [
{
"id": "installation-001",
"account_login": "acme"
}
],
"repository": {
"repo_full_name": "acme/web",
"html_url": "https://github.com/acme/web",
"default_branch": "main",
"test_folder_path": "bernops/e2e"
},
"pull_requests": [],
"can_manage": true,
"can_install": true,
"default_folder": "bernops/e2e"
}DELETE/api/projects/{projectId}/githubDisconnect repositoryJeton utilisateur
Disconnects the selected GitHub repository from a project. The workspace installation remains available for reconnecting this or another repository.
# DELETE /api/projects/{projectId}/githubParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
installed | boolean | Obligatoire | Whether a workspace installation remains available. |
connected | boolean | Obligatoire | Whether the project still has a selected repository. |
installations | GitHubInstallation[] | Obligatoire | Workspace installations still available after disconnecting. |
repository | GitHubRepository | null | Facultatif | Selected repository after disconnecting, normally null. |
pull_requests | GitHubPullRequest[] | Obligatoire | Tracked pull requests after disconnecting, normally empty. |
can_manage | boolean | Obligatoire | Whether the current user can manage the GitHub connection. |
can_install | boolean | Obligatoire | Whether the current user can create workspace-level GitHub App install URLs. |
default_folder | string | Obligatoire | Default export folder used by repository selection. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/githubExemple de réponse
{
"installed": true,
"connected": false,
"repository": null,
"pull_requests": []
}GET/api/projects/{projectId}/github/reposList GitHub repositoriesJeton utilisateur
Lists repositories available through each workspace GitHub App installation so a project admin can select one for BernOps sync.
# GET /api/projects/{projectId}/github/reposParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
installations | Array<{ installation: GitHubInstallation; repositories: GitHubRepository[] }> | Obligatoire | Repositories grouped by installation. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/github/reposExemple de réponse
{
"installations": [
{
"installation": {
"id": "installation-001",
"account_login": "acme"
},
"repositories": [
{
"id": 123,
"full_name": "acme/web",
"default_branch": "main"
}
]
}
]
}POST/api/projects/{projectId}/github/repos/selectSelect repositoryJeton utilisateur
Connects a project to one repository exposed by a workspace GitHub App installation and stores the folder where BernOps-managed tests are exported.
# POST /api/projects/{projectId}/github/repos/selectParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
installation_id | string | Obligatoire | BernOps installation row UUID returned by repository listing. |
github_repo_id | number | Obligatoire | GitHub repository ID to connect. |
test_folder_path | string | Facultatif | Repository folder for BernOps test exports. Defaults to bernops/e2e. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
connected | boolean | Obligatoire | Whether the project now has a selected repository. |
installed | boolean | Obligatoire | Whether the workspace has a GitHub App installation. |
installations | GitHubInstallation[] | Obligatoire | Workspace installations visible to the project. |
repository | GitHubRepository | Obligatoire | Stored repository connection. |
pull_requests | GitHubPullRequest[] | Obligatoire | Tracked BernOps pull requests for the selected repository. |
can_manage | boolean | Obligatoire | Whether the current user can manage the GitHub connection. |
can_install | boolean | Obligatoire | Whether the current user can create workspace-level GitHub App install URLs. |
default_folder | string | Obligatoire | Default export folder used by repository selection. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"installation_id":"installation-001","github_repo_id":123,"test_folder_path":"bernops/e2e"}' \
http://localhost:8080/api/projects/PROJECT_ID/github/repos/selectExemple de réponse
{
"installed": true,
"connected": true,
"repository": {
"repo_full_name": "acme/web",
"html_url": "https://github.com/acme/web",
"default_branch": "main",
"test_folder_path": "bernops/e2e"
}
}GET/api/projects/{projectId}/github/treeGet repository treeJeton utilisateur
Reads the selected repository tree through the project GitHub App installation. Use recursive=true to request a recursive tree from GitHub.
# GET /api/projects/{projectId}/github/treeParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ref | string | Facultatif | Branch, tag, or SHA to read. Defaults to the selected repository default branch. |
recursive | boolean | Facultatif | Whether GitHub should return the tree recursively. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
sha | string | Obligatoire | Tree SHA returned by GitHub. |
entries | GitHubTreeEntry[] | Obligatoire | Repository tree entries. |
truncated | boolean | Facultatif | Whether GitHub truncated the tree response. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
"http://localhost:8080/api/projects/PROJECT_ID/github/tree?recursive=true"Exemple de réponse
{
"sha": "tree-sha",
"entries": [
{
"path": "bernops/e2e/login.spec.ts",
"type": "blob",
"sha": "file-sha"
}
],
"truncated": false
}POST/api/projects/{projectId}/github/export-testsExport tests to GitHubJeton utilisateur
Exports BernOps-managed tests to the selected repository, commits them to a BernOps branch, and opens or updates a draft pull request.
# POST /api/projects/{projectId}/github/export-testsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
pull_request | GitHubPullRequest | Obligatoire | Created or updated GitHub pull request. |
commit | GitHubCommit | Obligatoire | Commit created on the BernOps export branch. |
exported | Array<{ job_id: string; path: string }> | Obligatoire | Tests written to GitHub. |
skipped | Array<{ job_id: string; path?: string; reason: string }> | Obligatoire | Tests skipped because they were empty, duplicated, or conflicted with remote content. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/github/export-testsExemple de réponse
{
"pull_request": {
"number": 42,
"url": "https://github.com/acme/web/pull/42",
"draft": true
},
"commit": {
"branch_name": "bernops/update-tests-20260503121000-ab12cd34",
"commit_sha": "commit-sha",
"tree_sha": "tree-sha"
},
"exported": [
{
"job_id": "job-001",
"path": "bernops/e2e/login.spec.ts"
}
],
"skipped": []
}GET/api/projects/{projectId}/github/pull-requestsList export pull requestsJeton utilisateur
Returns BernOps-tracked GitHub export pull requests for the selected project repository.
# GET /api/projects/{projectId}/github/pull-requestsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
pull_requests | GitHubPullRequest[] | Obligatoire | Tracked pull request records for the selected repository. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/PROJECT_ID/github/pull-requestsExemple de réponse
{
"pull_requests": [
{
"branch_name": "bernops/update-tests-20260503121000-ab12cd34",
"status": "open",
"draft": true,
"pr_number": 42,
"pr_url": "https://github.com/acme/web/pull/42"
}
]
}Project Variables
Manage project runtime variables. Secret values are encrypted, write-only, and only injected into authorized executions.
GET/api/projects/{projectId}/variablesList project variablesJeton utilisateur
Returns variable metadata and plain non-secret values for a project. Secret values are never returned.
# GET /api/projects/{projectId}/variablesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Variable UUID. |
name | string | Obligatoire | Environment variable name. |
is_secret | boolean | Obligatoire | Whether the value is encrypted and write-only. |
value | string | null | Facultatif | Plain value for non-secret variables only. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/project-001/variablesExemple de réponse
[
{
"id": "var-001",
"name": "BASE_URL",
"is_secret": false,
"value": "https://app.example.com"
},
{
"id": "var-002",
"name": "API_TOKEN",
"is_secret": true,
"value": null
}
]POST/api/projects/{projectId}/variablesCreate project variableJeton utilisateur
Creates a plain or secret runtime variable. Project admin access is required.
# POST /api/projects/{projectId}/variablesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Uppercase env var name. |
description | string | Facultatif | Operator-facing description. |
is_secret | boolean | Obligatoire | Encrypt and hide the value after save. |
value | string | Obligatoire | Variable value to store. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Variable UUID. |
name | string | Obligatoire | Environment variable name. |
is_secret | boolean | Obligatoire | Whether the value is secret. |
secret_version | number | Obligatoire | Secret version counter. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"API_TOKEN","description":"CI token","is_secret":true,"value":"secret-value"}' \
http://localhost:8080/api/projects/project-001/variablesExemple de réponse
{
"id": "var-002",
"name": "API_TOKEN",
"is_secret": true,
"value": null,
"secret_version": 1
}PUT/api/project-variables/{variableId}Update project variableJeton utilisateur
Updates variable metadata or value. Updating a secret value increments its secret version.
# PUT /api/project-variables/{variableId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
variableId | string | Obligatoire | UUID of the variable. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New uppercase env var name. |
description | string | Facultatif | New description. |
value | string | Facultatif | New value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Variable UUID. |
name | string | Obligatoire | Environment variable name. |
secret_version | number | Obligatoire | Secret version counter. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"description":"Rotated token"}' \
http://localhost:8080/api/project-variables/var-002Exemple de réponse
{
"id": "var-002",
"name": "API_TOKEN",
"is_secret": true,
"value": null,
"secret_version": 2
}DELETE/api/project-variables/{variableId}Delete project variableJeton utilisateur
Deletes a project variable after project admin access checks.
# DELETE /api/project-variables/{variableId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
variableId | string | Obligatoire | UUID of the variable. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
deleted | boolean | Obligatoire | Deletion confirmation. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/project-variables/var-002Exemple de réponse
{
"deleted": true
}POST/api/project-variables/{variableId}/rotateRotate secret variableJeton utilisateur
Replaces the value for a secret variable and increments its version.
# POST /api/project-variables/{variableId}/rotateParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
variableId | string | Obligatoire | UUID of the secret variable. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
value | string | Obligatoire | New secret value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Variable UUID. |
secret_version | number | Obligatoire | Incremented secret version. |
last_rotated_at | string | Obligatoire | Rotation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"value":"new-secret-value"}' \
http://localhost:8080/api/project-variables/var-002/rotateExemple de réponse
{
"id": "var-002",
"name": "API_TOKEN",
"is_secret": true,
"value": null,
"secret_version": 3
}Jobs
Manage Playwright test jobs within a project. Jobs contain the test code that can be executed on demand or via triggers.
GET/api/projects/{projectId}/jobsList jobsJeton utilisateur ou clé API
Returns all jobs belonging to the specified project.
# GET /api/projects/{projectId}/jobsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Job UUID. |
name | string | Obligatoire | Job display name. |
description | string | Facultatif | Optional description. |
file_name | string | Facultatif | Original file name. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/jobsExemple de réponse
[
{
"id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"name": "Login Flow",
"description": "Tests the sign-in flow end to end.",
"file_name": "login.spec.ts",
"created_at": "2026-03-10T14:00:00Z"
}
]POST/api/projects/{projectId}/jobsCreate jobJeton utilisateur ou clé API
Creates a new job within the specified project. Project API keys need jobs:write. The code field contains the Playwright test source.
# POST /api/projects/{projectId}/jobsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Job display name. |
description | string | Facultatif | Optional description of what the job tests. |
code | string | Obligatoire | Playwright test source code. |
file_name | string | Facultatif | Original file name (e.g. login.spec.ts). |
max_concurrent_executions | number | null | Facultatif | Optional per-job concurrency limit. Null inherits project and workspace limits. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created job. |
name | string | Obligatoire | Job name. |
code | string | Obligatoire | Job source code. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
max_concurrent_executions | number | null | Facultatif | Per-script concurrency limit, when configured. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name":"Login Flow","code":"import { test } from ...","file_name":"login.spec.ts","max_concurrent_executions":1}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/jobsExemple de réponse
{
"id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
"name": "Login Flow",
"code": "import { test } from '@playwright/test'; ...",
"max_concurrent_executions": 1,
"created_at": "2026-04-04T13:00:00Z"
}GET/api/jobs/{jobId}Get jobJeton utilisateur ou clé API
Returns the full details of a single job, including its code.
# GET /api/jobs/{jobId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the job. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Job UUID. |
name | string | Obligatoire | Job name. |
description | string | Facultatif | Optional description. |
code | string | Obligatoire | Playwright test source code. |
file_name | string | Facultatif | Original file name. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234Exemple de réponse
{
"id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"name": "Login Flow",
"description": "Tests the sign-in flow end to end.",
"code": "import { test } from '@playwright/test'; ...",
"file_name": "login.spec.ts",
"created_at": "2026-03-10T14:00:00Z"
}PUT/api/jobs/{jobId}Update jobJeton utilisateur ou clé API
Updates an existing job. Project API keys need jobs:write. All fields in the request body are optional; only provided fields are updated.
# PUT /api/jobs/{jobId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the job. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New job name. |
description | string | Facultatif | New description. |
code | string | Facultatif | Updated Playwright test source code. |
file_name | string | Facultatif | Updated file name. |
max_concurrent_executions | number | null | Facultatif | Set or clear the per-job concurrency limit. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Job UUID. |
name | string | Obligatoire | Updated job name. |
code | string | Obligatoire | Updated source code. |
max_concurrent_executions | number | null | Facultatif | Per-script concurrency limit, when configured. |
updated_at | string | Obligatoire | ISO 8601 update timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name":"Login Flow v2","code":"import { test } from ...","max_concurrent_executions":1}' \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234Exemple de réponse
{
"id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"name": "Login Flow v2",
"code": "import { test } from '@playwright/test'; ...",
"max_concurrent_executions": 1,
"updated_at": "2026-04-04T14:00:00Z"
}DELETE/api/jobs/{jobId}Delete jobJeton utilisateur ou clé API
Permanently deletes a job and its association with triggers. Project API keys need jobs:write. Existing test run history is preserved.
# DELETE /api/jobs/{jobId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the job to delete. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
message | string | Obligatoire | Confirmation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234Exemple de réponse
{
"message": "Job deleted successfully."
}GET/api/jobs/{jobId}/runsList job runsJeton utilisateur ou clé API
Returns all test runs associated with a specific job, ordered by most recent first.
# GET /api/jobs/{jobId}/runsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the job. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Test run execution ID. |
status | string | Obligatoire | Run status: "pending", "running", "passed", "failed", "cancelled". |
started_at | string | Facultatif | ISO 8601 start timestamp. |
completed_at | string | Facultatif | ISO 8601 completion timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234/runsExemple de réponse
[
{
"id": "run-001",
"status": "passed",
"started_at": "2026-04-04T10:00:00Z",
"completed_at": "2026-04-04T10:02:30Z"
}
]POST/api/jobs/{jobId}/executeExecute jobJeton utilisateur ou clé API
Starts a test run from a saved job and dispatches it to an available worker. Project API keys need `jobs:execute`; keys with `variables:use` include secret project variables by default unless `include_secret_variables` is false. JWT callers only include secrets when `include_secret_variables` is explicitly true.
# POST /api/jobs/{jobId}/executeParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the saved job to execute. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
base_url | string | Facultatif | Base URL override for this run. |
include_secret_variables | boolean | Facultatif | Whether to include secret project variables. Defaults to true for API keys with `variables:use`, false otherwise. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
execution_id | string | Obligatoire | Unique execution ID for this test run. |
status | string | Obligatoire | Initial status, typically "pending" or "running". |
worker_id | string | Facultatif | ID of the assigned worker, if dispatched immediately. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"base_url":"https://staging.example.com"}' \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234/executeExemple de réponse
{
"execution_id": "exec-a1b2c3d4",
"status": "running",
"worker_id": "worker-1"
}GET/api/jobs/{jobId}/statsGet job statsJeton utilisateur ou clé API
Returns aggregated statistics for a job: total runs, pass rate, average duration.
# GET /api/jobs/{jobId}/statsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
jobId | string | Obligatoire | UUID of the job. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
total_runs | number | Obligatoire | Total number of runs for this job. |
pass_rate | number | Obligatoire | Percentage of passed runs (0-100). |
avg_duration_ms | number | Obligatoire | Average run duration in milliseconds. |
last_run_at | string | Facultatif | ISO 8601 timestamp of the most recent run. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/jobs/e5f6a7b8-c9d0-1234-efab-345678901234/statsExemple de réponse
{
"total_runs": 42,
"pass_rate": 95.2,
"avg_duration_ms": 15200,
"last_run_at": "2026-04-04T10:02:30Z"
}Test Runs
Execute and monitor Playwright test runs. Runs are dispatched to connected workers and stream logs and steps in real time.
POST/api/projects/{projectId}/test-runsStart test runJeton utilisateur ou clé API
Creates a new test run and dispatches it to an available worker. Provide `test_files` for an ad-hoc run or a `job_id` to execute a saved job.
# POST /api/projects/{projectId}/test-runsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
test_files | TestFile[] | Facultatif | Inline Playwright files to execute. Each entry should include `file_name` and `code`. |
base_url | string | Facultatif | Base URL override for this run. |
job_id | string | Facultatif | UUID of a saved job to execute. When present, `jobs:execute` is sufficient. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
execution_id | string | Obligatoire | Unique execution ID for this test run. |
status | string | Obligatoire | Initial status (typically "pending" or "running"). |
worker_id | string | Facultatif | ID of the assigned worker, if dispatched immediately. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"test_files":[{"file_name":"checkout.spec.ts","code":"import { test } from "@playwright/test";"}],"base_url":"https://staging.example.com"}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/test-runsExemple de réponse
{
"execution_id": "exec-a1b2c3d4",
"status": "running",
"worker_id": "worker-1"
}GET/api/projects/{projectId}/test-runsList test runsJeton utilisateur ou clé API
Returns test runs for the specified project, ordered by most recent first. Job-scoped API keys only receive runs for their bound external job.
# GET /api/projects/{projectId}/test-runsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Test run execution ID. |
status | string | Obligatoire | Run status. |
job_id | string | Facultatif | Associated job UUID, if any. |
started_at | string | Facultatif | ISO 8601 start timestamp. |
completed_at | string | Facultatif | ISO 8601 completion timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/test-runsExemple de réponse
[
{
"id": "exec-a1b2c3d4",
"status": "passed",
"job_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"started_at": "2026-04-04T13:00:00Z",
"completed_at": "2026-04-04T13:02:15Z"
}
]GET/api/projects/{projectId}/statsGet project statsJeton utilisateur ou clé API
Returns exact aggregate execution statistics for the project. Job-scoped API keys receive only their bound external job's execution totals.
# GET /api/projects/{projectId}/statsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
total_runs | number | Obligatoire | Total test runs in this project. |
pass_rate | number | Obligatoire | Percentage of passed runs (0-100). |
passed | number | Obligatoire | Passed executions. |
failed | number | Obligatoire | Failed executions. |
errors | number | Obligatoire | Errored executions. |
running | number | Obligatoire | Pending or running executions. |
avg_duration_ms | number | Obligatoire | Average duration across executions that reported one. |
last_run_at | string | null | Obligatoire | Most recent execution creation time. |
job_count | number | Obligatoire | Saved jobs in the project for unscoped callers. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/statsExemple de réponse
{
"total_runs": 156,
"passed": 144,
"failed": 7,
"errors": 5,
"running": 0,
"avg_duration_ms": 2410,
"last_run_at": "2026-08-19T12:00:00Z",
"pass_rate": 92.3,
"job_count": 12
}GET/api/projects/{projectId}/run-activityGet project run activityJeton utilisateur ou clé API
Returns exact daily outcome buckets for the requested 1-30 day window. Dates use the requested IANA time zone, and job-scoped API keys receive only their bound external job's executions.
# GET /api/projects/{projectId}/run-activityParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
days | integer | Facultatif | Number of daily buckets to return, from 1 through 30. (Par défaut: 7) |
timezone | string | Facultatif | IANA time zone used to determine each execution's calendar date. (Par défaut: UTC) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
[].date | string | Obligatoire | Calendar date in YYYY-MM-DD format. |
[].passed | number | Obligatoire | Executions that passed on this date. |
[].unsuccessful | number | Obligatoire | Executions that failed or errored on this date. |
[].active | number | Obligatoire | Executions that are pending or running on this date. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
"http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/run-activity?days=7&timezone=America%2FToronto"Exemple de réponse
[
{
"date": "2026-08-18",
"passed": 18,
"unsuccessful": 2,
"active": 0
},
{
"date": "2026-08-19",
"passed": 11,
"unsuccessful": 1,
"active": 2
}
]GET/api/projects/{projectId}/dashboard-runsGet project dashboard run summariesJeton utilisateur ou clé API
Returns the latest 60 lightweight run summaries and the latest execution for each saved job without transferring execution results or runtime variables.
# GET /api/projects/{projectId}/dashboard-runsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
recent_runs | RunSummary[] | Obligatoire | At most 60 runs ordered newest first. |
latest_job_runs | RunSummary[] | Obligatoire | Latest execution for each saved job that has run. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/dashboard-runsExemple de réponse
{
"recent_runs": [
{
"id": "exec-a1b2c3d4",
"job_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"status": "passed",
"duration_ms": 2410,
"created_at": "2026-08-19T12:00:00Z"
}
],
"latest_job_runs": [
{
"id": "exec-a1b2c3d4",
"job_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"status": "passed",
"duration_ms": 2410,
"created_at": "2026-08-19T12:00:00Z"
}
]
}GET/api/test-runs/{executionId}Get test run detailsJeton utilisateur ou clé API
Returns detailed information about a specific test run, including its current status and timing.
# GET /api/test-runs/{executionId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution ID of the test run. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
[] | TestExecution[] | Obligatoire | Array containing the matching execution record. |
[].id | string | Obligatoire | Test run execution ID. |
[].status | string | Obligatoire | Current run status. |
[].project_id | string | Obligatoire | UUID of the parent project. |
[].progress | ProgressSnapshot | null | Obligatoire | Latest canonical progress snapshot, or null when no progress was reported. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/test-runs/exec-a1b2c3d4Exemple de réponse
[
{
"id": "exec-a1b2c3d4",
"status": "passed",
"project_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"worker_id": "worker-1",
"started_at": "2026-04-04T13:00:00Z",
"finished_at": "2026-04-04T13:02:15Z"
}
]GET/api/test-runs/{executionId}/logsGet test run logsJeton utilisateur ou clé API
Returns the console output and log entries from a test run execution.
# GET /api/test-runs/{executionId}/logsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution ID of the test run. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum number of log rows to return. (Par défaut: 50) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | LogEntry[] | Obligatoire | Array of log entries. |
total | number | Obligatoire | Total number of log rows for the execution. |
data[].timestamp | string | Obligatoire | ISO 8601 timestamp of the log entry. |
data[].level | string | Obligatoire | Log level: "info", "warn", "error", "debug". |
data[].message | string | Obligatoire | Log message content. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/test-runs/exec-a1b2c3d4/logsExemple de réponse
{
"data": [
{
"timestamp": "2026-04-04T13:00:01Z",
"level": "info",
"message": "Running test: login.spec.ts"
},
{
"timestamp": "2026-04-04T13:02:15Z",
"level": "info",
"message": "All tests passed."
}
],
"total": 2,
"limit": 50,
"offset": 0
}GET/api/test-runs/{executionId}/stepsGet test run stepsJeton utilisateur ou clé API
Returns the individual test steps and their results from a test run execution.
# GET /api/test-runs/{executionId}/stepsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution ID of the test run. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum number of step rows to return. (Par défaut: 50) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | TestStep[] | Obligatoire | Array of test steps. |
total | number | Obligatoire | Total number of stored step rows for the execution. |
data[].event | string | Obligatoire | Step event name such as test:start, step:start, or step:end. |
data[].title | string | Facultatif | Display title for the step event. |
data[].duration_ms | number | Facultatif | Step duration in milliseconds. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/test-runs/exec-a1b2c3d4/stepsExemple de réponse
{
"data": [
{
"event": "step:start",
"title": "navigate to /login",
"status": "running",
"duration_ms": 320
},
{
"event": "step:end",
"title": "fill #email",
"status": "passed",
"duration_ms": 45
}
],
"total": 2,
"limit": 50,
"offset": 0
}POST/api/test-runs/{executionId}/cancelCancel test runJeton utilisateur ou clé API
Marks a running or pending test run as cancelled and broadcasts the updated status to connected clients.
# POST /api/test-runs/{executionId}/cancelParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution ID of the test run to cancel. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
execution_id | string | Obligatoire | Execution ID of the cancelled run. |
status | string | Obligatoire | Updated status ("error"). |
message | string | Obligatoire | Human-readable cancellation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/test-runs/exec-a1b2c3d4/cancelExemple de réponse
{
"execution_id": "exec-a1b2c3d4",
"status": "error",
"message": "Run cancelled"
}External Jobs
Create job-scoped automation entry points, inspect external-job health, and run retention cleanup.
GET/api/projects/{projectId}/external-jobsList external jobsJeton utilisateur ou clé API
Returns external jobs for a project. Job-scoped API keys only receive their bound job.
# GET /api/projects/{projectId}/external-jobsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | Project UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | External job UUID. |
name | string | Obligatoire | Job display name. |
slug | string | Obligatoire | Project-unique slug. |
retention_policy | object | Obligatoire | Current retention policy. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/external-jobsExemple de réponse
[
{
"id": "job-001",
"name": "Morning billing sync",
"slug": "morning-billing-sync"
}
]POST/api/projects/{projectId}/external-jobsCreate external jobJeton utilisateur ou clé API
Creates a new external job. JWT callers receive the initial plaintext API key once; API-key-authenticated callers receive `api_key: null`.
# POST /api/projects/{projectId}/external-jobsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | Project UUID. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Job display name. |
description | string | Facultatif | Optional description. |
default_service | string | Facultatif | Default service for future runs. |
default_environment | string | Facultatif | Default environment for future runs. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
job | object | Obligatoire | Created external job. |
api_key | object | null | Obligatoire | Initial API key metadata, or `null` for API-key-authenticated callers. |
api_key.key | string | Facultatif | Plaintext key shown only once for JWT callers. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" -H "Content-Type: application/json" -d '{"name":"Morning billing sync"}' http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/external-jobsExemple de réponse
{
"job": {
"id": "job-001",
"name": "Morning billing sync"
},
"api_key": {
"key": "bo_live_abc123"
}
}GET/api/external-jobs/{externalJobId}Get external jobJeton utilisateur ou clé API
Returns the full configuration for one external job.
# GET /api/external-jobs/{externalJobId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | External job UUID. |
project_id | string | Obligatoire | Owning project UUID. |
retention_policy | object | Obligatoire | Retention policy. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/external-jobs/job-001Exemple de réponse
[
{
"id": "job-001",
"project_id": "proj-001"
}
]PUT/api/external-jobs/{externalJobId}Update external jobJeton utilisateur ou clé API
Updates retention and default metadata for an external job.
# PUT /api/external-jobs/{externalJobId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
retention_policy | object | Facultatif | Updated retention policy. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Updated job UUID. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer YOUR_JWT_TOKEN" -H "Content-Type: application/json" -d '{"retention_policy":{"events_days":7,"metrics_days":30,"attachments_days":7,"keep_run_summary_forever":true}}' http://localhost:8080/api/external-jobs/job-001Exemple de réponse
[
{
"id": "job-001"
}
]GET/api/external-jobs/{externalJobId}/statsGet external job statsJeton utilisateur ou clé API
Returns summary metrics such as total runs, pass rate, and average duration.
# GET /api/external-jobs/{externalJobId}/statsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
total_runs | number | Obligatoire | Total runs for this job. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/external-jobs/job-001/statsExemple de réponse
{
"total_runs": 12,
"pass_rate": 91.7,
"avg_duration_ms": 18420
}GET/api/external-jobs/{externalJobId}/metricsList external job metricsJeton utilisateur ou clé API
Returns metric points for one external job with optional name and time filters.
# GET /api/external-jobs/{externalJobId}/metricsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | Metric name to filter by. |
from | string | Facultatif | Inclusive ISO 8601 lower bound for event_at. |
to | string | Facultatif | Inclusive ISO 8601 upper bound for event_at. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Metric name. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/external-jobs/job-001/metrics?name=invoices.processed"Exemple de réponse
[
{
"name": "invoices.processed",
"value": 124
}
]GET/api/external-jobs/{externalJobId}/runsList external job runsJeton utilisateur ou clé API
Returns paginated runs for one external job.
# GET /api/external-jobs/{externalJobId}/runsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum number of runs to return. (Par défaut: 100) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | Run[] | Obligatoire | Paginated run data. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/external-jobs/job-001/runs?limit=5&offset=0"Exemple de réponse
{
"data": [
{
"id": "run-001",
"display_name": "Morning billing sync"
}
],
"total": 1,
"limit": 5,
"offset": 0
}GET/api/external-jobs/{externalJobId}/cleanup-statusGet cleanup statusJeton utilisateur ou clé API
Returns the most recent retention cleanup run for an external job.
# GET /api/external-jobs/{externalJobId}/cleanup-statusParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
cleanup | object | Facultatif | Latest cleanup record, if any. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/external-jobs/job-001/cleanup-statusExemple de réponse
{
"cleanup": {
"status": "completed",
"deleted_logs": 120
}
}POST/api/external-jobs/{externalJobId}/cleanupRun retention cleanupJeton utilisateur ou clé API
Triggers retention cleanup for one external job immediately.
# POST /api/external-jobs/{externalJobId}/cleanupParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
externalJobId | string | Obligatoire | External job UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
cleanup.status | string | Obligatoire | Cleanup result status. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/external-jobs/job-001/cleanupExemple de réponse
{
"cleanup": {
"status": "completed",
"deleted_storage_objects": 1
}
}External Ingest
Use a scoped external job key to start runs, stream telemetry, upload attachments, and finish runs from any system.
POST/api/ingest/runsStart external runJeton utilisateur ou clé API
Creates a new external run or returns the existing run when the same external_run_id is retried.
# POST /api/ingest/runsCorps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
external_job_id | string | Facultatif | External job UUID. Optional when the API key is already job-scoped. |
external_run_id | string | Facultatif | Caller-defined idempotency key for the run. |
display_name | string | Facultatif | Human-readable run title. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
execution_id | string | Obligatoire | Created or reused execution ID. |
duplicate | boolean | Obligatoire | Whether this call reused an existing run. |
progress_sequence | number | Obligatoire | Latest accepted producer sequence, or zero for a new run. |
progress_revision | number | Obligatoire | Latest persisted server revision, or zero for a new run. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"external_job_id":"job-001","external_run_id":"cron-2026-04-08T09:00:00Z","display_name":"Morning billing sync"}' http://localhost:8080/api/ingest/runsExemple de réponse
{
"execution_id": "run-001",
"status": "running",
"duplicate": false,
"progress_sequence": 0,
"progress_revision": 0
}POST/api/ingest/runs/{runId}/logsAppend log eventJeton utilisateur ou clé API
Stores one log event for a running external execution.
# POST /api/ingest/runs/{runId}/logsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
event_id | string | Facultatif | Idempotency key for this log. |
message | string | Obligatoire | Log message. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
accepted | boolean | Obligatoire | Whether the event was accepted. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"event_id":"log-001","message":"Fetched 124 invoices"}' http://localhost:8080/api/ingest/runs/run-001/logsExemple de réponse
{
"accepted": true,
"duplicate": false
}POST/api/ingest/runs/{runId}/stepsAppend step eventJeton utilisateur ou clé API
Stores one step event for the execution timeline.
# POST /api/ingest/runs/{runId}/stepsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
event_id | string | Facultatif | Idempotency key for this step event. |
event | string | Obligatoire | Event name such as step:start or step:end. |
title | string | Facultatif | Display title for the step. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
accepted | boolean | Obligatoire | Whether the event was accepted. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"event":"step:start","title":"Fetch invoices"}' http://localhost:8080/api/ingest/runs/run-001/stepsExemple de réponse
{
"accepted": true,
"duplicate": false
}POST/api/ingest/runs/{runId}/metricsAppend metric pointJeton utilisateur ou clé API
Stores one metric sample for the execution.
# POST /api/ingest/runs/{runId}/metricsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
event_id | string | Facultatif | Idempotency key for this metric sample. |
name | string | Obligatoire | Metric name. |
kind | string | Obligatoire | gauge, count, rate, or duration. |
value | number | Obligatoire | Metric value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
accepted | boolean | Obligatoire | Whether the metric was accepted. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"name":"invoices.processed","kind":"count","value":124}' http://localhost:8080/api/ingest/runs/run-001/metricsExemple de réponse
{
"accepted": true,
"duplicate": false
}POST/api/ingest/runs/{runId}/progressReport run progressJeton utilisateur ou clé API
Atomically stores count, percent-only, or indeterminate progress. Exact event retries return the original canonical snapshot.
# POST /api/ingest/runs/{runId}/progressParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
event_id | string | Obligatoire | Stable idempotency key for this progress report. |
sequence | number | Obligatoire | Positive increasing producer sequence. |
current | number | Facultatif | Current count; provide with total only. |
total | number | Facultatif | Positive total count; provide with current only. |
percent | number | Facultatif | Percent-only progress from 0 through 100. |
stage | string | Facultatif | Current stage, up to 128 characters. |
message | string | Facultatif | Progress message, up to 1024 characters. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
accepted | boolean | Obligatoire | Whether the report was accepted. |
duplicate | boolean | Obligatoire | Whether this was an exact retry. |
progress | ProgressSnapshot | Obligatoire | Canonical persisted snapshot with server revision. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"event_id":"progress-001","sequence":1,"current":62,"total":100,"stage":"processing"}' http://localhost:8080/api/ingest/runs/run-001/progressExemple de réponse
{
"accepted": true,
"duplicate": false,
"progress": {
"execution_id": "run-001",
"event_id": "progress-001",
"sequence": 1,
"revision": 1,
"mode": "count",
"current": 62,
"total": 100,
"percent": 62,
"stage": "processing",
"message": "Processed 62 invoices",
"reported_at": "2026-04-08T09:00:32Z",
"updated_at": "2026-04-08T09:00:32.100Z"
}
}POST/api/ingest/runs/{runId}/attachmentsUpload attachmentJeton utilisateur ou clé API
Streams one supported attachment into the private execution-attachments bucket and stores metadata on the run.
# POST /api/ingest/runs/{runId}/attachmentsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
file | multipart file | Obligatoire | Supported file to upload. |
event_id | string | Facultatif | Idempotency key for this attachment. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
attachment_id | string | Obligatoire | Created attachment UUID. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -F "[email protected];type=application/json" -F "event_id=att-001" http://localhost:8080/api/ingest/runs/run-001/attachmentsExemple de réponse
{
"attachment_id": "att-001",
"file_name": "report.json"
}POST/api/ingest/runs/{runId}/heartbeatUpdate heartbeatJeton utilisateur ou clé API
Updates the last heartbeat timestamp for a running external execution.
# POST /api/ingest/runs/{runId}/heartbeatParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
heartbeat_at | string | Facultatif | Optional ISO 8601 heartbeat timestamp. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
last_heartbeat_at | string | Obligatoire | Stored heartbeat timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"heartbeat_at":"2026-04-08T09:05:00Z"}' http://localhost:8080/api/ingest/runs/run-001/heartbeatExemple de réponse
{
"execution_id": "run-001",
"last_heartbeat_at": "2026-04-08T09:05:00Z"
}POST/api/ingest/runs/{runId}/completeComplete external runJeton utilisateur ou clé API
Marks the external execution as passed and stores a final summary.
# POST /api/ingest/runs/{runId}/completeParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
finished_at | string | Facultatif | ISO 8601 finish timestamp. |
duration_ms | number | Facultatif | Execution duration in milliseconds. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
status | string | Obligatoire | Final execution status. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"finished_at":"2026-04-08T09:10:00Z","duration_ms":600000}' http://localhost:8080/api/ingest/runs/run-001/completeExemple de réponse
{
"execution_id": "run-001",
"status": "passed"
}POST/api/ingest/runs/{runId}/failFail external runJeton utilisateur ou clé API
Marks the external execution as failed.
# POST /api/ingest/runs/{runId}/failParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
runId | string | Obligatoire | Execution UUID returned by start run. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
error | string | Obligatoire | Error message describing the failure. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
status | string | Obligatoire | Final execution status. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -d '{"error":"Unable to process invoices"}' http://localhost:8080/api/ingest/runs/run-001/failExemple de réponse
{
"execution_id": "run-001",
"status": "failed"
}GET/api/test-runs/{executionId}/metricsGet run metricsJeton utilisateur ou clé API
Returns paginated metric points for one execution.
# GET /api/test-runs/{executionId}/metricsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution UUID. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum records to return. (Par défaut: 100) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | Metric[] | Obligatoire | Paginated metric data. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/test-runs/run-001/metrics?limit=100&offset=0"Exemple de réponse
{
"data": [
{
"name": "invoices.processed",
"value": 124,
"unit": "items"
}
],
"total": 1,
"limit": 100,
"offset": 0
}GET/api/test-runs/{executionId}/progressGet run progress historyJeton utilisateur ou clé API
Returns paginated canonical progress snapshots ordered by server revision.
# GET /api/test-runs/{executionId}/progressParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution UUID. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum records to return. (Par défaut: 50) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | ProgressSnapshot[] | Obligatoire | Canonical progress history. |
total | number | Obligatoire | Total retained progress events. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/test-runs/run-001/progress?limit=50&offset=0"Exemple de réponse
{
"data": [
{
"execution_id": "run-001",
"event_id": "progress-001",
"sequence": 1,
"revision": 1,
"mode": "percent",
"current": null,
"total": null,
"percent": 72.5,
"stage": "uploading",
"message": null,
"reported_at": "2026-04-08T09:05:32Z",
"updated_at": "2026-04-08T09:05:32.100Z"
}
],
"total": 1,
"limit": 50,
"offset": 0
}GET/api/test-runs/{executionId}/attachmentsGet run attachmentsJeton utilisateur ou clé API
Returns paginated attachment metadata for one execution.
# GET /api/test-runs/{executionId}/attachmentsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution UUID. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | number | Facultatif | Maximum records to return. (Par défaut: 50) |
offset | number | Facultatif | Pagination offset. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | Attachment[] | Obligatoire | Paginated attachment data. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/test-runs/run-001/attachments?limit=50&offset=0"Exemple de réponse
{
"data": [
{
"file_name": "report.json",
"content_type": "application/json",
"size_bytes": 17
}
],
"total": 1,
"limit": 50,
"offset": 0
}GET/api/test-runs/{executionId}/attachments/{attachmentId}/downloadGet attachment download URLJeton utilisateur ou clé API
Returns a short-lived signed URL for downloading a private run attachment.
# GET /api/test-runs/{executionId}/attachments/{attachmentId}/downloadParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
executionId | string | Obligatoire | Execution UUID. |
attachmentId | string | Obligatoire | Attachment UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
attachment_id | string | Obligatoire | Attachment UUID. |
file_name | string | Obligatoire | Attachment file name. |
content_type | string | Obligatoire | Attachment content type. |
download_url | string | Obligatoire | Short-lived signed download URL. |
expires_at | string | Obligatoire | ISO 8601 expiration timestamp for the signed URL. |
expires_in_seconds | number | Obligatoire | Signed URL lifetime in seconds. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/test-runs/run-001/attachments/att-001/downloadExemple de réponse
{
"attachment_id": "att-001",
"file_name": "report.json",
"content_type": "application/json",
"download_url": "http://127.0.0.1:54321/storage/v1/object/sign/execution-attachments/project/...",
"expires_at": "2026-04-08T09:06:00Z",
"expires_in_seconds": 300
}Wiki
Manage the independent project wiki. Dual-auth routes accept a project member JWT or a project-bound API key with all documented wiki scopes. API keys never gain archive, unarchive, attachment-delete, or archive-import administration rights. Authentication middleware may return plain-text 401/403 errors before a coded wiki response.
GET/api/projects/{projectId}/wiki/pagesList or search wiki pagesJeton utilisateur ou clé API
Returns bounded page summaries without Markdown bodies, plus the normalized search options and caller capabilities. Results come from the project-scoped full-text search and can include active, archived, or all pages.
# GET /api/projects/{projectId}/wiki/pagesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
q | string | Facultatif | Trimmed full-text query, at most 500 Unicode characters. |
archive | active | archived | all | Facultatif | Archive-state filter. (Par défaut: active) |
limit | integer | Facultatif | Maximum page summaries, from 1 through 100. (Par défaut: 50) |
offset | integer | Facultatif | Zero-based result offset, from 0 through 10000. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
pages | WikiPageSummary[] | Obligatoire | Summaries with id, project_id, title, slug, filename, revision, archived_at, updated_at, and numeric rank; body_markdown is intentionally omitted. |
q | string | Obligatoire | Normalized query. |
archive | active | archived | all | Obligatoire | Applied archive filter. |
limit | integer | Obligatoire | Applied limit. |
offset | integer | Obligatoire | Applied offset. |
capabilities.can_create | boolean | Obligatoire | Whether this principal can create pages. |
capabilities.can_export | boolean | Obligatoire | Always true after project read authorization. |
capabilities.can_import | boolean | Obligatoire | True only for an authorized JWT project administrator. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
invalid_wiki_search | 400 | Facultatif | q, archive, limit, or offset is outside the accepted contract. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages?q=incident&archive=active&limit=50&offset=0"Exemple de réponse
{
"pages": [
{
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"title": "Incident response",
"slug": "incident-response",
"filename": "runbooks/incident-response.md",
"revision": 3,
"archived_at": null,
"updated_at": "2026-08-16T10:30:00Z",
"rank": 0.42
}
],
"q": "incident",
"archive": "active",
"limit": 50,
"offset": 0,
"capabilities": {
"can_create": true,
"can_export": true,
"can_import": false
}
}POST/api/projects/{projectId}/wiki/pagesCreate a wiki pageJeton utilisateur ou clé API
Creates revision 1 transactionally. JWT users need project mutation access; API keys need wiki:write and Idempotency-Key. Slug defaults from title, filename defaults from slug, and Markdown defaults to empty. JSON is capped at 8 MiB and unknown fields are rejected.
# POST /api/projects/{projectId}/wiki/pagesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
title | string | Obligatoire | Title normalized by trimming; final length is 1-300 characters. |
slug | string | Facultatif | Source for a lowercase kebab-case slug, at most 200 characters. Defaults to title. |
filename | string | Facultatif | Source for a lowercase relative .md path, 3-512 characters. Defaults to {slug}.md. |
body_markdown | string | Facultatif | UTF-8 Markdown; canonical result is at most 1 MiB. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | noop | Obligatoire | Whether this command changed the page. |
code | string | Obligatoire | Stable success/no-op code for this command. |
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
audit_event_id | UUID | null | Obligatoire | Append-only audit event ID, or null for a no-op. |
source_revision | integer | Facultatif | Source revision on a restore result. |
replayed | boolean | Obligatoire | True when an exact Idempotency-Key retry replayed this result. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
invalid_json_body | 400 | Facultatif | The body is not one JSON value, contains unknown fields, or has invalid field types. |
request_body_too_large | 413 | Facultatif | The JSON request exceeds the route's byte limit. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
invalid_title | 400 | Facultatif | The normalized title is empty or longer than 300 characters. |
invalid_slug | 400 | Facultatif | The normalized slug is empty, longer than 200 characters, or cannot match lowercase kebab-case. |
invalid_filename | 400 | Facultatif | The normalized Markdown filename is invalid, hidden, non-canonical, or longer than 512 characters. |
markdown_too_large | 413 | Facultatif | Canonical UTF-8 Markdown exceeds 1 MiB. |
wiki_slug_conflict | 409 | Facultatif | Another project wiki page already uses the normalized slug. |
wiki_filename_conflict | 409 | Facultatif | Another project wiki page already uses the normalized filename. |
revision_exhausted | 409 | Facultatif | The page reached revision 9007199254740991. |
wiki_attachment_reference_not_found | 409 | Facultatif | Markdown references an attachment that does not exist on this project page. |
invalid_create_input | 400 | Facultatif | title is missing or a request field has an invalid type. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -H "Idempotency-Key: create-incident-response-v1" -d '{"title":"Incident response","slug":"incident-response","filename":"runbooks/incident-response.md","body_markdown":"# Incident response\n"}' http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pagesExemple de réponse
{
"outcome": "applied",
"code": "wiki_page_created",
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"title": "Incident response",
"slug": "incident-response",
"normalized_slug": "incident-response",
"filename": "runbooks/incident-response.md",
"normalized_filename": "runbooks/incident-response.md",
"body_markdown": "# Incident response\n",
"revision": 1,
"archived_at": null,
"created_actor_kind": "api_key",
"created_actor_api_key_id": "d2600000-0000-0000-0000-000000000401",
"created_actor_display": "d2600000-0000-0000-0000-000000000401",
"updated_actor_kind": "api_key",
"updated_actor_api_key_id": "d2600000-0000-0000-0000-000000000401",
"updated_actor_display": "d2600000-0000-0000-0000-000000000401",
"created_at": "2026-08-16T10:00:00Z",
"updated_at": "2026-08-16T10:00:00Z"
},
"audit_event_id": "d2600000-0000-0000-0000-000000000501",
"replayed": false
}GET/api/projects/{projectId}/wiki/pages/{pageId}Get a wiki pageJeton utilisateur ou clé API
Returns the current page head, including canonical Markdown, actor metadata, archive state, and capabilities calculated for the principal.
# GET /api/projects/{projectId}/wiki/pages/{pageId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
capabilities.can_read | boolean | Obligatoire | True after read authorization. |
capabilities.can_export | boolean | Obligatoire | True after read authorization. |
capabilities.can_update | boolean | Obligatoire | True for a mutable active page and a mutation-capable principal. |
capabilities.can_restore | boolean | Obligatoire | True for a mutation-capable principal, including on archived pages. |
capabilities.can_archive | boolean | Obligatoire | True only for a JWT administrator and an active page. |
capabilities.can_unarchive | boolean | Obligatoire | True only for a JWT administrator and an archived page. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
Types de contenu: application/json → application/json
Exemple cURL
curl -i -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201Exemple de réponse
{
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"title": "Incident response",
"slug": "incident-response",
"normalized_slug": "incident-response",
"filename": "runbooks/incident-response.md",
"normalized_filename": "runbooks/incident-response.md",
"body_markdown": "# Incident response\n",
"revision": 1,
"archived_at": null,
"created_actor_kind": "user",
"created_actor_user_id": "d2600000-0000-0000-0000-000000000301",
"created_actor_display": "d2600000-0000-0000-0000-000000000301",
"updated_actor_kind": "user",
"updated_actor_user_id": "d2600000-0000-0000-0000-000000000301",
"updated_actor_display": "d2600000-0000-0000-0000-000000000301",
"created_at": "2026-08-16T10:00:00Z",
"updated_at": "2026-08-16T10:00:00Z"
},
"capabilities": {
"can_read": true,
"can_export": true,
"can_update": true,
"can_restore": true,
"can_archive": true,
"can_unarchive": false
}
}PUT/api/projects/{projectId}/wiki/pages/{pageId}Update a wiki pageJeton utilisateur ou clé API
Applies a partial page-head update under exact ETag concurrency. API keys need both wiki:read and wiki:write because successful and no-op responses include the current page body. Omitted fields are unchanged; an empty or equivalent change is a wiki_page_unchanged no-op. Archived pages cannot be updated. JSON is capped at 8 MiB and unknown fields are rejected.
# PUT /api/projects/{projectId}/wiki/pages/{pageId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
If-Match | strong ETag | Obligatoire | Exact current page ETag: "wiki-page:{pageId}:rev:{revision}". Weak tags, *, lists, another page ID, and non-canonical revision numbers are rejected. |
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
title | string | Facultatif | Trimmed title, 1-300 characters. |
slug | string | Facultatif | Lowercase kebab-case slug, at most 200 characters. |
filename | string | Facultatif | Lowercase project-relative .md filename, 3-512 characters. |
body_markdown | string | Facultatif | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | noop | Obligatoire | Whether this command changed the page. |
code | string | Obligatoire | Stable success/no-op code for this command. |
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
audit_event_id | UUID | null | Obligatoire | Append-only audit event ID, or null for a no-op. |
source_revision | integer | Facultatif | Source revision on a restore result. |
replayed | boolean | Obligatoire | True when an exact Idempotency-Key retry replayed this result. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_json_body | 400 | Facultatif | The body is not one JSON value, contains unknown fields, or has invalid field types. |
request_body_too_large | 413 | Facultatif | The JSON request exceeds the route's byte limit. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
invalid_title | 400 | Facultatif | The normalized title is empty or longer than 300 characters. |
invalid_slug | 400 | Facultatif | The normalized slug is empty, longer than 200 characters, or cannot match lowercase kebab-case. |
invalid_filename | 400 | Facultatif | The normalized Markdown filename is invalid, hidden, non-canonical, or longer than 512 characters. |
markdown_too_large | 413 | Facultatif | Canonical UTF-8 Markdown exceeds 1 MiB. |
wiki_slug_conflict | 409 | Facultatif | Another project wiki page already uses the normalized slug. |
wiki_filename_conflict | 409 | Facultatif | Another project wiki page already uses the normalized filename. |
revision_exhausted | 409 | Facultatif | The page reached revision 9007199254740991. |
wiki_attachment_reference_not_found | 409 | Facultatif | Markdown references an attachment that does not exist on this project page. |
if_match_required | 428 | Facultatif | If-Match is required for this page command. |
invalid_if_match | 400 | Facultatif | If-Match is not the exact strong ETag for this page. |
revision_conflict | 412 | Facultatif | The page has changed. The error details include expected_revision, current_revision, and current_etag; the response ETag is current. |
invalid_update_changes | 400 | Facultatif | A change is unknown, null, or not a string. |
wiki_page_archived | 409 | Facultatif | Archived pages cannot be updated. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -H 'If-Match: "wiki-page:d2600000-0000-0000-0000-000000000201:rev:1"' -H "Idempotency-Key: update-incident-response-v2" -d '{"title":"Incident response plan"}' http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201Exemple de réponse
{
"outcome": "applied",
"code": "wiki_page_updated",
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"revision": 2,
"title": "Incident response plan"
},
"audit_event_id": "d2600000-0000-0000-0000-000000000502",
"replayed": false
}POST/api/projects/{projectId}/wiki/pages/{pageId}/archiveArchive a wiki pageJeton utilisateur
JWT-admin-only soft archive under exact ETag concurrency. API keys are rejected regardless of scope. An already archived page returns a wiki_page_already_archived no-op. The body may be omitted or be exactly {}; non-empty JSON is rejected and the body limit is 1 KiB.
# POST /api/projects/{projectId}/wiki/pages/{pageId}/archiveParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
If-Match | strong ETag | Obligatoire | Exact current page ETag: "wiki-page:{pageId}:rev:{revision}". Weak tags, *, lists, another page ID, and non-canonical revision numbers are rejected. |
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | noop | Obligatoire | Whether this command changed the page. |
code | string | Obligatoire | Stable success/no-op code for this command. |
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
audit_event_id | UUID | null | Obligatoire | Append-only audit event ID, or null for a no-op. |
source_revision | integer | Facultatif | Source revision on a restore result. |
replayed | boolean | Obligatoire | True when an exact Idempotency-Key retry replayed this result. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_admin_required | 403 | Facultatif | The operation requires a JWT user who is a workspace owner/admin or explicit project admin. API keys cannot perform it. |
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_json_body | 400 | Facultatif | The body is not one JSON value, contains unknown fields, or has invalid field types. |
request_body_too_large | 413 | Facultatif | The JSON request exceeds the route's byte limit. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
if_match_required | 428 | Facultatif | If-Match is required for this page command. |
invalid_if_match | 400 | Facultatif | If-Match is not the exact strong ETag for this page. |
revision_conflict | 412 | Facultatif | The page has changed. The error details include expected_revision, current_revision, and current_etag; the response ETag is current. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" -H "Content-Type: application/json" -H 'If-Match: "wiki-page:d2600000-0000-0000-0000-000000000201:rev:1"' -H "Idempotency-Key: archive-incident-response-v1" -d '{}' http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/archiveExemple de réponse
{
"outcome": "applied",
"code": "wiki_page_archived",
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"revision": 2,
"archived_at": "2026-08-16T11:00:00Z"
},
"audit_event_id": "d2600000-0000-0000-0000-000000000503",
"replayed": false
}POST/api/projects/{projectId}/wiki/pages/{pageId}/unarchiveUnarchive a wiki pageJeton utilisateur
JWT-admin-only reactivation under exact ETag concurrency. API keys are rejected regardless of scope. An already active page returns a wiki_page_already_active no-op. The body may be omitted or be exactly {}; non-empty JSON is rejected and the body limit is 1 KiB.
# POST /api/projects/{projectId}/wiki/pages/{pageId}/unarchiveParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
If-Match | strong ETag | Obligatoire | Exact current page ETag: "wiki-page:{pageId}:rev:{revision}". Weak tags, *, lists, another page ID, and non-canonical revision numbers are rejected. |
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | noop | Obligatoire | Whether this command changed the page. |
code | string | Obligatoire | Stable success/no-op code for this command. |
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
audit_event_id | UUID | null | Obligatoire | Append-only audit event ID, or null for a no-op. |
source_revision | integer | Facultatif | Source revision on a restore result. |
replayed | boolean | Obligatoire | True when an exact Idempotency-Key retry replayed this result. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_admin_required | 403 | Facultatif | The operation requires a JWT user who is a workspace owner/admin or explicit project admin. API keys cannot perform it. |
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_json_body | 400 | Facultatif | The body is not one JSON value, contains unknown fields, or has invalid field types. |
request_body_too_large | 413 | Facultatif | The JSON request exceeds the route's byte limit. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
if_match_required | 428 | Facultatif | If-Match is required for this page command. |
invalid_if_match | 400 | Facultatif | If-Match is not the exact strong ETag for this page. |
revision_conflict | 412 | Facultatif | The page has changed. The error details include expected_revision, current_revision, and current_etag; the response ETag is current. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" -H "Content-Type: application/json" -H 'If-Match: "wiki-page:d2600000-0000-0000-0000-000000000201:rev:2"' -d '{}' http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/unarchiveExemple de réponse
{
"outcome": "applied",
"code": "wiki_page_unarchived",
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"revision": 3,
"archived_at": null
},
"audit_event_id": "d2600000-0000-0000-0000-000000000504",
"replayed": false
}GET/api/projects/{projectId}/wiki/pages/{pageId}/revisionsList wiki page revisionsJeton utilisateur ou clé API
Returns newest-first immutable revision metadata without Markdown bodies. The page must still exist, including when archived.
# GET /api/projects/{projectId}/wiki/pages/{pageId}/revisionsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
limit | integer | Facultatif | Maximum revision summaries, from 1 through 100. (Par défaut: 50) |
offset | integer | Facultatif | Zero-based revision offset, from 0 through 10000. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
revisions | WikiRevisionSummary[] | Obligatoire | Rows with id, project_id, page_id, revision, revision_kind, restored_from_revision, title, slug, filename, archived_at, actor fields, and recorded_at; body_markdown is omitted. |
page_id | UUID | Obligatoire | Requested page UUID. |
limit | integer | Obligatoire | Applied limit. |
offset | integer | Obligatoire | Applied offset. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_revision_query | 400 | Facultatif | limit or offset is outside the accepted range. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" "http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/revisions?limit=50&offset=0"Exemple de réponse
{
"revisions": [
{
"id": "d2600000-0000-0000-0000-000000000601",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"revision": 2,
"revision_kind": "updated",
"restored_from_revision": null,
"title": "Incident response plan",
"slug": "incident-response",
"filename": "runbooks/incident-response.md",
"archived_at": null,
"actor_kind": "api_key",
"actor_api_key_id": "d2600000-0000-0000-0000-000000000401",
"actor_display": "d2600000-0000-0000-0000-000000000401",
"recorded_at": "2026-08-16T10:30:00Z"
}
],
"page_id": "d2600000-0000-0000-0000-000000000201",
"limit": 50,
"offset": 0
}GET/api/projects/{projectId}/wiki/pages/{pageId}/revisions/{revision}Get a wiki page revisionJeton utilisateur ou clé API
Returns one immutable revision snapshot, including its Markdown body. Revision is a canonical decimal integer from 1 through 9007199254740991; signs, leading zeroes, fractions, and out-of-range values are not accepted.
# GET /api/projects/{projectId}/wiki/pages/{pageId}/revisions/{revision}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
revision | integer | Obligatoire | Canonical positive revision number, without leading zeroes. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
revision | WikiRevision | Obligatoire | Immutable snapshot with id, project_id, page_id, revision, revision_kind, restored_from_revision, title, slug, filename, body_markdown, archived_at, actor fields, and recorded_at. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
wiki_revision_not_found | 404 | Facultatif | The revision path is invalid or that revision does not exist for this page. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/revisions/1Exemple de réponse
{
"revision": {
"id": "d2600000-0000-0000-0000-000000000601",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"revision": 1,
"revision_kind": "created",
"restored_from_revision": null,
"title": "Incident response",
"slug": "incident-response",
"filename": "runbooks/incident-response.md",
"body_markdown": "# Incident response\n",
"archived_at": null,
"actor_kind": "user",
"actor_user_id": "d2600000-0000-0000-0000-000000000301",
"actor_display": "d2600000-0000-0000-0000-000000000301",
"recorded_at": "2026-08-16T10:00:00Z"
}
}POST/api/projects/{projectId}/wiki/pages/{pageId}/restoreRestore a wiki page revisionJeton utilisateur ou clé API
Copies one immutable snapshot's title, slug, filename, and Markdown into a new page-head revision under exact ETag concurrency. API keys need both wiki:read and wiki:write because successful and no-op responses include the current page body. Restore is available on active or archived pages, but it does not change archived_at. An identical snapshot is a wiki_page_unchanged no-op. The JSON body limit is 1 KiB.
# POST /api/projects/{projectId}/wiki/pages/{pageId}/restoreParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
If-Match | strong ETag | Obligatoire | Exact current page ETag: "wiki-page:{pageId}:rev:{revision}". Weak tags, *, lists, another page ID, and non-canonical revision numbers are rejected. |
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
source_revision | integer | Obligatoire | Existing positive revision to copy, up to 9007199254740991. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | noop | Obligatoire | Whether this command changed the page. |
code | string | Obligatoire | Stable success/no-op code for this command. |
page.id | UUID | Obligatoire | Page UUID. |
page.project_id | UUID | Obligatoire | Owning project UUID. |
page.title | string | Obligatoire | Trimmed title, 1-300 characters. |
page.slug | string | Obligatoire | Lowercase kebab-case slug, at most 200 characters. |
page.normalized_slug | string | Obligatoire | Stored normalized slug used for project uniqueness. |
page.filename | string | Obligatoire | Lowercase project-relative .md filename, 3-512 characters. |
page.normalized_filename | string | Obligatoire | Stored normalized filename used for project uniqueness. |
page.body_markdown | string | Obligatoire | Canonical Markdown head, at most 1 MiB; CRLF/CR is normalized to LF and non-empty content ends with LF. |
page.revision | integer | Obligatoire | Current positive revision, up to 9007199254740991. |
page.archived_at | ISO 8601 string | null | Obligatoire | Archive timestamp, or null while active. |
page.created_actor_kind | user | api_key | system | Obligatoire | Principal kind that created the page. |
page.created_actor_user_id | UUID | Facultatif | Creating user ID when actor_kind is user. |
page.created_actor_api_key_id | UUID | Facultatif | Creating API key ID when actor_kind is api_key. |
page.created_actor_display | string | null | Obligatoire | Stored display identity for the creating actor. |
page.updated_actor_kind | user | api_key | system | Obligatoire | Principal kind that last changed the page. |
page.updated_actor_user_id | UUID | Facultatif | Last updating user ID when actor_kind is user. |
page.updated_actor_api_key_id | UUID | Facultatif | Last updating API key ID when actor_kind is api_key. |
page.updated_actor_display | string | null | Obligatoire | Stored display identity for the last updating actor. |
page.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
page.updated_at | ISO 8601 string | Obligatoire | Last update timestamp. |
audit_event_id | UUID | null | Obligatoire | Append-only audit event ID, or null for a no-op. |
source_revision | integer | Facultatif | Source revision on a restore result. |
replayed | boolean | Obligatoire | True when an exact Idempotency-Key retry replayed this result. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_json_body | 400 | Facultatif | The body is not one JSON value, contains unknown fields, or has invalid field types. |
request_body_too_large | 413 | Facultatif | The JSON request exceeds the route's byte limit. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
if_match_required | 428 | Facultatif | If-Match is required for this page command. |
invalid_if_match | 400 | Facultatif | If-Match is not the exact strong ETag for this page. |
revision_conflict | 412 | Facultatif | The page has changed. The error details include expected_revision, current_revision, and current_etag; the response ETag is current. |
invalid_restore_input | 400 | Facultatif | source_revision is missing or not a canonical positive integer. |
wiki_revision_not_found | 404 | Facultatif | The source revision does not exist for this page. |
wiki_slug_conflict | 409 | Facultatif | Restoring the snapshot would collide with another page slug. |
wiki_filename_conflict | 409 | Facultatif | Restoring the snapshot would collide with another page filename. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -H "Content-Type: application/json" -H 'If-Match: "wiki-page:d2600000-0000-0000-0000-000000000201:rev:2"' -H "Idempotency-Key: restore-incident-response-r1" -d '{"source_revision":1}' http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/restoreExemple de réponse
{
"outcome": "applied",
"code": "wiki_page_restored",
"page": {
"id": "d2600000-0000-0000-0000-000000000201",
"project_id": "b0000000-0000-0000-0000-000000000001",
"revision": 3,
"title": "Incident response"
},
"audit_event_id": "d2600000-0000-0000-0000-000000000505",
"source_revision": 1,
"replayed": false
}GET/api/projects/{projectId}/wiki/templatesList system wiki templatesJeton utilisateur ou clé API
Returns the read-only seeded system templates ordered by template_key after project access is checked. There are no template mutation routes.
# GET /api/projects/{projectId}/wiki/templatesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
templates | WikiTemplate[] | Obligatoire | System templates with id, template_key, name, description, body_markdown, version, is_system, created_at, and updated_at. Template Markdown is at most 256 KiB. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/templatesExemple de réponse
{
"templates": [
{
"id": "d2600000-0000-0000-0000-000000000701",
"template_key": "runbook",
"name": "Runbook",
"description": "Operational procedure with verification and rollback.",
"body_markdown": "# Runbook\n\n## Prerequisites\n\n## Procedure\n\n## Verification\n\n## Rollback\n",
"version": 1,
"is_system": true,
"created_at": "2026-08-16T00:00:00Z",
"updated_at": "2026-08-16T00:00:00Z"
}
]
}GET/api/projects/{projectId}/wiki/pages/{pageId}/export.mdExport page MarkdownJeton utilisateur ou clé API
Streams the current canonical Markdown bytes without rendering or normalization. Archived pages can be exported. The download filename is sanitized from the page filename and capped at 180 bytes.
# GET /api/projects/{projectId}/wiki/pages/{pageId}/export.mdParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
ETag | strong ETag | Obligatoire | Current page version in the form "wiki-page:{pageId}:rev:{revision}". A revision_conflict response also returns the current value. |
Content-Disposition | string | Obligatoire | attachment with safe filename and RFC 5987 filename* parameters. |
Content-Length | integer | Obligatoire | Exact Markdown byte count. |
X-Content-Type-Options | nosniff | Obligatoire | Prevents browser MIME sniffing. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
Types de contenu: application/json → text/markdown; charset=utf-8
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" --output incident-response.md http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/export.mdExemple de réponse
# Incident response
Follow the project runbook.
GET/api/projects/{projectId}/wiki/pages/{pageId}/attachmentsList page attachmentsJeton utilisateur ou clé API
Returns ready image metadata and canonical wiki-attachment Markdown references for the page. Private storage bucket/path fields are never exposed.
# GET /api/projects/{projectId}/wiki/pages/{pageId}/attachmentsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
attachments | WikiAttachment[] | Obligatoire | Ready attachment metadata in storage query order. |
attachments[].id | UUID | Obligatoire | Attachment UUID. |
attachments[].project_id | UUID | Obligatoire | Owning project UUID. |
attachments[].page_id | UUID | Obligatoire | Owning wiki page UUID. |
attachments[].original_filename | string | Obligatoire | Sanitized image filename, at most 180 bytes. |
attachments[].content_type | image/png | image/jpeg | image/webp | Obligatoire | Verified media type detected from the bytes. |
attachments[].size_bytes | integer | Obligatoire | Image size from 1 byte through 8 MiB. |
attachments[].sha256 | string | Obligatoire | Lowercase SHA-256 hex digest. |
attachments[].width | integer | Obligatoire | Verified width from 1 through 8000 pixels. |
attachments[].height | integer | Obligatoire | Verified height from 1 through 8000 pixels. |
attachments[].actor_kind | user | api_key | system | Obligatoire | Uploading principal kind. |
attachments[].actor_user_id | UUID | null | Obligatoire | Uploading user ID, when applicable. |
attachments[].actor_api_key_id | UUID | null | Obligatoire | Uploading API key ID, when applicable. |
attachments[].actor_display | string | null | Obligatoire | Stored display identity for the uploader. |
attachments[].ready_at | ISO 8601 string | Obligatoire | Timestamp when storage and metadata became ready. |
attachments[].created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
attachments[].markdown | string | Obligatoire | Canonical  reference. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/attachmentsExemple de réponse
{
"attachments": [
{
"id": "d2600000-0000-0000-0000-000000000401",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"original_filename": "architecture.png",
"content_type": "image/png",
"size_bytes": 42137,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"width": 1280,
"height": 720,
"actor_kind": "user",
"actor_user_id": "d2600000-0000-0000-0000-000000000301",
"actor_api_key_id": null,
"actor_display": "d2600000-0000-0000-0000-000000000301",
"ready_at": "2026-08-16T11:30:00Z",
"created_at": "2026-08-16T11:30:00Z",
"markdown": ""
}
]
}POST/api/projects/{projectId}/wiki/pages/{pageId}/attachmentsUpload a page imageJeton utilisateur ou clé API
Accepts exactly one multipart file field named file on an active page. The request is capped at 10 MiB and the file at 8 MiB. Only fully decodable PNG, JPEG, and WebP bytes are accepted; declared media type and filename extension must match, dimensions must be 1-8000 pixels and at most 16 megapixels total, and the sanitized filename is capped at 180 bytes. Each project is capped at 200 images and 50 MiB.
# POST /api/projects/{projectId}/wiki/pages/{pageId}/attachmentsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
file | PNG | JPEG | WebP binary | Obligatoire | The only multipart part. It must have a filename and an image/png, image/jpeg, or image/webp Content-Type matching its bytes and extension. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
attachment.id | UUID | Obligatoire | Attachment UUID. |
attachment.project_id | UUID | Obligatoire | Owning project UUID. |
attachment.page_id | UUID | Obligatoire | Owning wiki page UUID. |
attachment.original_filename | string | Obligatoire | Sanitized image filename, at most 180 bytes. |
attachment.content_type | image/png | image/jpeg | image/webp | Obligatoire | Verified media type detected from the bytes. |
attachment.size_bytes | integer | Obligatoire | Image size from 1 byte through 8 MiB. |
attachment.sha256 | string | Obligatoire | Lowercase SHA-256 hex digest. |
attachment.width | integer | Obligatoire | Verified width from 1 through 8000 pixels. |
attachment.height | integer | Obligatoire | Verified height from 1 through 8000 pixels. |
attachment.actor_kind | user | api_key | system | Obligatoire | Uploading principal kind. |
attachment.actor_user_id | UUID | null | Obligatoire | Uploading user ID, when applicable. |
attachment.actor_api_key_id | UUID | null | Obligatoire | Uploading API key ID, when applicable. |
attachment.actor_display | string | null | Obligatoire | Stored display identity for the uploader. |
attachment.ready_at | ISO 8601 string | Obligatoire | Timestamp when storage and metadata became ready. |
attachment.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
attachment.markdown | string | Obligatoire | Canonical  reference. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
invalid_wiki_attachment_multipart | 400/415 | Facultatif | The request is not multipart/form-data or does not contain exactly one file part. |
invalid_wiki_attachment | 400 | Facultatif | The image part is empty. |
invalid_wiki_attachment_type | 415 | Facultatif | The file part has no valid declared Content-Type. |
unsupported_wiki_attachment_type | 415 | Facultatif | Detected bytes are not PNG, JPEG, or WebP. |
wiki_attachment_type_mismatch | 415 | Facultatif | Declared image media type does not match detected bytes. |
wiki_attachment_filename_type_mismatch | 400 | Facultatif | Filename extension does not match the image type. |
invalid_wiki_attachment_image | 400 | Facultatif | Image bytes are malformed or truncated. |
wiki_attachment_dimensions_exceeded | 400 | Facultatif | Image width or height is outside 1-8000 pixels, or total pixels exceed 16 megapixels. |
wiki_attachment_request_too_large | 413 | Facultatif | The multipart request exceeds 10 MiB. |
wiki_attachment_too_large | 413 | Facultatif | The image exceeds 8 MiB. |
wiki_page_archived | 409 | Facultatif | Archived pages cannot receive attachments. |
wiki_attachment_project_quota_exceeded | 409 | Facultatif | The project already has 200 images or 50 MiB of wiki image metadata. |
wiki_attachment_storage_unavailable | 503 | Facultatif | Private object storage could not accept the image. |
wiki_attachment_metadata_reconciliation_pending | 503 | Facultatif | The generated attachment ID could not be conclusively re-queried after an ambiguous insert response. Storage is preserved and a delayed reconciliation row prevents cleanup if metadata later appears. |
Types de contenu: multipart/form-data; boundary=... → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" -F "[email protected];type=image/png" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/attachmentsExemple de réponse
{
"attachment": {
"id": "d2600000-0000-0000-0000-000000000401",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"original_filename": "architecture.png",
"content_type": "image/png",
"size_bytes": 42137,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"width": 1280,
"height": 720,
"actor_kind": "api_key",
"actor_user_id": null,
"actor_api_key_id": "d2600000-0000-0000-0000-000000000402",
"actor_display": "d2600000-0000-0000-0000-000000000402",
"ready_at": "2026-08-16T11:30:00Z",
"created_at": "2026-08-16T11:30:00Z",
"markdown": ""
}
}GET/api/projects/{projectId}/wiki/pages/{pageId}/attachments/{attachmentId}Create an attachment access URLJeton utilisateur ou clé API
The sole browser/agent access broker for the private project-wiki-images bucket. It verifies project, page, attachment, bucket, and object-path metadata before returning a client-facing signed download URL valid for 300 seconds. The endpoint returns JSON, not the image bytes.
# GET /api/projects/{projectId}/wiki/pages/{pageId}/attachments/{attachmentId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
attachmentId | UUID | Obligatoire | Canonical UUID of an attachment on the page. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
attachment.id | UUID | Obligatoire | Attachment UUID. |
attachment.project_id | UUID | Obligatoire | Owning project UUID. |
attachment.page_id | UUID | Obligatoire | Owning wiki page UUID. |
attachment.original_filename | string | Obligatoire | Sanitized image filename, at most 180 bytes. |
attachment.content_type | image/png | image/jpeg | image/webp | Obligatoire | Verified media type detected from the bytes. |
attachment.size_bytes | integer | Obligatoire | Image size from 1 byte through 8 MiB. |
attachment.sha256 | string | Obligatoire | Lowercase SHA-256 hex digest. |
attachment.width | integer | Obligatoire | Verified width from 1 through 8000 pixels. |
attachment.height | integer | Obligatoire | Verified height from 1 through 8000 pixels. |
attachment.actor_kind | user | api_key | system | Obligatoire | Uploading principal kind. |
attachment.actor_user_id | UUID | null | Obligatoire | Uploading user ID, when applicable. |
attachment.actor_api_key_id | UUID | null | Obligatoire | Uploading API key ID, when applicable. |
attachment.actor_display | string | null | Obligatoire | Stored display identity for the uploader. |
attachment.ready_at | ISO 8601 string | Obligatoire | Timestamp when storage and metadata became ready. |
attachment.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
attachment.markdown | string | Obligatoire | Canonical  reference. |
download_url | URL | Obligatoire | Short-lived signed private-storage URL. |
expires_at | ISO 8601 string | Obligatoire | Approximate UTC expiry timestamp. |
expires_in_seconds | integer | Obligatoire | Signed URL lifetime; always 300. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
wiki_attachment_not_found | 404 | Facultatif | The attachment ID is invalid or does not belong to this page. |
wiki_attachment_unavailable | 503 | Facultatif | The attachment operation is temporarily unavailable. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/attachments/d2600000-0000-0000-0000-000000000401Exemple de réponse
{
"attachment": {
"id": "d2600000-0000-0000-0000-000000000401",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"original_filename": "architecture.png",
"content_type": "image/png",
"size_bytes": 42137,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"width": 1280,
"height": 720,
"actor_kind": "user",
"actor_user_id": "d2600000-0000-0000-0000-000000000301",
"actor_api_key_id": null,
"actor_display": "d2600000-0000-0000-0000-000000000301",
"ready_at": "2026-08-16T11:30:00Z",
"created_at": "2026-08-16T11:30:00Z",
"markdown": ""
},
"download_url": "http://localhost:54421/storage/v1/object/sign/project-wiki-images/...",
"expires_at": "2026-08-16T11:35:00Z",
"expires_in_seconds": 300
}DELETE/api/projects/{projectId}/wiki/pages/{pageId}/attachments/{attachmentId}Delete a wiki attachmentJeton utilisateur
JWT-admin-only destructive removal. API keys are rejected regardless of scope. A database trigger serializes the operation and returns wiki_attachment_in_use while current or immutable historical Markdown references the attachment. Otherwise metadata is deleted first and the private object path is durably queued in that transaction; storage is then removed and the queue row finalized.
# DELETE /api/projects/{projectId}/wiki/pages/{pageId}/attachments/{attachmentId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
pageId | UUID | Obligatoire | Canonical UUID of a wiki page in the project. |
attachmentId | UUID | Obligatoire | Canonical UUID of an attachment on the page. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
deleted | boolean | Obligatoire | True after object and metadata deletion. |
attachment.id | UUID | Obligatoire | Attachment UUID. |
attachment.project_id | UUID | Obligatoire | Owning project UUID. |
attachment.page_id | UUID | Obligatoire | Owning wiki page UUID. |
attachment.original_filename | string | Obligatoire | Sanitized image filename, at most 180 bytes. |
attachment.content_type | image/png | image/jpeg | image/webp | Obligatoire | Verified media type detected from the bytes. |
attachment.size_bytes | integer | Obligatoire | Image size from 1 byte through 8 MiB. |
attachment.sha256 | string | Obligatoire | Lowercase SHA-256 hex digest. |
attachment.width | integer | Obligatoire | Verified width from 1 through 8000 pixels. |
attachment.height | integer | Obligatoire | Verified height from 1 through 8000 pixels. |
attachment.actor_kind | user | api_key | system | Obligatoire | Uploading principal kind. |
attachment.actor_user_id | UUID | null | Obligatoire | Uploading user ID, when applicable. |
attachment.actor_api_key_id | UUID | null | Obligatoire | Uploading API key ID, when applicable. |
attachment.actor_display | string | null | Obligatoire | Stored display identity for the uploader. |
attachment.ready_at | ISO 8601 string | Obligatoire | Timestamp when storage and metadata became ready. |
attachment.created_at | ISO 8601 string | Obligatoire | Creation timestamp. |
attachment.markdown | string | Obligatoire | Canonical  reference. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_admin_required | 403 | Facultatif | The operation requires a JWT user who is a workspace owner/admin or explicit project admin. API keys cannot perform it. |
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_page_not_found | 404 | Facultatif | The page ID is invalid or no matching page exists in this project. |
wiki_attachment_not_found | 404 | Facultatif | The attachment ID is invalid or does not belong to this page. |
wiki_attachment_unavailable | 503 | Facultatif | The attachment operation is temporarily unavailable. |
wiki_attachment_in_use | 409 | Facultatif | Current or immutable historical page content still references the attachment. |
wiki_attachment_delete_metadata_failed | 503 | Facultatif | The database could not delete attachment metadata; storage is untouched. |
wiki_attachment_delete_reconciliation_pending | 503 | Facultatif | The metadata-delete response was ambiguous. Storage is untouched and any committed deletion remains durably queued. |
wiki_attachment_delete_cleanup_pending | 503 | Facultatif | Metadata was deleted but storage removal or queue finalization failed. The durable queue retries idempotent object removal; details reports completed phases. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer YOUR_JWT_TOKEN" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/pages/d2600000-0000-0000-0000-000000000201/attachments/d2600000-0000-0000-0000-000000000401Exemple de réponse
{
"deleted": true,
"attachment": {
"id": "d2600000-0000-0000-0000-000000000401",
"project_id": "b0000000-0000-0000-0000-000000000001",
"page_id": "d2600000-0000-0000-0000-000000000201",
"original_filename": "architecture.png",
"content_type": "image/png",
"size_bytes": 42137,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"width": 1280,
"height": 720,
"actor_kind": "user",
"actor_user_id": "d2600000-0000-0000-0000-000000000301",
"actor_api_key_id": null,
"actor_display": "d2600000-0000-0000-0000-000000000301",
"ready_at": "2026-08-16T11:30:00Z",
"created_at": "2026-08-16T11:30:00Z",
"markdown": ""
}
}GET/api/projects/{projectId}/wiki/export.zipExport the project wiki ZIPJeton utilisateur ou clé API
Builds and validates a deterministic current-state ZIP before streaming it. It contains active page heads only, ready image attachments, and root wiki-manifest.json version 1. Limits are 200 pages, 200 attachments, 500 entries, 50 MiB expanded, and 25 MiB output. Archived pages and their attachments are excluded; export rejects active pages whose stable links target an excluded page.
# GET /api/projects/{projectId}/wiki/export.zipParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
En-têtes de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Content-Disposition | string | Obligatoire | attachment filename project-{projectId}-wiki.zip. |
Content-Length | integer | Obligatoire | Exact completed ZIP byte count. |
X-Content-Type-Options | nosniff | Obligatoire | Prevents browser MIME sniffing. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_archive_expanded_too_large | 413 | Facultatif | An entry or the complete ZIP exceeds 50 MiB expanded. |
wiki_archive_page_limit | 413 | Facultatif | The archive or project contains more than 200 pages. |
wiki_archive_attachment_limit | 413 | Facultatif | The archive or project contains more than 200 attachments. |
wiki_archive_output_too_large | 413 | Facultatif | The generated ZIP exceeds the 25 MiB round-trip limit. |
wiki_archive_attachment_corrupt | 409 | Facultatif | Stored attachment bytes do not match ready metadata. |
wiki_archive_dangling_page_reference | 409 | Facultatif | An active page contains a stable link to a page excluded from the archive. |
wiki_archive_storage_unavailable | 503 | Facultatif | An attachment could not be downloaded for export. |
Types de contenu: application/json → application/zip
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" --output project-wiki.zip http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/export.zipExemple de réponse
Binary ZIP bytes beginning with PK (0x50 0x4b).POST/api/projects/{projectId}/wiki/importImport a project wiki ZIPJeton utilisateur
JWT-admin-only import of the version-1 current-state archive contract. API keys are rejected regardless of scope. The multipart request must contain exactly one application/zip file field named file. Limits are 25 MiB compressed plus 1 MiB multipart overhead, 50 MiB expanded, 500 entries, 200 pages, 200 attachments, 100:1 compression, 1 MiB per Markdown page, and 8 MiB per image. Import creates new destination IDs and revision 1 pages; image references are rewritten. Exact Idempotency-Key retries are replayed by archive SHA-256.
# POST /api/projects/{projectId}/wiki/importParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | UUID | Obligatoire | Canonical UUID of the project that owns the independent wiki. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Idempotency-Key | string | Facultatif | Required for API-key commands and optional for JWT commands. After trimming, must be 1-255 Unicode characters. An exact retry by the same actor replays the saved result; reuse for different input returns idempotency_mismatch. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
file | application/zip binary | Obligatoire | The only multipart part. The ZIP must contain root wiki-manifest.json version 1, pages/{filename} entries, and attachments/{sourceAttachmentId}/{filename} entries exactly referenced by the manifest. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
outcome | applied | Obligatoire | Successful import outcome. |
code | wiki_archive_imported | Obligatoire | Stable success code. |
project_id | UUID | Obligatoire | Destination project UUID. |
archive_sha256 | string | Obligatoire | SHA-256 of the uploaded ZIP bytes. |
page_count | integer | Obligatoire | Number of created pages. |
attachment_count | integer | Obligatoire | Number of created attachments. |
pages | WikiArchiveImportPage[] | Obligatoire | Mappings with source_id, destination id, title, slug, filename, source_revision, revision (1), and audit_event_id. |
attachments | WikiArchiveImportAttachment[] | Obligatoire | Mappings with source_id, destination id, destination page_id, and private object path. |
replayed | boolean | Obligatoire | True for an exact saved retry. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
project_not_found | 404 | Facultatif | The project ID is invalid or the project does not exist. |
project_access_denied | 403 | Facultatif | The JWT user cannot access the project or the API key is bound to another project. |
authentication_required | 401 | Facultatif | The authenticated JWT user could not be identified. |
wiki_admin_required | 403 | Facultatif | The operation requires a JWT user who is a workspace owner/admin or explicit project admin. API keys cannot perform it. |
invalid_idempotency_key | 400 | Facultatif | An API-key command omitted Idempotency-Key or the trimmed value exceeds 255 characters. |
idempotency_mismatch | 409 | Facultatif | The same actor already used this Idempotency-Key for different canonical command input. |
invalid_wiki_archive | 400 | Facultatif | The ZIP is malformed, truncated, or fails CRC/length validation. |
invalid_wiki_archive_manifest | 400 | Facultatif | wiki-manifest.json is not the exact valid version-1 schema. |
wiki_archive_manifest_missing | 400 | Facultatif | wiki-manifest.json is absent from the ZIP root. |
unsupported_wiki_archive_version | 400 | Facultatif | The manifest version is not 1. |
unsafe_wiki_archive_path | 400 | Facultatif | An entry path is absolute, non-canonical, non-ASCII, or traverses directories. |
duplicate_wiki_archive_path | 400 | Facultatif | Two ZIP paths normalize to the same case-insensitive path. |
unsupported_wiki_archive_entry | 400 | Facultatif | An entry is encrypted, not a regular file, or uses unsupported compression. |
nested_wiki_archive | 400 | Facultatif | The ZIP contains another archive file. |
invalid_wiki_archive_page | 400 | Facultatif | A page manifest entry or its canonical Markdown metadata is invalid. |
wiki_archive_page_missing | 400 | Facultatif | A manifest page path is absent from the ZIP. |
invalid_wiki_archive_attachment | 400 | Facultatif | An attachment manifest entry, filename, media type, or metadata is invalid. |
wiki_archive_attachment_missing | 400 | Facultatif | A manifest attachment path is absent from the ZIP. |
wiki_archive_attachment_size_mismatch | 400 | Facultatif | Attachment bytes do not match the manifest size. |
wiki_archive_attachment_hash_mismatch | 400 | Facultatif | Attachment bytes do not match the manifest SHA-256. |
invalid_wiki_archive_markdown | 400 | Facultatif | A Markdown entry is not valid UTF-8 or contains NUL. |
wiki_archive_page_collision | 409 | Facultatif | Imported page IDs, slugs, filenames, or paths collide. |
wiki_archive_id_collision | 409 | Facultatif | Manifest page and attachment IDs collide. |
wiki_archive_attachment_collision | 409 | Facultatif | Manifest attachment paths collide. |
wiki_archive_compressed_too_large | 413 | Facultatif | The ZIP exceeds 25 MiB compressed. |
wiki_archive_expanded_too_large | 413 | Facultatif | An entry or the complete ZIP exceeds 50 MiB expanded. |
wiki_archive_compression_ratio | 413 | Facultatif | An entry or the complete ZIP exceeds a 100:1 expansion ratio. |
wiki_archive_entry_limit | 413 | Facultatif | The ZIP does not contain 1-500 regular file entries. |
wiki_archive_page_limit | 413 | Facultatif | The archive or project contains more than 200 pages. |
wiki_archive_attachment_limit | 413 | Facultatif | The archive or project contains more than 200 attachments. |
wiki_archive_markdown_too_large | 413 | Facultatif | One imported Markdown page exceeds 1 MiB. |
wiki_archive_output_too_large | 413 | Facultatif | The generated ZIP exceeds the 25 MiB round-trip limit. |
invalid_wiki_archive_multipart | 400/415 | Facultatif | The request is not the exact one-file application/zip multipart contract. |
unexpected_wiki_archive_entry | 400 | Facultatif | The ZIP has a file not referenced by the manifest. |
wiki_attachment_project_quota_exceeded | 409 | Facultatif | Import would exceed the destination project's 200-image or 50 MiB wiki quota. |
wiki_archive_storage_unavailable | 503 | Facultatif | Attachment staging failed and completed cleanup succeeded. |
wiki_archive_staging_cleanup_pending | 503 | Facultatif | Attachment staging failed and storage cleanup remains pending. |
wiki_archive_database_cleanup_pending | 503 | Facultatif | Publication failed and staged-object cleanup remains pending. |
wiki_archive_replay_cleanup_pending | 503 | Facultatif | Replay succeeded but newly staged unused objects could not be removed. |
Types de contenu: multipart/form-data; boundary=... → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" -H "Idempotency-Key: import-project-wiki-2026-08-16" -F "[email protected];type=application/zip" http://localhost:8080/api/projects/b0000000-0000-0000-0000-000000000001/wiki/importExemple de réponse
{
"outcome": "applied",
"code": "wiki_archive_imported",
"project_id": "b0000000-0000-0000-0000-000000000001",
"archive_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"page_count": 1,
"attachment_count": 1,
"pages": [
{
"source_id": "d2600000-0000-0000-0000-000000000201",
"id": "d2600000-0000-0000-0000-000000000801",
"title": "Incident response",
"slug": "incident-response",
"filename": "runbooks/incident-response.md",
"source_revision": 3,
"revision": 1,
"audit_event_id": "d2600000-0000-0000-0000-000000000802"
}
],
"attachments": [
{
"source_id": "d2600000-0000-0000-0000-000000000401",
"id": "d2600000-0000-0000-0000-000000000803",
"page_id": "d2600000-0000-0000-0000-000000000801",
"path": "b0000000-0000-0000-0000-000000000001/d2600000-0000-0000-0000-000000000801/d2600000-0000-0000-0000-000000000803/architecture.png"
}
],
"replayed": false
}Agent App Control
Durable human approval for high-impact project actions requested by external coding agents.
POST/api/projects/{projectId}/app-control/requestsRequest approval for a high-impact actionJeton utilisateur ou clé API
A project API key submits an exact typed action. BernOps stores only a request hash and safe resource summary; no domain mutation occurs.
# POST /api/projects/{projectId}/app-control/requestsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | API key's project UUID. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Idempotency-Key | string | Obligatoire | Stable logical-request identity. Reuse only for an exact retry. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
operation | string | Obligatoire | Allowlisted high-impact app-control operation. |
call | object | Obligatoire | Exact typed params, query, body, and mutation preconditions for the operation. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
request_id | string | Obligatoire | Durable approval request UUID. |
project_id | string | Obligatoire | Project derived from the API key or stored request. |
operation | string | Obligatoire | High-impact operation awaiting or using approval. |
safe_summary | object | Obligatoire | Server-derived operation and resource IDs; never contains the request body. |
status | string | Obligatoire | pending, approved, denied, executing, completed, failed, or expired. |
expires_at | string | Obligatoire | Approval expiry timestamp. |
approval_path | string | Obligatoire | Static browser route where a project administrator reviews the action. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
app_control_approval_not_required | 400 | Facultatif | The operation is routine and must use its normal endpoint. |
app_control_insufficient_scope | 403 | Facultatif | The key lacks the operation's existing scope. |
app_control_idempotency_mismatch | 409 | Facultatif | The idempotency key was reused for a different action. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer $BERNOPS_API_KEY" \
-H "Idempotency-Key: approval-delete-label-v1" -H "Content-Type: application/json" \
-d '{"operation":"label.delete","call":{"params":{"labelId":"LABEL_UUID"},"mutation":{"ifMatch":"\"7\""}}}' \
http://localhost:8080/api/projects/PROJECT_UUID/app-control/requestsExemple de réponse
{
"request_id": "request-uuid",
"project_id": "project-uuid",
"operation": "label.delete",
"safe_summary": {
"operation": "label.delete",
"resource_ids": {
"labelId": "label-uuid"
}
},
"status": "pending",
"expires_at": "2026-08-28T18:00:00Z",
"approval_path": "/projects/agents/approvals?projectId=project-uuid&requestId=request-uuid"
}GET/api/app-control/requests/{requestId}Get approval statusJeton utilisateur ou clé API
Returns safe approval metadata to the originating API key or a project-visible JWT user.
# GET /api/app-control/requests/{requestId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
requestId | string | Obligatoire | Approval request UUID. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
request_id | string | Obligatoire | Durable approval request UUID. |
project_id | string | Obligatoire | Project derived from the API key or stored request. |
operation | string | Obligatoire | High-impact operation awaiting or using approval. |
safe_summary | object | Obligatoire | Server-derived operation and resource IDs; never contains the request body. |
status | string | Obligatoire | pending, approved, denied, executing, completed, failed, or expired. |
expires_at | string | Obligatoire | Approval expiry timestamp. |
approval_path | string | Obligatoire | Static browser route where a project administrator reviews the action. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer $BERNOPS_API_KEY" http://localhost:8080/api/app-control/requests/REQUEST_UUIDExemple de réponse
{
"request_id": "request-uuid",
"status": "approved"
}POST/api/app-control/requests/{requestId}/decisionApprove or deny an actionJeton utilisateur
A current project administrator makes the independent human decision. API keys cannot call this endpoint.
# POST /api/app-control/requests/{requestId}/decisionParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
requestId | string | Obligatoire | Approval request UUID. |
En-têtes de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
Idempotency-Key | string | Obligatoire | Stable logical-request identity. Reuse only for an exact retry. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
approved | boolean | Obligatoire | True to approve, false to deny. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
request_id | string | Obligatoire | Durable approval request UUID. |
project_id | string | Obligatoire | Project derived from the API key or stored request. |
operation | string | Obligatoire | High-impact operation awaiting or using approval. |
safe_summary | object | Obligatoire | Server-derived operation and resource IDs; never contains the request body. |
status | string | Obligatoire | pending, approved, denied, executing, completed, failed, or expired. |
expires_at | string | Obligatoire | Approval expiry timestamp. |
approval_path | string | Obligatoire | Static browser route where a project administrator reviews the action. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
app_control_admin_required | 403 | Facultatif | The user is not a project administrator. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer $JWT" -H "Idempotency-Key: decision-v1" \
-H "Content-Type: application/json" -d '{"approved":true}' \
http://localhost:8080/api/app-control/requests/REQUEST_UUID/decisionExemple de réponse
{
"request_id": "request-uuid",
"status": "approved"
}POST/api/app-control/requests/{requestId}/executeExecute an approved actionJeton utilisateur ou clé API
The same current API key resubmits the exact semantic action. BernOps rechecks scopes, project, approval, request hash, and domain preconditions before one replay-safe execution.
# POST /api/app-control/requests/{requestId}/executeParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
requestId | string | Obligatoire | Approved request UUID. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
operation | string | Obligatoire | Allowlisted high-impact app-control operation. |
call | object | Obligatoire | Exact typed params, query, body, and mutation preconditions for the operation. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
result | object | Obligatoire | Canonical result from the underlying domain command. |
Codes d’erreur
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
app_control_approval_pending | 409 | Facultatif | The request still awaits a human decision. |
app_control_request_denied | 403 | Facultatif | The request was denied. |
app_control_request_expired | 410 | Facultatif | The request expired. |
app_control_request_not_found | 404 | Facultatif | Key, project, operation, or request hash did not match. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer $BERNOPS_API_KEY" -H "Content-Type: application/json" \
-d '{"operation":"label.delete","call":{"params":{"labelId":"LABEL_UUID"},"mutation":{"ifMatch":"\"7\""}}}' \
http://localhost:8080/api/app-control/requests/REQUEST_UUID/executeExemple de réponse
{
"outcome": "applied",
"code": "label_deleted"
}Triggers
Manage cron-based triggers that automatically execute jobs on a schedule.
GET/api/projects/{projectId}/triggersList triggersJeton utilisateur ou clé API
Returns all triggers configured for the specified project.
# GET /api/projects/{projectId}/triggersParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Trigger UUID. |
name | string | Obligatoire | Trigger display name. |
job_id | string | Obligatoire | UUID of the associated job. |
cron_expression | string | Obligatoire | Cron schedule expression. |
enabled | boolean | Obligatoire | Whether the trigger is active. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/triggersExemple de réponse
[
{
"id": "trig-001",
"name": "Nightly Login Test",
"job_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"cron_expression": "0 2 * * *",
"enabled": true
}
]POST/api/projects/{projectId}/triggersCreate triggerJeton utilisateur ou clé API
Creates a new cron-based trigger that will execute the specified job on schedule. Project API keys need triggers:write.
# POST /api/projects/{projectId}/triggersParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Trigger display name. |
job_id | string | Obligatoire | UUID of the job to execute. |
cron_expression | string | Obligatoire | Cron schedule expression (5-field). |
enabled | boolean | Facultatif | Whether the trigger is active. Defaults to true. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created trigger. |
name | string | Obligatoire | Trigger name. |
cron_expression | string | Obligatoire | Cron schedule. |
enabled | boolean | Obligatoire | Active state. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name":"Hourly Smoke Test","job_id":"e5f6a7b8-...","cron_expression":"0 * * * *"}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/triggersExemple de réponse
{
"id": "trig-002",
"name": "Hourly Smoke Test",
"cron_expression": "0 * * * *",
"enabled": true,
"created_at": "2026-04-04T14:00:00Z"
}GET/api/triggers/{triggerId}Get triggerJeton utilisateur ou clé API
Returns the full details of a single trigger.
# GET /api/triggers/{triggerId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
triggerId | string | Obligatoire | UUID of the trigger. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Trigger UUID. |
name | string | Obligatoire | Trigger name. |
job_id | string | Obligatoire | Associated job UUID. |
cron_expression | string | Obligatoire | Cron schedule expression. |
enabled | boolean | Obligatoire | Whether the trigger is active. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/triggers/trig-001Exemple de réponse
{
"id": "trig-001",
"name": "Nightly Login Test",
"job_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"cron_expression": "0 2 * * *",
"enabled": true,
"created_at": "2026-03-15T09:00:00Z"
}PUT/api/triggers/{triggerId}Update triggerJeton utilisateur ou clé API
Updates an existing trigger. Project API keys need triggers:write. Only provided fields are changed.
# PUT /api/triggers/{triggerId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
triggerId | string | Obligatoire | UUID of the trigger. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New trigger name. |
job_id | string | Facultatif | New job UUID. |
cron_expression | string | Facultatif | New cron schedule expression. |
enabled | boolean | Facultatif | Enable or disable the trigger. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Trigger UUID. |
name | string | Obligatoire | Updated trigger name. |
cron_expression | string | Obligatoire | Updated cron schedule. |
enabled | boolean | Obligatoire | Updated active state. |
updated_at | string | Obligatoire | ISO 8601 update timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"cron_expression":"30 1 * * *"}' \
http://localhost:8080/api/triggers/trig-001Exemple de réponse
{
"id": "trig-001",
"name": "Nightly Login Test v2",
"cron_expression": "30 1 * * *",
"enabled": true,
"updated_at": "2026-04-04T14:30:00Z"
}DELETE/api/triggers/{triggerId}Delete triggerJeton utilisateur ou clé API
Permanently deletes a trigger. Project API keys need triggers:write. The associated job is not affected.
# DELETE /api/triggers/{triggerId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
triggerId | string | Obligatoire | UUID of the trigger to delete. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
message | string | Obligatoire | Confirmation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/triggers/trig-001Exemple de réponse
{
"message": "Trigger deleted successfully."
}Queues
Manage work queues for RPA automation. Queues hold items that can be processed by workers sequentially or in parallel.
GET/api/projects/{projectId}/queuesList queuesJeton utilisateur ou clé API
Returns all queues configured for the specified project.
# GET /api/projects/{projectId}/queuesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue UUID. |
name | string | Obligatoire | Queue display name. |
description | string | Facultatif | Optional queue description. |
max_retries | number | Obligatoire | Maximum retry attempts per item. |
custom_statuses | string[] | Obligatoire | Queue-specific custom statuses. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/queuesExemple de réponse
[
{
"id": "queue-001",
"name": "Invoice Processing",
"description": "Incoming invoices to be processed.",
"max_retries": 3,
"custom_statuses": [
"blocked"
],
"created_at": "2026-03-20T08:00:00Z"
}
]POST/api/projects/{projectId}/queuesCreate queueJeton utilisateur ou clé API
Creates a new work queue within the specified project.
# POST /api/projects/{projectId}/queuesParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Queue display name. |
description | string | Facultatif | Optional description. |
max_retries | number | Facultatif | Maximum retry attempts per item. Defaults to 3. |
retry_delay_seconds | number | Facultatif | Delay between retries in seconds. Defaults to 60. |
deadline_seconds | number | Facultatif | Maximum time in seconds before an in-progress item is considered timed out. |
auto_trigger_job_id | string | Facultatif | UUID of a job to auto-trigger when items are added. |
custom_statuses | string[] | Facultatif | Additional queue-specific statuses allowed by the custom status endpoint. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created queue. |
name | string | Obligatoire | Queue name. |
max_retries | number | Obligatoire | Configured max retries. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name":"Order Fulfillment","max_retries":5,"retry_delay_seconds":120,"custom_statuses":["blocked"]}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/queuesExemple de réponse
{
"id": "queue-002",
"name": "Order Fulfillment",
"max_retries": 5,
"custom_statuses": [
"blocked"
],
"created_at": "2026-04-04T15:00:00Z"
}GET/api/queues/{queueId}Get queueJeton utilisateur ou clé API
Returns the full details of a single queue, including its configuration.
# GET /api/queues/{queueId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue UUID. |
name | string | Obligatoire | Queue name. |
description | string | Facultatif | Queue description. |
max_retries | number | Obligatoire | Maximum retries. |
retry_delay_seconds | number | Obligatoire | Delay between retries. |
deadline_seconds | number | Facultatif | Item processing deadline. |
custom_statuses | string[] | Obligatoire | Queue-specific custom statuses. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queues/queue-001Exemple de réponse
{
"id": "queue-001",
"name": "Invoice Processing",
"description": "Incoming invoices to be processed.",
"max_retries": 3,
"retry_delay_seconds": 60,
"deadline_seconds": 300,
"custom_statuses": [
"blocked"
],
"created_at": "2026-03-20T08:00:00Z"
}PUT/api/queues/{queueId}Update queueJeton utilisateur ou clé API
Updates an existing queue configuration. Only provided fields are changed.
# PUT /api/queues/{queueId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Facultatif | New queue name. |
description | string | Facultatif | New description. |
max_retries | number | Facultatif | New max retry count. |
retry_delay_seconds | number | Facultatif | New retry delay. |
deadline_seconds | number | Facultatif | New processing deadline. |
auto_trigger_job_id | string | Facultatif | New auto-trigger job UUID. |
custom_statuses | string[] | Facultatif | Replace the queue-specific custom statuses. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue UUID. |
name | string | Obligatoire | Updated queue name. |
max_retries | number | Obligatoire | Updated max retries. |
updated_at | string | Obligatoire | ISO 8601 update timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"max_retries":5,"custom_statuses":["blocked"]}' \
http://localhost:8080/api/queues/queue-001Exemple de réponse
{
"id": "queue-001",
"name": "Invoice Processing v2",
"max_retries": 5,
"custom_statuses": [
"blocked"
],
"updated_at": "2026-04-04T15:30:00Z"
}DELETE/api/queues/{queueId}Delete queueJeton utilisateur ou clé API
Permanently deletes a queue and all its items. This action cannot be undone.
# DELETE /api/queues/{queueId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue to delete. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
message | string | Obligatoire | Confirmation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queues/queue-001Exemple de réponse
{
"message": "Queue deleted successfully."
}GET/api/queues/{queueId}/statsGet queue statsJeton utilisateur ou clé API
Returns aggregated statistics for a queue: item counts by status, throughput, and error rates.
# GET /api/queues/{queueId}/statsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
total | number | Obligatoire | Total items in the queue. |
status_counts | object | Obligatoire | Counts keyed by item status. |
avg_processing_ms | number | Obligatoire | Average processing duration for completed items. |
due_today | number | Obligatoire | New items due by the end of today. |
retry_rate | number | Obligatoire | Percentage of items that have retried at least once. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queues/queue-001/statsExemple de réponse
{
"total": 250,
"status_counts": {
"new": 45,
"in_progress": 3,
"completed": 190,
"failed": 12
},
"avg_processing_ms": 1830,
"due_today": 8,
"retry_rate": 4.8
}Queue Items
Manage individual items within a work queue. Items flow through a fixed lifecycle: new, in_progress, completed, failed, or abandoned.
GET/api/queues/{queueId}/itemsList queue itemsJeton utilisateur ou clé API
Returns items in the specified queue, with optional filtering by status and reference.
# GET /api/queues/{queueId}/itemsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Paramètres de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
status | string | Facultatif | Filter by status: "new", "in_progress", "completed", "failed", "abandoned". |
reference | string | Facultatif | Filter by reference identifier. |
limit | number | Facultatif | Maximum number of items to return. (Par défaut: 50) |
offset | number | Facultatif | Number of items to skip for pagination. (Par défaut: 0) |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Item status. |
reference | string | Facultatif | External reference identifier. |
priority | number | Obligatoire | Item priority (higher = more urgent). |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
"http://localhost:8080/api/queues/queue-001/items?status=new&limit=20"Exemple de réponse
[
{
"id": "item-001",
"status": "new",
"reference": "INV-2026-0042",
"priority": 10,
"created_at": "2026-04-04T10:00:00Z"
}
]POST/api/queues/{queueId}/itemsAdd queue itemJeton utilisateur ou clé API
Adds a single item to the queue for processing.
# POST /api/queues/{queueId}/itemsParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | object | Obligatoire | Arbitrary JSON payload for the item. |
reference | string | Facultatif | External reference identifier (e.g. invoice number). |
priority | number | Facultatif | Item priority. Higher values are processed first. |
tags | string[] | Facultatif | Tags for categorization and filtering. |
due_date | string | Facultatif | ISO 8601 deadline for processing this item. |
defer_until | string | Facultatif | ISO 8601 timestamp before which the item should not be processed. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | UUID of the newly created item. |
status | string | Obligatoire | Initial status ("new"). |
reference | string | Facultatif | Reference identifier. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"data":{"invoice_id":"INV-2026-0043","amount":150.00},"reference":"INV-2026-0043","priority":5}' \
http://localhost:8080/api/queues/queue-001/itemsExemple de réponse
{
"id": "item-002",
"status": "new",
"reference": "INV-2026-0043",
"created_at": "2026-04-04T15:00:00Z"
}POST/api/queues/{queueId}/items/bulkBulk add queue itemsJeton utilisateur ou clé API
Adds multiple items to the queue in a single request. Each item follows the same schema as the single-add endpoint.
# POST /api/queues/{queueId}/items/bulkParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
items | QueueItemInput[] | Obligatoire | Array of items to add. Each item has: data (required), reference, priority, tags, due_date, defer_until. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
created | number | Obligatoire | Number of items successfully created. |
items | QueueItem[] | Obligatoire | Array of created item summaries. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"items":[{"data":{"order":"ORD-001"},"reference":"ORD-001"},{"data":{"order":"ORD-002"},"reference":"ORD-002"}]}' \
http://localhost:8080/api/queues/queue-001/items/bulkExemple de réponse
{
"created": 3,
"items": [
{
"id": "item-003",
"status": "new",
"reference": "ORD-001"
},
{
"id": "item-004",
"status": "new",
"reference": "ORD-002"
},
{
"id": "item-005",
"status": "new",
"reference": "ORD-003"
}
]
}POST/api/queues/{queueId}/nextGet next queue itemJeton utilisateur ou clé API
Atomically fetches and locks the next available item from the queue. The item transitions to in_progress status.
# POST /api/queues/{queueId}/nextParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
queueId | string | Obligatoire | UUID of the queue. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated status ("in_progress"). |
data | object | Obligatoire | Item payload. |
reference | string | Facultatif | External reference. |
retry_count | number | Obligatoire | Number of times this item has been retried. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queues/queue-001/nextExemple de réponse
{
"id": "item-001",
"status": "in_progress",
"data": {
"invoice_id": "INV-2026-0042",
"amount": 99.99
},
"reference": "INV-2026-0042",
"retry_count": 0
}GET/api/queue-items/{itemId}Get queue itemJeton utilisateur ou clé API
Returns the full details of a single queue item, including its data payload and processing history.
# GET /api/queue-items/{itemId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
queue_id | string | Obligatoire | UUID of the parent queue. |
status | string | Obligatoire | Current item status. |
data | object | Obligatoire | Item payload. |
reference | string | Facultatif | External reference. |
retry_count | number | Obligatoire | Number of retries attempted. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queue-items/item-001Exemple de réponse
{
"id": "item-001",
"queue_id": "queue-001",
"status": "in_progress",
"data": {
"invoice_id": "INV-2026-0042",
"amount": 99.99
},
"reference": "INV-2026-0042",
"retry_count": 0,
"created_at": "2026-04-04T10:00:00Z"
}PUT/api/queue-items/{itemId}Update queue itemJeton utilisateur ou clé API
Updates an existing queue item's data, reference, priority, or tags.
# PUT /api/queue-items/{itemId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
data | object | Facultatif | Updated item payload. |
reference | string | Facultatif | Updated reference identifier. |
priority | number | Facultatif | Updated priority. |
tags | string[] | Facultatif | Updated tags. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Current item status. |
updated_at | string | Obligatoire | ISO 8601 update timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X PUT -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"priority":20,"tags":["urgent"]}' \
http://localhost:8080/api/queue-items/item-001Exemple de réponse
{
"id": "item-001",
"status": "new",
"updated_at": "2026-04-04T16:00:00Z"
}POST/api/queue-items/{itemId}/statusSet queue item statusJeton utilisateur ou clé API
Sets a queue item to a default status or a custom status configured on the queue.
# POST /api/queue-items/{itemId}/statusParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
status | string | Obligatoire | Default or queue-defined custom status. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated item status. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"status":"failed"}' \
http://localhost:8080/api/queue-items/item-001/statusExemple de réponse
{
"id": "item-001",
"status": "failed"
}DELETE/api/queue-items/{itemId}Delete queue itemJeton utilisateur ou clé API
Permanently removes a queue item. Only allowed for items in new or terminal states.
# DELETE /api/queue-items/{itemId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item to delete. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
message | string | Obligatoire | Confirmation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queue-items/item-001Exemple de réponse
{
"message": "Queue item deleted successfully."
}POST/api/queue-items/{itemId}/completeComplete queue itemJeton utilisateur ou clé API
Marks an in-progress queue item as successfully completed. Optionally attach output data.
# POST /api/queue-items/{itemId}/completeParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
output | object | Facultatif | Optional output data from processing (results, generated files, etc.). |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated status ("completed"). |
completed_at | string | Obligatoire | ISO 8601 completion timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"output":{"processed":true,"pdf_url":"https://storage.example.com/inv-42.pdf"}}' \
http://localhost:8080/api/queue-items/item-001/completeExemple de réponse
{
"id": "item-001",
"status": "completed",
"completed_at": "2026-04-04T16:05:00Z"
}POST/api/queue-items/{itemId}/failFail queue itemJeton utilisateur ou clé API
Marks an in-progress queue item as failed. Optionally attach an error message. If retries remain, the item may be automatically requeued.
# POST /api/queue-items/{itemId}/failParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
error_message | string | Facultatif | Error message describing the failure. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated status ("failed"). |
retry_count | number | Obligatoire | Current retry count. |
max_retries | number | Obligatoire | Max retries configured for the queue. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{"error_message":"Timeout waiting for page load"}' \
http://localhost:8080/api/queue-items/item-001/failExemple de réponse
{
"id": "item-001",
"status": "failed",
"retry_count": 2,
"max_retries": 3
}POST/api/queue-items/{itemId}/abandonAbandon queue itemJeton utilisateur ou clé API
Marks an in-progress queue item as abandoned without counting it as a retry.
# POST /api/queue-items/{itemId}/abandonParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated status ("abandoned"). |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queue-items/item-001/abandonExemple de réponse
{
"id": "item-001",
"status": "abandoned"
}POST/api/queue-items/{itemId}/retryRetry queue itemJeton utilisateur ou clé API
Manually retries a failed queue item by resetting it to new status and incrementing the retry count.
# POST /api/queue-items/{itemId}/retryParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
itemId | string | Obligatoire | UUID of the queue item. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | Queue item UUID. |
status | string | Obligatoire | Updated status ("new"). |
retry_count | number | Obligatoire | Updated retry count. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer bo_live_your_api_key" \
http://localhost:8080/api/queue-items/item-001/retryExemple de réponse
{
"id": "item-001",
"status": "new",
"retry_count": 3
}API Keys
Manage API keys for programmatic access. API keys provide an alternative to JWT tokens for automation and CI/CD integrations.
POST/api/projects/{projectId}/api-keysCreate API keyJeton utilisateur
Creates a new project-scoped API key. The raw key value is returned only once in the response.
# POST /api/projects/{projectId}/api-keysParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project that will own the key. |
Corps de requête
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
name | string | Obligatoire | Display name for the API key. |
scopes | string[] | Obligatoire | Array of granted scopes such as "jobs:read", "runs:write", or "queues:execute". |
expires_at | string | Facultatif | ISO 8601 expiration timestamp. Omit for a non-expiring key. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | API key UUID. |
key | string | Obligatoire | The raw API key value (bo_live_...). Shown only once. |
name | string | Obligatoire | Key display name. |
scopes | string[] | Obligatoire | Granted scopes. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X POST -H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"CI Pipeline","scopes":["jobs:read","queues:execute"]}' \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/api-keysExemple de réponse
{
"id": "key-001",
"key": "bo_live_abc123def456ghi789jkl012mno345",
"name": "CI Pipeline",
"scopes": [
"jobs:read",
"queues:execute"
],
"created_at": "2026-04-04T17:00:00Z"
}GET/api/projects/{projectId}/api-keysList API keysJeton utilisateur
Returns all API keys for the specified project. The raw key value is never returned.
# GET /api/projects/{projectId}/api-keysParamètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
projectId | string | Obligatoire | UUID of the project. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
id | string | Obligatoire | API key UUID. |
name | string | Obligatoire | Key display name. |
key_prefix | string | Obligatoire | First 12 characters of the key for identification. |
scopes | string[] | Obligatoire | Granted scopes. |
last_used_at | string | Facultatif | ISO 8601 timestamp of last use. |
created_at | string | Obligatoire | ISO 8601 creation timestamp. |
Types de contenu: application/json → application/json
Exemple cURL
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/projects/c3d4e5f6-a7b8-9012-cdef-123456789012/api-keysExemple de réponse
[
{
"id": "key-001",
"name": "CI Pipeline",
"key_prefix": "bo_live_abcd",
"scopes": [
"jobs:read",
"queues:execute"
],
"last_used_at": "2026-04-04T16:30:00Z",
"created_at": "2026-04-04T17:00:00Z"
}
]DELETE/api/api-keys/{keyId}Revoke API keyJeton utilisateur
Permanently revokes an API key. Any requests using this key will immediately fail authentication.
# DELETE /api/api-keys/{keyId}Paramètres de chemin
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
keyId | string | Obligatoire | UUID of the API key to revoke. |
Corps de réponse
| Champ | Type / statut | Obligatoire | Description |
|---|---|---|---|
message | string | Obligatoire | Confirmation message. |
Types de contenu: application/json → application/json
Exemple cURL
curl -X DELETE -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8080/api/api-keys/key-001Exemple de réponse
{
"message": "API key revoked"
}