---
title: "Add an app to a computer"
method: POST
path: "/api/computers/{id}/services"
tags: ["apps"]
---

# Add an app to a computer

`POST /api/computers/{id}/services`

## Request

- Base URL: `https://www.orgo.ai`
- URL: `https://www.orgo.ai/api/computers/{id}/services`
- Auth: HTTP bearer

Body: { name, command, cwd?, port?, restart?, run_as?, enabled?, env?, secret_env? }. name: 1-32 lowercase letters, digits and hyphens, unique on the computer. command runs with bash in cwd (default the user’s home), after /root/.env and the app’s variables are loaded; values are used as typed. restart: always (default), on-failure (started again after a non-zero exit; an exit in its first 3 seconds counts as a failed start and is retried) or no (once per boot). run_as: root by default. port: what the app listens on, unique on the computer; the computer’s own ports (22, 3389, 5900-5999, 6080-6099, 8080, 9000) are refused. secret_env values are stored encrypted and never returned (only their names, in secret_env_keys). Applied at once when the computer is running (apply.state "applied"); otherwise saved and applied when it next runs ("pending"). Never wakes the computer. At most 20 apps a computer.

## Path parameters

- `id` string, required

## Request body

- CreateComputerApp
  - `name` string, required
  - `command` string, required
  - `cwd` string, nullable: An absolute path. Default: the user’s home.
  - `port` integer, nullable
  - `restart` 'always' | 'on-failure' | 'no'
  - `run_as` string
  - `enabled` boolean
  - `env` object
  - `secret_env` object

## Response `201`

Added.

- ComputerAppWrite
  - `id` string, uuid, required
  - `name` string, required
  - `kind` 'command' | 'deploy', required: deploy: the app of a deploy, changed from the deploy.
  - `deploy_project_id` string, uuid, nullable
  - `command` string, required
  - `cwd` string, nullable
  - `env` object, required
  - `secret_env_keys` string[], required: Names of the secret variables. Their values are never returned.
  - `port` integer, nullable
  - `restart` 'always' | 'on-failure' | 'no', required
  - `run_as` string, required
  - `enabled` boolean, required
  - `status` 'running' | 'starting' | 'crashing' | 'stopped' | 'exited' | 'failed' | 'pending' | 'off' | 'unknown', required: pending: saved, not on the computer yet. crashing: it keeps exiting soon after it starts. failed: it could not be started.
  - `status_detail` string, nullable: The process manager’s own words, e.g. "pid 812, uptime 2:14:09".
  - `status_at` string, date-time, nullable
  - `listening` boolean, nullable: Something listens on port (null: no port, or the computer was not asked).
  - `listening_publicly` boolean, nullable: It listens beyond 127.0.0.1, so a public URL reaches it.
  - `applied` boolean, required: The computer has this version of the app.
  - `error` string, nullable
  - `public_url` string, nullable: The public URL on this port, where public URLs are on.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `apply` ComputerAppApply
    - `state` 'applied' | 'pending' | 'failed', required: pending: applied when the computer next runs, or on Orgo’s next try.
    - `error` string

## Other responses

- `400`: A field is not valid (INVALID_NAME, INVALID_COMMAND, INVALID_CWD, INVALID_PORT, INVALID_RESTART, INVALID_RUN_AS, INVALID_ENV), the apps are too large to apply together (SERVICES_TOO_LARGE), or the computer cannot have apps (SERVICES_UNSUPPORTED).
- `401`: Unauthenticated.
- `403`: No access to this computer, view-only access, or a share-link guest.
- `409`: The name or the port is taken on this computer (NAME_TAKEN, PORT_TAKEN), or it has 20 apps (SERVICE_LIMIT).
- `429`: Over one of the account's rate limits (rate_limited): `limit` names it, `retry_after` and Retry-After say how many seconds to wait. Limits are per account (the workspace owner when the request acts on a computer or a workspace) and set by its plan (x-rate-limits).

## Changes

- **2026-11-01** `60e768a2bb9d`: 6 info
  - added the optional property `docs_url` to the response with the `400` status
  - added the optional property `docs_url` to the response with the `409` status
  - added the optional property `next` to the response with the `400` status
  - added the optional property `next` to the response with the `409` status
  - …2 more
- **2026-10-30** `afb6f0ee1aac`: 1 info
  - added the non-success response with the status `429`
- **2026-10-18** `dcaee154d80e`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/orgo/apis/orgo-api/changes/api/computers/:id/services/post.md)

---

[API](https://skmtc.dev/orgo/apis/orgo-api.md) - [All operations](https://skmtc.dev/orgo/apis/orgo-api/llms.txt) - [OpenAPI document](https://skmtc.dev/orgo/apis/orgo-api/revisions/e4c1e7379fa5?raw)
