Skip to content

API overview ​

Everything you can do in the dashboard, you can do with the Fjordrun API. The dashboard and the CLI use the same API.

  • Base URL: https://api.fjordrun.com/api/v1
  • Format: JSON request and response bodies (Content-Type: application/json)
  • OpenAPI document: docs.fjordrun.com/openapi.json. Import it into Postman, Insomnia or a client generator. The live document is at https://api.fjordrun.com/openapi.json.
  • Reference: every endpoint, grouped by resource, in the sidebar. Start with Teams, Projects and Services.

Authentication ​

Send a token in the Authorization header:

bash
curl -H "Authorization: Bearer $FJORDRUN_TOKEN" https://api.fjordrun.com/api/v1/teams

Two kinds of tokens work (see API tokens):

TokenPrefixActs asUse it for
Team API tokenfjr_its creator's role, in one team (optionally one project)CI, deploy scripts, automation
Personal access tokenfjr_pat_you, in all your teamsthe CLI, your own scripts

Create team tokens in Team settings → API tokens. A request without a valid token gets 401.

A few endpoints only work from a dashboard session (for example changing your password). Called with a token, they answer 403.

Roles ​

Each team member has a role: viewer (read only), member (create and deploy), admin (members, tokens, billing) or owner. A request that needs more than the token's role gets 403. A project-scoped team token gets 404 for anything outside its project.

IDs and environments ​

Resources are identified by UUIDs. A project has one or more environments (the first is production), and a service exists in every environment of its project, with its own configuration, variables, domains and deployments.

Service endpoints take an optional environment_id query parameter. Without it, they act on the production environment.

Errors ​

Errors use the HTTP status code and a JSON body with a detail message:

json
{ "detail": "Your plan allows up to 2 vCPU per service" }
StatusMeaning
400The request can't be carried out as sent (for example a template without the variables it needs)
401Missing, invalid or expired token
402The team has no credit left, or its plan doesn't allow this
403Your role (or token) doesn't allow this
404Not found, or not visible to your token
409Conflicts with the current state (for example a hostname already in use, or the team is suspended)
410Gone (for example an expired invite)
422Validation error. FastAPI validation errors have detail as a list of {loc, msg, type} objects
429Too many requests. Wait and retry
502, 503A provider Fjordrun depends on (payments, GitHub) failed or is not available. Retry later

Streaming endpoints ​

Live logs (/deployments/{id}/logs/stream), live metrics (/services/{id}/metrics/live) and workflow runs (/runs/{id}/stream) are Server-Sent Events. Browsers can't set headers on an EventSource, so these endpoints also accept the token as a token query parameter. Prefer the header everywhere else, because URLs end up in logs.

bash
curl -N -H "Authorization: Bearer $FJORDRUN_TOKEN" \
  "https://api.fjordrun.com/api/v1/deployments/$DEPLOYMENT_ID/logs/stream?type=build"

Walkthrough: deploy a container image ​

This walkthrough creates a project, deploys a public image, changes a variable and adds a domain. It uses curl and jq.

bash
export FJORDRUN_TOKEN=fjr_...           # Team settings → API tokens
export API=https://api.fjordrun.com/api/v1
auth=(-H "Authorization: Bearer $FJORDRUN_TOKEN" -H "Content-Type: application/json")

1. Find your team. A team token sees only its own team.

bash
TEAM_ID=$(curl -s "${auth[@]}" $API/teams | jq -r '.[0].id')

2. Create a project. Pick a region (nbg1 Nuremberg, fsn1 Falkenstein or hel1 Helsinki). The response includes the project's environments; the first is production.

bash
PROJECT=$(curl -s "${auth[@]}" -X POST $API/teams/$TEAM_ID/projects \
  -d '{"name": "hello", "region": "nbg1"}')
PROJECT_ID=$(echo "$PROJECT" | jq -r .id)
ENV_ID=$(echo "$PROJECT" | jq -r '.environments[0].id')

3. Create a service. A service with a source deploys right away. config only needs the settings you change; see ServiceConfig for all of them.

bash
SERVICE=$(curl -s "${auth[@]}" -X POST $API/projects/$PROJECT_ID/services -d '{
  "environment_id": "'"$ENV_ID"'",
  "name": "web",
  "kind": "web",
  "source": {"type": "image", "image": "nginxdemos/hello:latest"},
  "config": {"deploy": {"port": 80}},
  "variables": {"GREETING": "hej"}
}')
SERVICE_ID=$(echo "$SERVICE" | jq -r .id)
DEPLOYMENT_ID=$(echo "$SERVICE" | jq -r .latest_deployment.id)

To build from GitHub instead, use "source": {"type": "github", "repo": "owner/repo", "branch": "main"}. Someone in the team must have linked their GitHub account (in the dashboard) with access to the repository. Fjordrun then adds a push webhook, so pushes to the branch deploy automatically. See How builds work.

4. Wait for the deployment. A deployment goes through queued, building (GitHub sources), deploying and ends as success, failed, crashed or cancelled. Later, it becomes removed when a newer deployment replaces it.

bash
until s=$(curl -s "${auth[@]}" $API/deployments/$DEPLOYMENT_ID | jq -r .status); \
      [[ $s =~ ^(success|failed|crashed|cancelled)$ ]]; do sleep 5; done; echo $s
curl -s "${auth[@]}" "$API/deployments/$DEPLOYMENT_ID/logs?type=deploy" | jq -r '.[].message'

5. Give it a public URL. Services are private until they have a domain. An empty body creates a generated *.fjordrun.app domain with HTTPS:

bash
curl -s "${auth[@]}" -X POST $API/services/$SERVICE_ID/domains -d '{}' | jq -r .url

6. Change a variable. PATCH merges: keys you send are set, null removes a key, others stay. PUT replaces all of them. A running service is redeployed with the new values.

bash
curl -s "${auth[@]}" -X PATCH $API/services/$SERVICE_ID/variables \
  -d '{"variables": {"GREETING": "hallo"}}' | jq .variables

7. Deploy a new version. Point the service at another image (or change any setting) and a running service is redeployed. POST /services/{id}/deploy deploys the current settings again.

bash
curl -s "${auth[@]}" -X PATCH $API/services/$SERVICE_ID/config \
  -d '{"source": {"image": "nginxdemos/hello:plain-text"}}' | jq .latest_deployment.status

8. Add a custom domain (Hobby plan or higher). Create the DNS records from the response at your DNS provider, then verify. The status changes from pending_dns to active, and the HTTPS certificate is issued automatically.

bash
DOMAIN=$(curl -s "${auth[@]}" -X POST $API/services/$SERVICE_ID/domains -d '{"hostname": "hello.example.com"}')
echo "$DOMAIN" | jq -r '.dns_records[] | "\(.type) \(.name) \(.value)"'
curl -s "${auth[@]}" -X POST $API/domains/$(echo "$DOMAIN" | jq -r .id)/verify | jq .status

9. Clean up. Deleting the project removes its services, volumes and domains. It needs the admin role (the other steps need member).

bash
curl -s "${auth[@]}" -X DELETE $API/projects/$PROJECT_ID

CI/CD ​

For GitHub Actions, see CI/CD with GitHub Actions. Elsewhere, the CLI (fjordrun deploy --wait) or the two calls above (PATCH /services/{id}/config with the new image, then poll the deployment) do the same.

Fjordrun is hosted in the EU (Hetzner, Nuremberg, Germany). Private beta.