REST APIv1

FolderPal API

Copy complete Google Drive folders from your own apps and automations. Send a copy job request, and FolderPal handles the work in the background.

Base URLhttps://api.folderpal.io/api/v1

Authentication

Create a workspace API key at FolderPal > Settings > API. All API requests require this key as a Bearer token in the request header.

Note you may be asked to connect to Google Drive. This is a simple consent prompt for Google Drive permissions so FolderPal can run in the background using a refresh token.

When creating a key, the following scopes are granted:

  • folders:copy allows copying folders.
  • jobs:read allows reading FolderPal jobs and job statuses.

Copy a folder

POST/folders/{folderId}/copy

Copy a Google Drive folder into another folder. Subfolders are always included, and files are included by default.

Requires the folders:copy scope.

cURL
curl --request POST \
  "https://api.folderpal.io/api/v1/folders/{SOURCE_FOLDER_ID}/copy" \
  --header "Authorization: Bearer {YOUR_API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{"parent":"{DESTINATION_FOLDER_ID}","includeFiles":true,"folderName":"Acme Onboarding"}'

Parameters

folderIdRequired

Path · string

The source Google Drive folder ID. Use the ID itself, not a Drive URL.
Idempotency-KeyOptional

Header · string

Optionally, set a unique key for safe retries. Retrying with the same key and body within 24 hours returns the original job instead of creating a duplicate; reusing a key with a different body returns 409.
parentRequired

Body · string

The destination Google Drive folder ID.
includeFilesOptional

Body · boolean

Include files in the copy. Defaults to true; set it to false to copy only the folder structure.
folderNameOptional

Body · string

Optionally, set a name for the copied top-level folder. Defaults to the source folder's name.

Response

202Job accepted
Response
{
  "jobId": "a1b2c3d4-0000-4000-8000-000000000000",
  "status": "accepted"
}

Folder copy operations are asynchronous. Each request queues a folder copy job, which runs in the background. Check a job's status with GET /jobs/{jobId}, or view all jobs at FolderPal > History. Webhook notifications are coming soon.

Get a job

GET/jobs/{jobId}

Check the status of a job and find the folder it created. Jobs and generations are the same thing.

Requires the jobs:read scope.

cURL
curl "https://api.folderpal.io/api/v1/jobs/{JOB_ID}" \
  --header "Authorization: Bearer {YOUR_API_KEY}"

Parameters

jobIdRequired

Path · string

The jobId returned when the copy was accepted.

Response

200Job found
Response
{
  "jobId": "a1b2c3d4-0000-4000-8000-000000000000",
  "status": "completed",
  "source": "api",
  "kind": "copy",
  "createdAt": "2026-09-17T01:00:00Z",
  "startedAt": "2026-09-17T01:01:00Z",
  "completedAt": "2026-09-17T01:05:00Z",
  "folder": {
    "id": "{GOOGLE_DRIVE_FOLDER_ID}",
    "name": "Acme Project",
    "mimeType": "application/vnd.google-apps.folder",
    "webViewLink": "https://drive.google.com/drive/folders/{GOOGLE_DRIVE_FOLDER_ID}"
  }
}
status

string

One of pending, processing, completed, partial, failed, or canceled. Only completed means everything was copied.
source

string · nullable

Where the job started: web, api, or google_workspace.
kind

string

copy or template.
completedAt

string · nullable

When processing ended, including failed jobs. null while the job is still running.
folder

object · nullable

A snapshot of the completed top-level folder for that generation.

List completed jobs

GET/jobs

List completed jobs in the workspace, most recently completed first. Useful for polling triggers in tools like Zapier.

Requires the jobs:read scope.

cURL
curl "https://api.folderpal.io/api/v1/jobs?status=completed&limit=100" \
  --header "Authorization: Bearer {YOUR_API_KEY}"

Parameters

statusOptional

Query · string

Only completed is supported. Defaults to completed.
limitOptional

Query · integer

Number of jobs per page, from 1 to 100. Defaults to 100.
cursorOptional

Query · string

The nextCursor value from a previous response, to fetch older jobs. When nextCursor is null, there are no more pages.

Response

200Completed jobs
Response
{
  "jobs": [
    {
      "jobId": "a1b2c3d4-0000-4000-8000-000000000000",
      "status": "completed",
      ...
    }
  ],
  "nextCursor": null
}

Each job uses the same format as Get a job.

Verify a key

GET/me

Check that an API key works and see which workspace, key name, and scopes it belongs to. This does not create a copy job.

Works with either the folders:copy or jobs:read scope.

cURL
curl "https://api.folderpal.io/api/v1/me" \
  --header "Authorization: Bearer {YOUR_API_KEY}"
Response
{
  "workspaceId": "a1b2c3d4-0000-4000-8000-000000000000",
  "workspaceName": "Acme Inc",
  "keyId": "b2c3d4e5-0000-4000-8000-000000000000",
  "keyName": "Production automation",
  "scopes": ["folders:copy", "jobs:read"]
}

Errors and retries

Every error uses the same JSON format. Use the HTTP status and code field to decide what your automation should do next.

Error response
{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "Invalid request",
  "code": "VALIDATION_ERROR",
  "requestId": "a1b2c3d4-0000-4000-8000-000000000000"
}
StatusMeaning
400The request is malformed or contains invalid fields.
401The API key is missing, invalid, or revoked.
403The key is missing the required scope, or Drive background access is unavailable.
404The job was not found in this workspace.
409An idempotency key conflicts or the workspace quota is exhausted.
429The request limit is exhausted. Wait for the Retry-After value.
5xxA temporary service error. Retry conservatively with the same idempotency key.

Request limits are 20 requests per key and 60 per workspace per minute, shared across all endpoints. Do not automatically retry other 4xx responses.