Export to Callsheet Pro
Push call sheets from any tool straight into a Callsheet Pro account. No PDF, no import step: send the data and the day appears in the app on the account owner's phone within seconds.
You don't have to read this page. The prompt below does the work for you.
Quick start: paste one prompt
No coding knowledge needed. Three steps:
- Press Copy prompt below.
- Paste it into the AI tool that builds your software (Claude Code, Codex, Cursor, or similar) and let it work.
- When it asks for your API key: open the Callsheet Pro app, go to Settings, then API Access, and copy the key. It's a Pro feature.
That's it. Your tool gets an Export to Callsheet Pro action, and sheets you export land straight in the app.
Add an "Export to Callsheet Pro" feature to this project.
API: POST https://us-central1-callsheet-pro.cloudfunctions.net/api/v1/days
Auth: header "Authorization: Bearer <key>". The key starts with csp_. For a
single-account server integration, load it from an environment variable (for
example CALLSHEET_PRO_API_KEY). For a multi-user product, collect one key per
Callsheet Pro user and store it encrypted in your backend. Never hardcode,
log, commit, or ship keys in a public frontend bundle. The user finds their
key in the Callsheet Pro app under Settings, API Access (Pro feature).
Body: JSON object { "externalId"?: string, "day": object }.
- externalId: strongly recommended. Use this project's stable id for the
callsheet (max 128 chars).
Re-sending the same externalId updates the day in the app instead of
duplicating it, so exports are safe to repeat after every change.
- day: the callsheet as JSON. Required: productionTitle, and dateISO
("YYYY-MM-DD") or date (free text). Optional fields: seriesName,
episodeInfo, dayNumber, country, generalCallTime, wrapTime, weather,
sunrise, sunset, warnings (string[]),
locations [{name, address, callTime, parking, contactName, contactPhone}],
crew [{role, name, phone, email, callTime, callLocation, team}],
schedule [{time, endTime, description, teams (string[]), sceneNumber}],
scenes [{number, description, cast (string[]), scheduledTime, locationName}],
transport [{kind, label, driver, driverPhone, passengers, time, from, to, ref}],
cast [{role, name, phone, pickupTime, makeupTime, wardrobeTime, callTime,
onSetTime, note}], emergency {hospitalName, hospitalAddress, hospitalPhone,
firstAid, counselor}, invoiceEmail, invoiceCompany, invoiceDetails,
projectNumber.
Every scene.locationName should exactly match a locations[].name.
Always send the FULL day on every export: omitted lists are cleared.
Alternative when structured mapping is not feasible: send
{ "externalId": string, "input": "<the callsheet as plain text>" } instead of
"day". That costs the user 1 AI parse credit per call and allows one call per
15 seconds, so prefer "day".
Responses: 201 created / 200 updated, body { result, dayId, warnings }.
Surface warnings to the user. API-handler errors are
{ error: { code, message, issues } }; the message says how to fix. Handle:
401 invalid key (tell the user to
re-copy it from Settings), 403 PRO_REQUIRED (subscription lapsed), 422
INVALID_DAY (fix the listed issues), 429 (back off and retry sequentially,
never parallel), 503 (retry once after a minute).
If this project has a user interface, use the official "Export to Callsheet
Pro" button for the export action: ready-made HTML snippet and image assets
at https://share.callsheetpro.app/developers#button
Verify the integration by sending a minimal day and confirming a 201 created
or 200 updated response. Then tell the user to open the Callsheet Pro app:
the day appears there automatically within seconds, grouped under its
production title.
Full docs: https://share.callsheetpro.app/developers
Full API reference
Everything from here down is reference for engineers, and for curious AI agents, who want to build or check the integration by hand. If you pasted the prompt above, you're done. Prefer plain text? The same docs live at /developers.md.
Get your API key Pro
- Open the Callsheet Pro app (iOS, Android, or app.callsheetpro.app).
- Go to Settings, then API Access.
- Copy your personal key. It starts with
csp_.
The key writes into your own account only. Rotate it from the same screen if it ever leaks; the old key stops working immediately.
Store the key safely
- Single-account backend: store the key in a server-side secret or environment variable.
- Multi-user product: collect and encrypt one key per Callsheet Pro user in your backend, then use that user's key for their exports.
- User-owned desktop or mobile app: use the operating system's secure credential storage.
- Never log, commit, or embed a key in a public website bundle. Treat it like a password: anyone holding it can write call sheets into that account.
Endpoint
POST https://us-central1-callsheet-pro.cloudfunctions.net/api/v1/days
Authorization: Bearer csp_YOUR_KEY
Content-Type: application/json
One call sends one callsheet day. The response tells you whether it was created or updated.
Structured mode (recommended)
Send the day as JSON in a day object. Instant, exact, and free of AI parse credits.
{
"externalId": "your-stable-id-for-this-sheet",
"day": {
"productionTitle": "Night Shift",
"dateISO": "2026-07-14",
"generalCallTime": "07:00",
"wrapTime": "19:00",
"locations": [
{ "name": "Studio A", "address": "Kleine Weg 1, Amsterdam",
"callTime": "07:00", "parking": "Lot B" }
],
"crew": [
{ "role": "Gaffer", "name": "A. Person",
"phone": "+31600000000", "callTime": "07:00" }
],
"schedule": [
{ "time": "08:00", "description": "First setup", "teams": [] }
]
}
}
Required: productionTitle, and a date (dateISO as YYYY-MM-DD, preferred, or date as free text). Everything else is optional.
Updates (upsert by externalId)
externalId is your tool's own stable id for the sheet (max 128 characters). Re-send the same externalId and the existing day in the app is updated in place instead of duplicated. This is how live changes work: when the sheet changes in your tool, just send it again.
- Always send the full day, every time. Fields you omit are cleared. An omitted
crewlist empties the crew section. - The API owns the callsheet content (title, times, locations, crew, schedule, scenes, transport, cast, and so on). An update overwrites those with what you send.
- The user's personal data in the app always survives updates: private notes, work log, attached documents, pinned notes, custom crew order, and how the day is grouped into a production.
Without externalId, every call creates a new day.
Loose mode
If you cannot produce our JSON, send any text instead and our AI turns it into a structured day. Costs the account owner 1 parse credit per call (same as scanning a PDF in the app) and is limited to one call per 15 seconds.
{
"externalId": "your-stable-id-for-this-sheet",
"input": "CALL SHEET - Night Shift - Tuesday, July 14, 2026\nGeneral call 07:00 ..."
}
Send exactly one of day or input, never both. input is capped at 100,000 characters.
Field reference (day object)
| Field | Type | Notes |
|---|---|---|
productionTitle | string | Required. Days with the same title group into one production in the app. |
seriesName | string | Optional series name. |
episodeInfo | string | For example "S2E05". |
dayNumber | number | Shoot day number. |
dateISO | string | YYYY-MM-DD. Preferred date field. |
date | string | Human-readable date, fallback when dateISO is absent. |
country | string | ISO country code of the shoot, used for phone number formatting. |
generalCallTime | string | For example "07:00". |
wrapTime | string | Expected wrap. |
weather | string | Free text. |
sunrise / sunset | string | For example "05:42". |
warnings | string[] | Safety or general warnings shown prominently. |
locations | Location[] | See shapes below. |
crew | CrewMember[] | See shapes below. |
schedule | ScheduleItem[] | See shapes below. |
scenes | Scene[] | See shapes below. |
transport | TransportRow[] | See shapes below. |
cast | CastMember[] | See shapes below. |
emergency | object | hospitalName, hospitalAddress, hospitalPhone, firstAid, counselor. |
invoiceEmail and friends | string | invoiceCompany, invoiceDetails, projectNumber: billing info for crew invoices. |
gearAndSettings | object | gear: string[], settings: [{ label, value }], warning: string. |
Object shapes:
- Location:
name,address,callTime,parking,contactName,contactPhone - CrewMember:
role,name,phone(E.164 preferred),email,callTime,callLocation,team - ScheduleItem:
time,endTime,description,teams(string[]),sceneNumber - Scene:
number,description,cast(string[]),scheduledTime,locationName(must exactly match a locations[].name to link) - TransportRow:
kind,label,driver,driverPhone,passengers(string[]),time,from,to,ref - CastMember:
role,name,phone,pickupTime,makeupTime,wardrobeTime,callTime,onSetTime,note
All string fields accept null or can be omitted; they default to empty.
Responses
{ "result": "created", "dayId": "...", "dayIds": ["..."],
"externalId": "...", "warnings": [] }
201 for created, 200 for updated. warnings lists non-fatal problems (for example a scene pointing at an unknown location). Fix them when convenient; the day was saved.
Errors produced by the API handler look like:
{ "error": { "code": "INVALID_DAY", "message": "how to fix it",
"issues": ["field: problem"], "hint": "docs url" } }
An HTTP platform or proxy can reject malformed HTTP or malformed application/json before the handler runs; in that case the response may be a plain 400. Clients should check the HTTP status and content type before decoding the JSON error envelope.
| HTTP | code | Meaning and fix |
|---|---|---|
| 400 | INVALID_JSON / INVALID_BODY | Malformed body. Send a JSON object with exactly one of day or input. |
| 401 | MISSING_AUTH / INVALID_API_KEY | Key absent, wrong, or rotated. Copy the current key from Settings, API Access. |
| 403 | PRO_REQUIRED | The account's Pro subscription lapsed. Renew, then retry. |
| 413 | PAYLOAD_TOO_LARGE | Body over 1 MB or input over 100,000 characters. Send one day per request. |
| 422 | INVALID_DAY | Day rejected; the issues array lists exactly what to fix. |
| 422 | PARSE_FAILED | Loose mode could not produce a usable day. Check the optional issues array, improve the input, or use structured mode. |
| 429 | RATE_LIMITED | Too fast. Send requests sequentially and retry after a short wait. |
| 429 | DAILY_LIMIT_REACHED | 500 requests per day used. Retry after midnight UTC. |
| 429 | PARSE_LIMIT_REACHED | Monthly AI parse allowance used. Switch to structured mode (free) or wait for the monthly reset. |
| 503 | UPSTREAM_BUSY | AI parser busy (loose mode only). Retry in a minute; no credit was charged. |
curl example
curl -X POST "https://us-central1-callsheet-pro.cloudfunctions.net/api/v1/days" \
-H "Authorization: Bearer $CALLSHEET_PRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalId": "sheet-2026-07-14",
"day": {
"productionTitle": "Night Shift",
"dateISO": "2026-07-14",
"generalCallTime": "07:00"
}
}'
The official button
Put this in your tool's interface on the action that sends a sheet to Callsheet Pro. Use it as-is; don't change the colors or the wording.
Downloads: dark SVG / PNG / PNG 2x, yellow SVG / PNG / PNG 2x.
Or render it natively with plain HTML (no image, no font files needed):
<!-- Export to Callsheet Pro button (dark). Attach your export handler. -->
<button type="button" style="display:inline-flex; align-items:center; gap:8px;
height:44px; padding:0 20px; background:#000; border:1px solid #46484d;
border-radius:12px; cursor:pointer;
font-family:Inter, system-ui, -apple-system, 'Segoe UI', sans-serif;">
<span style="font-size:14px; color:#aaabb0;">Export to</span>
<span style="font-size:15px; font-weight:800; letter-spacing:-0.02em;
color:#f6f6fc;">CALLSHEET<span style="color:#facc15;">PRO</span></span>
</button>
<!-- Yellow variant: swap the three style blocks for -->
<!-- button: background:#facc15; border:none; -->
<!-- "Export to" span: color:rgba(0,0,0,0.78); -->
<!-- wordmark span: color:#000; (and drop the inner PRO span) -->
