# Dockup PaaS > Dockup is a self-hosted container Platform-as-a-Service. It deploys Docker > containers and exposes them at `https://{slug}-app.{base_domain}`. > The web UI at the root URL is for humans — everything is also controllable > via a fully-documented HTTP JSON API. **Agents should use the API, not the > HTML login screen.** ## Base URL All API calls use the host the user gave you (e.g. `https://dockup.cc`). API root is `/api/v1`. ## Machine-readable docs (fetch these first) - [OpenAPI 3 spec](/api/v1/openapi.json) — full endpoint reference, request/response shapes - [OpenAPI (well-known)](/.well-known/openapi.json) — same spec, standard discovery path - [AI plugin manifest](/.well-known/ai-plugin.json) — ChatGPT/Claude plugin descriptor - [Swagger alias](/swagger.json) — same spec - [Public status](/api/v1/system/status) — no auth; use to verify the host is Dockup ## Authentication Send `Authorization: Bearer ` on every API call. Two token types: 1. **API key** — starts with `dkp_`. Preferred for agents. Create one in the UI (API Keys page) and paste it. It is now visible/copyable after creation. 2. **JWT** — `POST /api/v1/auth/login` with `{email, password}` returns a JWT. For WebSocket endpoints (logs stream, exec, codex) pass the token as `?token=` query param instead of a header. ## Golden-path workflow (deploy an app) ``` # 1. List projects, create one if empty GET /api/v1/projects POST /api/v1/projects {"name": "My Project"} # 2. Create an app in that project POST /api/v1/projects/{projectId}/apps { "name": "my-app", "slug": "my-app", # globally unique, becomes subdomain "image": "nginx:alpine", # Docker Hub image, or omit for git deploy "internal_port": 80 } # 3. Deploy it POST /api/v1/apps/{appId}/deploy # or, preferred for CI/CD (slug is stable): POST /api/v1/deploy/{slug} # 4. App is live at https://{slug}-app.{base_domain} ``` ## Rules that trip agents up - **Slug is globally unique** across all users. Lowercase, hyphens, no reuse. Duplicate → `409 slug_taken`. Pick a unique slug or update the existing app. - **Image field vs. git deploy**: set `git_repo_url` + `git_provider=github` to auto-build from source. Do not set `image` in that case — it is generated. - **Upload a local image**: `POST /api/v1/apps/{id}/upload-image` or `POST /api/v1/deploy/{slug}` with the output of `docker save` as the body. - **Resource changes are live**: `PUT /api/v1/apps/{id}` with new `cpu_limit` or `memory_limit` applies without restart. - **Status sync**: app responses include `status` (running/stopped/paused/ restarting/starting), `cpu_usage` (percent), `memory_usage` (MB) synced with Docker every 30 s. ## Common operations | What | Endpoint | |------|----------| | Logs (JSON) | `GET /api/v1/apps/{id}/logs?tail=100` | | Logs (stream) | `WS /api/v1/apps/{id}/logs/stream?token=...` | | Interactive shell | `WS /api/v1/apps/{id}/exec?token=...&cmd=/bin/sh` | | Live stats | `GET /api/v1/apps/{id}/stats` | | Stats history | `GET /api/v1/apps/{id}/stats/history?minutes=60` | | Events (deploy, errors) | `GET /api/v1/apps/{id}/events` | | Deployment history | `GET /api/v1/apps/{id}/deployments` | | Start / stop / restart | `POST /api/v1/apps/{id}/{start,stop,restart}` | | Update config | `PUT /api/v1/apps/{id}` | | Delete | `DELETE /api/v1/apps/{id}` | | Autoscale | `GET/PUT /api/v1/apps/{id}/autoscale` | | Persistent volumes | `GET/POST/DELETE /api/v1/apps/{id}/volumes` | | Private registries | `/api/v1/registries` | | Git repos (OAuth) | `/api/v1/git/repos` | All `/apps/{appId}` routes accept the **slug** as well as the ID. ## Quick examples ``` # Deploy nginx curl -X POST https://dockup.cc/api/v1/projects/$PID/apps \ -H "Authorization: Bearer $HBR" \ -H "Content-Type: application/json" \ -d '{"name":"demo","slug":"demo","image":"nginx:alpine","internal_port":80}' curl -X POST https://dockup.cc/api/v1/deploy/demo \ -H "Authorization: Bearer $HBR" # Push a locally-built image docker save myapp:v1 | \ curl -X POST --data-binary @- \ -H "Authorization: Bearer $HBR" \ -H "Content-Type: application/octet-stream" \ https://dockup.cc/api/v1/deploy/my-app ``` ## When the user says "put this on dockup.cc" 1. Fetch `/api/v1/openapi.json` for the current spec. 2. Ask the user for an API key (or get one from the API Keys page). 3. Pick or create a project, pick a unique slug, create the app, deploy. 4. Report the URL: `https://{slug}-app.{base_domain}`.