# Import from Dropbox

Pull files from Dropbox — including private and team folders — into a Playbook board without clicking through the web app. Useful when creators keep dropping content into Dropbox and an agent or script should bring it into Playbook on a schedule.

## How it works[​](#how-it-works "Direct link to How it works")

1. **A person connects Dropbox once, in the Playbook web app.** Dropbox requires this consent step in a browser, so there is no API call or MCP tool for it.
2. **Your script or agent lists that connection** and gets its `token`.
3. **It starts an import** with one or more folders. Each folder becomes a sub-board, named after the folder, inside the board you import into; its sub-folders are nested below.
4. **It polls the import** until it finishes.

After step 1, nothing else is manual. The connection keeps working until someone disconnects Playbook in their Dropbox settings.

Connections belong to a Playbook user

Only the Playbook user who connected Dropbox can use that connection. The API token (or the account signed in to MCP) must belong to that same user, or the connection is missing from the list.

***

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

* **Access token**: an API token with the `write` scope, belonging to a workspace **owner or admin**.
* **Organization Slug**: your workspace identifier.
* **Dropbox connected** by the same Playbook user: in Playbook, open **Apps** in the sidebar, click **Dropbox** under **Importers**, and sign in with a Dropbox account that can see the folders. You can close the folder picker that opens afterwards — the connection is already saved.

For a Dropbox team account, the connection sees the team folders that account can open.

***

## 1. List connections[​](#1-list-connections "Direct link to 1. List connections")

```
curl "https://api.playbook.com/v1/my-org/imports/sources" \

  -H "Authorization: Bearer YOUR_TOKEN"
```

**Response:**

```
{

  "data": [

    {

      "token": "Rq8nW2vK5tLp",

      "provider": "dropbox",

      "email": "content@example.com",

      "created_at": "2026-09-22T10:12:03Z"

    }

  ],

  "meta": {

    "connect_url": "https://www.playbook.com/my-org/new-app"

  }

}
```

The list also contains Google Drive connections (`provider: "google_drive"`); use a `dropbox` one. `email` is filled in a few seconds after connecting, so it can briefly be `null`. If there is no `dropbox` connection, send the user to `meta.connect_url` to connect Dropbox, then list again.

***

## 2. Start an import[​](#2-start-an-import "Direct link to 2. Start an import")

```
curl -X POST "https://api.playbook.com/v1/my-org/imports" \

  -H "Authorization: Bearer YOUR_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{

    "import": {

      "source_token": "Rq8nW2vK5tLp",

      "folders": ["https://www.dropbox.com/home/Clients/Acme"],

      "board_token": "optional-board-token"

    }

  }'
```

| Field          | Required | Description                                                                                        |
| -------------- | -------- | -------------------------------------------------------------------------------------------------- |
| `source_token` | yes      | Token of a `dropbox` connection from the connection list.                                          |
| `folders`      | yes      | 1–20 Dropbox folders, in any of the formats below. Folders only — files are refused.               |
| `board_token`  | no       | Board to import into. Omit it to create a new top-level board named `Dropbox import (dd-mm-yyyy)`. |

A folder can be given as:

* **The URL from the Dropbox address bar** while the folder is open. A personal account shows `https://www.dropbox.com/home/Clients/Acme`; a member of a Dropbox team sees `https://www.dropbox.com/work/Team%20Folder/Clients` instead. Both work.
* **Its path**, e.g. `/Clients/Acme`.
* **Its Dropbox ID**, e.g. `id:a4ayc_80_OEAAAAAAAAAXw`.

**Shared links** (`https://www.dropbox.com/scl/fo/…`) are not supported and are refused with a `422`: open the folder in Dropbox and use the address-bar URL or path instead. The Dropbox root cannot be imported as a whole; pass its folders.

Paths are read in the account's own root: for a team member that is the team space, so `/Team Folder/Clients` and the member's own folder (`/Jane Doe/Drafts`) both resolve, exactly as the address-bar URL spells them.

Files do not land in `board_token` itself: importing the Dropbox folder `Acme` into the board `Content` puts them in `Content / Acme`. List that sub-board with the board children endpoint.

Each folder is checked against the connected Dropbox account before anything starts, so a folder the account cannot find fails right away with a `422` naming that account.

**Response:**

```
{

  "data": {

    "token": "q7Wm2LkP9sRt",

    "status": "pending",

    "cancel_reason": null,

    "scanning": true,

    "board_token": "b8Jd3KxQ1vNz",

    "pending_folders": 0,

    "files": { "total": 0, "pending": 0, "completed": 0, "skipped": 0, "failed": 0 },

    "created_at": "2026-09-22T10:15:00Z",

    "started_at": null,

    "completed_at": null,

    "canceled_at": null

  }

}
```

Keep `board_token` if you plan to re-sync the same folder later.

***

## 3. Poll the import[​](#3-poll-the-import "Direct link to 3. Poll the import")

```
curl "https://api.playbook.com/v1/my-org/imports/q7Wm2LkP9sRt" \

  -H "Authorization: Bearer YOUR_TOKEN"
```

`status` moves from `pending` to `active` to one of two final states:

* `completed` — every file was imported or skipped.

* `canceled` — see `cancel_reason`:

  <!-- -->

  * `incomplete` — some files or folders failed (`files.failed`).
  * `overlimit` — the workspace ran out of storage or assets, or the next file would have crossed into storage overage the workspace has not agreed to. Nothing past that point was stored.
  * `failed_to_start` — the import could not start after retrying, for example under sustained Dropbox rate limiting.
  * `oauth_credential_deleted` — the Dropbox connection was removed while importing.
  * `target_collection_deleted` — the board was deleted while importing.
  * `blocked` — the import was blocked by an admin.

`scanning` is `true` while folders are still being listed, so `files.total` keeps growing until it turns `false`. Poll every 15–30 seconds; large folders take a while.

***

## Re-syncing a folder[​](#re-syncing-a-folder "Direct link to Re-syncing a folder")

Import the same folder into the same `board_token` again to pick up what creators added since the last run. Files already there and unchanged — compared by Dropbox's content hash — are counted as `skipped` and not downloaded again; new files are imported. `files.completed` is therefore what the run added.

This is not a mirror of the folder. Things that produce duplicates or extra downloads:

* **Files changed in Dropbox.** The new version is added as a second asset next to the old one; the old asset is not updated or removed.
* **Renamed folders.** Sub-boards are matched by name, so renaming a Dropbox folder — or its sub-board in Playbook — imports that folder again in full into a new sub-board.
* **Files moved to another board**, or given a new version in Playbook. Skipping only applies to files still in the sub-board they were imported into, unchanged. Such files are imported again.
* **Files first imported before this skipping shipped** are downloaded again on every re-sync. The copies are usually merged away by duplicate detection, but a workspace that turned duplicate merging off, or an asset kept inside a group, ends up with real duplicates. Import into a new board once to get skipping for them.

Files deleted from Dropbox stay in Playbook.

***

## Limits[​](#limits "Direct link to Limits")

* **One active import per workspace** on plans without unrestricted imports. The refusal names the active import's token, so a client whose earlier start request timed out can poll that import instead of starting another.
* **An API import never bills storage overage the workspace has not agreed to.** Overage cannot be confirmed through the API. A start request is refused when the workspace has no storage left before that level, and a running import is canceled with `overlimit` before storing the file that would cross it — files imported up to then are kept. To import more, agree to the overage in the web app first.
* Plan limits on import size and asset counts apply exactly as they do in the web app.

***

## Errors[​](#errors "Direct link to Errors")

| Status | When                                                                                                                                                                                                                                                                                                                                          |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 403    | The token's user is not a workspace owner or admin, or the token lacks the `write` scope.                                                                                                                                                                                                                                                     |
| 404    | `source_token` is not one of **this user's** connections, or `board_token` is not a board in the workspace (deleted boards included).                                                                                                                                                                                                         |
| 406    | The `import` object or `source_token` is missing.                                                                                                                                                                                                                                                                                             |
| 422    | Not a Dropbox folder URL, path or ID; a shared link; the Dropbox root; folder not found in the connected Dropbox account; a file instead of a folder; connection no longer authorized (reconnect at `connect_url`); another import active (the message names it); storage or asset limit reached; no storage left before unconsented overage. |
| 429    | Dropbox is rate limiting the connection. Retry after the `Retry-After` header's seconds.                                                                                                                                                                                                                                                      |
| 502    | Dropbox returned another error; the message has Dropbox's text.                                                                                                                                                                                                                                                                               |

***

## Using it from an AI assistant[​](#using-it-from-an-ai-assistant "Direct link to Using it from an AI assistant")

The [MCP server](/docs/guides/mcp.md) exposes the same flow as `list_import_sources`, `import_from_dropbox`, and `get_import`. Ask your assistant something like *"Import the Dropbox folder /Clients/Acme into the Creator Content board, then tag the new files"* — it lists the connection, starts the import, polls until it finishes, and finds the files in the sub-board named after the folder.

***

## Related API Endpoints[​](#related-api-endpoints "Direct link to Related API Endpoints")

* [List Import Sources](/docs/api/list-import-sources.md)
* [Start Import](/docs/api/start-import.md)
* [Get Import](/docs/api/get-import.md)
