Documentation › Day to day
Using the API
Personal access tokens: script the platform and rebuild from CI (GitHub Actions) without a browser session.
Access tokens
Everything the dashboard does goes through the same API under https://cloud.example.com/api . Scripts and CI jobs authenticate with a personal access token : create one in Profile → Access tokens , pick its scopes, its projects and when it expires (30, 90 or 365 days, or a date up to a year away). The token is shown once : copy it into a password manager or a CI secret straight away.
read Projects, branches, builds, build logs, the list of backups and the status page data.
builds:write Rebuild a branch, create a branch from another one, wake a sleeping build.
backups:write Make a backup, download backups and database dumps.
admin covers everything you can do on your projects (settings, domains, restores, upgrades…). Prefer the narrow scopes: a CI job that rebuilds staging needs read and builds:write , nothing else. Whatever its scopes, a token acts as you and never has more rights than you: your role on each project still applies, and if you're removed from a project, your tokens lose it too.
Never possible with a token Creating or revoking tokens, two-factor settings, collaborators and roles, deleting a project, billing, platform settings, SSH keys, and the shell, editor and notebook. Sign in to the dashboard for those.
Send it in the Authorization: Bearer kvp_… header only. A token in a URL ( ?token= ) is refused.
Creating one needs a sign-in from the last 30 minutes and, with two-factor on, a code from your authenticator app. You get an email and a notification each time one is created, and a reminder a week before one expires.
Each token can make 600 requests a minute; past that the API answers 429 . Poll a build every 10 to 30 seconds, not in a tight loop.
Revoke a token from your Profile the moment you suspect it leaked: it stops working at once. Its last used date and address help you spot misuse.
Examples with curl
These use jq to read the JSON answers. Set the address and the token once per shell:
shell
# The token goes in an environment variable, never in a URL or a script you commit
export KV_URL=https://cloud.example.com
export KV_TOKEN=kvp_… # paste your token here
# Who am I, and with which token?
curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/me/token"
List your projects and find a branch's id:
shell
# Your projects (scope: read)
curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/projects" | jq '.[] | {id, name}'
# The branches of project 12, with their ids and stages
curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/projects/12/branches" | jq '.[] | {id, name, stage}'
Rebuild a branch (as the Rebuild button does). The answer is the new build; a build already queued or running for that branch gives 409 .
shell
# Rebuild branch 34 (scope: builds:write); the answer is the new build
BUILD_ID=$(curl -fsS -X POST -H "Authorization: Bearer $KV_TOKEN" \
"$KV_URL/api/branches/34/build" | jq -r .id)
echo "Build $BUILD_ID queued"
Wait for its result:
shell
# Wait for the build's result (scope: read): queued → building → running (success or warning), or failed
while :; do
STATE=$(curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/builds/$BUILD_ID" | jq -r '.status + " " + .result')
case "$STATE" in
"queued "* | "building "*) sleep 20 ;;
"running success" | "running warning") echo "Build $BUILD_ID is live"; break ;;
*) echo "Build $BUILD_ID ended as: $STATE"; exit 1 ;;
esac
done
Download the latest backup (only admins of the project get production backups; testers get staging's):
shell
# Download the latest backup of project 12 (scopes: read to list, backups:write to download)
BACKUP_ID=$(curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/projects/12/backups" \
| jq '[.[] | select(.status == "done" and .local)][0].id')
curl -fSL -H "Authorization: Bearer $KV_TOKEN" -o "backup-$BACKUP_ID.zip" \
"$KV_URL/api/backups/$BACKUP_ID/download"
# Or make a fresh backup of production first (answers the new backup; it is ready once its status is "done")
curl -fsS -X POST -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/projects/12/backups" | jq '{id, status}'
GitHub Actions: rebuild staging after the tests pass
Create a token with the read and builds:write scopes, restricted to the project, and store it as the repository secret KV_TOKEN ( Settings → Secrets and variables → Actions ). This workflow runs when your Tests workflow succeeds on the staging branch, rebuilds staging (a fresh copy of production with the new code) and fails the job if the build fails:
.github/workflows/rebuild-staging.yml
# .github/workflows/rebuild-staging.yml
# Repository → Settings → Secrets and variables → Actions: add KV_TOKEN (a token with the read and builds:write scopes)
name: Rebuild staging
on:
workflow_run:
workflows: ["Tests"] # the name of your test workflow
types: [completed]
branches: [staging]
jobs:
rebuild:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
timeout-minutes: 45
env:
KV_URL: https://cloud.example.com
KV_TOKEN: ${{ secrets.KV_TOKEN }}
BRANCH_ID: "34" # the staging branch's id (GET /api/projects/<id>/branches)
steps:
- name: Rebuild staging
run: |
BUILD_ID=$(curl -fsS -X POST -H "Authorization: Bearer $KV_TOKEN" \
"$KV_URL/api/branches/$BRANCH_ID/build" | jq -r .id)
echo "BUILD_ID=$BUILD_ID" >> "$GITHUB_ENV"
echo "Build $BUILD_ID queued"
- name: Wait for the result
run: |
while :; do
STATE=$(curl -fsS -H "Authorization: Bearer $KV_TOKEN" "$KV_URL/api/builds/$BUILD_ID" | jq -r '.status + " " + .result')
case "$STATE" in
"queued "* | "building "*) sleep 20 ;;
"running success" | "running warning") echo "Staging is live"; break ;;
*) echo "::error::Build $BUILD_ID ended as: $STATE"; exit 1 ;;
esac
done
Pushes already build A push to a branch builds it through the GitHub webhook. Use the API when you want a rebuild on your own terms, e.g. only after your test suite passed, on a schedule, or from another repository.
Reference
The interactive reference at https://cloud.example.com/api/docs lists every endpoint. Each one says whether it accepts an access token and with which scope; the others need a dashboard session. GET /api/me/token tells a script which account and token it is using.