---
title: "Move sites from the test project to the live project"
method: POST
path: "/project/move-to-live"
tags: ["Project"]
---

# Move sites from the test project to the live project

`POST /project/move-to-live`

## Request

- Base URL: `https://api.hypamoon.com/api/v1`
- URL: `https://api.hypamoon.com/api/v1/project/move-to-live`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.hypamoon.com/oauth/authorize`, token URL `https://api.hypamoon.com/oauth/token`, scopes: `project:write`)

Moves the chosen sites of the test project (default: all) to its live project, with every version, label, password and address, the collections they use with all documents, an app on the site with its sign-in users, files and database, the agents on those collections (paused) and domains connected for real. Simulated domains do not come along. The test form token (hm_pubtest_) in the site files is replaced by a new live token with the same allowed origins, as a new site version labelled 'moved to live'. A collection that a site staying in test also uses is refused by default (409 with the list); shared_collections copy gives the live project its own copy. Everything in the database happens in one transaction, and a move log keeps the rows from before, so the move can be undone within 24 hours. Works with a test or a live key of the same project, but only for an owner (through OAuth, or a key made by an owner) and only when the live project is verified: otherwise verification_required with the missing steps (company details, a payment with SCA, a verified phone). The plan limits of the live project apply (sites, files, data, apps). A chat connected through OAuth to the test project stays on test: reconnect and choose the live project, or switch the connection to live in the portal under Connections.

## Request body

- MoveToLiveInput: Move sites from the test project to the live project.
  - `sites` string[]: Optional. The sites to move, by id or slug. Leave it out to move every site of the test project.
  - `collections` string[]: Optional. The collections to move, by name or id. Leave it out to move the collections the chosen sites use (a site uses a collection when its files name it, like a form from get_form_snippet).
  - `shared_collections` 'refuse' | 'copy': What to do with a collection that a site staying in test also uses. refuse (default): nothing is moved and the answer lists them. copy: the live project gets its own copy with all documents; the test site keeps the original.

## Response `200`

What moved, what stayed, and the next step.

- MoveToLive
  - `id` string, required: The id of this move, for undo_move_to_live.
  - `status` 'done' | 'partly_done', required: partly_done: some steps after the move did not finish; see errors. Support is notified.
  - `from_project` object, required
    - `id` string, required
    - `name` string, required
    - `mode` 'test' | 'live', required
  - `to_project` object, required
    - `id` string, required
    - `name` string, required
    - `mode` 'test' | 'live', required
  - `moved` object, required
    - `sites` object[], required
      - `id` string, required
      - `slug` string, required
      - `url` string, required
      - `new_version` number, nullable, required: The new version with the live form token, labelled "moved to live"; null when no file had a test token.
      - `form_token_replaced` boolean, required
      - `waiting_for_approval` true
    - `collections` object[], required
      - `id` string, required
      - `name` string, required
      - `documents` number, nullable, required
    - `copied_collections` object[], required
      - `name` string, required
      - `test_id` string, required
      - `live_id` string, required
      - `documents` number, nullable, required
    - `apps` object[], required
      - `id` string, required
      - `site_id` string, required
    - `agents` object[], required
      - `id` string, required
      - `name` string, required
      - `status` 'paused', required
    - `domains` string[], required
    - `form_tokens` object[], required
      - `name` string, required
      - `live_token_id` string, required
      - `replaces_test_token_id` string, required
    - `webhooks` number, required
  - `stayed_in_test` object, required
    - `sites` object[], required
      - `id` string, required
      - `slug` string, required
    - `collections` string[], required
    - `simulated_domains` string[], required
  - `warnings` string[], required
  - `errors` string[], required
  - `undo` object, required
    - `until` string, required
    - `how` string, required
  - `connection` object, nullable, required: For a chat connected through OAuth: which project the connection points to now.
    - `mode` 'test' | 'live', required
    - `note` string, required
  - `summary` string, required
  - `next_step` string, required

## Other responses

- `400`: Bad Request: invalid_json.
- `401`: Unauthorized: unauthorized, missing_api_key, invalid_api_key, api_key_revoked, project_deleted.
- `402`: Payment Required: plan_limit_reached.
- `403`: Forbidden: project_not_enabled, key_mode_mismatch, missing_scope, verification_required, forbidden.
- `404`: Not Found: not_found.
- `409`: Conflict: conflict, plan_limit_reached.
- `422`: Unprocessable Content: validation_failed.
- `429`: Too Many Requests: rate_limited.
- `500`: Internal Server Error: internal_error.
- `503`: Service Unavailable: service_unavailable.

---

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