---
title: "Create app service"
method: POST
path: "/api/v1/apps/services"
tags: ["Raff Apps"]
---

# Create app service

`POST /api/v1/apps/services`

Create an app service. Provisioning is asynchronous — the service is
created in status `pending` and moves through `building` and
`deploying` to `live`; poll `GET /api/v1/apps/services/{service_id}`
for progress.

Choose a `service_type`: `web` (public HTTPS URL), `private`
(in-cluster only), `worker` (long-running, no URL), `cron`
(scheduled), or `job` (one-off). Pick a `source_type`: `git` (a
connected GitHub repo), `image` (a prebuilt image), `template` (a
starter), or `compose`. Deploy code afterwards with a source upload
and a deployment, or set `deploy_now` for image sources.

## Headers

- `X-Project-ID` string, uuid, required

## Request body

- CreateAppServiceRequest
  - `name` string, required
  - `description` string
  - `service_type` 'web' | 'private' | 'worker' | 'cron' | 'job', required
  - `source_type` 'git' | 'image' | 'template' | 'compose'
  - `builder` 'buildpacks' | 'dockerfile' | 'image'
  - `image_ref` string — Prebuilt image reference (for source_type `image`)
  - `repo_full_name` string — GitHub repo (owner/name) for source_type `git`
  - `repo_branch` string
  - `repo_root_dir` string
  - `dockerfile_path` string
  - `start_command` string
  - `tier_id` integer
  - `replicas` integer
  - `autoscaling_enabled` boolean
  - `min_replicas` integer
  - `max_replicas` integer
  - `scale_to_zero` boolean
  - `http_port` integer
  - `health_check_path` string
  - `cron_schedule` string
  - `cron_timezone` string
  - `region` string
  - `deploy_now` boolean — Queue a deployment immediately (prebuilt-image services)

## Response `201`

App service created (status `pending` while provisioning)

- object
  - `success` boolean
  - `service` AppService — An app service on the Raff PaaS — a web service, private service, worker, cron job, or one-off job.
    - `id` string, uuid
    - `service_id` string — Short reference id used in URLs
    - `project_id` string, uuid
    - `name` string — Display name, unique within the project
    - `slug` string — URL label — the name plus a short random suffix
    - `description` string
    - `service_type` 'web' | 'private' | 'worker' | 'cron' | 'job'
    - `source_type` 'git' | 'image' | 'template' | 'compose'
    - `builder` 'buildpacks' | 'dockerfile' | 'image'
    - `repo_full_name` string — GitHub source only (owner/name)
    - `repo_branch` string
    - `repo_root_dir` string
    - `dockerfile_path` string
    - `image_ref` string — Prebuilt image source only
    - `start_command` string
    - `tier_id` integer — Pricing tier ID (see `GET /api/v1/apps/tiers`)
    - `tier_name` string
    - `replicas` integer
    - `autoscaling_enabled` boolean
    - `min_replicas` integer
    - `max_replicas` integer
    - `autoscaling_metric` string
    - `autoscaling_target` integer
    - `scale_to_zero` boolean
    - `http_port` integer
    - `health_check_path` string
    - `cron_schedule` string — Cron services only
    - `cron_timezone` string
    - `region` string
    - `url` string — Public HTTPS endpoint (web services; automatic TLS)
    - `internal_host` string — In-cluster hostname (private services)
    - `status` 'pending' | 'building' | 'deploying' | 'live' | 'paused' | 'suspended' | 'error' | 'deleting' | 'deleted'
    - `status_message` string
    - `paused_by_cap` boolean — True when a spend cap paused the service
    - `billing_type` 'payg' | 'subscription'
    - `current_deployment_id` string, uuid
    - `created_at` string, date-time
    - `updated_at` string, date-time
  - `deployment_id` string, uuid — Set when a deployment was queued at create time

## Other responses

- `400` — Invalid request parameters
- `401` — Authentication required
- `402` — Account balance is insufficient for this operation. Top up the balance and retry.
- `403` — Billing validation failed. The account is not in good standing. Check the `reason` field: - `banned` — account suspended - `failed` — last payment failed; top up the account balance - `no_billing_customer` — billing not set up
- `409` — A service with this name already exists in the project

---

[API](https://skmtc.dev/rafftechnologies/apis/raff-api.md) · [All operations](https://skmtc.dev/rafftechnologies/apis/raff-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/rafftechnologies/raff-api/revisions/2f4df56be77c/schema)
