# Imports

An **import** moves a local project into a workspace as a new cloud project. It is a three-step protocol — create, upload the bundle, finalize — so the manifest, the bundle hash and the protected data are all bound to one reviewed scan.

Generated from contract version `1.0.0` — the same document [`/v1/api/openapi.json`](/api/openapi/) serves.

## Prerequisites

- An API key in `x-api-key`, or a browser session cookie
- `X-Organization-Id` naming the workspace to act in, unless the session already has an active one
- The base URL for your deployment, `https://server.hlix.ai` by default

## Operations

| Method | Path | Operation |
| --- | --- | --- |
| `POST` | `/v1/api/imports` | [Create an idempotent project import session](#create-an-idempotent-project-import-session) |
| `GET` | `/v1/api/imports/{id}` | [Get an owned project import session](#get-an-owned-project-import-session) |
| `PUT` | `/v1/api/imports/{id}/bundle` | [Stream a Git bundle to a local hlix backend](#stream-a-git-bundle-to-a-local-hlix-backend) |
| `POST` | `/v1/api/imports/{id}/finalize` | [Verify, restore, and atomically create an imported project](#verify-restore-and-atomically-create-an-imported-project) |
| `POST` | `/v1/api/projects/{id}/resources/agent` | [Create a project-scoped agent from local instructions](#create-a-project-scoped-agent-from-local-instructions) |
| `POST` | `/v1/api/projects/{id}/resources/mcp` | [Explicitly activate a validated MCP server for one project](#explicitly-activate-a-validated-mcp-server-for-one-project) |
| `POST` | `/v1/api/projects/{id}/resources/skill` | [Explicitly activate a quarantined skill for one project](#explicitly-activate-a-quarantined-skill-for-one-project) |

## Create an idempotent project import session

`POST /v1/api/imports` · operation ID `createProjectImport`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/json`, `CreateProjectImport` (required)

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `bundleSha256` | string | **yes** |  |
| `bundleSize` | integer | **yes** | max 5368709120 |
| `commitSha` | string | **yes** |  |
| `defaultBranch` | string | **yes** |  |
| `historyMode` | `preserve` | `abort_on_findings` | **yes** |  |
| `idempotencyKey` | string | **yes** | min length 16, max length 200 |
| `manifest` | object | **yes** |  |
| `manifestSha256` | string | **yes** |  |
| `name` | string | **yes** | min length 1, max length 200 |
| `stack` | string | **yes** | min length 1, max length 100 |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | ProjectImportCreated | The existing idempotent import session. |
| `201` | ProjectImportCreated | A new import session and scoped upload target. |
| `400` | ValidationError \| ApiError | The JSON body failed schema validation (`ValidationError`), or the request named no active organization (`ApiError`). |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `409` | ApiError | The idempotency key names a different payload. |

## Get an owned project import session

`GET /v1/api/imports/{id}` · operation ID `getProjectImport`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | ProjectImportStatus | The current import state. |
| `400` | ApiError | The request named no active organization. |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | The import does not exist or belongs to another actor. |

## Stream a Git bundle to a local hlix backend

`PUT /v1/api/imports/{id}/bundle` · operation ID `uploadProjectImportBundle`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/x-git-bundle` (required)

The contract does not pin this body's properties.

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | UploadAccepted | The bundle passed its declared hash and size. |
| `400` | ApiError | The request named no active organization. |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | The import does not exist or belongs to another actor. |
| `409` | ApiError | The import no longer accepts an upload. |
| `415` | ApiError | The upload is not a Git bundle. |

## Verify, restore, and atomically create an imported project

`POST /v1/api/imports/{id}/finalize` · operation ID `finalizeProjectImport`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/json`, `FinalizeProjectImport` (required)

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `protectedFiles` | object[] | **yes** |  |
| `secrets` | object | **yes** |  |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `200` | ProjectImportFinalized | The import was already finalized. |
| `201` | ProjectImportFinalized | The project and initial immutable revision were created. |
| `400` | ValidationError \| ApiError | The JSON body failed schema validation (`ValidationError`), or the request named no active organization (`ApiError`). |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |
| `404` | ApiError | The import does not exist or belongs to another actor. |
| `409` | ApiError | Another finalizer owns the import transition. |
| `503` | ApiError \| WorkspaceBudgetError | Encrypted secret storage is not configured, or this backend instance is at its Coding Workspace budget (then `active`/`limit` are present, the import was reset, and a retry is safe). |

## Create a project-scoped agent from local instructions

`POST /v1/api/projects/{id}/resources/agent` · operation ID `importProjectAgent`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/json`, `ImportAgent` (required)

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | max length 2000 |
| `instructions` | string | **yes** | min length 1, max length 20000 |
| `name` | string | **yes** | min length 1, max length 120 |
| `runtimeKind` | `claude-code` | `codex` | `cursor-agent` | `hlix` | **yes** |  |
| `sandboxProfile` | `builder` | `desktop` | `e2e` | **yes** |  |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `201` | ImportedAgent | The project-scoped agent was created. |
| `400` | ValidationError \| ApiError | The JSON body failed schema validation (`ValidationError`), or the request named no active organization (`ApiError`). |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |

## Explicitly activate a validated MCP server for one project

`POST /v1/api/projects/{id}/resources/mcp` · operation ID `importProjectMcp`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/json`, `ImportMcp` (required)

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `args` | string[] | no |  |
| `command` | string | no | max length 100 |
| `envKeys` | string[] | no |  |
| `headers` | object | no |  |
| `name` | string | **yes** | min length 1, max length 100 |
| `transport` | `stdio` | `http` | `sse` | **yes** |  |
| `url` | string (uri) | no | max length 2000 |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `201` | ImportedMcp | The MCP server was activated with secret references. |
| `400` | ValidationError \| ApiError | The JSON body failed schema validation (`ValidationError`), or the request named no active organization (`ApiError`). |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |

## Explicitly activate a quarantined skill for one project

`POST /v1/api/projects/{id}/resources/skill` · operation ID `importProjectSkill`

**Parameters**

| Name | In | Required | Type | Description |
| --- | --- | --- | --- | --- |
| `id` | path | **yes** | string |  |
| `X-Organization-Id` | header | no | string | The workspace (organization) to act in. Omitted, the session's active organization is used. |

**Request body** — `application/json`, `ImportSkill` (required)

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `content` | string | **yes** | min length 1, max length 200000 |
| `slug` | string | **yes** | min length 1, max length 100 |

**Responses**

| Status | Body | Description |
| --- | --- | --- |
| `201` | ImportedSkill | The skill is available in this project sandbox. |
| `400` | ValidationError \| ApiError | The JSON body failed schema validation (`ValidationError`), or the request named no active organization (`ApiError`). |
| `401` | ApiError | No valid session or API key. |
| `403` | ApiError | Authenticated, but not a member of the named organization — or a client collaborator without the required access on this project. |

## If a request fails

These apply to every operation on this page.

- `400` — the body failed schema validation, or the request named no active organization. A `ValidationError` body carries the failing fields; an `ApiError` body carries only `error`.
- `401` — no valid session or API key.
- `403` — authenticated, but not a member of the named organization, or a client collaborator without the required access.
- `404` — no such resource **in this workspace**. Absent and not-visible are deliberately the same answer; do not infer cross-tenant existence from it.
- `409` — the expected revision or state is stale, or another operation currently owns the transition.
- `500` — the operation failed server-side. Retry only where an idempotency key makes that safe.

## Next steps

[API reference](/api/reference/)
  [API & OpenAPI](/api/openapi/)
  [TypeScript SDK](/sdk/typescript/)
  [CLI reference](/reference/cli/)