# Import from Google Drive

Pull files from Google Drive — including private folders and shared drives — into a Playbook board without clicking through the web app. Useful when creators keep dropping content into Drive 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 Google Drive once, in the Playbook web app.** Google 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 folder URLs. 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 revokes Playbook's access in their Google account.

Connections belong to a Playbook user

Only the Playbook user who connected Google Drive can use that connection. The API token (or the account signed in to MCP) must belong to that same user, or the connection list comes back empty.

***

## 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.
* **Google Drive connected** by the same Playbook user: in Playbook, open **Apps** in the sidebar, click **Google Drive** under **Sync integrations**, and sign in with a Google account that can see the folders. You can close the folder picker that opens afterwards — the connection is already saved.

The Google account needs access to the folders you import. If creators upload to their own Drive, have them share the folder with that account.

***

## 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": "Hk3vT9pQ2mX8",

      "provider": "google_drive",

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

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

    }

  ],

  "meta": {

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

  }

}
```

`email` is filled in a few seconds after connecting, so it can briefly be `null`. If `data` is empty, send the user to `meta.connect_url` to connect Google Drive, 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": "Hk3vT9pQ2mX8",

      "folders": ["https://drive.google.com/drive/folders/1AbCdEfGhIjKlMnOp"],

      "board_token": "optional-board-token"

    }

  }'
```

| Field          | Required | Description                                                                                             |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `source_token` | yes      | Token from the connection list.                                                                         |
| `folders`      | yes      | 1–20 Google Drive folder URLs or folder IDs. Folders only — file URLs are refused.                      |
| `board_token`  | no       | Board to import into. Omit it to create a new top-level board named `Google Drive import (dd-mm-yyyy)`. |

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

Each folder is checked against the connected Google account before anything starts, so a folder the account cannot see 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-14T10: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 Google rate limiting.
  * `oauth_credential_deleted` — the Google Drive 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 are counted as `skipped` and not downloaded again; new files are imported.

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

* **Files changed in Drive.** 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 Drive folder — or its sub-board in Playbook — imports that folder again in full into a new sub-board.
* **Files moved to another board.** Skipping only applies to files still in the sub-board they were imported into. Moved files are imported again.
* **Google Docs, Sheets, and Slides** have no checksum, so they are added again as links on every run.

Files deleted from Drive 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 folder URL or ID; folder not visible to the connected Google 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    | Google is rate limiting the connection. Retry after the `Retry-After` header's seconds.                                                                                                                                                                                                         |
| 502    | Google Drive returned another error, e.g. a Google Workspace policy blocking access; the message has Google'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_google_drive`, and `get_import`. Ask your assistant something like *"Import the Drive folder [https://drive.google.com/drive/folders/…](https://drive.google.com/drive/folders/%E2%80%A6) 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)
