API & integrations
The ProductionPlanner.io public API lets you connect your production data to the rest of your stack — automations (Zapier, Make), internal dashboards, CI pipelines, or your own scripts. Every project, schedule, team list, task, budget line, location, and resource you manage in the app can be read and updated over a simple REST interface.
The API is organization-scoped: each API key belongs to one organization and can only reach the projects owned by that organization. Keys never expire on their own, but you can revoke them at any time.
Getting an API key
API keys are managed by organization members inside the app.
- Open your organization and go to Integrations (it’s in the dashboard sidebar).
- Enter a name for the key (for example,
Zapier integrationorExternal API) and click Create Key. - Copy the full key. It begins with
pp_followed by 64 hex characters, e.g.pp_3f9a...c21d. - Store it somewhere safe and treat it like a password. Anyone with the key has the same API access to your organization’s projects.
You can reveal, copy, or revoke any key from the same page. Revoking takes effect immediately — the next request made with that key returns 401.
Keys remain readable on the Integrations page after creation, so you can always retrieve an existing key rather than rotating it.
Base URL
https://api.productionplanner.io/v1
Every endpoint below is relative to this base URL. All request and response bodies are JSON.
Authentication
Pass your key as a Bearer token in the Authorization header on every request:
Authorization: Bearer pp_your_api_key_here
A missing or malformed header returns 401:
{ "status": "error", "message": "Missing or invalid Authorization header. Use: Bearer <api-key>" }
An unknown or revoked key returns 401:
{ "status": "error", "message": "Invalid or revoked API key" }
Interactive reference
A live, try-it-out Swagger UI is published alongside the API:
https://api.productionplanner.io/docs
The raw OpenAPI 3 spec is available at /docs.json on the same host.
Response format
Every response uses the same envelope:
{
"status": "ok",
"message": "Human-readable summary",
"data": { }
}
statusis"ok"on success or"error"on failure.messageis a short description you can log or surface to users.dataholds the payload — an object or an array, depending on the endpoint. It is omitted on errors.
Status codes
| Code | Meaning |
|---|---|
200 | Request succeeded. |
201 | Resource created. |
400 | Validation failed (e.g. a required field is missing). |
401 | Missing, invalid, or revoked API key. |
404 | The project (or other resource) does not exist, or is not owned by your organization. |
409 | Conflict — for example, adding a date that already exists. |
For security, a project that belongs to another organization returns
404(not403), so keys cannot be used to probe for projects outside your org.
Identity
Get the authenticated key
GET /info
Returns the organization the current key belongs to. Useful for verifying a key works.
curl https://api.productionplanner.io/v1/info \
-H "Authorization: Bearer $PP_KEY"
{
"status": "ok",
"data": {
"orgId": "9bX2k7...",
"orgName": "Acme Live Events",
"keyId": "a1b2c3..."
}
}
Projects
List projects
GET /projects
Returns all active projects in your organization, newest-updated first. Archived projects are included; soft-deleted projects and templates are excluded.
curl https://api.productionplanner.io/v1/projects \
-H "Authorization: Bearer $PP_KEY"
{
"status": "ok",
"message": "Projects",
"data": [
{
"id": "p_8f2a...",
"name": "Summer Tour 2026",
"description": "12-city arena run",
"timezone": "America/New_York",
"dates": [{ "date": "2026-06-01", "label": "Load-in" }],
"orgId": "9bX2k7...",
"status": "active",
"createdAt": "2026-05-01T09:12:00.000Z",
"updatedAt": "2026-05-20T16:40:00.000Z",
"archivedAt": null,
"deletedAt": null
}
]
}
Create a project
POST /projects
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✅ | Project name. |
description | string | — | Optional summary. |
timezone | string | — | IANA timezone (e.g. America/New_York). |
curl -X POST https://api.productionplanner.io/v1/projects \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Autumn Gala", "description": "Annual fundraiser", "timezone": "Europe/London" }'
Returns 201 with the created project. Projects created via the API record createdBy as api:<keyId>.
Get a project
GET /projects/{projectId}
curl https://api.productionplanner.io/v1/projects/p_8f2a... \
-H "Authorization: Bearer $PP_KEY"
Returns the full project document, or 404 if it does not exist in your organization.
Update a project
PATCH /projects/{projectId}
Send only the fields you want to change. Accepted fields: name, description, timezone, links, theme, totalBudget, budgetCurrency, scheduleSettings, scheduleItemTypes. Any other keys are ignored; sending no recognised field returns 400.
curl -X PATCH https://api.productionplanner.io/v1/projects/p_8f2a... \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Autumn Gala 2026", "totalBudget": 50000, "budgetCurrency": "GBP" }'
Dates
Project dates are the calendar days a production runs (load-in, show days, strike, etc.).
List dates
GET /projects/{projectId}/dates
{
"status": "ok",
"message": "Dates",
"data": [
{ "date": "2026-06-01", "label": "Load-in", "allDay": true },
{ "date": "2026-06-02", "label": "Show Day", "startTime": "18:00", "endTime": "23:00" }
]
}
Add a date
POST /projects/{projectId}/dates
| Field | Type | Required | Notes |
|---|---|---|---|
date | string | ✅ | YYYY-MM-DD format. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../dates \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "date": "2026-06-03" }'
Returns 201 with the project’s full, updated dates array. A duplicate date returns 409.
Schedule
Schedule items are the timed run-of-show entries on a given day. They are addressed by date (YYYY-MM-DD).
Get the schedule for a date
GET /projects/{projectId}/schedule/{date}
curl https://api.productionplanner.io/v1/projects/p_8f2a.../schedule/2026-06-02 \
-H "Authorization: Bearer $PP_KEY"
{
"status": "ok",
"message": "Schedule items",
"data": [
{ "id": "s_01", "time": "08:00", "duration": 120, "activity": "Crew call", "type": "setup" }
]
}
Add a schedule item
POST /projects/{projectId}/schedule/{date}
| Field | Type | Required | Notes |
|---|---|---|---|
time | string | — | Wall-clock HH:mm in the project timezone. |
duration | number | — | Duration in minutes. |
activity | string | — | What’s happening. |
type | string | — | A schedule item type id defined on the project. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../schedule/2026-06-02 \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "time": "18:00", "duration": 90, "activity": "Doors open", "type": "showtime" }'
Returns 201 with the day’s full item list, sorted by time.
Team
List team members
GET /projects/{projectId}/team
{
"status": "ok",
"message": "Team members",
"data": [
{ "id": "t_01", "name": "Jordan Lee", "role": "Stage Manager", "email": "jordan@example.com", "permission": "read", "status": "accepted" }
]
}
Add a team member
POST /projects/{projectId}/team
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✅ | Member’s name. |
role | string | — | Job title / department role. |
email | string | — | Contact email. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../team \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Sam Rivera", "role": "Lighting Designer", "email": "sam@example.com" }'
Members added via the API are created with read permission and accepted status.
Tasks
List tasks
GET /projects/{projectId}/tasks
Add a task
POST /projects/{projectId}/tasks
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | ✅ | The task description. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../tasks \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "label": "Confirm catering headcount" }'
{
"status": "ok",
"message": "Task created",
"data": { "id": "k_01", "label": "Confirm catering headcount", "done": false, "createdBy": "api:a1b2c3..." }
}
Budget
List budget items
GET /projects/{projectId}/budget
Add a budget item
POST /projects/{projectId}/budget
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✅ | Line-item name. |
description | string | — | Optional detail. |
category | string | — | One of the categories below; anything else falls back to other. |
estimatedCost | number | — | Defaults to 0. |
actualCost | number | — | Defaults to 0. |
Categories: venue, catering, equipment, talent, travel, marketing, staffing, decor, permits, other.
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../budget \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Stage rental", "category": "equipment", "estimatedCost": 8000 }'
Locations
List locations
GET /projects/{projectId}/locations
Add a location
POST /projects/{projectId}/locations
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✅ | Location name. |
type | string | — | physical (default) or digital. |
details | string | — | Address, room, or joining info. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../locations \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Main Arena", "type": "physical", "details": "123 Stadium Way" }'
Resources
List resources and folders
GET /projects/{projectId}/resources
Returns both the project’s resources and its folders.
{
"status": "ok",
"message": "Resources",
"data": {
"resources": [
{ "id": "r_01", "name": "Run sheet", "type": "link", "url": "https://docs.example.com/run", "version": 1 }
],
"folders": [
{ "id": "f_01", "name": "Production" }
]
}
}
Add a resource link
POST /projects/{projectId}/resources/link
Adds an external link as a resource. (File uploads are managed in the app, not over the API.)
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | ✅ | Display name. |
url | string | ✅ | The link target. |
folderId | string | — | Folder to place it in; omit for the root. |
curl -X POST https://api.productionplanner.io/v1/projects/p_8f2a.../resources/link \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Tech rider", "url": "https://drive.example.com/rider.pdf" }'
Endpoint summary
| Method | Path | Description |
|---|---|---|
GET | /info | Identify the authenticated key and organization. |
GET | /projects | List active projects. |
POST | /projects | Create a project. |
GET | /projects/{id} | Get a project. |
PATCH | /projects/{id} | Update a project. |
GET | /projects/{id}/dates | List project dates. |
POST | /projects/{id}/dates | Add a date. |
GET | /projects/{id}/schedule/{date} | Get a day’s schedule. |
POST | /projects/{id}/schedule/{date} | Add a schedule item. |
GET | /projects/{id}/team | List team members. |
POST | /projects/{id}/team | Add a team member. |
GET | /projects/{id}/tasks | List tasks. |
POST | /projects/{id}/tasks | Add a task. |
GET | /projects/{id}/budget | List budget items. |
POST | /projects/{id}/budget | Add a budget item. |
GET | /projects/{id}/locations | List locations. |
POST | /projects/{id}/locations | Add a location. |
GET | /projects/{id}/resources | List resources and folders. |
POST | /projects/{id}/resources/link | Add a resource link. |
Related features