# Import bundle

> Import a JSON bundle into a workspace

- Source: https://www.taskade.com/docs/actions/import-bundle
- Section: Action API
- Endpoint: `POST /importBundle` (API v2)
- Index of all pages: https://www.taskade.com/docs/llms.txt

## POST `/importBundle`

Import a JSON bundle into a workspace

Base URL: `https://www.taskade.com/api/v2`

### Authentication

Send a personal access token or an OAuth 2.0 access token as a bearer token. Create a personal access token at [taskade.com/settings/api](https://www.taskade.com/settings/api).

```http
Authorization: Bearer tskdp_your_token_here
```

### Request body

`application/json`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `workspaceId` | `string` | Yes | The target workspace ID to import the bundle into. |
| `bundleData` | `object` | Yes | The Workspace DNA bundle to import (SpaceBundleData v1). |
| `bundleData.version` | `string` | Yes | Bundle format version. Allowed values: `1`. |
| `bundleData.items` | `object` | Yes | Map of bundle items keyed by ID. Each item has a `type` field: space-bundle-flow-item, space-bundle-project-item, space-bundle-agent-item, space-bundle-template-item, space-bundle-media-item, space-bundle-app-item, space-bundle-agent-team-item. Agent-team items name their members by SOURCE agent id in `agentIds`; the importer remaps them and drops any member whose agent is not also in the bundle. |

A nested field marked Yes is required whenever its parent object is present.

### Example request

```bash
curl -X POST "https://www.taskade.com/api/v2/importBundle" \
  -H "Authorization: Bearer $TASKADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"workspaceId":"<workspaceId>","bundleData":{"version":"1","items":{}}}'
```

### Responses

#### `200` — Default response

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ok` | `boolean` | Yes | — |
| `item` | `object` | Yes | — |
| `item.id` | `string` | Yes | Unique identifier for the bundle installation. |
| `item.projectCount` | `number` | Yes | Number of projects installed. |
| `item.flowCount` | `number` | Yes | Number of automations installed. |
| `item.agentCount` | `number` | Yes | Number of agents installed. |
| `item.templateCount` | `number` | Yes | Number of templates installed. |
| `item.mediaCount` | `number` | Yes | Number of media files installed. |
| `item.appCount` | `number` | Yes | Number of apps installed. |

### Errors

Errors return an `ok: false` envelope. Rate limiting returns `429` with `x-rate-limit-limit`, `x-rate-limit-remaining` and `x-rate-limit-reset` headers. `x-rate-limit-reset` is the number of seconds until the window reopens. `Retry-After` is not sent, so schedule retries from `x-rate-limit-reset`; retrying sooner will fail again.

```json
{ "ok": false, "message": "Unauthorized", "code": "UNAUTHORIZED" }
```

Rate limits for this version: enforced per endpoint; ceilings are not published and can change without notice. A `429` response carries `x-rate-limit-limit`, `x-rate-limit-remaining`, and `x-rate-limit-reset` (seconds until the window reopens). Back off from those headers rather than hardcoding numbers. If you need sustained throughput, prefer batching (operations like `/createTask` accept arrays) over tightening polling loops. See [Rate limits](https://www.taskade.com/docs/getting-started/action-api-guide#rate-limits).
