# POST /v1/organizations/migrate (/docs/api/reference/organizations/migrate)



<Endpoint method="POST" path="/v1/organizations/migrate" auth="Bearer" scope="org:admin" phase="1" />

If you started with flat [projects](/docs/api/concepts/projects) directly under your org and want to adopt the [sub-organization](/docs/api/concepts/organizations) model, migrate them in one call instead of recreating anything. You send a `mapping` of project → child-org name; Layers **creates the named child orgs and moves the mapped projects under them**, atomically. You call this with your parent (`org:admin`) key, and it acts on your own org — there's no `:orgId` in the path.

Each distinct child-org name in the mapping becomes **one** new child org. Two projects mapped to the same name land under the same new child; two different names create two children.

<Callout type="warn">
  The migration is **all-or-nothing**. If any mapped project has an in-flight execution, the whole call is rejected and nothing moves — retry once those workflows finish.
</Callout>

<Parameters
  title="Body"
  rows="[
  { name: 'mapping', type: 'object', required: true, description: <>A map of <code>projectId</code> → <code>childOrgName</code>. Keys are project ids (<code>prj_…</code> or bare UUID); each value is the name (1–128 chars) of the child org to create and move that project into.</> },
]"
/>

<Parameters
  title="Headers"
  rows="[
  { name: 'Idempotency-Key', type: 'string (UUID)', required: false, description: 'Strongly recommended. A replay returns the original result without migrating twice.' },
]"
/>

## Example [#example]

```bash
curl -X POST https://api.layers.com/v1/organizations/migrate \
  -H "Authorization: Bearer $PARENT_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "mapping": {
      "prj_13fd8406-387a-4472-b6a2-531860557a6e": "Acme Coffee",
      "prj_9b2c7d10-5e44-4a01-8f3a-2c1d6e7f8a90": "Wayne Labs"
    }
  }'
```

<Response status="201" description="Created — child orgs created, projects moved">
  ```json
  {
    "projectsMoved": 2,
    "childrenCreated": 2,
    "children": [
      {
        "id": "org_d4e5f6a7-8b9c-4d0e-9f2a-3b4c5d6e7f80",
        "name": "Acme Coffee",
        "projectIds": ["prj_13fd8406-387a-4472-b6a2-531860557a6e"]
      },
      {
        "id": "org_a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "name": "Wayne Labs",
        "projectIds": ["prj_9b2c7d10-5e44-4a01-8f3a-2c1d6e7f8a90"]
      }
    ]
  }
  ```
</Response>

### Field notes [#field-notes]

* `projectsMoved` is the total count of projects relocated; `childrenCreated` is the number of new child orgs minted.
* `children` lists each created child with its new `org_…` `id` and the `projectIds` now under it. Persist the ids against your customer records.
* **History stays with the parent.** A migrated project's past credit events remain on the parent's [ledger](/docs/api/reference/credits/list-events); only its *future* spend bills to the new child wallet.
* **30-day read grace.** For 30 days after the move, your parent key can still read a migrated project, so dashboards and reconciliation don't break the moment you migrate. After that, reach the project through its child (the [`X-Layers-Organization`](/docs/api/getting-started/authentication#acting-on-behalf-of-a-child-org) header or a child key).

## Errors [#errors]

| Status | Code              | When                                                                                                                          |
| ------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| 409    | `CONFLICT`        | One or more mapped projects have in-flight executions. Nothing moved — `details.detail` names them; retry once they complete. |
| 404    | `NOT_FOUND`       | One or more mapped projects aren't under your org (anti-enumeration — we don't confirm which).                                |
| 422    | `VALIDATION`      | Malformed body, a non-UUID project key, or a name outside 1–128 chars.                                                        |
| 403    | `FORBIDDEN_SCOPE` | Key lacks `org:admin`.                                                                                                        |
| 503    | `KILL_SWITCH`     | Your key or org is suspended.                                                                                                 |

## See also [#see-also]

* [Organizations concept → migrating existing projects](/docs/api/concepts/organizations#migrating-existing-projects-into-children) — when and why to migrate.
* [Manage customers with sub-organizations](/docs/api/guides/manage-customers-with-sub-organizations) — the full customer lifecycle.
* [Allocate credits](/docs/api/reference/organizations/credits/allocate) — fund the new children after migrating.
