Falcon Operations REST API v1
Overview
The Falcon Operations REST API is the supported integration surface for managing Operations workspaces, productions, people and assets, bookings and handover, production planning data, notes and files. It uses the same workspace roles, access groups, production filters, module permissions and license limits as the Falcon Operations web app.
Use this API for scheduling tools, production dashboards, inventory integrations, automation services, migration scripts and other server-to-server workflows that need concrete Operations data.
Public REST API vs the browser API
| Surface | Use | Authentication | Stability |
|---|---|---|---|
/api/v1 | External integrations and automation. | Bearer token with explicit scopes. | Versioned public contract. |
Unversioned /api/* | Falcon Operations web application. | Falcon login session and CSRF token. | Internal; do not integrate against it. |
Falcon Rundown Gateway/MOS APIs solve published-rundown and media exchange workflows. Use this Operations REST API for Operations management data.
Authentication and token lifecycle
Every REST endpoint requires a Bearer token:
Authorization: Bearer fo_live_...
Create tokens in Falcon Operations from the footer user menu under API Tokens. Enter a descriptive name, choose scopes and optionally set an expiry. Falcon shows the full token once and stores only an HMAC-SHA-256 hash. The dialog shows each token's prefix, scopes, expiry, last use and state, and lets the owner revoke it.
export FALCON_OPERATIONS_TOKEN='fo_live_...'
curl \
-H "Authorization: Bearer $FALCON_OPERATIONS_TOKEN" \
https://operations.wearefalcon.tv/api/v1/me
Scopes
Write scopes also grant the matching read permission. Scopes do not bypass the token user's normal Falcon permissions.
workspaces:read/writeRead, create and manage workspaces.members:read/writeRead members and manage members/access groups.productions:read/writeRead and manage productions.resources:read/writeRead and manage non-login people/resources.assets:read/writeEquipment, vehicles, spaces and locations.bookings:read/writeBookings, checkout and return.tasks:read/writeProduction tasks.calendar:read/writeProduction calendar events.call-sheets:read/writeCall sheets/production plans.crew:read/writeProduction crew assignments.budgets:read/writeAccounts, budget sheets and rows.guests:read/writeGuest contacts and guest bookings.notes:read/writeTag notes, notebooks and rich notes.files:read/writeFile metadata, upload, download and deletion.Roles and access rules
| Layer | REST behaviour |
|---|---|
| Token scope | The token must include the endpoint's scope. A missing scope returns 403 scope_required. |
| Falcon account | The token owner must still be an active Falcon user with Operations access. |
| Workspace role | owner and superuser perform administration; workspace deletion is owner-only. |
| Access group | Module access can be rw, ro or none. Selected-production filters are enforced. |
| License | Workspace feature and quota checks are identical to the app. |
Opaque IDs and field names
REST responses use opaque public IDs and snake_case JSON fields. Sequential database IDs and legacy browser-route IDs are never part of the public contract.
usr_ userwsp_ workspaceagp_ access groupprj_ productionres_ resourceeqp_ equipmentveh_ vehiclespc_ spaceloc_ locationbkg_ bookingtsk_ taskevt_ eventcsh_ call sheetcrm_ crew assignmentacc_ budget accountbsh_ budget sheetbgr_ budget rowgst_ guestgbk_ guest bookingcsp_ call sheet personcse_ call sheet equipmentcsv_ call sheet vehiclecss_ schedule itemcsc_ call sheet contactnte_ tag notepnb_ notebookpnp_ rich notefil_ fileResponses, pagination and errors
Single resource
{
"data": {
"id": "prj_...",
"workspace_id": "wsp_...",
"name": "Summer campaign"
}
}
List
{
"data": [],
"meta": {
"count": 0,
"limit": 100,
"offset": 0
}
}
List endpoints accept limit (1-200), offset, and resource-specific search and status filters. Bookings also accept production_id.
Error
{
"error": {
"code": "scope_required",
"message": "Token scope tasks:write is required.",
"request_id": "..."
}
}
Deletes return 204 No Content.
Endpoint summary
Current user and workspaces
| Method | Path | Purpose |
|---|---|---|
| GET | /me | Token user and accessible workspaces. |
| GET / POST | /workspaces | List or create workspaces. |
| GET / PATCH / DELETE | /workspaces/{workspace_id} | Read, update or delete a workspace. |
Members and access groups
| Method | Path |
|---|---|
| GET / POST | /workspaces/{workspace_id}/members |
| PATCH / DELETE | /workspaces/{workspace_id}/members/{user_id_or_email} |
| GET / POST | /workspaces/{workspace_id}/access-groups |
| GET / PATCH / DELETE | /workspaces/{workspace_id}/access-groups/{access_group_id} |
Productions
| Method | Path |
|---|---|
| GET / POST | /workspaces/{workspace_id}/productions |
| GET / PATCH / DELETE | /productions/{production_id} |
| POST / DELETE | /productions/{production_id}/archive |
Resources and assets
| Collection | List/create | Read/update/delete |
|---|---|---|
| Resources | /workspaces/{workspace_id}/resources | /resources/{resource_id} |
| Equipment | /workspaces/{workspace_id}/equipment | /equipment/{equipment_id} |
| Vehicles | /workspaces/{workspace_id}/vehicles | /vehicles/{vehicle_id} |
| Spaces | /workspaces/{workspace_id}/spaces | /spaces/{space_id} |
| Locations | /workspaces/{workspace_id}/locations | /locations/{location_id} |
Bookings and handover
| Method | Path |
|---|---|
| GET / POST | /workspaces/{workspace_id}/bookings |
| GET / PATCH / DELETE | /bookings/{booking_id} |
| POST | /bookings/{booking_id}/checkout |
| POST | /bookings/{booking_id}/return |
Production planning
| Collection | List/create | Read/update/delete |
|---|---|---|
| Tasks | /productions/{production_id}/tasks | /tasks/{task_id} |
| Crew | /productions/{production_id}/crew | /crew/{crew_id} |
| Calendar events | /productions/{production_id}/calendar-events | /calendar-events/{event_id} |
| Call sheets | /productions/{production_id}/call-sheets | /call-sheets/{call_sheet_id} |
| Tag notes | /productions/{production_id}/tag-notes | /tag-notes/{note_id} |
| Notebooks | /productions/{production_id}/notebooks | /notebooks/{notebook_id} |
| Rich notes | /notebooks/{notebook_id}/notes | /production-notes/{note_id} |
| Files | /productions/{production_id}/files | /files/{file_id} |
Budgets
| Resource | List/create | Read/update/delete |
|---|---|---|
| Accounts | /productions/{production_id}/accounts | /productions/{production_id}/accounts/{account_id} |
| Budget sheets | /productions/{production_id}/budget-sheets | /budget-sheets/{budget_sheet_id} |
| All production rows | /productions/{production_id}/budget-rows | /budget-rows/{budget_row_id} |
| Rows in a sheet | /budget-sheets/{budget_sheet_id}/rows | /budget-rows/{budget_row_id} |
Budget-sheet responses include row count, income, expenses, actuals and results. Account-plan entries are organisation-wide but routed through a production so normal budget access is always checked.
Guests
| Resource | List/create | Read/update/delete |
|---|---|---|
| Guest contacts | /productions/{production_id}/guests | /guests/{guest_id} |
| Guest bookings | /productions/{production_id}/guest-bookings | /guest-bookings/{guest_booking_id} |
Guest-booking lists accept start, end and status. Acceptance secrets and accepting IP addresses are never exposed.
Call sheet content
| Resource | List/create | Read/update/delete |
|---|---|---|
| People | /call-sheets/{call_sheet_id}/people | /call-sheets/{call_sheet_id}/people/{item_id} |
| Equipment | /call-sheets/{call_sheet_id}/equipment | /call-sheets/{call_sheet_id}/equipment/{item_id} |
| Vehicles | /call-sheets/{call_sheet_id}/vehicles | /call-sheets/{call_sheet_id}/vehicles/{item_id} |
| Schedule | /call-sheets/{call_sheet_id}/schedule | /call-sheets/{call_sheet_id}/schedule/{item_id} |
| Contacts | /call-sheets/{call_sheet_id}/contacts | /call-sheets/{call_sheet_id}/contacts/{item_id} |
Each collection supports GET/POST; each item supports GET/PATCH/DELETE. Creates reference resource_id, equipment_id or vehicle_id. Schedule items require start_time and activity; contacts require name.
Common examples
Create a production
curl -X POST \
-H "Authorization: Bearer $FALCON_OPERATIONS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer campaign",
"code": "SUM-26",
"type": "commercial",
"status": "planning",
"client_name": "Example Client",
"start_date": "2026-08-01",
"end_date": "2026-08-14",
"currency": "DKK",
"total_budget": 250000
}' \
https://operations.wearefalcon.tv/api/v1/workspaces/wsp_.../productions
Create equipment
{
"name": "Sony FX6",
"category": "Camera",
"manufacturer": "Sony",
"model": "FX6",
"serial_number": "EXAMPLE-001",
"status": "available",
"home_location_id": "loc_...",
"daily_rate": 1250,
"currency": "DKK",
"tags": ["camera", "full-frame"]
}
Equipment, vehicle and space status values are available, in_use, maintenance and retired. Active bookings must be completed or cancelled before deleting an asset.
Create a booking
{
"title": "Camera package",
"booked_for_resource_id": "res_...",
"production_id": "prj_...",
"starts_at": "2026-08-03T08:00:00+02:00",
"ends_at": "2026-08-03T18:00:00+02:00",
"status": "confirmed",
"purpose": "Location shoot",
"items": [
{"asset_type": "equipment", "asset_id": "eqp_..."},
{"asset_type": "vehicle", "asset_id": "veh_..."}
]
}
Detected overlaps are returned in meta.conflicts. Checkout locks ordinary status and manifest changes until all items are returned.
Checkout
{
"asset_type": "equipment",
"asset_id": "eqp_...",
"condition": "Complete and undamaged"
}
Return
{
"asset_type": "equipment",
"asset_id": "eqp_...",
"location_id": "loc_...",
"condition": "Returned in good condition"
}
Create a task
{
"title": "Confirm camera crew",
"description": "Confirm availability and rates",
"status": "todo",
"priority": "high",
"assignee_email": "producer@example.com",
"due_date": "2026-08-01",
"tags": ["crew"]
}
Task status is the production's task-column key. Priority values are low, medium, high and urgent.
Assign production crew
{
"resource_id": "res_...",
"role": "Director of Photography",
"start_date": "2026-08-01",
"end_date": "2026-08-14",
"daily_rate": 6500
}
Create a budget row
{
"account_id": "acc_...",
"description": "Camera crew",
"quantity": 3,
"unit": "days",
"unit_price": 6500,
"currency": "DKK",
"approval_status": "draft"
}
row_type is entry, groupHeader, subtotal or textOnly. Approval status is draft, pending, approved or rejected.
Create a guest booking
{
"guest_id": "gst_...",
"title": "Guest appearance",
"starts_at": "2026-08-03T10:00:00+02:00",
"ends_at": "2026-08-03T11:00:00+02:00",
"location": "Studio A",
"live_link": "https://example.com/live"
}
Create a calendar event
{
"title": "Location scout",
"start_at": "2026-08-01T09:00:00+02:00",
"end_at": "2026-08-01T11:00:00+02:00",
"all_day": false,
"location": "Example address"
}
Create a call sheet
{
"title": "Shoot day 1",
"date": "2026-08-03",
"call_time": "07:00:00",
"wrap_time": "18:00:00",
"location": "Studio A",
"status": "draft",
"general_notes": "Bring ID"
}
Call sheet status values are draft, published, archived and cancelled.
Update a rich production note
Rich note content is TipTap JSON. Updates use optimistic concurrency and require the version most recently read:
{
"expected_version": 3,
"title": "Updated production note",
"content": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [{"type": "text", "text": "Hello"}]
}
]
},
"plain_text": "Hello"
}
A stale version returns 409 version_conflict.
Upload a file
curl -X POST \
-H "Authorization: Bearer $FALCON_OPERATIONS_TOKEN" \
-F "file=@brief.pdf" \
-F "description=Client brief" \
https://operations.wearefalcon.tv/api/v1/productions/prj_.../files
The maximum file size is 20 MB. Executable and active web content types are blocked. The returned content_url also requires the Bearer token.
Validation and conflict protections
- Location trees reject cycles and duplicate sibling codes. Locations with children or assigned assets cannot be deleted.
- Bookings validate that resources and assets belong to the same workspace and return overlap details.
- Booking handover uses database row locks and records checkout/return condition and location history.
- Rich notes use versions to prevent overwriting another editor's changes.
- Workspace, module, production-filter and license checks run for every endpoint.
- Every REST mutation writes actor, token, request ID, action and public resource ID to the Operations audit log.
HTTP status codes
| Status | Meaning |
|---|---|
| 200 | Successful read or update. |
| 201 | Resource created. |
| 204 | Resource deleted; no response body. |
| 400 | Invalid JSON. |
| 401 | Missing, invalid, expired or revoked token. |
| 403 | Missing scope or insufficient Falcon access. |
| 404 | Route or resource not found. |
| 405 | HTTP method not supported. |
| 409 | Data, hierarchy, handover or version conflict. |
| 422 | Validation error. |
| 500 | Unexpected server error; report the request ID. |
Troubleshooting
401 authentication_required
Add the Authorization: Bearer ... header. Do not send tokens in the URL.
401 invalid_token
The token is wrong, expired or revoked, or its Falcon user is no longer active. Create a new token in Operations.
403 scope_required
Create a new token with the named scope. Existing token scopes cannot be broadened after creation.
403 forbidden
The token user lacks the required workspace, production, access-group, module or license permission.
404 not_found
Confirm that the opaque ID uses the correct prefix for the route and that the resource has not been deleted.
409 handover_locked
Return every checked-out item before replacing the manifest, changing ordinary status or deleting the booking.
409 version_conflict
Reload the rich note and retry with its newest version as expected_version.
Browser integrations
The API is designed primarily for server-to-server clients. If a browser sends Origin or Referer, it must match the configured Falcon Operations origin.