---
title: "Create a template"
method: POST
path: "/templates/{slug}/instantiate"
tags: ["Templates"]
---

# Create a template

`POST /templates/{slug}/instantiate`

## Request

- Base URL: `/api` (relative, and the document was published on a file host, not at the API’s origin)
- URL: `/api/templates/{slug}/instantiate`
- Auth: HTTP bearer

Creates every service of a template, the databases it needs, and, for a
template going into a project, its shared variables and path routes. The
request is checked in full, then runs in the background: poll
`GET /instantiations/{id}`. Sending the same `idempotency_key` again
returns the same instantiation.

## Path parameters

- `slug` string, required

## Request body

- InstantiateTemplateRequest: Create a template.
  - `databases` object: One choice per database type the template needs.
  - `environment_variables` TemplateVariableInput[]
    - `is_secret` boolean
    - `name` string, required
    - `service` string, nullable: The service the variable belongs to. Needed only when the name is not declared by the template, or is declared by several services.
    - `value` string, required
  - `fork` ForkRequest: Fork the template's repository into a git account, so the code becomes the user's and pushes deploy. Starters only.
    - `automatic_deploy` boolean: Deploy on push to the fork.
    - `git_provider_connection_id` integer, required
    - `private` boolean
    - `repository_name` string, required: Name of the repository to create.
    - `repository_owner` string, nullable: Account or organization to create it in; the connection's user when omitted.
  - `idempotency_key` string, required: Chosen by the client. Sending the same key again returns the same instantiation instead of creating the template twice.
  - `runtime_overrides` object: Runtime overrides for services that run a prebuilt image, by the template's service name.
  - `service_names` object: Names for the created services, by the template's service name.
  - `target` union, required: Where the services of a template go.
    - object: A new project named `name`.
      - `name` string, required
      - `slug` string, nullable: Explicit slug for the project. When omitted the slug is derived from `name` via `ProjectGroupService::slugify`. Useful when the name does not produce a valid Latin slug (non-Latin scripts, emoji-only names).
      - `type` 'new_project', required
    - object: A project that exists. Its services receive the template's shared variables only where the project does not define them already.
      - `group_id` integer, required
      - `type` 'existing_project', required
    - object: No project; only for templates with a single service.
      - `type` 'no_project', required

## Response `200`

The instantiation already started with this idempotency key

- InstantiationResponse
  - `created_at` string, date-time, required
  - `error` string, nullable: Why it failed, when it did.
  - `finished_at` string, date-time, nullable
  - `group_id` integer, nullable: The project the services go into, once known.
  - `id` integer, required
  - `kind` string, required: `template` or `import`.
  - `name` string, required
  - `services` InstantiatedService[], required
    - `name` string, required
    - `project_id` integer, nullable: Set once the service exists.
    - `slug` string, required
    - `template_service` string, required: Name of the service in the template.
  - `status` 'pending' | 'running' | 'succeeded' | 'failed' | 'interrupted', required
  - `steps` InstantiationStep[], required
    - `error` string, nullable
    - `key` string, required: Stable identifier, such as `service:backend`.
    - `label` string, required: What the step does, for display.
    - `status` 'pending' | 'done' | 'failed', required
  - `template_slug` string, nullable
  - `updated_at` string, date-time, required

## Other responses

- `202`: Accepted; the services are being created
- `400`: Invalid request
- `403`: Insufficient permissions, or a reserved slug only an instance admin may claim
- `404`: Template or project not found
- `409`: The idempotency key was used for a different request
- `428`: A reserved slug requires a recently MFA-verified session

## Changes

> 77 revisions in range; 1 not diffed.

- **2026-10-14** `daf87435065e`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/gotempsh/apis/temps/changes/templates/:slug/instantiate/post.md)

---

[API](https://skmtc.dev/gotempsh/apis/temps.md) · [All operations](https://skmtc.dev/gotempsh/apis/temps/llms.txt) · [OpenAPI document](https://skmtc.dev/gotempsh/apis/temps/revisions/24add76f6317?raw)
