---
title: "Deploy an app"
method: POST
path: "/client/apps"
tags: ["Apps"]
---

# Deploy an app

`POST /client/apps`

## Request

- Base URL: `https://api.roar-ai.com`
- URL: `https://api.roar-ai.com/client/apps`
- Auth: HTTP bearer

Provision + deploy from a git repo. Returns 202 with the app, its web service and the queued deployment; poll `/client/apps/{id}/progress` for the rest. Requires `apps:deploy`.

This route takes no `databaseEnabled` — a database Roar provides is `POST /client/apps/github`. To use your own, send its `DATABASE_URL` in `env`.

A repository we can read and already know cannot build — several apps and no `rootDir`, or nothing we know how to build — is refused with 400 before anything is created, and the message says what to change. One we cannot tell how to START passes once `startCommand` says how (one line, at most 300 characters; an obviously unfinished command such as a bare `node` or one ending in a folder is refused). The body is strict: a field this route does not take is a 400, never silently ignored. `GET /client/github/build-check` asks the same question first.

## Request body

- DeployAppRequest
  - `name` string, required
  - `repo` string, required: owner/name
  - `branch` string
  - `rootDir` string: The app’s folder in a repository that holds several apps. Absent means found automatically.
  - `startCommand` string: How the app starts, when the repository does not say (one line, at most 300 characters). Stored as the build settings start command.
  - `env` object
  - `projectId` string, uuid, nullable

## Response `202`

Deploy started

- AppDeployAccepted
  - `project` App, required
    - `id` string, uuid, required
    - `clientId` string, uuid, required
    - `groupId` string, uuid, nullable, required: The project this app is filed under, if any
    - `name` string, required
    - `status` string, required
    - `region` string, nullable: The app's home cell — the region chosen at create time, not its current placement
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `service` AppServiceView, required
    - `id` string, uuid, required
    - `projectId` string, uuid, required: The APP's id — a service belongs to an app
    - `kind` string, required
    - `name` string, required
    - `sourceRepo` string, nullable, required: "owner/name" of the repo it deploys from
    - `status` string, required
    - `runMigrations` boolean, required
    - `deployOnPush` boolean, required
    - `branch` string, nullable, required
    - `memoryLimitMb` integer, nullable, required: The most memory the app may use, in MB — a ceiling set automatically from the server it runs on, not a reservation and not a setting. Billing is on what the app actually uses. Null until the app has been placed on a server.
    - `cpuLimit` number, nullable, required: The most CPU the app may use, in vCPU — set automatically, like memoryLimitMb. Null until the app has been placed on a server.
    - `emailFrom` string, nullable, required
    - `aiUsesTools` boolean, required: “Let this app's AI use its tools”: Roar adds your company's tools to the app's own chat requests that bring none
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `deployment` AppDeploymentQueued, required
    - `id` string, uuid, required
    - `serviceId` string, uuid, required
    - `status` string, required
    - `commitSha` string, nullable, required
    - `errorSummary` string, nullable, required
    - `failureLabel` string, nullable
    - `createdAt` string, date-time, required
    - `finishedAt` string, date-time, nullable, required
    - `trigger` 'first_deploy' | 'push' | 'redeploy' | 'restore' | 'settings' | 'database' | 'autofix' | 'retry' | 'maintenance', nullable
    - `triggeredVia` 'console' | 'api_key' | 'mcp' | 'github' | 'platform', nullable
    - `triggeredBy` string, nullable
    - `branch` string, nullable
    - `commitMessage` string, nullable
    - `restoredFromId` string, uuid, nullable
    - `timings` object, nullable, required: Always null here — this deploy has not run, so there is nothing measured. GET /client/services/{id}/deployments carries the phase breakdown of a finished deploy.

## Other responses

- `400`: A DATABASE_URL of your own alongside a Roar database, or a repository that cannot build as it stands
- `403`: Key lacks apps:deploy

---

[API](https://skmtc.dev/roar-ai/apis/roar-ai-api.md) · [All operations](https://skmtc.dev/roar-ai/apis/roar-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/roar-ai/apis/roar-ai-api/revisions/37e4d0d5a7fe?raw)
