---
title: "POST /sandbox-clones"
method: POST
path: "/sandbox-clones"
tags: ["Sandboxes"]
---

# POST /sandbox-clones

`POST /sandbox-clones`

## Request

- Base URL: `https://api.greentally.ai/v1`
- URL: `https://api.greentally.ai/v1/sandbox-clones`
- Auth: HTTP bearer

Start copying a live business organization's data for whole months (at most 36), optionally only some sites, into a new sandbox (spec part B). Needs access.manage on the source, in the caller's tenant; a source outside it, or one the caller holds no grant on, is 404. Repeating a requestId with the same body returns the same clone (200). The sandbox stays hidden until the copy finishes; a failed or cancelled copy archives it.

The months and sites select records, and each selected record is copied whole: all of its raw rows, even those outside the chosen months. A copied upload brings its whole original file (a file is evidence and cannot be copied in part), so the file can hold other sites' and other months' data. It also brings every analysis (review) row of that upload; rows for records the clone left behind arrive un-submitted and without a record. Whoever is given the sandbox can see all of this. The start is recorded on the source organization's activity (access.sandbox_clone_data_copied_out). Support sessions are refused (403).

## Request body

- SandboxCloneRequest
  - `copyAccess` boolean
  - `copyDashboard` boolean
  - `fromMonth` string, required
  - `name` string, required
  - `requestId` string, required
  - `siteIds` string[]
  - `sourceOrganizationId` string, required
  - `toMonth` string, required

## Response `200`

The clone this requestId already started.

- SandboxCloneResponse
  - `data` SandboxClone, required
    - `cancelRequested` boolean, required
    - `cancellable` boolean, required
    - `copyAccess` boolean, required
    - `copyDashboard` boolean, required
    - `createdAt` string, date-time, required
    - `error` string
    - `errorCode` 'CLONE_TOO_LARGE' | 'CLONE_SOURCE_NOT_LIVE' | 'CLONE_SOURCE_CHANGED' | 'CLONE_FACTOR_NOT_COPYABLE' | 'CLONE_SANDBOX_GONE' | 'CLONE_NOT_FOUND' | 'SANDBOX_CLONE_DISABLED' | 'CANCELLED' | 'RETRIES_EXHAUSTED' | 'INTERRUPTED' | 'DISPATCH_FAILED' | 'INVALID_CHECKPOINT' | 'UNKNOWN_KIND': Why the copy failed or ended: the clone's own CLONE_TOO_LARGE (the months grew past the limit after the start), CLONE_SOURCE_NOT_LIVE (the source was archived, made a sandbox or moved to another tenant), CLONE_SOURCE_CHANGED (a site, entity or upload was added to the source after its phase), CLONE_FACTOR_NOT_COPYABLE (a row references another organization's private factor), CLONE_SANDBOX_GONE (the sandbox was no longer being provisioned when the copy finished), CLONE_NOT_FOUND (the clone's record was deleted while its job ran) and SANDBOX_CLONE_DISABLED, or the document jobs' CANCELLED, RETRIES_EXHAUSTED, INTERRUPTED, DISPATCH_FAILED, INVALID_CHECKPOINT (the job's stored progress could not be read) and UNKNOWN_KIND (the process that ran the job had no sandbox clone handler).
    - `finishedAt` string, date-time
    - `fromMonth` string, required
    - `id` string, required
    - `progress` SandboxCloneProgress
      - `done` integer, required
      - `message` string
      - `phase` 'prepare' | 'reference' | 'uploads' | 'records' | 'analysis' | 'dashboard' | 'finalize' | 'done', required
      - `total` integer, required
    - `rawRowCount` integer, required
    - `result` SandboxCloneResult
      - `analysisRows` integer, required
      - `dashboardCopied` boolean, required
      - `entities` integer, required
      - `factorEntries` integer, required
      - `missingOriginals` integer, required
      - `rawRows` integer, required
      - `sites` integer, required
      - `sourceRecords` integer, required
      - `suppliers` integer, required
      - `uploads` integer, required
    - `sandboxName` string, required
    - `sandboxOrganizationId` string, required
    - `siteIds` string[], required
    - `sourceOrganizationId` string, required
    - `sourceOrganizationName` string, required
    - `status` 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled', required
    - `toMonth` string, required

## Other responses

- `202`: Accepted; the copy runs as a job.
- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `409`: CLONE_TOO_LARGE (details {rawRows, limit}; more than 250,000 raw rows), CLONE_EMPTY (no data in the months and sites), CLONE_IN_PROGRESS (details {cloneId}; one live clone per tenant), CLONE_SOURCE_NOT_LIVE (the source is archived or a sandbox), CLONE_REQUEST_MISMATCH (the requestId was already used with a different body), or PLAN_LIMIT (details.resource sandboxes, sites or entities).
- `503`: SANDBOX_CLONE_UNAVAILABLE (document jobs are off).

## Changes

- **2026-10-09** `840a458f7a4d`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/greentally/apis/esgai-api/changes/sandbox-clones/post.md)

---

[API](https://skmtc.dev/greentally/apis/esgai-api.md) · [All operations](https://skmtc.dev/greentally/apis/esgai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/greentally/apis/esgai-api/revisions/7eab940f1dd0?raw)
