# dudbox API

Deploy and run apps on dudbox over HTTP. These docs are for people and for agents. Each page is also plain Markdown: add `.md` to its address. This page is [/docs/api/index.md](/docs/api/index.md), all pages are listed in [/llms.txt](/llms.txt), and the OpenAPI 3.1 file is [/api/v1/openapi.json](/api/v1/openapi.json).

## Start

1. Make a token on [your account page](https://dudbox.com/account), under "API tokens". It starts with `dud_`. dudbox shows it only once.
2. Keep it in an env var and send it in the `Authorization` header:

```sh
export DUDBOX_TOKEN=dud_…
curl -s https://dudbox.com/api/v1/me -H "Authorization: Bearer $DUDBOX_TOKEN"
```

- Base URL: `https://dudbox.com/api/v1`.
- JSON in, JSON out. A request with a body needs `content-type: application/json`.
- Times are ISO 8601 in UTC, like `2026-11-04T09:30:00Z`.
- A service has a project and a name. Its `id` is `project/service`, and paths use both: `/api/v1/services/{project}/{service}`.
- Every key in an answer is always there. A missing value is `null`, never a missing key.

## Rules for agents

- Read the token from `$DUDBOX_TOKEN`. Never print it, log it or put it in a URL.
- When a call fails, test `code`, not the text of `error`, and do what `hint` says. See [Errors, limits and versions](/docs/api/errors.md).
- A deploy takes from seconds to a few minutes. Wait for it with `GET /api/v1/deployments/{id}?wait=300`. Do not poll in a tight loop.
- A deploy that fails leaves the app before it live. Read the build log before you change anything.
- Delete needs the service name in the body: `{"confirm": "<service>"}`. Ask the person first.

## Recipes

Each recipe uses these two lines first:

```sh
API=https://dudbox.com/api/v1
AUTH="Authorization: Bearer $DUDBOX_TOKEN"
```

**Add a one-click app and wait until it is live.**

```sh
curl -s $API/templates -H "$AUTH"                     # pick one with "deployable": true
curl -s $API/services -H "$AUTH" -H 'content-type: application/json' \
  -d '{"template": "uptime-kuma"}'                     # answer: the service, with pending_deployment.id
curl -s "$API/deployments/42?wait=300" -H "$AUTH"      # until "done": true; "status": "live" means it runs
```

Then open `url` from the service. If `login` is not null, the app has an admin login: the user is `login.user`, and the password is the env var `login.password_env`:

```sh
curl -s $API/services/o3k9x2a/uptime-kuma/env/ADMIN_PASSWORD -H "$AUTH"
```

**Import a GitHub repo.** The dudbox GitHub App must be installed on the repo first. `GET /api/v1/repos` lists the repos you can import, and its `install_url` adds more.

```sh
curl -s $API/repos -H "$AUTH"
curl -s $API/services/import -H "$AUTH" -H 'content-type: application/json' \
  -d '{"repo": "acme/shop", "env": {"DATABASE_URL": "postgres://…"}}'
curl -s "$API/deployments/43?wait=300" -H "$AUTH"
```

Every push to the branch deploys again by itself.

**Change an env var and apply it.** The app gets env vars on its next deploy.

```sh
curl -s -X PUT $API/services/acme/shop/env/LOG_LEVEL -H "$AUTH" -H 'content-type: application/json' \
  -d '{"value": "debug"}'
curl -s -X POST $API/services/acme/shop/redeploy -H "$AUTH"   # answer: the new deployment
curl -s "$API/deployments/44?wait=300" -H "$AUTH"
```

**Find out why a deploy failed.** `error` has one line. The build log has the rest. If the build worked but the app did not start, its own output is in the app logs.

```sh
curl -s $API/services/acme/shop -H "$AUTH"             # live_deployment, pending_deployment, deployments
curl -s $API/deployments/44/log -H "$AUTH"             # the build and start log
curl -s "$API/services/acme/shop/logs?deployment=44&lines=100" -H "$AUTH"
```

**Roll back.** This makes an older deployment live again, with no build.

```sh
curl -s -X POST $API/services/acme/shop/rollback -H "$AUTH"   # to the one before the live one
curl -s -X POST $API/services/acme/shop/rollback -H "$AUTH" -H 'content-type: application/json' -d '{"to": 41}'
```

**Read what the app says.**

```sh
curl -s "$API/services/acme/shop/logs?lines=50" -H "$AUTH"
curl -sN "$API/services/acme/shop/logs?follow=true" -H "$AUTH"   # stays open, new lines as they come
```

## Pages

- [Tokens](/docs/api/auth.md): make a token, check it, the OpenAPI file.
- [Services](/docs/api/services.md): one-click apps, GitHub imports, list, get, delete.
- [Deployments](/docs/api/deployments.md): redeploy, deploy, roll back, wait, build logs, cancel.
- [Env vars](/docs/api/env.md): list, read, set, delete.
- [Logs](/docs/api/logs.md): what the app writes, old and live.
- [Errors, limits and versions](/docs/api/errors.md): the error shape, codes, the rate limit, what stays stable.
