{"openapi":"3.1.0","info":{"title":"Fronteam Events API","version":"1.0.0","description":"Create, update and cancel events in a Fronteam company calendar from your system (ERP, CRM, Make, Zapier...).\n\n**Base URL:** `https://fline.app/api/v1` (only this host - direct requests to other hosts are refused).\n\n**Authentication:** `Authorization: Bearer ftk_live_...` (or `X-Api-Key: ftk_live_...`). A Fronteam admin creates keys in\n*External system connection* (in the Plugins menu) and\nsees each key once. A key exposes all events and customer details, so only an admin who may view events and customers can\ncreate one (a key that writes - also edit them). **Test keys** (`ftk_test_...`) run every write as a dry run: you get the exact response, nothing is saved.\nAny write can also be tried with `?dry_run=true`.\n\n**Your id, our id.** You address events by **your** `external_id` (1-128 characters: letters, digits, `. _ : ~ -`).\n`PUT /events/{external_id}` creates the event the first time and updates it afterwards. To link an event that already exists\nin Fronteam, send its `fronteam_id` in the first `PUT`.\n\n**What you send is merged, not overwritten.**\n- A field you don't send is not touched; `null` clears it (where allowed).\n- If you send the same value you sent last time, we treat it as unchanged - so resending your whole object is safe and never\n  undoes an edit made in Fronteam.\n- If both sides changed the same field since your last update, the integration's conflict policy decides (default:\n  **Fronteam wins**). Conflicts are returned in `conflicts` and shown to the Fronteam manager.\n\n**Changes that affect a crew wait for a manager.** Dates, cancelling and un-cancelling are applied right away only when no\ncrew is assigned and nothing about the event is still waiting: no open invitation, no scheduled message, no approval request\n(and for cancelling, no equipment out on the job). Otherwise the change is held: the response is `202` with `held[]`\n(`reason` - the first that applies: `crew_assigned` / `pending_invites` / `scheduled_messages` /\n`pending_approvals` / `equipment_out` / `conflicts`; `impact` has the numbers; the event's `sync.state` is\n`pending_review`) until a Fronteam manager decides. Venue and time changes are applied, and the manager is asked whether to\ntell the crew. **The API never sends messages to workers.**\n\n**DELETE cancels, it never deletes.** `DELETE /events/{external_id}` moves the event to the integration's cancellation status.\n\n**Schedule** (`schedule[]`) is used only when the event is created; later changes are reported to the manager.\n\n**Dates and times** are in the company's local time (`GET /me` → `company.timezone`): `YYYY-MM-DD` and `HH:MM`.\nTimestamps (`updated_at`) are UTC.\n\n**Don't put prices in `notes` or `description`** - crew members can read them.\n\n**Retries:** send `Idempotency-Key` on writes (kept 24 hours; a retry returns the original response with\n`Idempotency-Replayed: true`). Use `If-Match: \"<revision>\"` (from `ETag` / `revision`) to avoid overwriting a newer version. `revision` also\nchanges when Fronteam-only fields change: on `409 revision_mismatch`, `GET` the event and try again.\n\n**Limits:** `RateLimit-Limit` / `RateLimit-Remaining` / `RateLimit-Reset` on every response; over the limit - `429` with\n`Retry-After`. Bodies up to 256 KB (batch: 2 MB, up to 100 items).\n\n**Changes made in Fronteam come to you** (when the Fronteam admin checks *Send changes to their system*):\n- **Webhooks:** we `POST` every change to a linked event to your URL (`https`, port 443): `event.created` / `updated` /\n  `cancelled` / `uncancelled` / `deleted` / `restored`, always with the event's **current** state - several quick changes\n  arrive as one delivery, with `data.sequence` (keep the higher one if two arrive out of order). Treat `event.updated` for an\n  event you don't know as a create. A change you made through the API is not sent back to you. You get `change.rejected`\n  when Fronteam kept its own value in a conflict, or when a change that waited for a manager was declined (`held[].decision`).\n  Editing a customer card alone doesn't send anything - the event's customer details go out with the event's next change.\n  You get events linked to you; if the Fronteam admin chose \"all company events\", also events you never sent\n  (`external_id: null`) - the only case where `event.created` arrives. `change.rejected` is webhook-only.\n  There is no fixed outgoing IP address: verify the signature.\n- **Signature** ([Standard Webhooks](https://www.standardwebhooks.com)): headers `webhook-id`, `webhook-timestamp` (Unix\n  seconds) and `webhook-signature: v1,<base64>` = `base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{raw body}\"))`, where\n  `key` is the base64-decoded part of your secret after `whsec_`. While a secret is being rotated the header holds two\n  signatures separated by a space - accept the request if one of them matches. Reject timestamps older than 5 minutes.\n- **Answer 2xx within 10 seconds.** Anything else - including redirects, which are not followed - is retried after 1 min,\n  5 min, 30 min, 2 h, 6 h, 12 h and 24 h, then dropped (the manager can send it again). `webhook-id` and the body are the\n  same on every retry: use the id to ignore duplicates. If the event changes while a delivery waits for a retry, that delivery\n  is replaced by a new one (a new `webhook-id`) with the current state. Answer `410 Gone` to stop the deliveries; 72 hours of failures also turn the webhook off\n  and alert the manager.\n- **Or poll** `GET /changes?cursor=...` (only while sending is on - otherwise `403 outbound_disabled`): each event that\n  changed since your cursor, in the order the changes were saved, in its current state; keep `next_cursor` for the next call.\n  A change saved late is listed after what you already got - never skipped. Changes are kept 30 days: a cursor older than\n  that, or from before sending was turned off and on again, returns `410 cursor_expired` (start again from `GET /events`).\n\n**Errors** always look like `{\"error\": {\"code\", \"message\", \"request_id\", \"details\"}}`. Quote the `request_id` (also in the\n`X-Request-Id` header) when contacting support."},"servers":[{"url":"https://fline.app/api/v1"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"paths":{"/me":{"get":{"operationId":"getMe","summary":"Who am I: integration, company, key and limits","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/statuses":{"get":{"operationId":"listStatuses","summary":"The company's event statuses and the codes mapped to them","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Statuses"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/events":{"get":{"operationId":"listEvents","summary":"Events, oldest change first, page by page","parameters":[{"name":"updated_since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only events whose row changed after this time (schedule changes are not included)."},{"name":"from","in":"query","schema":{"type":"string","format":"date"},"description":"Events that end on/after."},{"name":"to","in":"query","schema":{"type":"string","format":"date"},"description":"Events that start on/before."},{"name":"status","in":"query","schema":{"type":"string"},"description":"A status code (see /statuses)."},{"name":"include_cancelled","in":"query","schema":{"type":"boolean","default":true}},{"name":"include_deleted","in":"query","schema":{"type":"boolean","default":false},"description":"Include linked events deleted in Fronteam (as tombstones)."},{"name":"linked","in":"query","schema":{"type":"boolean","default":true},"description":"false = all company events (only for integrations with scope \"all\")."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"`next_cursor` from the previous page."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/events/batch":{"post":{"operationId":"batchEvents","summary":"Up to 100 upserts / patches / cancels; each item succeeds or fails on its own","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Run the request without saving anything; the response says what would happen."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (1-255 visible ASCII characters). Kept 24 hours."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"200":{"description":"Per-item results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResult"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"413":{"$ref":"#/components/responses/E413"},"415":{"$ref":"#/components/responses/E415"},"422":{"$ref":"#/components/responses/E422"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/events/by-fronteam-id/{fronteam_id}":{"get":{"operationId":"getEventByFronteamId","summary":"An event by our id (linked events; any event with scope \"all\")","parameters":[{"name":"fronteam_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/events/{external_id}":{"get":{"operationId":"getEvent","summary":"An event by your id","parameters":[{"name":"external_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:~-]{1,128}$"},"description":"Your id for the event."}],"responses":{"200":{"description":"OK (ETag = revision)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"410":{"$ref":"#/components/responses/E410"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}},"put":{"operationId":"upsertEvent","summary":"Create (first time) or update (merge) an event","parameters":[{"name":"external_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:~-]{1,128}$"},"description":"Your id for the event."},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Run the request without saving anything; the response says what would happen."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (1-255 visible ASCII characters). Kept 24 hours."},{"name":"If-Match","in":"header","required":false,"schema":{"type":"string","example":"\"12\""},"description":"The event revision you based the change on. A newer revision returns 409 revision_mismatch."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}},"responses":{"200":{"description":"Updated, or unchanged (nothing new).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"202":{"description":"Held for a Fronteam manager (crew, invitations, messages, approvals or equipment) - see `held[]`; other fields may have been applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"410":{"$ref":"#/components/responses/E410"},"413":{"$ref":"#/components/responses/E413"},"415":{"$ref":"#/components/responses/E415"},"422":{"$ref":"#/components/responses/E422"},"429":{"$ref":"#/components/responses/E429"},"500":{"$ref":"#/components/responses/E500"},"503":{"$ref":"#/components/responses/E503"}}},"patch":{"operationId":"patchEvent","summary":"Update an existing event (404 if not linked)","parameters":[{"name":"external_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:~-]{1,128}$"},"description":"Your id for the event."},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Run the request without saving anything; the response says what would happen."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (1-255 visible ASCII characters). Kept 24 hours."},{"name":"If-Match","in":"header","required":false,"schema":{"type":"string","example":"\"12\""},"description":"The event revision you based the change on. A newer revision returns 409 revision_mismatch."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}},"responses":{"200":{"description":"Updated, or unchanged (nothing new).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"202":{"description":"Held for a Fronteam manager (crew, invitations, messages, approvals or equipment) - see `held[]`; other fields may have been applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"410":{"$ref":"#/components/responses/E410"},"413":{"$ref":"#/components/responses/E413"},"415":{"$ref":"#/components/responses/E415"},"422":{"$ref":"#/components/responses/E422"},"429":{"$ref":"#/components/responses/E429"},"500":{"$ref":"#/components/responses/E500"},"503":{"$ref":"#/components/responses/E503"}}},"delete":{"operationId":"cancelEvent","summary":"Cancel the event (never deletes it)","parameters":[{"name":"external_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:~-]{1,128}$"},"description":"Your id for the event."},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Run the request without saving anything; the response says what would happen."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (1-255 visible ASCII characters). Kept 24 hours."},{"name":"If-Match","in":"header","required":false,"schema":{"type":"string","example":"\"12\""},"description":"The event revision you based the change on. A newer revision returns 409 revision_mismatch."}],"responses":{"200":{"description":"Updated, or unchanged (nothing new).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"202":{"description":"Held for a Fronteam manager (crew, invitations, messages, approvals or equipment) - see `held[]`; other fields may have been applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteResult"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"409":{"$ref":"#/components/responses/E409"},"410":{"$ref":"#/components/responses/E410"},"413":{"$ref":"#/components/responses/E413"},"415":{"$ref":"#/components/responses/E415"},"422":{"$ref":"#/components/responses/E422"},"429":{"$ref":"#/components/responses/E429"},"500":{"$ref":"#/components/responses/E500"},"503":{"$ref":"#/components/responses/E503"}}}},"/events/{external_id}/link":{"delete":{"operationId":"unlinkEvent","summary":"Forget the link between your id and the event (the event stays)","parameters":[{"name":"external_id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:~-]{1,128}$"},"description":"Your id for the event."},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Run the request without saving anything; the response says what would happen."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (1-255 visible ASCII characters). Kept 24 hours."}],"responses":{"200":{"description":"Unlinked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnlinkResult"}}}},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"404":{"$ref":"#/components/responses/E404"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/changes":{"get":{"operationId":"listChanges","summary":"What changed in Fronteam since your cursor (latest change of each event, oldest first)","parameters":[{"name":"cursor","in":"query","schema":{"type":"string","pattern":"^[0-9]{1,18}$"},"description":"`next_cursor` from the previous call. Without it - from the oldest change still kept (30 days)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeList"}}}},"400":{"$ref":"#/components/responses/E400"},"401":{"$ref":"#/components/responses/E401"},"403":{"$ref":"#/components/responses/E403"},"410":{"$ref":"#/components/responses/E410"},"429":{"$ref":"#/components/responses/E429"},"503":{"$ref":"#/components/responses/E503"}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","security":[],"responses":{"200":{"description":"OpenAPI 3.1","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"webhooks":{"eventChanged":{"post":{"summary":"event.created / event.updated / event.cancelled / event.uncancelled / event.deleted / event.restored","description":"A linked event changed in Fronteam (not by your own API key). `data.event` is its current state; a deleted event is a tombstone with `recoverable_until`.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"The same on every retry of this delivery - use it to ignore duplicates."},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Unix seconds when this attempt was sent."},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`v1,<base64>` (two, separated by a space, while the secret is being rotated)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"410":{"description":"Stop sending: the webhook is turned off and the Fronteam manager is told."},"2XX":{"description":"Received."},"default":{"description":"Retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h."}}}},"changeRejected":{"post":{"summary":"change.rejected - part of your write was not applied","description":"Fronteam kept its own value (conflict policy) or the change waits for a manager. `data.event` is the current state; `data.request_id` is the `X-Request-Id` of your request.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"The same on every retry of this delivery - use it to ignore duplicates."},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Unix seconds when this attempt was sent."},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`v1,<base64>` (two, separated by a space, while the secret is being rotated)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookChangeRejected"}}}},"responses":{"410":{"description":"Stop sending: the webhook is turned off and the Fronteam manager is told."},"2XX":{"description":"Received."},"default":{"description":"Retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h."}}}},"ping":{"post":{"summary":"ping - the \"Send test\" button in Fronteam (never retried)","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"The same on every retry of this delivery - use it to ignore duplicates."},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Unix seconds when this attempt was sent."},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"},"description":"`v1,<base64>` (two, separated by a space, while the secret is being rotated)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPing"}}}},"responses":{"410":{"description":"Stop sending: the webhook is turned off and the Fronteam manager is told."},"2XX":{"description":"Received."},"default":{"description":"Retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"ftk_live_… / ftk_test_…"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"responses":{"E400":{"description":"invalid_json, invalid_request, invalid_cursor, unknown_status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E401":{"description":"missing_api_key, invalid_api_key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E403":{"description":"insufficient_scope, integration_disabled, inbound_disabled, outbound_disabled, company_inactive, ip_not_allowed, proxy_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E404":{"description":"route_not_found, event_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E409":{"description":"revision_mismatch, already_linked, external_id_conflict, idempotency_in_progress, employee_on_option","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E410":{"description":"event_deleted, cursor_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E415":{"description":"unsupported_media_type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E422":{"description":"validation_failed, unknown_field, idempotency_key_reused, no_cancel_status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E429":{"description":"rate_limited, too_many_failed_auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E500":{"description":"internal_error, read_only_transaction","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"E503":{"description":"integrations_paused, server_busy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","enum":["invalid_json","invalid_request","invalid_cursor","unknown_status","missing_api_key","invalid_api_key","insufficient_scope","integration_disabled","inbound_disabled","outbound_disabled","company_inactive","ip_not_allowed","proxy_required","route_not_found","event_not_found","method_not_allowed","revision_mismatch","already_linked","external_id_conflict","idempotency_in_progress","employee_on_option","event_deleted","cursor_expired","payload_too_large","unsupported_media_type","validation_failed","unknown_field","idempotency_key_reused","no_cancel_status","rate_limited","too_many_failed_auth","internal_error","read_only_transaction","not_implemented","integrations_paused","server_busy","timeout"]},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid"},"details":{"type":"object","additionalProperties":true}}}}},"StatusRef":{"type":"object","properties":{"code":{"type":["string","null"]},"name":{"type":"string"},"cancelled":{"type":"boolean"}}},"Customer":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":160},"tax_id":{"type":"string","maxLength":20},"phone":{"type":"string","maxLength":30},"email":{"type":"string","format":"email","maxLength":120},"fronteam_id":{"type":"string","format":"uuid","readOnly":true},"external_id":{"type":"string","description":"Reserved - ignored in v1."}},"description":"Matched to an existing customer by tax id, then name, phone, email; otherwise created (per the integration's customer policy). Existing customers are never modified."},"Contact":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":120},"phone":{"type":"string","maxLength":30},"email":{"type":"string","format":"email","maxLength":120}}},"ScheduleItem":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","maxLength":80,"description":"loading / setup / rehearsal / event / teardown, or any label."},"date":{"type":"string","format":"date","description":"Default: the event's start date."},"end_date":{"type":"string","format":"date"},"start":{"type":"string","pattern":"^\\d{1,2}:\\d{2}(:\\d{2})?$"},"end":{"type":"string","pattern":"^\\d{1,2}:\\d{2}(:\\d{2})?$"}}},"EventInput":{"type":"object","additionalProperties":false,"description":"Every field is optional on update; on create `name` and `dates.start` are required.","properties":{"name":{"type":"string","maxLength":200},"description":{"type":["string","null"],"maxLength":4000},"notes":{"type":["string","null"],"maxLength":4000,"description":"Visible to the crew - no prices."},"status":{"oneOf":[{"type":"string"},{"type":"object","properties":{"code":{"type":"string"}}}],"description":"A status code mapped by the Fronteam admin (see /statuses). Unmapped codes are reported, not applied."},"dates":{"type":"object","additionalProperties":false,"properties":{"start":{"type":"string","format":"date"},"end":{"type":["string","null"],"format":"date"}}},"times":{"type":["object","null"],"additionalProperties":false,"properties":{"setup":{"type":["string","null"]},"start":{"type":["string","null"]},"end":{"type":["string","null"]}}},"venue":{"type":["object","null"],"additionalProperties":false,"properties":{"name":{"type":["string","null"],"maxLength":200},"address":{"type":["string","null"],"maxLength":300},"contact_name":{"type":["string","null"],"maxLength":120},"contact_phone":{"type":["string","null"],"maxLength":30}}},"customer":{"oneOf":[{"$ref":"#/components/schemas/Customer"},{"type":"null"}]},"contact":{"oneOf":[{"$ref":"#/components/schemas/Contact"},{"type":"null"}]},"sales_agent":{"oneOf":[{"type":"string"},{"type":"object","properties":{"code":{"type":"string"}}},{"type":"null"}],"description":"The agent code set on the Fronteam employee card."},"schedule":{"type":"array","maxItems":50,"items":{"$ref":"#/components/schemas/ScheduleItem"},"description":"Used on create only."},"fronteam_id":{"type":"string","format":"uuid","description":"First PUT only: link an existing Fronteam event."},"external_id":{"type":"string","description":"Ignored if equal to the id in the URL; otherwise 422."},"revision":{"type":"integer","readOnly":true},"sync":{"type":"object","readOnly":true},"updated_at":{"type":"string","readOnly":true},"deleted":{"type":"boolean","readOnly":true},"sequence":{"type":"integer","readOnly":true}}},"Event":{"type":"object","properties":{"external_id":{"type":["string","null"]},"fronteam_id":{"type":"string","format":"uuid"},"revision":{"type":"integer"},"name":{"type":"string"},"description":{"type":["string","null"]},"notes":{"type":["string","null"]},"status":{"oneOf":[{"$ref":"#/components/schemas/StatusRef"},{"type":"null"}]},"dates":{"type":"object","properties":{"start":{"type":"string","format":"date"},"end":{"type":"string","format":"date"}}},"times":{"type":"object","properties":{"setup":{"type":["string","null"]},"start":{"type":["string","null"]},"end":{"type":["string","null"]}}},"venue":{"type":"object"},"customer":{"type":["object","null"]},"contact":{"type":["object","null"]},"sales_agent":{"type":["object","null"],"properties":{"code":{"type":["string","null"]},"name":{"type":"string"}}},"schedule":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleItem"}},"sync":{"type":"object","properties":{"state":{"type":"string","enum":["synced","pending_review"]},"pending":{"type":"array","items":{"type":"object","properties":{"review_id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"fields":{"type":"array","items":{"type":"string"}},"since":{"type":"string","format":"date-time"}}}}}},"deleted":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"}}},"Tombstone":{"type":"object","properties":{"external_id":{"type":"string"},"fronteam_id":{"type":"string","format":"uuid"},"deleted":{"const":true},"deleted_at":{"type":"string","format":"date-time"},"recoverable_until":{"type":"string","format":"date-time"}}},"EventList":{"type":"object","properties":{"data":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/Event"},{"$ref":"#/components/schemas/Tombstone"}]}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"WriteResult":{"type":"object","properties":{"result":{"type":"string","enum":["created","updated","unchanged","pending_review","partially_applied","adopted","cancelled"]},"event":{"$ref":"#/components/schemas/Event"},"applied_fields":{"type":"array","items":{"type":"string"}},"held":{"type":"array","items":{"type":"object","properties":{"review_id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["dates_impact","cancel_impact","uncancel_impact"]},"fields":{"type":"array","items":{"type":"string"}},"reason":{"type":"string","description":"The first that applies (crew → invitations → scheduled messages → approval requests → equipment out; conflicts - un-cancelling into a busy date).","enum":["crew_assigned","pending_invites","scheduled_messages","pending_approvals","equipment_out","conflicts"]},"impact":{"type":"object","description":"The numbers behind the hold, e.g. {\"assigned\": 5, \"open_invites\": 2, \"scheduled_messages\": 1, \"pending_approvals\": 0, \"equipment_out\": false}"}}}},"conflicts":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"ours":{},"theirs":{},"resolution":{"type":"string","enum":["kept_ours","applied_theirs","held"]}}}},"warnings":{"type":"array","description":"Not errors - the rest was applied. field_not_writable: the company set this field to \"only from Fronteam\" or \"not synced\", so it is not taken from you (name and dates.start are always taken on create). Fields that are \"only from you\" or \"not synced\" are left out of GET, webhooks and /changes - a missing field means not sent, never cleared.","items":{"type":"object","properties":{"code":{"type":"string"},"field":{"type":"string"}}}},"dry_run":{"type":"boolean"}}},"UnlinkResult":{"type":"object","properties":{"result":{"const":"unlinked"},"external_id":{"type":"string"},"fronteam_id":{"type":"string","format":"uuid"}}},"BatchRequest":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","required":["external_id"],"properties":{"op":{"type":"string","enum":["upsert","patch","cancel"],"default":"upsert"},"external_id":{"type":"string"},"if_match":{"type":"string"},"event":{"$ref":"#/components/schemas/EventInput"}}}}}},"BatchResult":{"type":"object","properties":{"result":{"const":"batch"},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"external_id":{"type":"string"},"status":{"type":"integer"},"body":{"description":"The same body a single request would return (WriteResult or Error)."}}}},"summary":{"type":"object","additionalProperties":{"type":"integer"}},"side_effects":{"type":"object"},"dry_run":{"type":"boolean"}}},"Change":{"type":"object","properties":{"sequence":{"type":"integer","description":"Grows with every change in the company; the cursor is the last one you got."},"type":{"type":"string","enum":["event.created","event.updated","event.cancelled","event.uncancelled","event.deleted","event.restored"]},"occurred_at":{"type":"string","format":"date-time"},"event":{"oneOf":[{"$ref":"#/components/schemas/Event"},{"$ref":"#/components/schemas/Tombstone"}]}}},"ChangeList":{"type":"object","properties":{"changes":{"type":"array","items":{"$ref":"#/components/schemas/Change"}},"next_cursor":{"type":"string"},"has_more":{"type":"boolean","description":"true = call again with next_cursor right away."}}},"WebhookEvent":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"type":"string","enum":["event.created","event.updated","event.cancelled","event.uncancelled","event.deleted","event.restored"]},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"event":{"oneOf":[{"$ref":"#/components/schemas/Event"},{"$ref":"#/components/schemas/Tombstone"}]},"sequence":{"type":"integer","description":"The last change in this delivery (as in GET /changes). Two deliveries for the same event out of order - keep the higher one."}}}}},"WebhookChangeRejected":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"const":"change.rejected"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/Event"},"request_id":{"type":["string","null"],"format":"uuid"},"held":{"type":"array","items":{"type":"object"},"description":"As in WriteResult.held."},"conflicts":{"type":"array","items":{"type":"object"},"description":"As in WriteResult.conflicts."}}}}},"WebhookPing":{"type":"object","required":["type","timestamp","data"],"properties":{"type":{"const":"ping"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"integration":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"message":{"type":"string"}}}}},"Me":{"type":"object","properties":{"api_version":{"type":"string"},"integration":{"type":"object"},"company":{"type":"object"},"key":{"type":"object"},"limits":{"type":"object"}}},"Statuses":{"type":"object","properties":{"statuses":{"type":"array","items":{"type":"object","properties":{"fronteam_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"cancelled":{"type":"boolean"},"default":{"type":"boolean"},"code":{"type":["string","null"],"description":"The code we send for this status."},"accepts":{"type":"array","items":{"type":"string"},"description":"Codes you may send for it."}}}}}}}}}