openapi: 3.1.0 info: title: Saturation API version: 1.0.0 description: 'Read and write production finance data in Saturation. Authenticate with a personal token in the `Authorization` header: `Bearer `. Create a token under Settings > Developers > API. Each token belongs to one workspace. Conventions: - Successful responses contain the requested resource. Lists contain `data` and an optional `nextCursor`. Errors contain `success`, `code`, `message`, and `requestId`. - Money uses integer minor units and an ISO-4217 currency, for example `{ "amount": 152900, "currency": "USD" }`. Dates use ISO 8601. - Lists default to 50 items and allow up to 100. Pass `nextCursor` as `cursor` for the next page. Set `withCount=true` to include the total count. - `404 not_found` means the resource does not exist or is not available to the token.' contact: name: Saturation API url: https://docs.saturation.io license: name: Proprietary url: https://saturation.io/terms servers: - url: https://next-api.saturation.io/v1 description: Production - url: http://localhost:4300/v1 description: Local development security: - bearerAuth: [] tags: - name: Meta description: Identity and workspace for the current token. - name: Projects description: Create and manage projects. - name: Spaces description: Folders that group projects in a workspace. - name: Contacts description: Vendors, crew, and other workspace contacts. - name: Tokens description: List and revoke API tokens. - name: Library description: Reusable budget items for a workspace or project. - name: Budget description: Budget lines, phases, phase data, and totals. - name: Transactions description: Financial transactions and their items. - name: Purchase Orders description: Purchase orders, items, approvals, payments, and history. - name: Payment Requests description: Requests to pay a person or company. A request stays separate from the payment that follows. - name: Payments description: Payments from request through settlement, with linked records and a Timeline. - name: Documents description: Upload documents, read their content, and link them to other resources. - name: Search description: Search transactions, documents, contacts, and budget lines. - name: Comments description: Comments within a project. - name: Webhook Subscriptions description: Subscribe to events and review webhook deliveries. paths: /projects/{projectId}/budget: get: operationId: budget_get summary: Get a budget description: Returns the budget's visible phases, totals, lines, and editable phase data. Use `path` or `accountId` to select an account and its descendants. Use `parentId` to build the line tree. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: path in: query required: false description: Select this account path and its descendants, such as `1100/1110`. schema: type: string - name: accountId in: query required: false description: Select this account number and its descendants. An account number used by multiple lines returns `409 account_code_ambiguous`. schema: type: string - name: phase in: query required: false description: Select a visible phase by ID, alias, name, or type. An ambiguous value returns `400 validation`. schema: type: string - name: If-None-Match in: header required: false description: A previous `ETag`. Returns `304 Not Modified` when the budget is unchanged. schema: type: string responses: '200': description: The budget document. headers: ETag: description: A value for a later `If-None-Match` request. schema: type: string Cache-Control: description: How long the response may be cached. schema: type: string content: application/json: schema: $ref: '#/components/schemas/BudgetDocument' '304': description: Budget unchanged. '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '413': $ref: '#/components/responses/Error413' '429': $ref: '#/components/responses/Error429' '504': $ref: '#/components/responses/Error504' /projects/{projectId}/budget/totals: get: operationId: budget_getTotals summary: Get budget totals description: Returns totals at `computedAt`. Use `phase`, `accountId`, or `path` to select part of the budget. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: phase in: query required: false description: Select a phase by ID or type, such as `estimate`. schema: type: string example: estimate - name: accountId in: query required: false description: Select this account number and its descendants. schema: type: string example: '1100' - name: path in: query required: false description: Select this account path and its descendants, such as `1100/1110`. schema: type: string example: 1100/1110 - name: If-None-Match in: header required: false description: A previous `ETag`. Returns `304 Not Modified` when the totals are unchanged. schema: type: string responses: '200': description: The budget totals. headers: ETag: schema: type: string Cache-Control: schema: type: string content: application/json: schema: $ref: '#/components/schemas/BudgetTotals' '304': description: Totals unchanged. '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '413': $ref: '#/components/responses/Error413' '429': $ref: '#/components/responses/Error429' '504': $ref: '#/components/responses/Error504' /projects/{projectId}/budget/lines: get: operationId: budget_listLines summary: List budget lines description: Returns budget lines that match all filters. Use `expand` to include contacts, phase totals, or phase data. Use the budget endpoint to get the full budget in one response. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: accountId in: query required: false description: Only lines with this account number. An account number may match multiple lines. schema: type: string example: '1100' - name: path in: query required: false description: Only the line at this account path, such as `1100/1110`. An ambiguous path returns `409 account_path_ambiguous`. schema: type: string example: 1100/1110 - name: tags in: query required: false description: Only lines with these comma-separated tag IDs. schema: type: string example: tag_vfx - name: tagMode in: query required: false description: How multiple `tags` values are combined. schema: $ref: '#/components/schemas/TagMode' - name: type in: query required: false description: Only lines with these comma-separated types. schema: type: string example: line,account - $ref: '#/components/parameters/budgetLineExpand' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' responses: '200': description: A page of budget lines. content: application/json: schema: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/BudgetLine' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching lines; present only when `withCount=true`. truncated: type: boolean description: Whether the page ended before `limit` because some results were unavailable. '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' post: operationId: budget_createLine summary: Create a budget line description: Creates a budget line under `parentId`, with optional phase data keyed by phase ID. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: Idempotency-Key in: header required: true description: A 16 to 255 character key for safe retries. Reusing the key with a different request returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BudgetLineCreate' responses: '201': description: The created budget line. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/BudgetLine' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/lines/bulk: post: operationId: budget_createLinesBulk summary: Create budget lines description: Creates up to 100 budget lines with optional phase data. If any line fails, none are created. Use `Idempotency-Key` to retry safely. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: Idempotency-Key in: header required: true description: A 16 to 255 character key for safe retries. Reusing the key with a different request returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BudgetLineBulkCreate' responses: '201': description: The created budget lines in request order. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/BudgetLineBulkCreateResponse' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/lines/phase-data/bulk: post: operationId: budget_updateLinePhaseDataBulk summary: Update phase data for budget lines description: Updates up to 500 line and phase entries. If any entry fails, none are changed. Use `Idempotency-Key` to retry safely. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: Idempotency-Key in: header required: true description: A 16 to 255 character key for safe retries. Reusing the key with a different request returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BudgetLinePhaseDataBulkUpsert' responses: '200': description: The updated phase data. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/BudgetLinePhaseDataBulkUpsertResponse' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/lines/{lineId}: get: operationId: budget_getLine summary: Get a budget line tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: lineId in: path required: true description: The budget line ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/budgetLineExpand' responses: '200': description: The budget line. content: application/json: schema: $ref: '#/components/schemas/BudgetLine' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: budget_updateLine summary: Update a budget line description: Updates a budget line and optional phase data. Omitted fields remain unchanged. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: lineId in: path required: true description: The budget line ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BudgetLineUpdate' responses: '200': description: The updated budget line. content: application/json: schema: $ref: '#/components/schemas/BudgetLine' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: budget_deleteLine summary: Delete a budget line description: Deletes a budget line. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: lineId in: path required: true description: The budget line ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Budget line deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/lines/{lineId}/phase-data/{phaseId}: put: operationId: budget_updateLinePhaseData summary: Update phase data for a budget line description: Updates one line and phase entry. Omitted fields remain unchanged. Null clears a nullable field. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: lineId in: path required: true description: The budget line ID. schema: $ref: '#/components/schemas/Id' - name: phaseId in: path required: true description: The phase ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BudgetLinePhaseDataUpsert' responses: '200': description: The updated phase data. content: application/json: schema: $ref: '#/components/schemas/BudgetLinePhaseDataUpsertResponse' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/phases: get: operationId: budget_listPhases summary: List budget phases description: Returns the budget's visible and hidden phases. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' responses: '200': description: The budget phases. content: application/json: schema: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/BudgetPhase' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total results when `withCount=true`. truncated: type: boolean description: Whether the page ended before `limit` because some results were unavailable. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: budget_createPhase summary: Create a budget phase description: Adds a phase to the budget. tags: - Budget parameters: - name: Idempotency-Key in: header required: true description: A 16 to 255 character key for safe retries. Reusing the key with a different request returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 - $ref: '#/components/parameters/projectId' requestBody: required: true content: application/json: schema: type: object required: - type - name additionalProperties: false properties: type: $ref: '#/components/schemas/PhaseType' name: type: string maxLength: 255 alias: type: string maxLength: 64 color: type: string maxLength: 32 isHidden: type: boolean displayDecimals: type: - integer - 'null' minimum: 0 maximum: 4 baseCurrencyId: type: - string - 'null' actualDateStart: type: - string - 'null' format: date actualDateEnd: type: - string - 'null' format: date actualStatuses: type: - array - 'null' items: type: string actualSourceTypes: type: - array - 'null' items: type: string actualCurrencies: type: - array - 'null' items: type: string minLength: 3 maxLength: 3 actualContactId: type: - string - 'null' actualTagIds: type: - array - 'null' items: type: string actualBudgetLineIds: type: - array - 'null' items: type: string estimateTagIds: type: array items: type: string overtimeFactors: type: array items: type: string enum: - qty - x committedDateStart: type: - string - 'null' format: date committedDateEnd: type: - string - 'null' format: date committedContactId: type: - string - 'null' committedPhaseIds: type: array items: type: string committedPoStatuses: type: array items: type: string enum: - approved - paymentRequested - paymentRejected - paymentProcessing derivedFromPhaseId: type: string description: 'The estimate phase to use as the starting point. Both phases must have `type: estimate`.' copyValues: type: boolean description: Whether to copy values from `derivedFromPhaseId`. Defaults to `true`. rollupFormula: type: string maxLength: 2000 pattern: ^(?:@\{[\w-]+\}|@[\w-]+|[\d\s+\-*/().,%])*$ description: A formula for a `rollup` phase. Reference phases as `@{phaseId}` and combine them with `+` or `-`. A rollup without a formula totals 0. rollupDisplayMode: type: - string - 'null' enum: - value - percent - bars - margin - null example: type: estimate name: Scenario B derivedFromPhaseId: ph_1a2b responses: '201': description: The created phase. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/BudgetPhase' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/budget/phases/{phaseId}: get: operationId: budget_getPhase summary: Get a budget phase tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: phaseId in: path required: true description: The phase ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The phase. content: application/json: schema: $ref: '#/components/schemas/BudgetPhase' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: budget_updatePhase summary: Update a budget phase description: Updates a budget phase. Omitted fields remain unchanged. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: phaseId in: path required: true description: The phase ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: type: object additionalProperties: false minProperties: 1 properties: name: type: string maxLength: 255 alias: type: string maxLength: 64 color: type: - string - 'null' maxLength: 32 isHidden: type: boolean displayDecimals: type: - integer - 'null' minimum: 0 maximum: 4 baseCurrencyId: type: - string - 'null' actualDateStart: type: - string - 'null' format: date actualDateEnd: type: - string - 'null' format: date actualStatuses: type: - array - 'null' items: type: string actualSourceTypes: type: - array - 'null' items: type: string actualCurrencies: type: - array - 'null' items: type: string minLength: 3 maxLength: 3 actualContactId: type: - string - 'null' actualTagIds: type: - array - 'null' items: type: string actualBudgetLineIds: type: - array - 'null' items: type: string estimateTagIds: type: array items: type: string overtimeFactors: type: array items: type: string enum: - qty - x committedDateStart: type: - string - 'null' format: date committedDateEnd: type: - string - 'null' format: date committedContactId: type: - string - 'null' committedPhaseIds: type: array items: type: string committedPoStatuses: type: array items: type: string enum: - approved - paymentRequested - paymentRejected - paymentProcessing rollupFormula: type: - string - 'null' maxLength: 2000 pattern: ^(?:@\{[\w-]+\}|@[\w-]+|[\d\s+\-*/().,%])*$ description: The formula for a `rollup` phase. Reference phases as `@{phaseId}` and combine them with `+` or `-`. Null clears the formula. rollupDisplayMode: type: - string - 'null' enum: - value - percent - bars - margin - null responses: '200': description: The updated phase. content: application/json: schema: $ref: '#/components/schemas/BudgetPhase' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: budget_deletePhase summary: Delete a budget phase description: Deletes the phase and its budget column. Delete estimate phases only when removing their data. Rename or reorder a phase to reorganize the budget. tags: - Budget parameters: - $ref: '#/components/parameters/projectId' - name: phaseId in: path required: true description: The phase ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Budget phase deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /documents: post: operationId: documents_upload tags: - Documents summary: Upload a document description: Upload a document and optionally link it to targets with `metadata.links`. Each target must have a different `kind`. If any link fails, the document is not created. This operation is billable. Use `Idempotency-Key` to retry safely. parameters: - name: Idempotency-Key in: header required: true description: A 16 to 255 character key for safe retries. Reusing the key with different content returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: multipart/form-data: schema: $ref: '#/components/schemas/DocumentCreateRequest' encoding: metadata: contentType: text/plain responses: '201': description: The created document and its links. content: application/json: schema: $ref: '#/components/schemas/Document' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' get: operationId: documents_list tags: - Documents summary: List documents description: Returns up to 100 documents per page. Use filters to narrow the results. parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/withCount' - name: folder in: query required: false description: Only documents in this folder. schema: $ref: '#/components/schemas/Id' - name: linkedTo in: query required: false description: Only documents linked to this target. Use `kind:id`, such as `transaction:txn_8f2a1c9e`. schema: type: string pattern: ^(project|contact|transaction|payment|purchaseOrder|budgetLine|paymentRequest):.+$ examples: byTransaction: value: transaction:txn_8f2a1c9e - name: unassigned in: query required: false description: When `true`, only documents with no links. schema: type: boolean - name: project in: query required: false description: Only documents in this project. schema: $ref: '#/components/schemas/Id' - name: status in: query required: false description: Only documents with this processing status. schema: $ref: '#/components/schemas/DocumentStatus' - name: classification in: query required: false description: Only documents with this classification. schema: type: string - name: coarseType in: query required: false description: Only documents in this category. schema: $ref: '#/components/schemas/DocumentCoarseType' - name: q in: query required: false description: Search document names and descriptions. schema: type: string responses: '200': description: A page of documents. content: application/json: schema: $ref: '#/components/schemas/DocumentCollection' examples: page: value: data: - id: doc_4b1f0a7c name: vendor-invoice-0425.pdf mimeType: application/pdf size: 184320 status: ready workspaceId: ws_71aa projectId: prj_71aa links: - kind: transaction id: txn_8f2a1c9e createdAt: '2026-05-28T14:03:11Z' updatedAt: '2026-05-28T14:03:40Z' nextCursor: eyJpZCI6ImRvY180YjFmMGE3YyJ9 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /documents/{documentId}: get: operationId: documents_get tags: - Documents summary: Get a document parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The document. content: application/json: schema: $ref: '#/components/schemas/Document' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: documents_update tags: - Documents summary: Update a document description: Update the document's name, description, or folder. Use the links endpoint to change its links. parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DocumentUpdateRequest' examples: rename: value: name: vendor-invoice-april.pdf responses: '200': description: The updated document. content: application/json: schema: $ref: '#/components/schemas/Document' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: documents_delete tags: - Documents summary: Delete a document description: Deletes the document. Safe to retry. parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Document deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /documents/{documentId}/content: get: operationId: documents_getContent tags: - Documents summary: Download a document description: Returns the file with its stored `mimeType` as the response `Content-Type`. parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The document file. content: application/octet-stream: schema: type: string format: binary '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /documents/{documentId}/links/{kind}: parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' - name: kind in: path required: true description: The type of target to link. schema: $ref: '#/components/schemas/DocumentWritableTargetKind' put: operationId: documents_link tags: - Documents summary: Link a document description: Links the document to one target of this kind. Linking the same target again has no effect. Set `replace` to change an existing link of this kind. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DocumentLinkRequest' responses: '200': description: The document with updated links. content: application/json: schema: $ref: '#/components/schemas/Document' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: documents_unlink tags: - Documents summary: Remove a document link description: Removes the link for this kind. Safe to retry. responses: '200': description: The document with updated links. content: application/json: schema: $ref: '#/components/schemas/Document' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /documents/{documentId}/extraction: get: operationId: documents_getExtraction tags: - Documents summary: Get extracted document data description: Returns the document's classification, extracted fields, line items, and confidence scores. Available when the document status is `ready`. Returns `404 not_found` while extraction is pending or processing. A failed document has no extraction. parameters: - name: documentId in: path required: true description: The document ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The extracted document data. content: application/json: schema: $ref: '#/components/schemas/DocumentExtraction' examples: invoice: value: documentId: doc_4b1f0a7c status: ready classification: invoice coarseType: financial extractedAt: '2026-05-28T14:03:40Z' fields: invoiceNumber: value: '4471' confidence: 0.98 vendorName: value: B&H Photo confidence: 0.95 total: value: '1529.00' confidence: 0.91 invoiceDate: value: '2026-05-20' confidence: 0.88 lineItems: - description: Camera body rental - 3 days amount: amount: 75000 currency: USD confidence: 0.86 '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/rate-packs: get: operationId: library_listRatePacks summary: List rate packs description: 'List public and workspace-owned rate packs. Deprecated packs already in use include `deprecated: true`.' tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - $ref: '#/components/parameters/ratePackExpand' - name: q in: query required: false description: Search pack names, publishers, and tags. schema: type: string - name: category in: query required: false description: Only rate packs in this category. schema: type: string - name: deprecated in: query required: false description: Filter by deprecation state. schema: type: boolean responses: '200': description: A page of rate packs. content: application/json: schema: $ref: '#/components/schemas/RatePackCollection' example: data: - id: rpk_2a9f slug: iatse-local-871 name: IATSE Local 871 category: union tags: - union - scripted visibility: PUBLIC isOwned: false deprecated: false enabled: true latestVersion: id: rpv_1 effectiveDate: '2026-01-01' itemCount: 142 nextCursor: eyJpZCI6InJwa18yYTlmIn0 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createRatePack summary: Create a rate pack description: Create a private rate pack for the workspace. The new pack is enabled automatically. tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RatePackCreate' example: name: My Crew Rates category: custom tags: - crew responses: '201': description: The created rate pack. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/RatePack' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/rate-packs/{packId}: get: operationId: library_getRatePack summary: Get a rate pack tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/ratePackExpand' responses: '200': description: The rate pack. content: application/json: schema: $ref: '#/components/schemas/RatePack' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateRatePack summary: Update a rate pack description: Update a workspace-owned rate pack. Other packs return `404 not_found`. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RatePackUpdate' example: name: My Crew Rates 2026 responses: '200': description: The updated rate pack. content: application/json: schema: $ref: '#/components/schemas/RatePack' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteRatePack summary: Delete a rate pack description: Delete a workspace-owned rate pack. Repeating the request has no additional effect. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/rate-packs/{packId}/enablement: post: operationId: library_enableRatePack summary: Enable a rate pack for the workspace description: Make a rate pack available to the workspace. Deprecated packs return `400 validation`; private packs owned by another workspace return `404 not_found`. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The enable link. content: application/json: schema: $ref: '#/components/schemas/RatePackEnableLink' example: id: wrp_5 ratePackId: rpk_2a9f enabledAt: '2026-05-28T10:00:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' delete: operationId: library_disableRatePack summary: Disable a rate pack for the workspace description: Remove a rate pack from the workspace. Repeating the request has no additional effect. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Disabled. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/rate-packs/{packId}/items: get: operationId: library_listRatePackItems summary: List rate pack items description: List current items in an available rate pack. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search item titles and aliases. schema: type: string - name: group in: query required: false description: Only rate pack items in this group. schema: type: string - name: agreement in: query required: false description: Only rate pack items for this agreement. schema: type: string - name: local in: query required: false description: Only rate pack items for this local. schema: type: string - name: unit in: query required: false description: Filter by unit. schema: type: string responses: '200': description: A page of pack items. content: application/json: schema: $ref: '#/components/schemas/RatePackItemCollection' example: data: - id: rpi_9c title: Costume Designer rate: amount: 6500 currency: USD unit: Day group: Wardrobe local: '871' labels: [] nextCursor: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_createRatePackItem summary: Add a rate pack item description: Add an item to a workspace-owned rate pack. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RatePackItemCreate' example: title: Key Grip rate: amount: 5800 currency: USD unit: Day group: Grip responses: '201': description: The created item. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/RatePackItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '409': $ref: '#/components/responses/Error409' /library/rate-packs/{packId}/items/{itemId}: patch: operationId: library_updateRatePackItem summary: Update a rate pack item tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RatePackItemUpdate' example: rate: amount: 6000 currency: USD responses: '200': description: The updated item. content: application/json: schema: $ref: '#/components/schemas/RatePackItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteRatePackItem summary: Delete a rate pack item description: Delete a rate pack item. Repeating the request has no additional effect. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/incentive-packs: get: operationId: library_listIncentivePacks summary: List incentive packs tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - $ref: '#/components/parameters/incentivePackExpand' - name: q in: query required: false description: Search incentive packs by name. schema: type: string - name: category in: query required: false description: Only incentive packs in this category. schema: type: string - name: jurisdiction in: query required: false description: Only incentive packs for this jurisdiction. schema: type: string - name: deprecated in: query required: false description: Filter by whether the incentive pack is deprecated. schema: type: boolean responses: '200': description: A page of incentive packs. content: application/json: schema: $ref: '#/components/schemas/IncentivePackCollection' example: data: - id: ipk_ga slug: georgia-film-credit name: Georgia Film Tax Credit jurisdiction: US-GA visibility: PUBLIC isOwned: false deprecated: false enabled: true '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' /library/incentive-packs/{packId}: get: operationId: library_getIncentivePack summary: Get an incentive pack tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/incentivePackExpand' responses: '200': description: The incentive pack. content: application/json: schema: $ref: '#/components/schemas/IncentivePack' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/incentive-packs/{packId}/programs: get: operationId: library_listIncentivePrograms summary: List incentive programs tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - name: jurisdiction in: query required: false description: Only programs for this jurisdiction. schema: type: string - name: status in: query required: false description: Only programs with this status. schema: type: string enum: - published - blocked - deprecated responses: '200': description: A page of incentive programs. content: application/json: schema: $ref: '#/components/schemas/IncentiveProgramCollection' example: data: - id: ipr_base name: Base Transferable Credit incentiveType: tax-credit incentiveStructure: transferable status: published currentVersionId: ipv_2026 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/incentive-packs/{packId}/enablement: post: operationId: library_enableIncentivePack summary: Enable an incentive pack for the workspace description: Make an incentive pack available to the workspace. Deprecated packs return `400 validation`; private packs owned by another workspace return `404 not_found`. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The enable link. content: application/json: schema: $ref: '#/components/schemas/IncentivePackEnableLink' example: id: wip_3 incentivePackId: ipk_ga enabledAt: '2026-05-28T10:00:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' delete: operationId: library_disableIncentivePack summary: Disable an incentive pack for the workspace description: Remove an incentive pack from the workspace. Repeating the request has no additional effect. tags: - Library parameters: - name: packId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Disabled. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/fringes: get: operationId: library_listFringes summary: List fringes tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search fringe names. schema: type: string - name: includeDeleted in: query required: false description: Include deleted fringes. schema: type: boolean default: false responses: '200': description: A page of workspace fringes. content: application/json: schema: $ref: '#/components/schemas/FringeCollection' example: data: - id: frg_pr name: Payroll Tax description: Employer payroll tax calculationType: percent rate: 7.65 cutoff: null fringeGroupIds: [] color: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createFringe summary: Create a fringe tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeWrite' example: name: Payroll Tax description: Employer payroll tax calculationType: percent rate: 7.65 responses: '201': description: The created fringe. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Fringe' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/fringes/{fringeId}: get: operationId: library_getFringe summary: Get a fringe tags: - Library parameters: - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The fringe. content: application/json: schema: $ref: '#/components/schemas/Fringe' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateFringe summary: Update a fringe tags: - Library parameters: - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeWrite' example: rate: 8 responses: '200': description: The updated fringe. content: application/json: schema: $ref: '#/components/schemas/Fringe' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteFringe summary: Delete a fringe description: Delete a workspace fringe. Project fringes created from it remain available. tags: - Library parameters: - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/globals: get: operationId: library_listGlobals summary: List globals tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search global names. schema: type: string - name: includeDeleted in: query required: false description: Include deleted globals. schema: type: boolean default: false responses: '200': description: A page of workspace globals. content: application/json: schema: $ref: '#/components/schemas/GlobalCollection' example: data: - id: gbl_days symbol: SHOOT_DAYS description: Shoot Days formula: '35' unit: Day '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createGlobal summary: Create a global tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GlobalWrite' example: symbol: SHOOT_DAYS description: Shoot Days formula: '35' unit: Day responses: '201': description: The created global. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Global' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/globals/{globalId}: get: operationId: library_getGlobal summary: Get a global tags: - Library parameters: - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The global. content: application/json: schema: $ref: '#/components/schemas/Global' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateGlobal summary: Update a global tags: - Library parameters: - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GlobalWrite' example: formula: '40' responses: '200': description: The updated global. content: application/json: schema: $ref: '#/components/schemas/Global' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteGlobal summary: Delete a global tags: - Library parameters: - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/currencies: get: operationId: library_listCurrencies summary: List currencies tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search currency names and codes. schema: type: string - name: includeDeleted in: query required: false description: Include deleted currencies. schema: type: boolean default: false responses: '200': description: A page of workspace currencies. content: application/json: schema: $ref: '#/components/schemas/CurrencyCollection' example: data: - id: cur_gbp code: GBP name: British Pound symbol: "\xA3" rateToUSD: 1.27 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createCurrency summary: Create a currency tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CurrencyWrite' example: code: GBP name: British Pound symbol: "\xA3" rateToUSD: 1.27 responses: '201': description: The created currency. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Currency' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/currencies/{currencyId}: get: operationId: library_getCurrency summary: Get a currency tags: - Library parameters: - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The currency. content: application/json: schema: $ref: '#/components/schemas/Currency' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateCurrency summary: Update a currency tags: - Library parameters: - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CurrencyWrite' example: rateToUSD: 1.31 responses: '200': description: The updated currency. content: application/json: schema: $ref: '#/components/schemas/Currency' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteCurrency summary: Delete a currency tags: - Library parameters: - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/fringe-groups: get: operationId: library_listFringeGroups summary: List fringe groups tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search fringe group names. schema: type: string - name: includeDeleted in: query required: false description: Include deleted fringe groups. schema: type: boolean default: false responses: '200': description: A page of workspace fringe groups. content: application/json: schema: $ref: '#/components/schemas/FringeGroupCollection' example: data: - id: frt_union name: Union color: blue '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createFringeGroup summary: Create a fringe group tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeGroupWrite' example: name: Union color: blue responses: '201': description: The created fringe group. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/FringeGroup' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/fringe-groups/{fringeGroupId}: get: operationId: library_getFringeGroup summary: Get a fringe group tags: - Library parameters: - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The fringe group. content: application/json: schema: $ref: '#/components/schemas/FringeGroup' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateFringeGroup summary: Update a fringe group tags: - Library parameters: - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeGroupWrite' example: color: green responses: '200': description: The updated fringe group. content: application/json: schema: $ref: '#/components/schemas/FringeGroup' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteFringeGroup summary: Delete a fringe group tags: - Library parameters: - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/tags: get: operationId: library_listTags summary: List tags tags: - Library parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search tag names. schema: type: string - name: eligibilityKey in: query required: false description: Only tags with this eligibility key. schema: type: string - name: includeDeleted in: query required: false description: Include deleted tags. schema: type: boolean default: false responses: '200': description: A page of tags. content: application/json: schema: $ref: '#/components/schemas/TagCollection' example: data: - id: tag_atl name: Atlanta color: orange createdAt: '2026-01-02T08:00:00Z' updatedAt: '2026-01-02T08:00:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createTag summary: Create a workspace tag description: Create a workspace tag. `color` accepts a supported display color or `null`. tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TagCreate' example: name: Atlanta color: orange responses: '201': description: The created tag. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Tag' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/tags/{tagId}: get: operationId: library_getTag summary: Get a workspace tag tags: - Library parameters: - name: tagId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '200': description: The tag. content: application/json: schema: $ref: '#/components/schemas/Tag' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateTag summary: Update a workspace tag tags: - Library parameters: - name: tagId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TagUpdate' example: color: green responses: '200': description: The updated tag. content: application/json: schema: $ref: '#/components/schemas/Tag' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteTag summary: Delete a workspace tag description: Delete a tag. Existing historical references remain available. tags: - Library parameters: - name: tagId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /library/units: get: operationId: library_listUnits summary: List units description: List built-in and workspace units. Built-in units are read-only. tags: - Library parameters: - name: q in: query required: false description: Search unit names and abbreviations. schema: type: string responses: '200': description: All units. content: application/json: schema: $ref: '#/components/schemas/UnitCollection' example: data: - id: Day label: Day isCustom: false - id: cun_box label: Box Rental isCustom: true createdAt: '2026-03-01T08:00:00Z' updatedAt: '2026-03-01T08:00:00Z' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: library_createUnit summary: Create a unit description: Create a workspace unit. Built-in units cannot be changed. tags: - Library parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UnitCreate' example: label: Box Rental responses: '201': description: The created unit. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Unit' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /library/units/{unitId}: get: operationId: library_getUnit summary: Get a unit description: Get a built-in or workspace unit. tags: - Library parameters: - name: unitId in: path required: true schema: type: string responses: '200': description: The unit. content: application/json: schema: $ref: '#/components/schemas/Unit' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateUnit summary: Update a unit tags: - Library parameters: - name: unitId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UnitUpdate' example: label: Box Rental (weekly) responses: '200': description: The updated unit. content: application/json: schema: $ref: '#/components/schemas/Unit' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteUnit summary: Delete a unit tags: - Library parameters: - name: unitId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/incentives: get: operationId: library_listProjectIncentives summary: List project incentives tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/projectIncentiveExpand' - name: isApplied in: query required: false description: Filter by whether the incentive is applied to the project. schema: type: boolean - name: jurisdiction in: query required: false description: Only project incentives for this jurisdiction. schema: type: string responses: '200': description: A page of project incentives. content: application/json: schema: $ref: '#/components/schemas/ProjectIncentiveCollection' example: data: - id: inc_ga1 name: Georgia Base Credit sourceType: saturation sourceIncentiveVersionId: ipv_2026 isApplied: true amount: amount: 1250000 currency: USD '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_addProjectIncentive summary: Add an incentive to a project description: Add the published version of an available incentive program. Unpublished or deprecated incentives return `400 validation`. tags: - Library parameters: - $ref: '#/components/parameters/projectId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProjectIncentiveAdd' example: programId: ipr_base responses: '200': description: The existing project incentive. content: application/json: schema: $ref: '#/components/schemas/ProjectIncentive' '201': description: The created project incentive. content: application/json: schema: $ref: '#/components/schemas/ProjectIncentive' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/incentives/{incentiveId}: get: operationId: library_getProjectIncentive summary: Get a project incentive tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: incentiveId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/projectIncentiveExpand' responses: '200': description: The project incentive. content: application/json: schema: $ref: '#/components/schemas/ProjectIncentive' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateProjectIncentive summary: Update a project incentive description: Update the supplied incentive fields. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: incentiveId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProjectIncentiveUpdate' example: isApplied: false responses: '200': description: The updated project incentive. content: application/json: schema: $ref: '#/components/schemas/ProjectIncentive' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteProjectIncentive summary: Remove a project incentive description: Remove an incentive from a project. Adding it again restores its previous settings. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: incentiveId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Removed. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/fringes: get: operationId: library_listProjectFringes summary: List project fringes tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/libraryExpand' - name: sourceId in: query required: false description: Filter by the workspace fringe used to create the project fringe. schema: $ref: '#/components/schemas/Id' responses: '200': description: A page of project fringes. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeCollection' example: data: - id: frg_project1 name: Payroll Tax description: Employer payroll tax calculationType: percent rate: 8 cutoff: null fringeGroupIds: [] color: null sourceType: workspace sourceId: frg_pr '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_addProjectFringe summary: Add a fringe to a project description: Add a workspace fringe to a project. Adding it again keeps project edits. Use `reset=true` to restore workspace values. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: reset in: query required: false description: Restore workspace values and replace project edits. schema: type: boolean default: false requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - sourceId properties: sourceId: $ref: '#/components/schemas/Id' example: sourceId: frg_pr responses: '200': description: The existing project fringe. content: application/json: schema: $ref: '#/components/schemas/ProjectFringe' '201': description: The created project fringe. content: application/json: schema: $ref: '#/components/schemas/ProjectFringe' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/fringes/{fringeId}: get: operationId: library_getProjectFringe summary: Get a project fringe tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/libraryExpand' responses: '200': description: The project fringe. content: application/json: schema: $ref: '#/components/schemas/ProjectFringe' example: id: frg_project1 name: Payroll Tax description: Employer payroll tax calculationType: percent rate: 8 cutoff: null fringeGroupIds: [] color: null sourceType: workspace sourceId: frg_pr source: id: frg_pr name: Payroll Tax description: Employer payroll tax calculationType: percent rate: 7.65 cutoff: null fringeGroupIds: [] color: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateProjectFringe summary: Update a project fringe description: Update the supplied project fringe fields. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeWrite' example: rate: 8.5 responses: '200': description: The updated project fringe. content: application/json: schema: $ref: '#/components/schemas/ProjectFringe' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteProjectFringe summary: Remove a project fringe description: Remove a fringe from a project. Adding it again restores its previous settings unless `reset=true`. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Removed. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/globals: get: operationId: library_listProjectGlobals summary: List project globals tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/libraryExpand' - name: sourceId in: query required: false description: Only globals copied from this workspace global. schema: $ref: '#/components/schemas/Id' responses: '200': description: A page of project globals. content: application/json: schema: $ref: '#/components/schemas/ProjectGlobalCollection' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_addProjectGlobal summary: Add a global to a project description: Add a workspace global to a project. Adding it again keeps project edits. Use `reset=true` to restore workspace values. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: reset in: query required: false description: Restore workspace values and replace project edits. schema: type: boolean default: false requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - sourceId properties: sourceId: $ref: '#/components/schemas/Id' example: sourceId: gbl_days responses: '200': description: The existing project global. content: application/json: schema: $ref: '#/components/schemas/ProjectGlobal' '201': description: The created project global. content: application/json: schema: $ref: '#/components/schemas/ProjectGlobal' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/globals/{globalId}: get: operationId: library_getProjectGlobal summary: Get a project global tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/libraryExpand' responses: '200': description: The project global. content: application/json: schema: $ref: '#/components/schemas/ProjectGlobal' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateProjectGlobal summary: Update a project global tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GlobalWrite' example: formula: '38' responses: '200': description: The updated project global. content: application/json: schema: $ref: '#/components/schemas/ProjectGlobal' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteProjectGlobal summary: Remove a project global tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: globalId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Removed. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/currencies: get: operationId: library_listProjectCurrencies summary: List project currencies tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/libraryExpand' - name: sourceId in: query required: false description: Only currencies copied from this workspace currency. schema: $ref: '#/components/schemas/Id' responses: '200': description: A page of project currencies. content: application/json: schema: $ref: '#/components/schemas/ProjectCurrencyCollection' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_addProjectCurrency summary: Add a currency to a project description: Add a workspace currency to a project. Adding it again keeps project edits. Use `reset=true` to restore workspace values. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: reset in: query required: false description: Restore workspace values and replace project edits. schema: type: boolean default: false requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - sourceId properties: sourceId: $ref: '#/components/schemas/Id' example: sourceId: cur_gbp responses: '200': description: The existing project currency. content: application/json: schema: $ref: '#/components/schemas/ProjectCurrency' '201': description: The created project currency. content: application/json: schema: $ref: '#/components/schemas/ProjectCurrency' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/currencies/{currencyId}: get: operationId: library_getProjectCurrency summary: Get a project currency tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/libraryExpand' responses: '200': description: The project currency. content: application/json: schema: $ref: '#/components/schemas/ProjectCurrency' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateProjectCurrency summary: Update a project currency tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CurrencyWrite' example: rateToUSD: 1.33 responses: '200': description: The updated project currency. content: application/json: schema: $ref: '#/components/schemas/ProjectCurrency' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteProjectCurrency summary: Remove a project currency tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: currencyId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Removed. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/fringe-groups: get: operationId: library_listProjectFringeGroups summary: List project fringe groups tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/libraryExpand' - name: sourceId in: query required: false description: Only fringe groups copied from this workspace fringe group. schema: $ref: '#/components/schemas/Id' responses: '200': description: A page of project fringe groups. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeGroupCollection' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: library_addProjectFringeGroup summary: Add a fringe group to a project description: Add a workspace Fringe Group to a project. Adding it again keeps project edits. Use `reset=true` to restore workspace values. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: reset in: query required: false description: Restore workspace values and replace project edits. schema: type: boolean default: false requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - sourceId properties: sourceId: $ref: '#/components/schemas/Id' example: sourceId: frt_union responses: '200': description: The existing project Fringe Group. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeGroup' '201': description: The created project Fringe Group. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeGroup' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/fringe-groups/{fringeGroupId}: get: operationId: library_getProjectFringeGroup summary: Get a project fringe group tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/libraryExpand' responses: '200': description: The project Fringe Group. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeGroup' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: library_updateProjectFringeGroup summary: Update a project fringe group tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FringeGroupWrite' example: color: red responses: '200': description: The updated project Fringe Group. content: application/json: schema: $ref: '#/components/schemas/ProjectFringeGroup' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: library_deleteProjectFringeGroup summary: Remove a project fringe group tags: - Library parameters: - $ref: '#/components/parameters/projectId' - name: fringeGroupId in: path required: true schema: $ref: '#/components/schemas/Id' responses: '204': description: Removed. '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/library/tags: get: operationId: library_listProjectTags summary: List project tags description: List tags used in the project. tags: - Library parameters: - $ref: '#/components/parameters/projectId' - $ref: '#/components/parameters/limit' responses: '200': description: A page of project tags. content: application/json: schema: $ref: '#/components/schemas/TagCollection' example: data: - id: tag_atl name: Atlanta color: orange createdAt: '2026-01-02T08:00:00Z' updatedAt: '2026-01-02T08:00:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects: get: operationId: projects_list tags: - Projects summary: List projects description: List projects you can access. Results are paginated and exclude deleted projects by default. Use `expand` to include the project brief (assumptions). parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/withCount' - $ref: '#/components/parameters/projectExpand' - name: status in: query required: false description: Filter by status. Separate multiple values with commas (for example, `active,archived`). schema: type: string example: active - name: spaceId in: query required: false description: Only projects filed under this space. schema: $ref: '#/components/schemas/Id' - name: q in: query required: false description: Search project names and slugs. schema: type: string - name: includeDeleted in: query required: false description: Include deleted projects. schema: type: boolean default: false responses: '200': description: A page of projects. content: application/json: schema: $ref: '#/components/schemas/ProjectList' example: data: - id: prj_8f2a1c9e slug: q3-feature-doc name: Q3 Feature Doc emoji: "\U0001F3AC" image: null status: active summary: A short documentary on Q3 features. spaceId: spc_1a2b3c createdAt: '2026-05-01T12:00:00Z' updatedAt: '2026-05-20T09:30:00Z' nextCursor: eyJpZCI6InByal84ZjJhMWM5ZSJ9 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: projects_create tags: - Projects summary: Create a project description: Create a project in the workspace. Read-only fields return `422 field_read_only` when supplied. parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProjectCreate' example: name: Q3 Feature Doc emoji: "\U0001F3AC" spaceId: spc_1a2b3c responses: '201': description: The created project. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/ProjectCreated' example: id: prj_8f2a1c9e slug: q3-feature-doc name: Q3 Feature Doc emoji: "\U0001F3AC" image: null status: active summary: null spaceId: spc_1a2b3c createdAt: '2026-05-29T10:00:00Z' updatedAt: '2026-05-29T10:00:00Z' defaultBudget: budgetId: bud_8f2a1c9e estimatePhaseId: phs_estimate '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '402': $ref: '#/components/responses/Error402' '423': $ref: '#/components/responses/Error423' '503': $ref: '#/components/responses/Error503' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' /projects/{projectId}: parameters: - name: projectId in: path required: true description: Project ID or slug. schema: type: string get: operationId: projects_get tags: - Projects summary: Get a project description: Get a project by ID or slug. Use `expand` to include the project brief (assumptions). parameters: - $ref: '#/components/parameters/projectExpand' responses: '200': description: The project. content: application/json: schema: $ref: '#/components/schemas/Project' example: id: prj_8f2a1c9e slug: q3-feature-doc name: Q3 Feature Doc emoji: "\U0001F3AC" image: null status: active summary: A short documentary on Q3 features. spaceId: spc_1a2b3c createdAt: '2026-05-01T12:00:00Z' updatedAt: '2026-05-20T09:30:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: projects_update tags: - Projects summary: Update a project description: Update the supplied project fields. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProjectUpdate' example: name: Q3 Feature Doc (final) status: archived responses: '200': description: The updated project. content: application/json: schema: $ref: '#/components/schemas/Project' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /spaces: get: operationId: spaces_list tags: - Spaces summary: List spaces description: List spaces in the workspace. parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/withCount' - name: parentId in: query required: false description: Only spaces directly nested under this parent space. schema: $ref: '#/components/schemas/Id' - name: includeDeleted in: query required: false description: Include deleted spaces. schema: type: boolean default: false responses: '200': description: A page of spaces. content: application/json: schema: $ref: '#/components/schemas/SpaceList' example: data: - id: spc_1a2b3c slug: features name: Features image: null parentId: null archived: false createdAt: '2026-04-01T12:00:00Z' updatedAt: '2026-04-01T12:00:00Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: spaces_create tags: - Spaces summary: Create a space parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SpaceCreate' example: name: Features responses: '201': description: The created space. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Space' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' /spaces/{spaceId}: parameters: - name: spaceId in: path required: true description: Space ID. schema: $ref: '#/components/schemas/Id' patch: operationId: spaces_update tags: - Spaces summary: Update a space requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SpaceUpdate' example: name: Feature Docs archived: true responses: '200': description: The updated space. content: application/json: schema: $ref: '#/components/schemas/Space' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: spaces_delete tags: - Spaces summary: Delete a space description: Delete a space. Its projects become ungrouped. Repeating the request has no additional effect. responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /contacts: get: operationId: contacts_list tags: - Contacts summary: List contacts description: List contacts in the workspace. Use `expand` to include accessible documents or transactions. parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/contactExpand' - $ref: '#/components/parameters/withCount' - name: q in: query required: false description: Search contact names, companies, and email addresses. schema: type: string - name: type in: query required: false description: Filter by one or more comma-separated contact types. schema: type: string example: contractor - name: tags in: query required: false description: Comma-separated tag handles to filter by. schema: type: string - name: tagMode in: query required: false description: How `tags` combine. schema: type: string enum: - any - all - none default: any - name: track1099 in: query required: false description: Filter by 1099 tracking status. schema: type: boolean - name: hasTaxId in: query required: false description: Filter by whether a tax ID is on file. schema: type: boolean - name: includeDeleted in: query required: false description: Include deleted contacts. schema: type: boolean default: false responses: '200': description: A page of contacts. content: application/json: schema: $ref: '#/components/schemas/ContactList' example: data: - id: con_5c4d3e2f displayName: Aerial Imaging LLC name: Jordan Lee company: Aerial Imaging LLC title: Drone Operator type: company email: jordan@aerialimaging.example phone: null address: null website: null instagram: null imdb: null rate: amount: 85000 currency: USD track1099: true taxIdLast4: '4821' hasTaxId: true notes: null createdAt: '2026-03-10T08:00:00Z' updatedAt: '2026-05-02T16:45:00Z' nextCursor: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: contacts_create tags: - Contacts summary: Create a contact parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ContactCreate' example: name: Jordan Lee company: Aerial Imaging LLC type: company email: jordan@aerialimaging.example track1099: true rate: amount: 85000 currency: USD responses: '201': description: The created contact. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Contact' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' /contacts/{contactId}: parameters: - name: contactId in: path required: true description: Contact ID. schema: $ref: '#/components/schemas/Id' get: operationId: contacts_get tags: - Contacts summary: Get a contact parameters: - $ref: '#/components/parameters/contactExpand' responses: '200': description: The contact. content: application/json: schema: $ref: '#/components/schemas/Contact' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: contacts_update tags: - Contacts summary: Update a contact requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ContactUpdate' example: title: Senior Drone Operator track1099: false responses: '200': description: The updated contact. content: application/json: schema: $ref: '#/components/schemas/Contact' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: contacts_delete tags: - Contacts summary: Delete a contact description: Delete a contact. Repeating the request has no additional effect. responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/comments: parameters: - name: projectId in: path required: true schema: $ref: '#/components/schemas/Id' get: operationId: comments_list tags: - Comments summary: List comments description: List comments in a project. Use `targetKind` and `targetId` together to filter by resource. parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/withCount' - name: targetKind in: query required: false description: Resource type. Use with `targetId`. schema: $ref: '#/components/schemas/CommentTargetKind' - name: targetId in: query required: false description: Resource ID. Use with `targetKind`. schema: $ref: '#/components/schemas/Id' - name: threadId in: query required: false description: Only replies under this root comment. schema: $ref: '#/components/schemas/Id' - name: resolved in: query required: false description: Filter by resolution state. schema: type: boolean responses: '200': description: A page of comments. content: application/json: schema: $ref: '#/components/schemas/CommentList' example: data: - id: cmt_7a8b9c projectId: prj_8f2a1c9e threadId: null target: kind: budgetLine id: bud_1234abcd authorId: usr_a1b2c3 authorName: Sam Rivera content: Can we confirm the drone day rate here? resolved: false createdAt: '2026-05-21T14:00:00Z' updatedAt: '2026-05-21T14:00:00Z' nextCursor: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' '404': $ref: '#/components/responses/Error404' post: operationId: comments_create tags: - Comments summary: Create a comment description: Add a comment to a project resource you can edit. parameters: - name: Idempotency-Key in: header required: true description: Unique request key, 16 to 255 characters. Retrying the same request returns the first response. Missing or invalid keys return `400 validation`; reuse with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CommentCreate' example: content: Can we confirm the drone day rate here? target: kind: budgetLine id: bud_1234abcd responses: '201': description: The created comment. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Comment' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /projects/{projectId}/comments/{commentId}: parameters: - name: projectId in: path required: true schema: $ref: '#/components/schemas/Id' - name: commentId in: path required: true description: Comment ID. schema: $ref: '#/components/schemas/Id' patch: operationId: comments_update tags: - Comments summary: Update a comment description: Edit the comment body or resolution. Only the author can edit the body. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CommentUpdate' example: resolved: true responses: '200': description: The updated comment. content: application/json: schema: $ref: '#/components/schemas/Comment' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: comments_delete tags: - Comments summary: Delete a comment description: Delete a comment and its replies. Repeating the request has no additional effect. responses: '204': description: Deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /me: get: operationId: me_get tags: - Meta summary: Get the current identity description: Returns the identity and workspaces associated with the token. responses: '200': description: The current identity and workspaces. content: application/json: schema: $ref: '#/components/schemas/Me' example: id: usr_4f1a8c2e type: user email: producer@example.com name: Dana Producer workspaces: - workspaceId: ws_2b9d7a1f workspaceName: Paradigm Pictures workspaceRole: admin '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '429': $ref: '#/components/responses/Error429' /payment-requests: get: operationId: payment-requests_list summary: List payment requests description: Returns payment requests. Use `expand` to include related records. tags: - Payment Requests parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - name: status in: query description: Only payment requests with this status. schema: $ref: '#/components/schemas/PaymentRequestStatus' - name: projectId in: query description: Only payment requests for this project. schema: $ref: '#/components/schemas/Id' - name: purchaseOrderId in: query description: Only payment requests linked to this purchase order. schema: $ref: '#/components/schemas/Id' - name: contactId in: query description: Only payment requests for this contact. schema: $ref: '#/components/schemas/Id' - name: expand in: query schema: type: array items: $ref: '#/components/schemas/PaymentRequestExpand' style: form explode: false description: Related records to include, separated by commas. responses: '200': description: Payment requests. content: application/json: schema: $ref: '#/components/schemas/PaymentRequestList' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' /payment-requests/{paymentRequestId}: get: operationId: payment-requests_get summary: Get a payment request description: Returns a payment request. Use `expand` to include related records. tags: - Payment Requests parameters: - name: paymentRequestId in: path required: true schema: $ref: '#/components/schemas/Id' - name: expand in: query schema: type: array items: $ref: '#/components/schemas/PaymentRequestExpand' style: form explode: false description: Related records to include, separated by commas. responses: '200': description: The payment request. content: application/json: schema: $ref: '#/components/schemas/PaymentRequest' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' /payments: get: operationId: payments_list summary: List payments description: Returns payments. tags: - Payments parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - name: status in: query description: Only payments with this status. schema: $ref: '#/components/schemas/PaymentStatus' - name: projectId in: query description: Only payments for this project. schema: $ref: '#/components/schemas/Id' - name: purchaseOrderId in: query description: Only payments linked to this purchase order. schema: $ref: '#/components/schemas/Id' - name: paymentRequestId in: query description: Only payments created from this payment request. schema: $ref: '#/components/schemas/Id' - name: contactId in: query description: Only payments for this contact. schema: $ref: '#/components/schemas/Id' - name: expand in: query schema: type: array items: $ref: '#/components/schemas/PaymentExpand' style: form explode: false description: Related records to include, separated by commas. responses: '200': description: Payments. content: application/json: schema: $ref: '#/components/schemas/PaymentList' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' /payments/{paymentId}: get: operationId: payments_get summary: Get a payment description: Returns a payment. Use `expand` to include related records. tags: - Payments parameters: - name: paymentId in: path required: true schema: $ref: '#/components/schemas/Id' - name: expand in: query schema: type: array items: $ref: '#/components/schemas/PaymentExpand' style: form explode: false description: Related records to include, separated by commas. responses: '200': description: The payment. content: application/json: schema: $ref: '#/components/schemas/Payment' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' /payments/{paymentId}/timeline: get: operationId: payments_getTimeline summary: Get a payment timeline description: Returns payment history, newest first. tags: - Payments parameters: - name: paymentId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' responses: '200': description: Payment history. content: application/json: schema: $ref: '#/components/schemas/PaymentTimelinePage' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' /purchase-orders: get: operationId: purchase-orders_list summary: List purchase orders description: Returns purchase orders you can access. Deleted orders are excluded by default. tags: - Purchase Orders parameters: - name: projectId in: query required: false description: Project ID or slug. Use `none` for unassigned purchase orders. schema: type: string - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/purchaseOrderSort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/purchaseOrderExpand' - $ref: '#/components/parameters/withCount' - name: status in: query required: false description: Purchase order status. schema: $ref: '#/components/schemas/PurchaseOrderStatus' - name: contactId in: query required: false description: Vendor contact ID. schema: type: string - name: budgetLineId in: query required: false description: Budget line ID. schema: type: string - name: number in: query required: false description: Purchase order number. Matching is exact. schema: type: string - name: q in: query required: false description: Search purchase order names. schema: type: string - name: includeDeleted in: query required: false description: Include deleted purchase orders. Defaults to `false`. schema: type: boolean default: false responses: '200': description: A page of purchase orders. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderList' examples: page: value: data: - id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo number: PO-0042 name: Camera package rental status: pending contactId: con_77a budgetLineId: bud_5510 dueDate: '2026-05-20' amount: amount: 152900 currency: USD createdAt: '2026-05-18T14:02:11.000Z' updatedAt: '2026-05-20T09:31:00.000Z' nextCursor: eyJpZCI6InBvXzhmMmExYzllIn0 '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: purchase-orders_create summary: Create a purchase order description: Creates a draft purchase order. Use `projectId` to assign it to a project. Requires an `Idempotency-Key`. tags: - Purchase Orders parameters: - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key with the same body returns the first result. Reusing it with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 - $ref: '#/components/parameters/purchaseOrderExpand' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderCreate' examples: create: value: number: PO-0042 name: Camera package rental contactId: con_77a budgetLineId: bud_5510 dueDate: '2026-05-20' items: - description: Alexa Mini LF body qty: 5 unit: day rate: 25000 responses: '201': description: The created purchase order (status `draft`). headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' examples: created: value: id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo number: PO-0042 name: Camera package rental status: draft contactId: con_77a budgetLineId: bud_5510 dueDate: '2026-05-20' createdById: usr_aa1 createdAt: '2026-05-18T14:02:11.000Z' updatedAt: '2026-05-18T14:02:11.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}: get: operationId: purchase-orders_get summary: Get a purchase order description: Returns a purchase order you can access. Otherwise returns `404 not_found`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/purchaseOrderExpand' responses: '200': description: The purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: purchase-orders_update summary: Update a purchase order description: Updates a draft or rejected purchase order. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/purchaseOrderExpand' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderUpdate' examples: rename: value: name: Camera package rental (updated) notes: Net-45 responses: '200': description: The updated purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: purchase-orders_delete summary: Delete a purchase order description: Deletes a draft purchase order. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. No content. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/submit: post: operationId: purchase-orders_submit summary: Submit a purchase order for approval description: Submits a draft or rejected purchase order for approval. Requires an `Idempotency-Key`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key returns the first submission result. schema: type: string minLength: 16 maxLength: 255 responses: '200': description: The submitted purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' '503': $ref: '#/components/responses/Error503' /purchase-orders/{purchaseOrderId}/cancel-submission: post: operationId: purchase-orders_cancelSubmission summary: Cancel a pending submission description: Cancels a pending approval and returns the purchase order to `draft`. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The purchase order back in `draft`. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' examples: cancelled: value: id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo status: draft updatedAt: '2026-05-18T14:10:00.000Z' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/void: post: operationId: purchase-orders_void summary: Void a purchase order description: Voids an approved or actualizing purchase order. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The voided purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' examples: voided: value: id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo status: void updatedAt: '2026-05-21T16:00:00.000Z' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/mark-paid: post: operationId: purchase-orders_markPaid summary: Mark a purchase order as paid description: Marks an approved or actualizing purchase order as paid. The purchase order must have a linked transaction. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' responses: '200': description: The paid purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' examples: paid: value: id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo status: paid updatedAt: '2026-05-21T18:00:00.000Z' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/transactions/{transactionId}: parameters: - name: purchaseOrderId in: path required: true schema: $ref: '#/components/schemas/Id' - name: transactionId in: path required: true schema: $ref: '#/components/schemas/Id' put: operationId: purchase-orders_linkTransaction tags: - Purchase Orders summary: Link a transaction to a purchase order responses: '200': description: The linked purchase order. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' delete: operationId: purchase-orders_unlinkTransaction tags: - Purchase Orders summary: Unlink a transaction from a purchase order responses: '200': description: The purchase order after unlinking. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' /purchase-orders/{purchaseOrderId}/timeline: get: operationId: purchase-orders_getTimeline summary: Get the purchase order timeline description: Returns purchase-order history, newest first. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' responses: '200': description: Purchase order history, newest first. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderTimelinePage' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/items: get: operationId: purchase-orders_listItems summary: List purchase order items description: Returns the items in a purchase order. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' responses: '200': description: A page of purchase-order items. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderItemList' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: purchase-orders_createItem summary: Add a purchase order item description: Adds an item to a draft or rejected purchase order. Other statuses return `409 po_invalid_status`. Requires an `Idempotency-Key`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key with the same body returns the first result. Reusing it with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderItemWrite' examples: create: value: description: Alexa Mini LF body budgetLineId: bud_5510 qty: 5 unit: day rate: 25000 responses: '201': description: The created item. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /purchase-orders/{purchaseOrderId}/items/{itemId}: patch: operationId: purchase-orders_updateItem summary: Update a purchase order item description: Updates an item on a draft or rejected purchase order. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true description: Purchase order item ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderItemWrite' examples: update: value: qty: 6 rate: 24000 responses: '200': description: The updated item. content: application/json: schema: $ref: '#/components/schemas/PurchaseOrderItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: purchase-orders_deleteItem summary: Delete a purchase order item description: Deletes an item from a draft or rejected purchase order. Other statuses return `409 po_invalid_status`. tags: - Purchase Orders parameters: - name: purchaseOrderId in: path required: true description: Purchase order ID. schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true description: Purchase order item ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. No content. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /search: get: operationId: search_workspace summary: Search the workspace or one project tags: - Search description: Searches the workspace or one project. Results are ranked by relevance and include only records available to the token. parameters: - name: q in: query required: true description: The search query. 1 to 500 characters. schema: type: string minLength: 1 maxLength: 500 examples: panavision: value: Panavision - name: types in: query required: false description: Resource types to search. Omit to search every supported type. style: form explode: false schema: type: array items: $ref: '#/components/schemas/SearchKind' examples: twoKinds: value: transactions,documents - name: projectId in: query required: false description: Limit results to one project. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' responses: '200': description: Ranked search results. content: application/json: schema: $ref: '#/components/schemas/SearchResponse' examples: panavision: summary: Workspace search for "Panavision" value: data: - kind: transactions id: txn_8f2a1c9e label: Panavision Camera Package snippet: Invoice 4471, Panavision rental score: 0.62 - kind: documents id: doc_4b71e0aa label: Panavision quote.pdf score: 0.41 nextCursor: eyJzIjowLjQxLCJrIjoiZG9jdW1lbnRzIiwiaWQiOiJkb2NfNGI3MSJ9 searchedTypes: - transactions - documents - budget-lines - purchase-orders '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '402': $ref: '#/components/responses/Error402' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /transactions: get: operationId: transactions_list tags: - Transactions summary: List transactions description: Returns transactions you can access. Filters combine with AND. Each page contains up to 100 transactions. parameters: - name: projectId in: query description: Project ID or slug. Use `none` for unassigned transactions. schema: type: string - name: source in: query description: Transaction source. Separate multiple values with commas. schema: $ref: '#/components/schemas/TransactionSource' - name: type in: query description: Transaction type. Separate multiple values with commas. schema: type: string - name: status in: query description: Filter by status. Separate multiple values with commas. schema: $ref: '#/components/schemas/TransactionStatus' - name: isReversal in: query description: Set to `true` for refunds and other reversals. schema: type: boolean - name: contactId in: query description: Assigned contact ID. schema: $ref: '#/components/schemas/Id' - name: budgetLineId in: query description: Budget line ID. schema: $ref: '#/components/schemas/Id' - name: purchaseOrderId in: query description: Linked purchase order ID. schema: $ref: '#/components/schemas/Id' - name: currency in: query description: Three-letter currency code. Required with `amountMin` or `amountMax`. schema: type: string minLength: 3 maxLength: 3 - name: dateFrom in: query description: Earliest transaction time, inclusive. Must be on or before `dateTo`. schema: type: string format: date-time - name: dateTo in: query description: Latest transaction time, inclusive. schema: type: string format: date-time - name: amountMin in: query description: Minimum amount, inclusive, in minor currency units. Requires `currency`. schema: type: integer format: int64 - name: amountMax in: query description: Maximum amount, inclusive, in minor currency units. Requires `currency`. schema: type: integer format: int64 - name: isItemized in: query description: Set to `true` for itemized transactions or `false` for transactions without items. schema: type: boolean - name: merchant in: query description: Merchant name. Matching is case-insensitive and partial. schema: type: string - name: hasDocuments in: query description: Set to `true` for transactions with documents or `false` for transactions without documents. schema: type: boolean - name: q in: query description: Search transaction descriptions. schema: type: string - $ref: '#/components/parameters/transactionExpand' - $ref: '#/components/parameters/transactionSort' - $ref: '#/components/parameters/order' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - $ref: '#/components/parameters/withCount' responses: '200': description: A page of transactions. content: application/json: schema: $ref: '#/components/schemas/TransactionCollection' example: data: - id: txn_8f2a1c9e source: plaid sourceId: plx_991 type: CreditCard status: posted isReversal: false amount: amount: 152900 currency: USD currency: USD timestamp: '2026-05-20T14:03:00.000Z' description: B&H Photo - camera rental merchant: B&H Photo contactId: con_4d5e projectId: prj_films budgetLineId: bud_camera isItemized: false purchaseOrderId: null createdAt: '2026-05-20T14:05:00.000Z' updatedAt: '2026-05-20T14:05:00.000Z' nextCursor: eyJ0cyI6MTY4 statusReachability: manual: - posted - void - projected plaid: - pending - posted - void - needs_review '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: transactions_create tags: - Transactions summary: Create a manual transaction description: Creates a manual transaction. Use `projectId` to assign it to a project. Requires an `Idempotency-Key`. parameters: - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key with the same body returns the first result. Reusing it with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransactionManualCreate' example: type: Invoice amount: amount: 50000 currency: USD timestamp: '2026-05-22T00:00:00.000Z' description: Vendor invoice contactId: con_4d5e budgetLineId: bud_postprod responses: '201': description: The created transaction. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/Transaction' example: id: txn_a1b2c3d4 source: manual sourceId: null type: Invoice status: posted isReversal: false amount: amount: 50000 currency: USD currency: USD timestamp: '2026-05-22T00:00:00.000Z' description: Vendor invoice contactId: con_4d5e projectId: prj_films budgetLineId: bud_postprod isItemized: false createdAt: '2026-05-22T09:00:00.000Z' updatedAt: '2026-05-22T09:00:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /transactions/stats: get: operationId: transactions_stats tags: - Transactions summary: Get transaction totals description: Returns the number and total amount of matching transactions in one currency. parameters: - name: projectId in: query description: Project ID or slug. Use `none` for unassigned transactions. schema: type: string - name: source in: query description: Transaction source. Separate multiple values with commas. schema: $ref: '#/components/schemas/TransactionSource' - name: type in: query description: Transaction type. Separate multiple values with commas. schema: type: string - name: status in: query description: Transaction status. Separate multiple values with commas. schema: $ref: '#/components/schemas/TransactionStatus' - name: isReversal in: query description: Set to `true` for refunds and other reversals. schema: type: boolean - name: contactId in: query description: Only transactions for this contact. schema: $ref: '#/components/schemas/Id' - name: budgetLineId in: query description: Only transactions coded to this budget line. schema: $ref: '#/components/schemas/Id' - name: purchaseOrderId in: query description: Linked purchase order ID. schema: $ref: '#/components/schemas/Id' - name: currency in: query required: true description: Three-letter currency code for the total. schema: type: string minLength: 3 maxLength: 3 - name: dateFrom in: query description: Earliest transaction time, inclusive. Must be on or before `dateTo`. schema: type: string format: date-time - name: dateTo in: query description: Latest transaction time, inclusive. schema: type: string format: date-time - name: amountMin in: query description: Minimum amount, inclusive, in minor currency units. schema: type: integer format: int64 - name: amountMax in: query description: Maximum amount, inclusive, in minor currency units. schema: type: integer format: int64 - name: isItemized in: query description: Set to `true` for itemized transactions or `false` for transactions without items. schema: type: boolean - name: merchant in: query description: Merchant name. Matching is case-insensitive and partial. schema: type: string - name: hasDocuments in: query description: Set to `true` for transactions with documents or `false` for transactions without documents. schema: type: boolean - name: q in: query description: Search transaction descriptions. schema: type: string responses: '200': description: Totals for matching transactions. content: application/json: schema: $ref: '#/components/schemas/TransactionStats' example: total: 142 amount: amount: 9381200 currency: USD '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /transactions/bulk: post: operationId: transactions_createBulk tags: - Transactions summary: Create manual transactions in bulk description: Creates up to 500 manual transactions in one request. If any transaction fails, none are created. Requires an `Idempotency-Key`. parameters: - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key with the same body returns the first result. Reusing it with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransactionBulkCreate' example: transactions: - type: Cash amount: amount: 2500 currency: USD timestamp: '2026-05-18T00:00:00.000Z' description: Petty cash - craft services - type: Check amount: amount: 120000 currency: USD timestamp: '2026-05-19T00:00:00.000Z' description: Location fee budgetLineId: bud_locations responses: '201': description: The created transactions. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/TransactionCollection' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '413': $ref: '#/components/responses/Error413' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /transactions/{transactionId}: get: operationId: transactions_get tags: - Transactions summary: Get a transaction description: Returns a transaction you can access. Otherwise returns `404 not_found`. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/transactionExpand' responses: '200': description: The transaction. content: application/json: schema: $ref: '#/components/schemas/Transaction' example: id: txn_8f2a1c9e source: saturation_credit sourceId: scx_771 type: CreditCard status: posted isReversal: true amount: amount: -4500 currency: USD currency: USD timestamp: '2026-05-21T10:00:00.000Z' description: Refund - duplicate charge merchant: B&H Photo sourceLast4: '4242' projectId: prj_films budgetLineId: bud_camera isItemized: false createdAt: '2026-05-21T10:02:00.000Z' updatedAt: '2026-05-21T10:02:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: transactions_update tags: - Transactions summary: Update a transaction description: Updates a transaction. Financial fields can be changed only on manual transactions. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransactionPatch' example: budgetLineId: bud_camera notes: Re-coded to camera package responses: '200': description: The updated transaction. content: application/json: schema: $ref: '#/components/schemas/Transaction' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: transactions_delete tags: - Transactions summary: Delete a manual transaction description: Deletes a manual transaction. Other transaction sources return `409`. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Transaction deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /transactions/{transactionId}/items: get: operationId: transactions_listItems tags: - Transactions summary: List transaction items description: Returns the items in a transaction. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' responses: '200': description: The items. content: application/json: schema: $ref: '#/components/schemas/TransactionItemCollection' example: data: - id: txi_4a1b2c3d lineNumber: '1' description: Camera body - 3 days budgetLineId: bud_camera qty: 3 unit: Day rate: amount: 25000 currency: USD amount: amount: 75000 currency: USD '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: transactions_createItem tags: - Transactions summary: Add a transaction item description: Adds an item to a transaction. Adding the first item moves budget coding from the transaction to its items. Requires an `Idempotency-Key`. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' - name: Idempotency-Key in: header required: true description: A unique 16-255 character key. Reusing the key with the same body returns the first result. Reusing it with a different body returns `409 idempotency_conflict`. schema: type: string minLength: 16 maxLength: 255 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransactionItemCreate' example: description: Lens kit - 3 days budgetLineId: bud_camera qty: 3 unit: Day rate: amount: 8000 currency: USD amount: amount: 24000 currency: USD responses: '201': description: The created item. headers: Idempotency-Replayed: $ref: '#/components/headers/IdempotencyReplayed' content: application/json: schema: $ref: '#/components/schemas/TransactionItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /transactions/{transactionId}/items/{itemId}: patch: operationId: transactions_updateItem tags: - Transactions summary: Update a transaction item description: Updates a transaction item. Read-only fields return `422 field_read_only`. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true description: Transaction item ID. schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TransactionItemPatch' example: qty: 4 amount: amount: 32000 currency: USD responses: '200': description: The updated item. content: application/json: schema: $ref: '#/components/schemas/TransactionItem' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: transactions_deleteItem tags: - Transactions summary: Delete a transaction item description: Deletes a transaction item. Deleting the last item marks the transaction as not itemized. parameters: - name: transactionId in: path required: true description: Transaction ID. schema: $ref: '#/components/schemas/Id' - name: itemId in: path required: true description: Transaction item ID. schema: $ref: '#/components/schemas/Id' responses: '204': description: Item deleted. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /webhooks: get: operationId: webhooks_list summary: List webhook subscriptions description: Returns webhook subscriptions. Filter by event type or active state. tags: - Webhook Subscriptions parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - name: order in: query required: false description: Sort direction. schema: type: string enum: - asc - desc default: asc - $ref: '#/components/parameters/withCount' - name: events in: query required: false description: Only subscriptions that include at least one of these comma-separated event types. schema: type: array items: $ref: '#/components/schemas/WebhookEvent' style: form explode: false - name: active in: query required: false description: Filter by whether the subscription is currently delivering (`isActive`). schema: type: boolean responses: '200': description: A page of webhook subscriptions. content: application/json: schema: $ref: '#/components/schemas/WebhookCollection' example: data: - id: whk_5c1a9e02 url: https://hooks.example.com/saturation events: - transaction.created - budget.changed isActive: true workspaceId: ws_1a2b3c4d createdAt: '2026-05-28T12:00:00.000Z' updatedAt: '2026-05-28T12:00:00.000Z' nextCursor: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' post: operationId: webhooks_create summary: Create a webhook subscription description: Creates a webhook subscription. The URL must use HTTPS and resolve to a public address. If `secret` is omitted, the response includes a generated secret once. tags: - Webhook Subscriptions requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookCreate' example: url: https://hooks.example.com/saturation events: - transaction.created - transaction.updated - budget.changed responses: '201': description: The created subscription and its signing secret. Store the secret before discarding the response. content: application/json: schema: $ref: '#/components/schemas/WebhookWithSecret' example: id: whk_5c1a9e02 url: https://hooks.example.com/saturation events: - transaction.created - transaction.updated - budget.changed isActive: true workspaceId: ws_1a2b3c4d secret: whsec_example createdAt: '2026-05-28T12:00:00.000Z' updatedAt: '2026-05-28T12:00:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' /webhooks/{webhookId}: get: operationId: webhooks_get summary: Get a webhook subscription description: Returns one webhook subscription. tags: - Webhook Subscriptions parameters: - name: webhookId in: path required: true description: "Webhook subscription identifier (`whk_\u2026`)." schema: $ref: '#/components/schemas/Id' responses: '200': description: The webhook subscription. content: application/json: schema: $ref: '#/components/schemas/Webhook' example: id: whk_5c1a9e02 url: https://hooks.example.com/saturation events: - transaction.created - budget.changed isActive: true workspaceId: ws_1a2b3c4d createdAt: '2026-05-28T12:00:00.000Z' updatedAt: '2026-05-28T12:00:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' patch: operationId: webhooks_update summary: Update a webhook subscription description: Updates the destination, event types, or active state. tags: - Webhook Subscriptions parameters: - name: webhookId in: path required: true description: "Webhook subscription identifier (`whk_\u2026`)." schema: $ref: '#/components/schemas/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookUpdate' example: events: - transaction.created - purchaseOrder.approved isActive: false responses: '200': description: The updated webhook subscription. content: application/json: schema: $ref: '#/components/schemas/Webhook' example: id: whk_5c1a9e02 url: https://hooks.example.com/saturation events: - transaction.created - purchaseOrder.approved isActive: false workspaceId: ws_1a2b3c4d createdAt: '2026-05-28T12:00:00.000Z' updatedAt: '2026-05-28T13:30:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '422': $ref: '#/components/responses/Error422' '429': $ref: '#/components/responses/Error429' delete: operationId: webhooks_delete summary: Delete a webhook subscription description: Deletes the subscription. Repeating the request returns `204`. tags: - Webhook Subscriptions parameters: - name: webhookId in: path required: true description: "Webhook subscription identifier (`whk_\u2026`)." schema: $ref: '#/components/schemas/Id' responses: '204': description: Deleted. No content. '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' /webhooks/{webhookId}/test-delivery: post: operationId: webhooks_sendTestDelivery summary: Send a test delivery description: Sends a signed test event and records the delivery attempt. tags: - Webhook Subscriptions parameters: - name: webhookId in: path required: true description: "Webhook subscription identifier (`whk_\u2026`)." schema: $ref: '#/components/schemas/Id' responses: '202': description: The queued test delivery. content: application/json: schema: $ref: '#/components/schemas/WebhookDelivery' example: id: whd_9a02c1e5 event: ping status: pending entityKind: ping entityId: whk_5c1a9e02 requestUrl: https://hooks.example.com/saturation attempts: 1 occurredAt: '2026-05-28T14:00:00.000Z' '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '409': $ref: '#/components/responses/Error409' '429': $ref: '#/components/responses/Error429' /webhooks/{webhookId}/deliveries: get: operationId: webhooks_listDeliveries summary: List recent deliveries description: Returns delivery attempts, newest first. Filter by status, event type, or time. tags: - Webhook Subscriptions parameters: - name: webhookId in: path required: true description: "Webhook subscription identifier (`whk_\u2026`)." schema: $ref: '#/components/schemas/Id' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/cursor' - name: order in: query required: false description: Sort direction. schema: type: string enum: - asc - desc default: desc - $ref: '#/components/parameters/withCount' - name: status in: query required: false description: Only deliveries with this attempt outcome. schema: $ref: '#/components/schemas/WebhookDeliveryStatus' - name: event in: query required: false description: Only deliveries for this event type. schema: $ref: '#/components/schemas/WebhookEvent' - name: since in: query required: false description: Only deliveries that occurred at or after this ISO-8601 timestamp. An end before the start (when paired with sort bounds) returns `400 invalid_date_range`. schema: type: string format: date-time responses: '200': description: A page of delivery attempts. content: application/json: schema: $ref: '#/components/schemas/WebhookDeliveryCollection' example: data: - id: whd_9a02c1e5 event: transaction.created status: success entityKind: transaction entityId: txn_8f2a1c9e requestUrl: https://hooks.example.com/saturation responseStatus: 200 attempts: 1 occurredAt: '2026-05-28T14:00:00.000Z' deliveredAt: '2026-05-28T14:00:00.420Z' nextCursor: null '400': $ref: '#/components/responses/Error400' '401': $ref: '#/components/responses/Error401' '403': $ref: '#/components/responses/Error403' '404': $ref: '#/components/responses/Error404' '429': $ref: '#/components/responses/Error429' webhooks: saturationEvent: post: operationId: webhooks_receiveEvent summary: Receive a Saturation event description: Saturation sends this request to a webhook subscription URL. security: [] parameters: - name: X-Saturation-Signature in: header required: true schema: type: string - name: X-Saturation-Timestamp in: header required: true schema: type: string format: date-time - name: X-Saturation-Delivery-Id in: header required: true schema: $ref: '#/components/schemas/Id' - name: X-Saturation-Event in: header required: true schema: $ref: '#/components/schemas/WebhookDeliveryEvent' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookEventPayload' responses: '200': description: Event accepted. components: headers: IdempotencyReplayed: description: Present when this response was replayed from an earlier request with the same `Idempotency-Key`. schema: type: string const: 'true' securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: Personal API token sent as `Bearer `. Each token belongs to one workspace. parameters: projectId: name: projectId in: path required: true description: Project ID or slug. schema: type: string limit: name: limit in: query required: false description: Maximum number of items to return on a page. Capped at 100. schema: type: integer minimum: 1 maximum: 100 default: 50 cursor: name: cursor in: query required: false description: Cursor from the previous page's `nextCursor`. Use it with the same filters and sort. schema: type: string sort: name: sort in: query required: false description: Field to sort by. Allowed fields depend on the resource. schema: type: string order: name: order in: query required: false description: Sort direction. schema: type: string enum: - asc - desc default: asc transactionSort: name: sort in: query required: false description: Field to sort the transactions list by. A non-unique field appends `,id` as the tiebreaker. Defaults to `timestamp` `desc`. schema: $ref: '#/components/schemas/TransactionSortField' purchaseOrderSort: name: sort in: query required: false description: Field to sort the purchase-order list by. A non-unique field appends `,id` as the tiebreaker. schema: $ref: '#/components/schemas/PurchaseOrderSort' transactionExpand: name: expand in: query required: false description: "Comma list of related data to inline on transactions (depth \u2264 2). Unknown or too-deep key returns\ \ `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/TransactionExpandKey' style: form explode: false purchaseOrderExpand: name: expand in: query required: false description: "Comma list of related data to inline on a purchase order (depth \u2264 2). Unknown key returns `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/PurchaseOrderExpand' style: form explode: false contactExpand: name: expand in: query required: false description: "Comma list of related data to inline on contacts (depth \u2264 2). Unknown key returns `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/ContactExpand' style: form explode: false projectExpand: name: expand in: query required: false description: "Comma list of related data to inline on projects (depth \u2264 2). Unknown key returns `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/ProjectExpand' style: form explode: false budgetLineExpand: name: expand in: query required: false description: "Comma list of related data to inline on budget lines (depth \u2264 2). Unknown or too-deep key returns\ \ `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/BudgetLineExpand' style: form explode: false libraryExpand: name: expand in: query required: false description: "Comma list of related data to inline on a project copy (depth \u2264 2). Unknown key returns `400 expand_invalid`." schema: type: array items: $ref: '#/components/schemas/LibraryExpand' style: form explode: false projectIncentiveExpand: name: expand in: query required: false description: "Comma list of related data to inline on a project incentive (depth \u2264 2). Unknown key returns `400\ \ expand_invalid`." schema: type: array items: $ref: '#/components/schemas/ProjectIncentiveExpand' style: form explode: false ratePackExpand: name: expand in: query required: false description: Comma list of related data to inline on a workspace-source rate pack. Unknown key returns `400 expand_invalid`. schema: type: array items: $ref: '#/components/schemas/RatePackExpand' style: form explode: false incentivePackExpand: name: expand in: query required: false description: Comma list of related data to inline on a workspace-source incentive pack. Unknown key returns `400 expand_invalid`. schema: type: array items: $ref: '#/components/schemas/IncentivePackExpand' style: form explode: false withCount: name: withCount in: query required: false description: Include the total number of matching items. Defaults to `false`. schema: type: boolean default: false responses: Error400: description: The request is invalid. content: application/json: schema: $ref: '#/components/schemas/Error' Error401: description: Unauthenticated, `unauthenticated`, `invalid_token`, `missing_authorization` or `token_revoked` (expired, malformed, missing or revoked credentials). content: application/json: schema: $ref: '#/components/schemas/Error' Error402: description: This feature is not available on the workspace plan. content: application/json: schema: $ref: '#/components/schemas/Error' Error403: description: Forbidden. The token does not allow this action. content: application/json: schema: $ref: '#/components/schemas/Error' Error404: description: Not found or unavailable to the token. content: application/json: schema: $ref: '#/components/schemas/Error' Error409: description: The request conflicts with the current resource state. content: application/json: schema: $ref: '#/components/schemas/Error' Error413: description: Payload / result too large, `budget_too_large` or `bulk_too_large`. content: application/json: schema: $ref: '#/components/schemas/Error' Error422: description: The request names a read-only field or cannot be processed. content: application/json: schema: $ref: '#/components/schemas/Error' Error423: description: The workspace is temporarily locked. content: application/json: schema: $ref: '#/components/schemas/Error' Error429: description: Rate limited. See `Retry-After` before retrying. headers: Retry-After: description: Seconds to wait before retrying. schema: type: integer content: application/json: schema: $ref: '#/components/schemas/Error' Error503: description: The service needed to complete this request is unavailable. content: application/json: schema: $ref: '#/components/schemas/Error' Error504: description: Budget calculation timed out. The request may be retried. content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Id: type: string description: "A stable resource ID, such as `prj_\u2026`, `txn_\u2026`, or `doc_\u2026`." examples: - txn_8f2a1c9e PublicResourceRef: type: object description: A reference to another resource. required: - type - id additionalProperties: false properties: type: type: string enum: - document - payment_request - payment - transaction - approval id: $ref: '#/components/schemas/Id' ErrorCode: type: string description: Error code for programmatic handling. enum: - unauthenticated - invalid_token - missing_authorization - token_revoked - permission_revoked - scope_exceeded - forbidden - feature_not_available - upgrade_required - capacity_exceeded - approval_required - resource_locked - temporarily_unavailable - role_ceiling_exceeded - api_access_disabled - not_found - document_target_not_found - validation - cursor_invalid - expand_invalid - invalid_date_range - webhook_https_required - range_too_large - account_path_ambiguous - account_code_ambiguous - budget_compute_stale - idempotency_conflict - already_linked - status_unreachable_for_source - po_invalid_status - webhook_url_invalid_ssrf - phase_copy_unsupported - field_read_only - scenario_too_large - source_not_postable - webhook_url_blocked - budget_too_large - bulk_too_large - rate_limited - signing_key_not_configured - internal_error - budget_compute_timeout Error: type: object description: 'The uniform error envelope. Only errors carry `success: false`; success responses are the bare resource or a `{ data, nextCursor? }` collection.' required: - success - code - message - requestId additionalProperties: false properties: success: type: boolean const: false description: Always `false`. Present only on errors. code: $ref: '#/components/schemas/ErrorCode' message: type: string description: Human-readable description of the failure. requestId: type: string description: Request ID for support and troubleshooting. examples: - req_3f9b2a7c fieldErrors: type: object description: Validation messages keyed by input field. additionalProperties: type: array items: type: string requiredAbility: type: string description: Permission required for the action, such as `update:Transaction`. retryAfter: type: integer description: Seconds to wait before retrying. accessDecision: $ref: '#/components/schemas/ProductAccessDecision' description: Product-access details when the operation is unavailable. ProductAccessDecision: type: object description: Explains why a product feature is unavailable and how to resolve it. required: - operationId - allowed - state - primary - remediations - resolvingPlanId additionalProperties: false properties: operationId: type: string minLength: 1 allowed: type: boolean state: type: string enum: - allowed - warning - denied - indeterminate primary: type: - object - 'null' additionalProperties: false required: - kind - status - reason properties: kind: type: string enum: - principal - authority - policy - rollout - provider - entitlement - quota status: type: string enum: - warning - denied - indeterminate reason: type: string enum: - principal_unauthenticated - principal_expired - principal_suspended - resource_unreachable - permission_denied - resource_locked - approval_required - safety_restricted - rollout_disabled - delivery_unavailable - provider_unavailable - provider_ineligible - legal_restricted - plan_excluded - contract_restricted - subscription_restricted - quota_warning - quota_exhausted - quota_unknown - quota_reservation_required - dependency_unknown quotaId: type: string minLength: 1 usage: type: integer minimum: 0 limit: type: integer minimum: 0 remediations: type: array items: type: string enum: - self_serve_upgrade - contact_billing_owner - contact_sales - buy_capacity - cleanup - authenticate - request_access - resolve_policy - wait_for_rollout - resolve_provider - recover_payment - reactivate_subscription - contact_support - renew_link currentPlanId: type: string enum: - free - pro - team - enterprise resolvingPlanId: type: - string - 'null' enum: - free - pro - team - enterprise - null correlationId: type: string minLength: 1 Money: type: object description: An amount in integer minor units and its ISO-4217 currency. required: - amount - currency additionalProperties: false properties: amount: type: integer format: int64 description: Amount in the currency's smallest unit, such as cents. May be negative. examples: - 152900 currency: type: string description: ISO-4217 currency code. minLength: 3 maxLength: 3 examples: - USD NextCursor: type: - string - 'null' description: Cursor for the next page. Pass it as `cursor` with the same filters and sort. Null on the last page. examples: - eyJpZCI6InR4bl84ZjJhMWM5ZSJ9 - null PhaseType: type: string description: The phase type. enum: - estimate - actual - rollup - committed examples: - estimate BudgetLineType: type: string description: The budget line type. enum: - account - line - subtotal - fringe - markup - credit - banner ComputedLineType: type: string description: The budget line types included in a budget document. enum: - account - line - credit - fringe BudgetLineExpand: type: string description: A related resource to include with a budget line. Pass multiple values as a comma-separated list. The maximum depth is 2. enum: - phaseTotals - phaseData - contact BudgetLineContactRef: type: object description: Contact details included with a budget line. required: - id - displayName - name - company - email - type additionalProperties: false properties: id: $ref: '#/components/schemas/Id' displayName: type: string name: type: - string - 'null' company: type: - string - 'null' email: type: - string - 'null' type: type: - string - 'null' TagMode: type: string description: How multiple tag filters are combined. `any` matches at least one tag, `all` matches every tag, and `none` excludes matching tags. enum: - any - all - none default: any FringeBreakdownEntry: type: object description: One fringe included in a phase total. required: - id - name - amount additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string description: The fringe name. amount: type: integer format: int64 description: The fringe amount in the workspace currency's minor units. PhaseValues: type: object description: Totals for one budget line and phase. Amounts use the workspace currency's minor units. `amount` and `combined` are equal. required: - base - overtime - fringe - fringeBreakdown - amount - combined - currency additionalProperties: false properties: base: type: integer format: int64 description: The amount before overtime and fringes, in minor units. overtime: type: integer format: int64 description: The overtime amount in minor units. fringe: type: integer format: int64 description: The total fringe amount in minor units. fringeBreakdown: type: array description: The fringes included in `fringe`. items: $ref: '#/components/schemas/FringeBreakdownEntry' amount: type: integer format: int64 description: The total amount in minor units. combined: type: integer format: int64 description: The total after overtime, fringes, and credits. Equal to `amount`. currency: type: string description: The workspace currency as an ISO 4217 code. minLength: 3 maxLength: 3 examples: - USD examples: - base: 1000000 overtime: 0 fringe: 220000 fringeBreakdown: - id: frg_pension name: Pension amount: 220000 amount: 1220000 combined: 1220000 currency: USD BudgetPhase: type: object description: A phase column in the budget. required: - id - type - name - sort - isHidden additionalProperties: false properties: id: $ref: '#/components/schemas/Id' type: $ref: '#/components/schemas/PhaseType' name: type: string description: The phase name. alias: type: - string - 'null' description: A short name for the phase column. color: type: - string - 'null' description: The phase color. sort: type: integer description: The phase's display order. isHidden: type: boolean description: Whether the phase is hidden. displayDecimals: type: - integer - 'null' minimum: 0 maximum: 4 description: Decimal places shown for phase amounts. Null uses the currency default. baseCurrencyId: description: The phase currency. Used by estimate, actual, and rollup phases. oneOf: - $ref: '#/components/schemas/Id' - type: 'null' actualDateStart: type: - string - 'null' format: date actualDateEnd: type: - string - 'null' format: date actualStatuses: type: - array - 'null' items: type: string actualSourceTypes: type: - array - 'null' description: Sources included in an actual phase. Manual transactions use `manual`. items: type: string actualCurrencies: type: - array - 'null' items: type: string minLength: 3 maxLength: 3 actualContactId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' actualTagIds: type: array items: $ref: '#/components/schemas/Id' actualBudgetLineIds: type: - array - 'null' items: $ref: '#/components/schemas/Id' estimateTagIds: type: array items: $ref: '#/components/schemas/Id' overtimeFactors: type: array items: type: string enum: - qty - x committedDateStart: type: - string - 'null' format: date committedDateEnd: type: - string - 'null' format: date committedContactId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' committedPhaseIds: type: array items: $ref: '#/components/schemas/Id' committedPoStatuses: type: array items: type: string enum: - approved - paymentRequested - paymentRejected - paymentProcessing rollupFormula: type: - string - 'null' description: The formula for a rollup phase. rollupDisplayMode: type: - string - 'null' enum: - value - percent - bars - margin - null examples: - id: phs_estimate type: estimate name: Estimate alias: EST color: blue sort: 0 isHidden: false BudgetLine: type: object description: A budget line. Related data appears when requested with `expand`. required: - id - type - description - parentId - sort additionalProperties: false properties: id: $ref: '#/components/schemas/Id' accountId: type: - string - 'null' description: The account number. It does not need to be unique. examples: - '1100' path: type: - string - 'null' description: The account path, such as `1100/1110`. examples: - 1100/1110 type: $ref: '#/components/schemas/BudgetLineType' description: type: string description: The line description. parentId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' depth: type: integer description: The line's depth in the account tree. Root accounts have depth 0. sort: type: integer description: The display order among lines with the same parent. contactId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' lineColor: type: - string - 'null' description: The line color. emoji: type: - string - 'null' notes: type: - string - 'null' description: A plain-text note on the line. tagIds: type: array description: The IDs of tags on this line. items: $ref: '#/components/schemas/Id' subtotalSumAllAbove: type: boolean description: For a `subtotal` line, whether to include every preceding line. subtotalIsBold: type: boolean markupAccountFilter: type: - string - 'null' description: For a `markup` line, the accounts included in the markup. contact: description: The contact. Included with `expand=contact`. oneOf: - $ref: '#/components/schemas/BudgetLineContactRef' - type: 'null' phaseTotals: type: object description: Totals keyed by phase ID. Included with `expand=phaseTotals`. additionalProperties: $ref: '#/components/schemas/PhaseValues' phaseData: type: object description: Editable phase data keyed by phase ID. Included with `expand=phaseData`. additionalProperties: $ref: '#/components/schemas/BudgetDocumentLinePhaseData' examples: - id: lin_7c1a2f accountId: '1100' path: '1100' type: account description: Camera parentId: lin_root depth: 0 sort: 0 contactId: null tagIds: - tag_vfx sourceId: null BudgetLineCreate: type: object description: Details for a new budget line. required: - description additionalProperties: false properties: description: type: string maxLength: 255 description: The line description. type: $ref: '#/components/schemas/BudgetLineType' accountId: type: string description: The account number. It does not need to be unique. parentId: $ref: '#/components/schemas/Id' contactId: $ref: '#/components/schemas/Id' lineColor: type: string emoji: type: string notes: type: string subtotalSumAllAbove: type: boolean subtotalIsBold: type: boolean markupAccountFilter: type: string phaseData: type: object description: Optional initial editable phase data keyed by phase id. additionalProperties: $ref: '#/components/schemas/BudgetLinePhaseDataWrite' examples: - description: Camera Package type: line accountId: '1110' parentId: lin_7c1a2f contactId: con_panavision phaseData: phs_estimate: rate: 25000 quantity: 4 multiplier: 1 BudgetLineUpdate: type: object description: Changes to a budget line. additionalProperties: false minProperties: 1 properties: description: type: string maxLength: 255 type: $ref: '#/components/schemas/BudgetLineType' accountId: type: string parentId: $ref: '#/components/schemas/Id' contactId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' lineColor: type: - string - 'null' emoji: type: - string - 'null' notes: type: - string - 'null' subtotalSumAllAbove: type: boolean subtotalIsBold: type: boolean markupAccountFilter: type: - string - 'null' phaseData: type: object description: Upsert editable phase data keyed by phase id. Omitted fields are left unchanged. additionalProperties: $ref: '#/components/schemas/BudgetLinePhaseDataWrite' examples: - description: Camera Package (A-cam) notes: Confirmed with vendor 5/12 BudgetDocumentPhaseDataValue: description: A phase value. Formulas and variable references remain strings. A missing value is null. type: - number - string - 'null' BudgetDocumentOvertime: type: - object - 'null' additionalProperties: false properties: mode: type: - string - 'null' flatAmount: type: - number - 'null' hours: type: - number - 'null' baseHours: type: - number - 'null' multipliers: description: Overtime multipliers. detail: description: Overtime details. BudgetDocumentLinePhaseData: type: object description: Editable data for one budget line and phase. required: - rate - quantity - multiplier - qtyAutoDerived - unit - customUnitId - unitLabel - startDate - endDate - fringeIds - fringeGroupIds - currencyId - overtime additionalProperties: false properties: rate: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' quantity: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' multiplier: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' qtyAutoDerived: type: boolean unit: type: - string - 'null' customUnitId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' unitLabel: type: - string - 'null' startDate: type: - string - 'null' endDate: type: - string - 'null' fringeIds: type: array items: $ref: '#/components/schemas/Id' fringeGroupIds: type: array items: $ref: '#/components/schemas/Id' currencyId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' overtime: $ref: '#/components/schemas/BudgetDocumentOvertime' BudgetLinePhaseDataWrite: type: object description: Changes to one budget line and phase. Omitted fields remain unchanged. additionalProperties: false properties: rate: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' quantity: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' multiplier: $ref: '#/components/schemas/BudgetDocumentPhaseDataValue' qtyAutoDerived: type: - boolean - 'null' unit: type: - string - 'null' customUnitId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' startDate: type: - string - 'null' endDate: type: - string - 'null' fringeIds: oneOf: - type: array items: $ref: '#/components/schemas/Id' - type: 'null' fringeGroupIds: oneOf: - type: array items: $ref: '#/components/schemas/Id' - type: 'null' currencyId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' overtime: $ref: '#/components/schemas/BudgetDocumentOvertime' BudgetLinePhaseDataUpsert: allOf: - $ref: '#/components/schemas/BudgetLinePhaseDataWrite' BudgetLinePhaseDataUpsertResponse: type: object required: - lineId - phaseId - phaseData additionalProperties: false properties: lineId: $ref: '#/components/schemas/Id' phaseId: $ref: '#/components/schemas/Id' phaseData: $ref: '#/components/schemas/BudgetDocumentLinePhaseData' BudgetLineBulkCreate: type: object required: - lines additionalProperties: false properties: lines: type: array minItems: 1 maxItems: 100 items: $ref: '#/components/schemas/BudgetLineCreate' BudgetLineBulkCreateResponse: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/BudgetLine' BudgetLinePhaseDataBulkUpsert: type: object required: - items additionalProperties: false properties: items: type: array minItems: 1 maxItems: 500 items: type: object required: - lineId - phaseId - phaseData additionalProperties: false properties: lineId: $ref: '#/components/schemas/Id' phaseId: $ref: '#/components/schemas/Id' phaseData: $ref: '#/components/schemas/BudgetLinePhaseDataWrite' BudgetLinePhaseDataBulkUpsertResponse: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/BudgetLinePhaseDataUpsertResponse' BudgetDocumentPhaseValues: type: object description: Totals for one phase. Amounts use the workspace currency's minor units. required: - base - overtime - fringe - fringeBreakdown - amount - currency additionalProperties: false properties: base: type: integer format: int64 overtime: type: integer format: int64 fringe: type: integer format: int64 fringeBreakdown: type: array items: $ref: '#/components/schemas/FringeBreakdownEntry' amount: type: integer format: int64 currency: type: string minLength: 3 maxLength: 3 BudgetDocumentSelection: type: object description: The filters applied to the budget document. additionalProperties: false properties: path: type: string accountId: type: string phase: type: string BudgetDocumentLine: type: object description: A budget line with totals and editable phase data. required: - id - description - parentId - depth - type - values - phaseData additionalProperties: false properties: id: $ref: '#/components/schemas/Id' accountId: type: - string - 'null' description: type: string parentId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' path: type: - string - 'null' depth: type: integer type: $ref: '#/components/schemas/ComputedLineType' values: type: object additionalProperties: $ref: '#/components/schemas/BudgetDocumentPhaseValues' phaseData: type: object additionalProperties: $ref: '#/components/schemas/BudgetDocumentLinePhaseData' BudgetDocument: type: object description: The budget's visible phases, totals, lines, and editable phase data. required: - id - computedAt - selection - phases - totals - lines additionalProperties: false properties: id: allOf: - $ref: '#/components/schemas/Id' description: The budget ID. computedAt: type: string format: date-time selection: $ref: '#/components/schemas/BudgetDocumentSelection' phases: type: array items: $ref: '#/components/schemas/BudgetPhase' totals: type: object description: Totals keyed by visible phase ID. additionalProperties: $ref: '#/components/schemas/BudgetDocumentPhaseValues' lines: type: array description: Budget lines in flat order. Use `parentId` to build the tree. items: $ref: '#/components/schemas/BudgetDocumentLine' BudgetTotals: type: object description: Budget totals at `computedAt`, optionally filtered by phase or account. required: - computedAt - totals additionalProperties: false properties: computedAt: type: string format: date-time totals: type: object description: Totals keyed by phase ID. additionalProperties: $ref: '#/components/schemas/PhaseValues' filter: type: object description: The filters applied to these totals. additionalProperties: false properties: phase: type: string accountId: type: string path: type: string examples: - computedAt: '2026-05-28T18:04:11Z' totals: phs_estimate: base: 1000000 overtime: 0 fringe: 220000 fringeBreakdown: [] amount: 1220000 combined: 1220000 currency: USD DocumentTargetKind: type: string description: The type of entity linked to a document. A document can have one link of each kind. enum: - project - contact - transaction - payment - purchaseOrder - budgetLine - paymentRequest examples: - transaction DocumentWritableTargetKind: type: string description: A target callers can link directly. Payment-request links are managed by approvals. enum: - project - contact - transaction - payment - purchaseOrder - budgetLine DocumentStatus: type: string description: The document's extraction status. `ready` means extracted data is available. enum: - pending - processing - ready - failed examples: - ready DocumentCoarseType: type: string description: The document category found during extraction. enum: - financial - tax - legal - insurance - production - other examples: - financial DocumentTargetRef: type: object description: An entity linked to a document. required: - kind - id additionalProperties: false properties: kind: $ref: '#/components/schemas/DocumentTargetKind' id: allOf: - $ref: '#/components/schemas/Id' description: The linked entity's ID. Its prefix must match `kind`. phaseId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: The phase for a budget-line link. examples: - kind: transaction id: txn_8f2a1c9e Document: type: object description: An uploaded document and its links. required: - id - name - mimeType - size - status - workspaceId - links - createdAt - updatedAt additionalProperties: false properties: id: allOf: - $ref: '#/components/schemas/Id' description: The document ID. name: type: string description: The document's display name. mimeType: type: string description: The file's MIME type. examples: - application/pdf size: type: integer format: int64 description: The file size in bytes. examples: - 184320 status: $ref: '#/components/schemas/DocumentStatus' workspaceId: allOf: - $ref: '#/components/schemas/Id' description: The workspace ID. pageCount: type: - integer - 'null' description: The number of pages, or null until extraction finishes. classification: type: - string - 'null' description: The document classification, such as `invoice` or `receipt`. coarseType: description: The document category, or null until classification finishes. anyOf: - allOf: - $ref: '#/components/schemas/DocumentCoarseType' - type: 'null' hasSensitiveInfo: type: - boolean - 'null' description: Whether the document may contain sensitive information. description: type: - string - 'null' description: The document description. source: type: - string - 'null' description: How the document was added, such as `api`, `agent`, or `upload`. folderId: description: The folder ID, or null for the workspace root. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' projectId: description: The project ID, or null for a workspace document. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' contentHash: type: - string - 'null' description: A hash of the file contents. links: type: array description: The entities linked to this document. items: $ref: '#/components/schemas/DocumentTargetRef' createdAt: type: string format: date-time description: When the document was created. updatedAt: type: string format: date-time description: When the document was last updated. examples: - id: doc_4b1f0a7c name: vendor-invoice-0425.pdf mimeType: application/pdf size: 184320 status: ready workspaceId: ws_71aa pageCount: 2 classification: invoice coarseType: financial folderId: fld_9c2d projectId: prj_71aa links: - kind: transaction id: txn_8f2a1c9e createdAt: '2026-05-28T14:03:11Z' updatedAt: '2026-05-28T14:03:40Z' DocumentExtractedField: type: object description: A field extracted from a document. required: - value additionalProperties: false properties: value: type: - string - 'null' description: The extracted value. Money uses decimal strings and dates use ISO 8601. Null means no value was found. confidence: type: - number - 'null' description: Confidence from 0 to 1, or null when unavailable. minimum: 0 maximum: 1 examples: - value: B&H Photo confidence: 0.95 DocumentExtractedLineItem: type: object description: A line item extracted from a document. additionalProperties: false properties: description: type: - string - 'null' amount: description: The extracted line amount. anyOf: - allOf: - $ref: '#/components/schemas/Money' - type: 'null' confidence: type: - number - 'null' description: Confidence from 0 to 1, or null when unavailable. minimum: 0 maximum: 1 DocumentExtraction: type: object description: Data extracted from a document. Available when the document status is `ready`. required: - documentId - status - fields additionalProperties: false properties: documentId: allOf: - $ref: '#/components/schemas/Id' description: The document ID. status: $ref: '#/components/schemas/DocumentStatus' classification: type: - string - 'null' description: The document classification, such as `invoice` or `receipt`. coarseType: description: The document category. anyOf: - allOf: - $ref: '#/components/schemas/DocumentCoarseType' - type: 'null' extractedAt: type: - string - 'null' format: date-time description: When extraction finished, or null while unavailable. fields: type: object description: Extracted values and confidence scores keyed by field name. Keys vary by classification. additionalProperties: $ref: '#/components/schemas/DocumentExtractedField' lineItems: type: array description: Extracted line items, when available. items: $ref: '#/components/schemas/DocumentExtractedLineItem' examples: - documentId: doc_4b1f0a7c status: ready classification: invoice coarseType: financial extractedAt: '2026-05-28T14:03:40Z' fields: invoiceNumber: value: '4471' confidence: 0.98 total: value: '1529.00' confidence: 0.91 lineItems: - description: Camera body rental - 3 days amount: amount: 75000 currency: USD confidence: 0.86 DocumentCollection: type: object description: A page of documents. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Document' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total results when `withCount=true`. truncated: type: boolean description: Whether the page ended before `limit` because some results were unavailable. DocumentLinkRequest: type: object description: Links a document to an entity. required: - targetId additionalProperties: false properties: targetId: $ref: '#/components/schemas/Id' phaseId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: The phase for a budget-line link. replace: type: boolean default: false description: Replace the existing link of this kind. DocumentCreateRequest: type: object description: A multipart upload with a file and optional JSON-serialized metadata. required: - file additionalProperties: false properties: file: type: string format: binary description: The file to upload. metadata: type: string description: JSON-serialized `DocumentCreateMetadata`. examples: - '{"name":"vendor-invoice-0425.pdf","links":{"kind":"transaction","id":"txn_8f2a1c9e"}}' DocumentUpdateRequest: type: object description: Changes a document's name, description, or folder. additionalProperties: false minProperties: 1 properties: name: type: string description: The new display name. description: type: - string - 'null' description: The new description, or null to clear it. folderId: description: The new folder ID, or null for the workspace root. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' examples: - name: vendor-invoice-april.pdf folderId: fld_9c2d PackVisibility: type: string description: Who can access the pack. Public packs are available to every workspace; private packs belong to one workspace. enum: - public - private - shared TagColor: type: - string - 'null' description: Display color for a tag, or `null` for the default color. enum: - slate - gray - zinc - red - orange - amber - yellow - lime - green - emerald - teal - cyan - sky - blue - indigo - violet - purple - pink - rose - null SourceType: type: string description: Where the project Library item came from. enum: - workspace - saturation SourceTombstone: type: object description: Identifies a deleted Library source when `expand=source` is requested. required: - id - deleted additionalProperties: false properties: id: $ref: '#/components/schemas/Id' deleted: type: boolean const: true LibraryExpand: type: string description: Related data to include with a project Library item. enum: - source ProjectIncentiveExpand: type: string description: Related data to include with a project incentive. enum: - source RatePackExpand: type: string description: Related data to include with a rate pack. enum: - items IncentivePackExpand: type: string description: Related data to include with an incentive pack. enum: - programs RatePackVersionRef: type: object description: Current rate pack version. additionalProperties: false properties: id: $ref: '#/components/schemas/Id' effectiveDate: type: - string - 'null' format: date itemCount: type: integer description: Count of non-blank items in the latest version. RatePack: type: object description: A public or workspace-owned rate pack. additionalProperties: false properties: id: $ref: '#/components/schemas/Id' slug: type: string name: type: string description: type: - string - 'null' publisher: type: - string - 'null' category: type: string tags: type: array items: type: string visibility: $ref: '#/components/schemas/PackVisibility' isOwned: type: boolean description: Whether the workspace owns the pack. deprecated: type: boolean description: Whether the pack is deprecated. Deprecated packs cannot be newly enabled or added. enabled: type: boolean description: Whether the pack is enabled for the workspace. enabledAt: type: - string - 'null' format: date-time enabledBy: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' latestVersion: $ref: '#/components/schemas/RatePackVersionRef' items: type: array description: Accessible rate pack items. Included with `expand=items`. items: $ref: '#/components/schemas/RatePackItem' required: - id - slug - name - category - visibility - isOwned - deprecated - enabled RatePackCreate: type: object description: Fields accepted when creating a workspace rate pack. The new pack is enabled automatically. additionalProperties: false required: - name properties: name: type: string minLength: 1 description: type: string category: type: string default: custom tags: type: array items: type: string RatePackUpdate: type: object description: Fields accepted when updating a workspace-owned rate pack. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 description: type: - string - 'null' category: type: string tags: type: array items: type: string RatePackItem: type: object description: A rate in the current pack version. additionalProperties: false properties: id: $ref: '#/components/schemas/Id' title: type: string description: type: - string - 'null' rate: $ref: '#/components/schemas/Money' unit: type: string quantity: type: - number - 'null' multiplier: type: - number - 'null' group: type: - string - 'null' agreement: type: - string - 'null' local: type: - string - 'null' effectiveDate: type: - string - 'null' format: date labels: type: array items: type: string displayTags: type: array items: type: string version: $ref: '#/components/schemas/RatePackVersionRef' required: - id - title - rate - unit RatePackItemCreate: type: object description: Fields accepted when adding a rate pack item. additionalProperties: false required: - title - rate - unit properties: title: type: string minLength: 1 rate: $ref: '#/components/schemas/Money' unit: type: string description: type: string quantity: type: number multiplier: type: number group: type: string agreement: type: string local: type: string effectiveDate: type: string format: date labels: type: array items: type: string displayTags: type: array items: type: string RatePackItemUpdate: type: object description: Fields accepted when updating a rate pack item. Only supplied fields change. additionalProperties: false minProperties: 1 properties: title: type: string minLength: 1 rate: $ref: '#/components/schemas/Money' unit: type: string description: type: - string - 'null' quantity: type: - number - 'null' multiplier: type: - number - 'null' group: type: - string - 'null' agreement: type: - string - 'null' local: type: - string - 'null' effectiveDate: type: - string - 'null' format: date labels: type: array items: type: string IncentivePack: type: object description: A collection of incentive programs available to the workspace. additionalProperties: false required: - id - slug - name - jurisdiction - visibility - isOwned - deprecated - enabled properties: id: $ref: '#/components/schemas/Id' slug: type: string name: type: string description: type: - string - 'null' category: type: - string - 'null' jurisdiction: type: string description: Country, state, or province where the incentive applies. visibility: $ref: '#/components/schemas/PackVisibility' isOwned: type: boolean deprecated: type: boolean enabled: type: boolean enabledAt: type: - string - 'null' format: date-time programs: type: array description: Incentive programs. Included with `expand=programs`. items: $ref: '#/components/schemas/IncentiveProgram' IncentiveProgramVersion: type: object description: The current published version of an incentive program. additionalProperties: false required: - id - effectiveDate properties: id: $ref: '#/components/schemas/Id' effectiveDate: type: string format: date IncentiveProgram: type: object description: An incentive program that can be added to a project when published. additionalProperties: false required: - id - name - incentiveType - incentiveStructure - rate - discountPercent - status - currentVersion properties: id: $ref: '#/components/schemas/Id' name: type: string description: type: - string - 'null' jurisdiction: type: - string - 'null' incentiveType: type: string description: Type of incentive. enum: - tax_credit - rebate - grant incentiveStructure: type: string description: How the incentive is paid or transferred. enum: - tax_credit_refundable - tax_credit_transferable - tax_credit_nonrefundable - cash_rebate - grant rate: type: number minimum: 0 maximum: 100 description: Headline rate as a percentage. For example, `30` means 30%. discountPercent: type: number minimum: 0 maximum: 100 description: Fee deducted from the incentive, as a percentage. status: type: string enum: - published - blocked - deprecated currentVersion: description: Current published version, or `null` when none is available. anyOf: - allOf: - $ref: '#/components/schemas/IncentiveProgramVersion' - type: 'null' ProjectIncentive: type: object description: An incentive added to a project. additionalProperties: false required: - id - name - sourceType - isApplied properties: id: $ref: '#/components/schemas/Id' name: type: string jurisdiction: type: - string - 'null' incentiveType: type: - string - 'null' sourceType: $ref: '#/components/schemas/SourceType' sourceId: description: Workspace Library source ID, when applicable. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' sourceIncentiveVersionId: description: Incentive version used to create this project incentive. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' isApplied: type: boolean description: Whether the incentive is currently applied to the project's budget. accountNumber: type: - string - 'null' description: Budget account number for the incentive. rate: type: - number - 'null' description: Credit rate as a percentage. For example, `30` means 30%. appliedCreditCap: type: - integer - 'null' description: Maximum credit in minor currency units, or `null` for no limit. discountPercent: type: - number - 'null' description: Broker fee deducted from the credit, as a percentage. tierOverrideKey: type: - string - 'null' description: Selected incentive tier, or `null` to choose the tier from qualified spend. source: description: Incentive program or deleted source. Included with `expand=source`. oneOf: - $ref: '#/components/schemas/IncentiveProgram' - $ref: '#/components/schemas/SourceTombstone' ProjectIncentiveAdd: type: object description: Selects the published incentive program to add to a project. additionalProperties: false required: - programId properties: programId: allOf: - $ref: '#/components/schemas/Id' description: The incentive program to add. versionId: allOf: - $ref: '#/components/schemas/Id' description: Published version to add. Defaults to the current published version. ProjectIncentiveUpdate: type: object description: Fields accepted when updating a project incentive. Money uses minor currency units; `rate` and `discountPercent` use percentages. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 isApplied: type: boolean accountNumber: type: string incentiveType: type: string enum: - tax_credit - rebate - grant jurisdiction: type: string rate: type: number minimum: 0 maximum: 100 appliedCreditCap: type: - integer - 'null' minimum: 0 multipleOf: 100 discountPercent: type: number minimum: 0 maximum: 100 tierOverrideKey: type: - string - 'null' Fringe: type: object description: A fringe in the workspace Library. additionalProperties: false required: - id - name - description - calculationType - fringeGroupIds - color properties: id: $ref: '#/components/schemas/Id' name: type: string description: type: - string - 'null' calculationType: type: string enum: - percent - flat - total rate: type: - number - 'null' description: Percentage for percent fringes, or the amount for flat and total fringes. For example, `7.65` means 7.65%. cutoff: type: - number - 'null' fringeGroupIds: type: array items: $ref: '#/components/schemas/Id' color: type: - string - 'null' FringeWrite: type: object description: Fields accepted when creating or updating a workspace fringe. additionalProperties: false properties: name: type: string minLength: 1 description: type: - string - 'null' calculationType: type: string enum: - percent - flat - total rate: type: - number - 'null' cutoff: type: - number - 'null' fringeGroupIds: type: array items: $ref: '#/components/schemas/Id' color: type: - string - 'null' ProjectFringe: type: object description: A fringe added to a project from the workspace Library. additionalProperties: false required: - id - name - description - calculationType - fringeGroupIds - color - sourceType properties: id: $ref: '#/components/schemas/Id' name: type: string description: type: - string - 'null' calculationType: type: string enum: - percent - flat - total rate: type: - number - 'null' cutoff: type: - number - 'null' fringeGroupIds: type: array items: $ref: '#/components/schemas/Id' color: type: - string - 'null' sourceType: $ref: '#/components/schemas/SourceType' sourceId: description: Workspace fringe used to create this project fringe. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' source: description: Workspace fringe or deleted source. Included with `expand=source`. oneOf: - $ref: '#/components/schemas/Fringe' - $ref: '#/components/schemas/SourceTombstone' Global: type: object description: A global in the workspace Library. additionalProperties: false required: - id - symbol - description - formula properties: id: $ref: '#/components/schemas/Id' symbol: type: - string - 'null' description: type: - string - 'null' formula: type: - string - 'null' unit: type: - string - 'null' customUnitId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' phaseOverrides: type: - object - 'null' additionalProperties: type: string GlobalWrite: type: object description: Fields accepted when creating or updating a workspace global. additionalProperties: false properties: symbol: type: - string - 'null' minLength: 1 description: type: - string - 'null' formula: type: - string - 'null' unit: type: - string - 'null' customUnitId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' ProjectGlobal: type: object description: A global added to a project from the workspace Library. additionalProperties: false required: - id - symbol - description - formula - sourceType properties: id: $ref: '#/components/schemas/Id' symbol: type: - string - 'null' description: type: - string - 'null' formula: type: - string - 'null' unit: type: - string - 'null' customUnitId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' phaseOverrides: type: - object - 'null' additionalProperties: type: string sourceType: $ref: '#/components/schemas/SourceType' sourceId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' source: oneOf: - $ref: '#/components/schemas/Global' - $ref: '#/components/schemas/SourceTombstone' Currency: type: object description: A currency and exchange rate in the workspace Library. additionalProperties: false required: - id - code properties: id: $ref: '#/components/schemas/Id' code: type: string description: ISO 4217 currency code. minLength: 3 maxLength: 3 name: type: - string - 'null' symbol: type: - string - 'null' rateToUSD: type: - number - 'null' description: USD value of one unit of this currency. CurrencyWrite: type: object description: Fields accepted when creating or updating a workspace currency. additionalProperties: false properties: code: type: string minLength: 3 maxLength: 3 name: type: - string - 'null' symbol: type: - string - 'null' rateToUSD: type: - number - 'null' description: USD value of one unit of this currency. For example, use `1.17` for EUR when one EUR equals 1.17 USD. ProjectCurrency: type: object description: A currency added to a project from the workspace Library. additionalProperties: false required: - id - code - sourceType properties: id: $ref: '#/components/schemas/Id' code: type: string minLength: 3 maxLength: 3 name: type: - string - 'null' symbol: type: - string - 'null' rateToUSD: type: - number - 'null' description: USD value of one unit of this currency. sourceType: $ref: '#/components/schemas/SourceType' sourceId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' source: oneOf: - $ref: '#/components/schemas/Currency' - $ref: '#/components/schemas/SourceTombstone' FringeGroup: type: object description: A Fringe Group in the workspace Library. additionalProperties: false required: - id - name properties: id: $ref: '#/components/schemas/Id' name: type: string color: $ref: '#/components/schemas/TagColor' FringeGroupWrite: type: object description: Fields accepted when creating or updating a workspace Fringe Group. additionalProperties: false properties: name: type: string minLength: 1 color: $ref: '#/components/schemas/TagColor' ProjectFringeGroup: type: object description: A Fringe Group added to a project from the workspace Library. additionalProperties: false required: - id - name - sourceType properties: id: $ref: '#/components/schemas/Id' name: type: string color: $ref: '#/components/schemas/TagColor' sourceType: $ref: '#/components/schemas/SourceType' sourceId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' source: oneOf: - $ref: '#/components/schemas/FringeGroup' - $ref: '#/components/schemas/SourceTombstone' Tag: type: object description: A tag in the workspace Library. additionalProperties: false required: - id - name - createdAt - updatedAt properties: id: $ref: '#/components/schemas/Id' name: type: string color: $ref: '#/components/schemas/TagColor' description: type: - string - 'null' eligibilityKey: type: - string - 'null' description: Key used to match the tag to an eligibility rule. sort: type: - number - 'null' createdAt: type: string format: date-time updatedAt: type: string format: date-time TagCreate: type: object description: Fields accepted when creating a workspace tag. additionalProperties: false required: - name properties: name: type: string minLength: 1 color: $ref: '#/components/schemas/TagColor' description: type: string eligibilityKey: type: string TagUpdate: type: object description: Fields accepted when updating a workspace tag. Only supplied fields change. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 color: $ref: '#/components/schemas/TagColor' description: type: - string - 'null' eligibilityKey: type: - string - 'null' Unit: type: object description: A unit in the Library. `isCustom` identifies workspace units; built-in units are read-only. additionalProperties: false required: - id - label - pluralLabel - category - hoursPerUnit - color - isCustom properties: id: type: string description: Unit ID. label: type: string pluralLabel: type: - string - 'null' category: type: string enum: - time - quantity - flat hoursPerUnit: type: - number - 'null' minimum: 0 color: type: - string - 'null' description: type: - string - 'null' isCustom: type: boolean createdAt: type: string format: date-time description: Creation time for a workspace unit. updatedAt: type: string format: date-time description: Last update time for a workspace unit. UnitCreate: type: object description: Fields accepted when creating a workspace unit. additionalProperties: false required: - label properties: label: type: string minLength: 1 pluralLabel: type: - string - 'null' category: type: string enum: - time - quantity - flat default: quantity hoursPerUnit: type: - number - 'null' minimum: 0 color: type: - string - 'null' description: type: string UnitUpdate: type: object description: Fields accepted when updating a workspace unit. Only supplied fields change. additionalProperties: false minProperties: 1 properties: label: type: string minLength: 1 pluralLabel: type: - string - 'null' category: type: string enum: - time - quantity - flat hoursPerUnit: type: - number - 'null' minimum: 0 color: type: - string - 'null' description: type: - string - 'null' RatePackCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/RatePack' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. RatePackItemCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/RatePackItem' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. IncentivePackCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/IncentivePack' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. IncentiveProgramCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/IncentiveProgram' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ProjectIncentiveCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/ProjectIncentive' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. FringeCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Fringe' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ProjectFringeCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/ProjectFringe' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. GlobalCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Global' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ProjectGlobalCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/ProjectGlobal' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. CurrencyCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Currency' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ProjectCurrencyCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/ProjectCurrency' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. FringeGroupCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/FringeGroup' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ProjectFringeGroupCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/ProjectFringeGroup' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. TagCollection: type: object additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Tag' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. UnitCollection: type: object description: Built-in and workspace units. additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Unit' RatePackEnableLink: type: object description: A rate pack enabled for the workspace. additionalProperties: false required: - id - ratePackId - enabledAt properties: id: $ref: '#/components/schemas/Id' ratePackId: $ref: '#/components/schemas/Id' enabledAt: type: string format: date-time IncentivePackEnableLink: type: object description: An incentive pack enabled for the workspace. additionalProperties: false required: - id - incentivePackId - enabledAt properties: id: $ref: '#/components/schemas/Id' incentivePackId: $ref: '#/components/schemas/Id' enabledAt: type: string format: date-time ProjectStatus: type: string description: Project status. enum: - active - archived ProjectAccess: oneOf: - type: object required: - state - effectivePlanId additionalProperties: false properties: state: type: string const: available effectivePlanId: type: string - type: object required: - state - effectivePlanId - reason - remediation additionalProperties: false properties: state: type: string const: locked effectivePlanId: type: string reason: type: string enum: - project_limit - subscription_restricted - contract_restricted remediation: type: string enum: - upgrade - recover_payment - reactivate_subscription - contact_sales ProjectTag: type: object required: - id - name - color additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string color: type: string description: Color used for the tag in Saturation. ProjectCreator: type: object required: - id - name - image additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string image: type: - string - 'null' description: Profile image URL. Project: type: object description: A production project with its budget, transactions, documents, and Library items. required: - id - slug - name - status - createdAt - updatedAt additionalProperties: false properties: id: &id001 $ref: '#/components/schemas/Id' slug: &id002 type: string description: The project's human handle, unique per workspace. examples: - q3-feature-doc name: &id003 type: string description: Display name. examples: - Q3 Feature Doc emoji: &id004 type: - string - 'null' description: Emoji shown with the project. image: &id005 type: - string - 'null' description: Cover image URL. status: &id006 $ref: '#/components/schemas/ProjectStatus' summary: &id007 type: - string - 'null' description: A short project summary. spaceId: &id008 description: Space containing the project, or `null` when ungrouped. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' projectType: &id009 type: - string - 'null' description: Production format, such as Feature film or Commercial. tags: &id010 type: array items: $ref: '#/components/schemas/ProjectTag' createdBy: &id011 description: Person who created the project. anyOf: - $ref: '#/components/schemas/ProjectCreator' - type: 'null' createdAt: &id012 type: string format: date-time description: ISO 8601 creation time. updatedAt: &id013 type: string format: date-time description: ISO 8601 last update time. access: &id014 $ref: '#/components/schemas/ProjectAccess' assumptions: description: The project brief. Present only when `expand=assumptions` is set; `null` when the project has no pinned brief. anyOf: - allOf: - $ref: '#/components/schemas/ProjectAssumptions' - type: 'null' ProjectDefaultBudget: type: object required: - budgetId - estimatePhaseId additionalProperties: false properties: budgetId: $ref: '#/components/schemas/Id' estimatePhaseId: $ref: '#/components/schemas/Id' ProjectAssumptions: type: object description: The project brief, the note pinned on the project. Present only when the request expands `assumptions`. required: - noteId - title - content - preview - updatedAt additionalProperties: false properties: noteId: $ref: '#/components/schemas/Id' title: type: string description: Note title. content: type: string description: The brief as Markdown. preview: type: - string - 'null' description: A short plain-text preview of the brief. updatedAt: type: string format: date-time description: ISO 8601 last update time. ProjectCreated: type: object additionalProperties: false required: - id - slug - name - status - createdAt - updatedAt - defaultBudget properties: id: *id001 slug: *id002 name: *id003 emoji: *id004 image: *id005 status: *id006 summary: *id007 spaceId: *id008 projectType: *id009 tags: *id010 createdBy: *id011 createdAt: *id012 updatedAt: *id013 access: *id014 assumptions: description: The project brief. Present only when `expand=assumptions` is set; `null` when the project has no pinned brief. anyOf: - allOf: - $ref: '#/components/schemas/ProjectAssumptions' - type: 'null' defaultBudget: $ref: '#/components/schemas/ProjectDefaultBudget' ProjectCreate: type: object description: Fields accepted when creating a project. required: - name additionalProperties: false properties: name: type: string minLength: 1 examples: - Q3 Feature Doc slug: type: string description: Unique project handle. Generated from `name` when omitted. emoji: type: - string - 'null' image: type: - string - 'null' summary: type: - string - 'null' spaceId: description: Space containing the project. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' projectType: type: - string - 'null' description: Production format, such as Feature film or Commercial. tagIds: type: array description: Project tag IDs to assign. Duplicate IDs are ignored. items: $ref: '#/components/schemas/Id' ProjectUpdate: type: object description: Fields accepted when updating a project. Only supplied fields change. `status` accepts `active` or `archived`. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 slug: type: string emoji: type: - string - 'null' image: type: - string - 'null' summary: type: - string - 'null' spaceId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' status: type: string enum: - active - archived projectType: type: - string - 'null' description: Project type shown in Saturation. tagIds: type: array description: Replaces the project's tags. Send an empty array to remove all tags. items: $ref: '#/components/schemas/Id' ProjectList: type: object description: A page of projects. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Project' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. Space: type: object description: A folder that groups projects and can sit inside another space. required: - id - slug - name - archived - createdAt - updatedAt additionalProperties: false properties: id: $ref: '#/components/schemas/Id' slug: type: string description: The space's human handle (unique per workspace). examples: - features name: type: string examples: - Features image: type: - string - 'null' parentId: description: Parent space for nesting, or `null` for a top-level space. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' archived: type: boolean description: Whether the space is archived. createdAt: type: string format: date-time updatedAt: type: string format: date-time SpaceCreate: type: object description: Fields accepted when creating a space. required: - name additionalProperties: false properties: name: type: string minLength: 1 examples: - Features slug: type: string description: Unique space handle. Generated from `name` when omitted. image: type: - string - 'null' parentId: description: Parent space, or `null` for a top-level space. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' SpaceUpdate: type: object description: Fields accepted when updating a space. Only supplied fields change. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 slug: type: string image: type: - string - 'null' parentId: anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' archived: type: boolean SpaceList: type: object description: A page of spaces. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Space' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ContactType: type: string description: Contact type. Vendors are organizations; contractors and employees are people. enum: - contractor - employee - company - vendor ContactDocumentRef: type: object description: A document shown with a contact. required: - id - name - size - mimeType - status - description - classification additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string size: type: integer format: int64 mimeType: type: string status: type: string description: type: - string - 'null' classification: type: - string - 'null' ContactTransactionRef: type: object description: A transaction shown with a contact. required: - id - description - amount - timestamp - status - merchant - logoUrl - category - projectId - budgetLineId additionalProperties: false properties: id: $ref: '#/components/schemas/Id' description: type: - string - 'null' amount: type: - integer - 'null' format: int64 timestamp: type: - string - 'null' format: date-time status: type: string merchant: type: - string - 'null' logoUrl: type: - string - 'null' category: type: - string - 'null' projectId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' budgetLineId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' Contact: type: object description: A vendor, crew member, or other payee in the workspace. required: - id - displayName - track1099 - createdAt - updatedAt additionalProperties: false properties: id: $ref: '#/components/schemas/Id' displayName: type: string description: Display name for the contact. examples: - Aerial Imaging LLC name: type: - string - 'null' description: Person or primary contact name. company: type: - string - 'null' title: type: - string - 'null' description: Role or job title, such as `Director of Photography`. type: anyOf: - allOf: - $ref: '#/components/schemas/ContactType' - type: 'null' email: type: - string - 'null' phone: type: - string - 'null' address: type: - string - 'null' description: Free-form address as entered. website: type: - string - 'null' instagram: type: - string - 'null' imdb: type: - string - 'null' rate: description: Default day or labor rate. anyOf: - allOf: - $ref: '#/components/schemas/Money' - type: 'null' track1099: type: boolean description: Whether this contact is tracked for 1099 reporting. taxIdLast4: type: - string - 'null' description: Last four digits of the tax ID. hasTaxId: type: boolean description: Whether a tax ID is on file. notes: type: - string - 'null' description: Markdown notes. createdAt: type: string format: date-time updatedAt: type: string format: date-time documents: type: array description: Documents linked to the contact. Included with `expand=documents`. items: $ref: '#/components/schemas/ContactDocumentRef' transactions: type: array description: Accessible transactions for the contact. Included with `expand=transactions`. items: $ref: '#/components/schemas/ContactTransactionRef' ContactCreate: type: object description: Fields accepted when creating a contact. Tax and bank account numbers are added through documents. required: - name additionalProperties: false properties: name: type: string minLength: 1 company: type: - string - 'null' title: type: - string - 'null' type: $ref: '#/components/schemas/ContactType' email: type: - string - 'null' phone: type: - string - 'null' address: type: - string - 'null' website: type: - string - 'null' instagram: type: - string - 'null' imdb: type: - string - 'null' rate: anyOf: - allOf: - $ref: '#/components/schemas/Money' - type: 'null' track1099: type: boolean notes: type: - string - 'null' ContactUpdate: type: object description: Fields accepted when updating a contact. Only supplied fields change. additionalProperties: false minProperties: 1 properties: name: type: string minLength: 1 company: type: - string - 'null' title: type: - string - 'null' type: $ref: '#/components/schemas/ContactType' email: type: - string - 'null' phone: type: - string - 'null' address: type: - string - 'null' website: type: - string - 'null' instagram: type: - string - 'null' imdb: type: - string - 'null' rate: anyOf: - allOf: - $ref: '#/components/schemas/Money' - type: 'null' track1099: type: boolean notes: type: - string - 'null' ContactList: type: object description: A page of contacts. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Contact' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. ContactExpand: type: string description: Related contact data to include. enum: - documents - transactions ProjectExpand: type: string description: Related project data to include. enum: - assumptions CommentTargetKind: type: string description: Resource type associated with a comment. enum: - project - budgetLine - transaction - purchaseOrder - contact - document CommentTarget: type: object description: Resource associated with a comment. required: - kind - id additionalProperties: false properties: kind: $ref: '#/components/schemas/CommentTargetKind' id: $ref: '#/components/schemas/Id' CommentAuthor: type: object required: - id - name - avatar additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string avatar: type: - string - 'null' CommentTag: type: object required: - id - targetType - targetId - label - kind additionalProperties: false properties: id: $ref: '#/components/schemas/Id' targetType: type: string targetId: $ref: '#/components/schemas/Id' label: type: string kind: type: string enum: - mention - anchor CommentTagWrite: type: object required: - targetType - targetId - label additionalProperties: false properties: targetType: type: string minLength: 1 targetId: $ref: '#/components/schemas/Id' label: type: string minLength: 1 kind: type: string enum: - mention - anchor CommentReaction: type: object required: - emoji - count - users additionalProperties: false properties: emoji: type: string count: type: integer minimum: 0 users: type: array items: type: object required: - id - name additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string Comment: type: object description: A comment on a project resource. Replies reference the first comment with `threadId`. required: - id - projectId - author - content - resolved - tags - reactions - replyCount - readByCurrentUser - edited - createdAt - updatedAt additionalProperties: false properties: id: $ref: '#/components/schemas/Id' projectId: $ref: '#/components/schemas/Id' threadId: description: The root comment id when this is a reply; `null` for a root comment. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' target: description: Resource associated with the comment. anyOf: - allOf: - $ref: '#/components/schemas/CommentTarget' - type: 'null' author: $ref: '#/components/schemas/CommentAuthor' content: type: string description: Markdown comment body. resolved: type: boolean description: Whether the comment thread is resolved. tags: type: array items: $ref: '#/components/schemas/CommentTag' reactions: type: array items: $ref: '#/components/schemas/CommentReaction' replyCount: type: integer minimum: 0 readByCurrentUser: type: boolean edited: type: boolean createdAt: type: string format: date-time updatedAt: type: string format: date-time CommentCreate: type: object description: Fields accepted when creating a comment. required: - content - target additionalProperties: false properties: content: type: string minLength: 1 target: $ref: '#/components/schemas/CommentTarget' threadId: description: Root comment ID when adding a reply. anyOf: - allOf: - $ref: '#/components/schemas/Id' - type: 'null' tags: type: array description: Mentions and resource links in the comment. items: $ref: '#/components/schemas/CommentTagWrite' CommentUpdate: type: object description: Fields accepted when updating a comment. Only the author can change `content`. additionalProperties: false minProperties: 1 properties: content: type: string minLength: 1 resolved: type: boolean tags: type: array description: Replaces the comment's mentions and resource links. items: $ref: '#/components/schemas/CommentTagWrite' reactionEmojis: type: array description: Replaces the current user's reactions. Duplicate emoji are ignored. items: type: string minLength: 1 CommentList: type: object description: A page of comments. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Comment' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether some matching items were omitted from the response. PrincipalType: type: string description: Type of identity associated with the token. enum: - user - service WorkspaceReach: type: object description: A workspace and role associated with the token. required: - workspaceId - workspaceRole additionalProperties: false properties: workspaceId: $ref: '#/components/schemas/Id' workspaceName: type: string description: Workspace name. workspaceRole: $ref: '#/components/schemas/WorkspaceRole' WorkspaceRole: type: string description: Role in the workspace. enum: - owner - admin - accountant - edit - comment - view Me: type: object description: Identity and workspaces associated with the token. required: - id - type - workspaces additionalProperties: false properties: id: $ref: '#/components/schemas/Id' type: $ref: '#/components/schemas/PrincipalType' email: type: string format: email description: Email address. Present for user identities. name: type: string description: Display name. workspaces: type: array description: Workspaces associated with the token. items: $ref: '#/components/schemas/WorkspaceReach' example: id: usr_4f1a8c2e type: user email: producer@example.com name: Dana Producer workspaces: - workspaceId: ws_2b9d7a1f workspaceName: Paradigm Pictures workspaceRole: admin PaymentRequestStatus: type: string description: Current payment-request status. `unknown` means the status is unavailable. enum: - submitted - pending - approved - paid - rejected - canceled - unknown PaymentStatus: type: string description: Current payment status. enum: - requested - needs_approval - scheduled - sending - settled - returned - failed - rejected - canceled PaymentRequestExpand: type: string description: Related record available through `expand`. enum: - contact - purchaseOrder - document - payment - transactions - budgetLine PaymentExpand: type: string description: Related record available through `expand`. enum: - request - purchaseOrder - transactions - contact - budgetLine - document PaymentContactLink: type: object required: - id - name - displayTitle - company - email - type additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: - string - 'null' displayTitle: type: - string - 'null' company: type: - string - 'null' email: type: - string - 'null' type: type: - string - 'null' PaymentPurchaseOrderLink: type: object required: - id - projectId - number - name - status additionalProperties: false properties: id: $ref: '#/components/schemas/Id' projectId: type: - string - 'null' number: type: - string - 'null' name: type: - string - 'null' status: type: string PaymentDocumentLink: type: object required: - id - projectId - name - mimeType - status - size - classification additionalProperties: false properties: id: $ref: '#/components/schemas/Id' projectId: type: - string - 'null' name: type: string mimeType: type: - string - 'null' status: type: string size: type: integer classification: type: - string - 'null' PaymentBudgetLineLink: type: object required: - id - accountId - description - type additionalProperties: false properties: id: $ref: '#/components/schemas/Id' accountId: type: - string - 'null' description: type: - string - 'null' type: type: - string - 'null' PaymentTransactionLink: type: object required: - id - projectId - amount - description - status - timestamp additionalProperties: false properties: id: $ref: '#/components/schemas/Id' projectId: type: - string - 'null' amount: oneOf: - $ref: '#/components/schemas/Money' - type: 'null' description: type: - string - 'null' status: type: string timestamp: type: - string - 'null' format: date-time PaymentRequestBase: type: object description: A request to pay a person or company. required: &id015 - id - workspaceId - projectId - purchaseOrderId - contactId - budgetLineId - amount - description - memo - dueDate - method - status - submittedAt - approvedAt - rejectedAt - completedAt - createdAt - updatedAt additionalProperties: false properties: id: &id016 $ref: '#/components/schemas/Id' workspaceId: &id017 $ref: '#/components/schemas/Id' projectId: &id018 type: - string - 'null' purchaseOrderId: &id019 type: - string - 'null' contactId: &id020 type: - string - 'null' budgetLineId: &id021 type: - string - 'null' amount: &id022 $ref: '#/components/schemas/Money' description: &id023 type: - string - 'null' memo: &id024 type: - string - 'null' dueDate: &id025 type: - string - 'null' format: date-time method: &id026 type: - string - 'null' status: &id027 $ref: '#/components/schemas/PaymentRequestStatus' submittedAt: &id028 type: string format: date-time approvedAt: &id029 type: - string - 'null' format: date-time rejectedAt: &id030 type: - string - 'null' format: date-time completedAt: &id031 type: - string - 'null' format: date-time createdAt: &id032 type: string format: date-time updatedAt: &id033 type: string format: date-time PaymentBase: type: object description: A payment and its current status. required: &id034 - id - workspaceId - projectId - paymentRequestId - purchaseOrderId - contactId - budgetLineId - status - amount - destinationAmount - rail - description - memo - notes - scheduledFor - expectedArrivalAt - destination - cancellationRequested - needsSupport - failureReason - createdAt - updatedAt additionalProperties: false properties: id: &id035 $ref: '#/components/schemas/Id' workspaceId: &id036 $ref: '#/components/schemas/Id' projectId: &id037 type: - string - 'null' paymentRequestId: &id038 type: - string - 'null' purchaseOrderId: &id039 type: - string - 'null' contactId: &id040 type: - string - 'null' budgetLineId: &id041 type: - string - 'null' status: &id042 $ref: '#/components/schemas/PaymentStatus' amount: &id043 $ref: '#/components/schemas/Money' destinationAmount: &id044 oneOf: - $ref: '#/components/schemas/Money' - type: 'null' rail: &id045 type: - string - 'null' description: &id046 type: - string - 'null' memo: &id047 type: - string - 'null' notes: &id048 type: - string - 'null' scheduledFor: &id049 type: - string - 'null' format: date-time expectedArrivalAt: &id050 type: - string - 'null' format: date-time destination: &id051 oneOf: - type: object required: - bankName - accountType - accountLast4 - network additionalProperties: false properties: bankName: type: - string - 'null' accountType: type: - string - 'null' accountLast4: type: - string - 'null' network: type: - string - 'null' - type: 'null' cancellationRequested: &id052 type: boolean needsSupport: &id053 type: boolean failureReason: &id054 type: - string - 'null' createdAt: &id055 type: string format: date-time updatedAt: &id056 type: string format: date-time PaymentRequest: type: object required: *id015 additionalProperties: false properties: id: *id016 workspaceId: *id017 projectId: *id018 purchaseOrderId: *id019 contactId: *id020 budgetLineId: *id021 amount: *id022 description: *id023 memo: *id024 dueDate: *id025 method: *id026 status: *id027 submittedAt: *id028 approvedAt: *id029 rejectedAt: *id030 completedAt: *id031 createdAt: *id032 updatedAt: *id033 contact: oneOf: - $ref: '#/components/schemas/PaymentContactLink' - type: 'null' purchaseOrder: oneOf: - $ref: '#/components/schemas/PaymentPurchaseOrderLink' - type: 'null' document: oneOf: - $ref: '#/components/schemas/PaymentDocumentLink' - type: 'null' payment: oneOf: - $ref: '#/components/schemas/PaymentBase' - type: 'null' transactions: type: array items: $ref: '#/components/schemas/PaymentTransactionLink' budgetLine: oneOf: - $ref: '#/components/schemas/PaymentBudgetLineLink' - type: 'null' Payment: type: object required: *id034 additionalProperties: false properties: id: *id035 workspaceId: *id036 projectId: *id037 paymentRequestId: *id038 purchaseOrderId: *id039 contactId: *id040 budgetLineId: *id041 status: *id042 amount: *id043 destinationAmount: *id044 rail: *id045 description: *id046 memo: *id047 notes: *id048 scheduledFor: *id049 expectedArrivalAt: *id050 destination: *id051 cancellationRequested: *id052 needsSupport: *id053 failureReason: *id054 createdAt: *id055 updatedAt: *id056 request: oneOf: - $ref: '#/components/schemas/PaymentRequestBase' - type: 'null' purchaseOrder: oneOf: - $ref: '#/components/schemas/PaymentPurchaseOrderLink' - type: 'null' transactions: type: array items: $ref: '#/components/schemas/PaymentTransactionLink' contact: oneOf: - $ref: '#/components/schemas/PaymentContactLink' - type: 'null' budgetLine: oneOf: - $ref: '#/components/schemas/PaymentBudgetLineLink' - type: 'null' document: oneOf: - $ref: '#/components/schemas/PaymentDocumentLink' - type: 'null' PaymentTimelineEvent: type: object required: - id - type - label - occurredAt - actor - related additionalProperties: false properties: id: $ref: '#/components/schemas/Id' type: type: string label: type: string occurredAt: type: string format: date-time actor: oneOf: - type: object required: - id - name - avatarUrl additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string avatarUrl: type: - string - 'null' - type: 'null' related: type: array items: type: object required: - type - id additionalProperties: false properties: type: type: string enum: - document - payment_request - payment - transaction - purchase_order - approval id: $ref: '#/components/schemas/Id' PaymentTimelinePage: type: object required: - data - nextCursor additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/PaymentTimelineEvent' nextCursor: type: - string - 'null' PaymentRequestList: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/PaymentRequest' nextCursor: $ref: '#/components/schemas/NextCursor' PaymentList: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/Payment' nextCursor: $ref: '#/components/schemas/NextCursor' PurchaseOrderStatus: type: string description: Current purchase order status. enum: - draft - pending - approved - rejected - actualizing - paid - void examples: - pending PurchaseOrderActivityType: type: string description: Activity shown in the purchase order Activity column. enum: - invoice_requested - invoice_received - invoice_rejected - payment_requested - payment_approval_pending - payment_approved - payment_processing - payment_sent - payment_failed - payment_returned - actualized_needs_review - split_needs_review - transaction_match_needs_review PurchaseOrderActivitySeverity: type: string enum: - neutral - info - warning - danger - success PurchaseOrderExpand: type: string description: Related records available through `expand`. Unknown keys return `400 expand_invalid`. enum: - items - contact - transactions - documents - paymentRequests - payments - budgetLine - activity - summary PurchaseOrderSort: type: string description: Fields available for sorting purchase orders. enum: - number - name - dueDate - serviceStartAt - serviceEndAt - status - sort - createdAt - updatedAt PurchaseOrderContactRef: type: object description: Vendor details included with a purchase order. required: - id - displayName - name - company - email - type additionalProperties: false properties: id: $ref: '#/components/schemas/Id' displayName: type: string name: type: - string - 'null' company: type: - string - 'null' email: type: - string - 'null' type: type: - string - 'null' PurchaseOrderTransactionRef: type: object description: Transaction details included with a purchase order. required: - id - projectId - purchaseOrderId - amount - description - timestamp - status - type - contactId - budgetLineId additionalProperties: false properties: id: $ref: '#/components/schemas/Id' projectId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' purchaseOrderId: $ref: '#/components/schemas/Id' amount: type: - integer - 'null' format: int64 description: type: - string - 'null' timestamp: type: - string - 'null' format: date-time status: type: string type: type: - string - 'null' contactId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' budgetLineId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' PurchaseOrderDocumentRef: type: object description: Document details included with a purchase order. required: - id - name - mimeType - status - size - classification additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string mimeType: type: string status: type: string size: type: integer format: int64 classification: type: - string - 'null' PurchaseOrderBudgetLineRef: type: object description: Budget line details included with a purchase order. required: - id - accountId - type - description - parentId - sort - contactId - lineColor - emoji - notes additionalProperties: false properties: id: $ref: '#/components/schemas/Id' accountId: type: - string - 'null' type: type: string description: type: - string - 'null' parentId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' sort: type: - string - 'null' contactId: oneOf: - $ref: '#/components/schemas/Id' - type: 'null' lineColor: type: - string - 'null' emoji: type: - string - 'null' notes: type: - string - 'null' PurchaseOrder: type: object description: A purchase order in Saturation. required: - id - workspaceId - projectId - status - currency - exchangeRate - exchangeRateSource - amount - createdAt - updatedAt additionalProperties: false properties: id: $ref: '#/components/schemas/Id' workspaceId: $ref: '#/components/schemas/Id' projectId: description: Assigned project ID, or `null` when unassigned. oneOf: - $ref: '#/components/schemas/Id' - type: 'null' number: type: - string - 'null' description: Purchase order number, such as `PO-0042`. name: type: - string - 'null' description: Purchase order name. status: $ref: '#/components/schemas/PurchaseOrderStatus' contactId: type: - string - 'null' description: Vendor contact ID. budgetLineId: type: - string - 'null' description: Budget line ID. dueDate: type: - string - 'null' format: date description: Payment due date. serviceStartAt: type: - string - 'null' format: date description: First service date. serviceEndAt: type: - string - 'null' format: date description: Last service date. notes: type: - string - 'null' description: Notes about the purchase order. sort: type: - number - 'null' description: Display order within the project. currency: type: string minLength: 3 maxLength: 3 description: Purchase order currency. exchangeRate: type: - number - 'null' description: Rate from the purchase order currency to the workspace currency. exchangeRateSource: type: - string - 'null' description: Where the exchange rate came from. createdById: type: - string - 'null' description: ID of the user who created the purchase order. amount: allOf: - $ref: '#/components/schemas/Money' description: Sum of item amounts in the purchase order currency. createdAt: type: string format: date-time description: Time the purchase order was created. updatedAt: type: string format: date-time description: Time the purchase order was last updated. items: type: array description: Purchase order items. Included with `expand=items`. items: $ref: '#/components/schemas/PurchaseOrderItem' contact: description: Vendor contact. Included with `expand=contact`. oneOf: - $ref: '#/components/schemas/PurchaseOrderContactRef' - type: 'null' transactions: type: array description: Linked transactions. Included with `expand=transactions`. items: $ref: '#/components/schemas/PurchaseOrderTransactionRef' documents: type: array description: Related documents. Included with `expand=documents`. items: $ref: '#/components/schemas/PurchaseOrderDocumentRef' paymentRequests: type: array description: Related payment requests. Included with `expand=paymentRequests`. items: $ref: '#/components/schemas/PaymentRequestBase' payments: type: array description: Related payments. Included with `expand=payments`. items: $ref: '#/components/schemas/PaymentBase' budgetLine: description: Budget line charged by the purchase order. Included with `expand=budgetLine`. oneOf: - $ref: '#/components/schemas/PurchaseOrderBudgetLineRef' - type: 'null' activity: description: Current Activity column details. Included with `expand=activity`. oneOf: - $ref: '#/components/schemas/PurchaseOrderActivitySummary' - type: 'null' summary: description: Purchase order totals. Included on detail responses or with `expand=summary`. oneOf: - $ref: '#/components/schemas/PurchaseOrderSummary' - type: 'null' examples: - id: po_8f2a1c9e workspaceId: ws_3b1 projectId: prj_demo number: PO-0042 name: Camera package rental status: pending contactId: con_77a budgetLineId: bud_5510 dueDate: '2026-05-20' serviceStartAt: '2026-05-21' serviceEndAt: '2026-05-24' notes: Net-30 sort: 1000 createdById: usr_aa1 amount: amount: 152900 currency: USD createdAt: '2026-05-18T14:02:11.000Z' updatedAt: '2026-05-20T09:31:00.000Z' PurchaseOrderItem: type: object description: An item in a purchase order. required: - id - purchaseOrderId - sort additionalProperties: false properties: id: $ref: '#/components/schemas/Id' purchaseOrderId: $ref: '#/components/schemas/Id' lineNumber: type: - string - 'null' description: Line number shown in the itemization. description: type: - string - 'null' description: Item description. budgetLineId: type: - string - 'null' description: Budget line ID. qty: type: - string - 'null' description: Quantity or formula. unit: type: - string - 'null' description: Unit, such as `day`, `week`, or `each`. rate: type: - string - 'null' description: Rate or formula. amount: type: - integer - 'null' format: int64 description: Item total in minor currency units. sort: type: string description: Display order within the purchase order. examples: - id: poi_1a purchaseOrderId: po_8f2a1c9e lineNumber: '1' description: Alexa Mini LF body budgetLineId: bud_5510 qty: '5' unit: day rate: '25000' amount: 125000 sort: '1000' PurchaseOrderActivityItem: type: object description: One entry in the purchase order Activity column. required: - type - label - severity - count - sourceIds additionalProperties: false properties: type: $ref: '#/components/schemas/PurchaseOrderActivityType' label: type: string severity: $ref: '#/components/schemas/PurchaseOrderActivitySeverity' count: type: integer minimum: 0 sourceIds: type: array items: type: string PurchaseOrderActivitySummary: type: object description: Current purchase order activity. required: - primaryActivity - items additionalProperties: false properties: primaryActivity: oneOf: - $ref: '#/components/schemas/PurchaseOrderActivityItem' - type: 'null' items: type: array items: $ref: '#/components/schemas/PurchaseOrderActivityItem' PurchaseOrderSummary: type: object description: Purchase order totals in its currency. required: - purchaseOrderId - currency - amounts additionalProperties: false properties: purchaseOrderId: $ref: '#/components/schemas/Id' currency: type: string minLength: 3 maxLength: 3 amounts: type: object required: - ordered - requested - invoiced - sent - actualized - remaining - variance additionalProperties: false properties: ordered: $ref: '#/components/schemas/Money' requested: $ref: '#/components/schemas/Money' invoiced: $ref: '#/components/schemas/Money' sent: $ref: '#/components/schemas/Money' actualized: $ref: '#/components/schemas/Money' remaining: $ref: '#/components/schemas/Money' variance: $ref: '#/components/schemas/Money' PurchaseOrderTimelineEventType: type: string description: Purchase order history event type. enum: - created - item_added - submitted_for_approval - approved - rejected - approval_request_canceled - voided - transaction_linked - transaction_unlinked - marked_paid - invoice_requested - invoice_uploaded - attachment_uploaded - document_linked - decision_recorded - decision_undone - status_changed - approval_decision - details_updated PurchaseOrderTimelineActor: type: object required: - id - name - avatarUrl additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: string avatarUrl: type: - string - 'null' PurchaseOrderTimelineEvent: type: object required: - id - type - label - occurredAt - actor - related - superseded additionalProperties: false properties: id: $ref: '#/components/schemas/Id' type: $ref: '#/components/schemas/PurchaseOrderTimelineEventType' label: type: string occurredAt: type: string format: date-time actor: oneOf: - $ref: '#/components/schemas/PurchaseOrderTimelineActor' - type: 'null' related: type: array items: $ref: '#/components/schemas/PublicResourceRef' superseded: type: boolean PurchaseOrderTimelinePage: type: object required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/PurchaseOrderTimelineEvent' nextCursor: $ref: '#/components/schemas/NextCursor' PurchaseOrderCreate: type: object description: Fields for a new draft purchase order. additionalProperties: false properties: projectId: type: string description: Project ID or slug. Omit to leave the purchase order unassigned. number: type: string description: Purchase order number. name: type: string description: Purchase order name. contactId: type: string description: Vendor contact ID. budgetLineId: type: string description: Budget line ID. dueDate: type: string format: date description: Payment due date. serviceStartAt: type: string format: date description: First service date. serviceEndAt: type: string format: date description: Last service date. notes: type: string sort: type: number items: type: array maxItems: 100 description: Items to create with the purchase order. items: $ref: '#/components/schemas/PurchaseOrderItemWrite' examples: - number: PO-0042 name: Camera package rental contactId: con_77a budgetLineId: bud_5510 dueDate: '2026-05-20' serviceStartAt: '2026-05-21' serviceEndAt: '2026-05-24' notes: Net-30 items: - description: Alexa Mini LF body qty: '5' unit: day rate: '25000' PurchaseOrderUpdate: type: object description: Fields to update on a draft or rejected purchase order. additionalProperties: false properties: projectId: type: - string - 'null' description: Project ID or slug. Set to `null` to unassign the purchase order. number: type: - string - 'null' name: type: - string - 'null' contactId: type: - string - 'null' budgetLineId: type: - string - 'null' dueDate: type: - string - 'null' format: date serviceStartAt: type: - string - 'null' format: date serviceEndAt: type: - string - 'null' format: date notes: type: - string - 'null' sort: type: - number - 'null' examples: - name: Camera package rental (updated) notes: Net-45 PurchaseOrderItemWrite: type: object description: Fields for a new or updated purchase order item. additionalProperties: false properties: lineNumber: type: - string - 'null' description: type: - string - 'null' budgetLineId: type: - string - 'null' qty: type: - string - 'null' unit: type: - string - 'null' rate: type: - string - 'null' amount: type: - integer - 'null' format: int64 description: "Item total in minor currency units. Defaults to `qty \xD7 rate`." sort: type: - string - 'null' examples: - description: Alexa Mini LF body budgetLineId: bud_5510 qty: '5' unit: day rate: '25000' PurchaseOrderList: type: object description: A paginated page of purchase orders. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/PurchaseOrder' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total number of matches. Included when `withCount=true`. truncated: type: boolean description: Whether the page contains fewer results than requested. PurchaseOrderItemList: type: object description: A page of purchase-order line items. required: - data additionalProperties: false properties: data: type: array items: $ref: '#/components/schemas/PurchaseOrderItem' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total number of matches. Included when `withCount=true`. truncated: type: boolean description: Whether the page contains fewer results than requested. SearchKind: type: string description: Resource types included in search. enum: - transactions - documents - contacts - budget-lines - purchase-orders examples: - transactions SearchHit: type: object description: One search result. required: - kind - id - label - score additionalProperties: false properties: kind: $ref: '#/components/schemas/SearchKind' id: allOf: - $ref: '#/components/schemas/Id' description: ID of the matched resource. label: type: string description: Display label for the result. examples: - Panavision Camera Package snippet: type: string description: Matching text when it differs from `label`. examples: - Invoice 4471, Panavision rental score: type: number format: float minimum: 0 maximum: 1 description: Relevance from 0 to 1. Higher values are more relevant. examples: - 0.62 SearchResponse: type: object description: A page of search results ordered by relevance. required: - data - searchedTypes additionalProperties: false properties: data: type: array description: Results for this page. items: $ref: '#/components/schemas/SearchHit' nextCursor: allOf: - $ref: '#/components/schemas/NextCursor' description: Cursor for the next page. Use it with the same `q` and `types`. examples: - eyJzIjowLjYyLCJrIjoidHJhbnNhY3Rpb25zIiwiaWQiOiJ0eG5fOGYyYSJ9 count: type: integer description: Total matching hits; present only when `withCount=true`. searchedTypes: type: array description: Resource types searched for this request. items: $ref: '#/components/schemas/SearchKind' examples: - - transactions - documents - budget-lines TransactionSource: type: string description: How the transaction entered Saturation. Financial fields are editable only for `manual` transactions. enum: - manual - plaid - saturation_pay - saturation_credit examples: - manual TransactionType: type: string description: Transaction type. The API may return values not listed below. x-extensible-enum: true enum: - SaturationPCard - ACH - Cash - Check - CreditCard - Deposit - ETransfer - Invoice - Projection - TimeCard - Wire - Withdrawal examples: - CreditCard TransactionManualType: type: string description: Transaction types available for manual transactions. enum: - Invoice - Projection - Cash - Check - Wire - ACH - CreditCard - TimeCard - ETransfer examples: - Invoice TransactionStatus: type: string description: Current transaction status. Available statuses vary by source. enum: - unpaid - pending - posted - void - needs_review - projected - rejected examples: - posted ExchangeRateSource: type: string description: Source of the exchange rate. The API may return values not listed below. x-extensible-enum: true enum: - bank - api - user examples: - bank TransactionExpandKey: type: string description: Related records available through `expand`. Unknown keys or nesting beyond two levels return `400 expand_invalid`. enum: - contact - documents - items - account - purchaseOrder - items.account examples: - items.account TransactionSortField: type: string description: Fields available for sorting. The default is `timestamp` in descending order. enum: - timestamp - amount - status - type - description - createdAt - updatedAt default: timestamp examples: - timestamp TransactionItem: type: object description: An item in an itemized transaction. Budget coding belongs to each item instead of the transaction. additionalProperties: false required: - id - lineNumber - amount - tagIds - tags properties: id: allOf: - $ref: '#/components/schemas/Id' description: Transaction item ID. examples: - txi_4a1b2c3d lineNumber: type: - string - 'null' description: Line number shown in the itemization. examples: - '1' description: type: - string - 'null' description: Item description. budgetLineId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Budget line ID. fringeId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Applied fringe ID. contactId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Contact for this item. qty: type: - string - 'null' description: Quantity or formula. examples: - '3' unit: type: - string - 'null' description: Unit, such as `Day`, `Hour`, or `Flat`. examples: - Day customUnitId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Custom unit ID. rate: type: - string - 'null' description: Rate or formula. amount: oneOf: - $ref: '#/components/schemas/Money' - type: 'null' overtime: type: - string - 'null' description: Overtime amount or formula. taxable: type: - string - 'null' description: Taxable amount or formula. nonTaxable: type: - string - 'null' description: Non-taxable amount or formula. account: description: Budget account for the item. Included with `expand=items.account`. oneOf: - $ref: '#/components/schemas/TransactionAccountRef' - type: 'null' tagIds: type: array description: Tag IDs assigned to this item. items: $ref: '#/components/schemas/Id' tags: type: array description: Tags assigned to this item. items: $ref: '#/components/schemas/TransactionItemTag' TransactionItemTag: type: object additionalProperties: false required: - id - name - color properties: id: $ref: '#/components/schemas/Id' name: type: string color: type: - string - 'null' TransactionItemCreate: type: object description: Fields for a new transaction item. additionalProperties: false required: - amount properties: lineNumber: type: string description: type: string budgetLineId: $ref: '#/components/schemas/Id' fringeId: $ref: '#/components/schemas/Id' contactId: $ref: '#/components/schemas/Id' qty: type: string unit: type: string customUnitId: $ref: '#/components/schemas/Id' rate: type: string amount: $ref: '#/components/schemas/Money' overtime: type: string taxable: type: string nonTaxable: type: string tagIds: type: array description: Tag IDs to assign. Duplicate IDs are ignored. items: $ref: '#/components/schemas/Id' TransactionItemPatch: type: object description: Fields to update on a transaction item. Read-only fields return `422 field_read_only`. additionalProperties: false minProperties: 1 properties: lineNumber: type: - string - 'null' description: type: - string - 'null' budgetLineId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' fringeId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' contactId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' qty: type: - string - 'null' unit: type: - string - 'null' customUnitId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' rate: type: - string - 'null' amount: oneOf: - $ref: '#/components/schemas/Money' - type: 'null' overtime: type: - string - 'null' taxable: type: - string - 'null' nonTaxable: type: - string - 'null' tagIds: type: array description: Replaces the item's tags. Send an empty array to remove all tags. items: $ref: '#/components/schemas/Id' TransactionAccountRef: type: object description: Budget account included through `expand=account` or `expand=items.account`. additionalProperties: false required: - id properties: id: $ref: '#/components/schemas/Id' name: type: string examples: - Camera code: type: - string - 'null' description: Account code. examples: - '1200' Transaction: type: object description: A transaction in Saturation. Money uses minor currency units. additionalProperties: false required: - id - source - type - status - isReversal - amount - timestamp - isItemized - actualized - projectId - createdAt - updatedAt properties: id: allOf: - $ref: '#/components/schemas/Id' description: Transaction ID. examples: - txn_8f2a1c9e source: $ref: '#/components/schemas/TransactionSource' sourceId: type: - string - 'null' description: Reference supplied by the transaction source. type: anyOf: - $ref: '#/components/schemas/TransactionType' - type: 'null' status: $ref: '#/components/schemas/TransactionStatus' isReversal: type: boolean description: Whether the transaction is a refund or another reversal. amount: $ref: '#/components/schemas/Money' exchangeRate: type: - number - 'null' description: Exchange rate to the workspace currency. exchangeRateSource: oneOf: - $ref: '#/components/schemas/ExchangeRateSource' - type: 'null' timestamp: type: string format: date-time description: Time the transaction occurred. examples: - '2026-05-20T14:03:00.000Z' description: type: - string - 'null' merchant: type: - string - 'null' description: Merchant name supplied by the transaction source. logoUrl: type: - string - 'null' format: uri description: Merchant logo URL. category: type: - string - 'null' description: Category supplied by the transaction source. sourceLast4: type: - string - 'null' description: Last four characters of the source account or card. sourceName: type: - string - 'null' description: Name of the source account or card. number: type: - string - 'null' description: Document, check, or invoice number. ref: type: - string - 'null' description: External reference. payId: type: - string - 'null' description: Related Saturation Pay payment ID. notes: type: - string - 'null' description: Notes about the transaction. contactId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Assigned contact ID. projectId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Assigned project ID, or `null` when unassigned. budgetLineId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Budget line ID. Itemized transactions store this on each item instead. fringeId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' isItemized: type: boolean description: Whether the transaction has items. actualized: type: boolean description: Whether the transaction is included in budget actuals. purchaseOrderId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Linked purchase order ID. createdAt: type: string format: date-time updatedAt: type: string format: date-time contact: description: Assigned contact. Included with `expand=contact`. oneOf: - $ref: '#/components/schemas/TransactionContactRef' - type: 'null' documents: description: Related documents. Included with `expand=documents`. type: array items: $ref: '#/components/schemas/TransactionDocumentRef' items: type: array description: Transaction items. Included with `expand=items`. items: $ref: '#/components/schemas/TransactionItem' account: description: Budget account. Included with `expand=account`. oneOf: - $ref: '#/components/schemas/TransactionAccountRef' - type: 'null' purchaseOrder: description: Linked purchase order. Included with `expand=purchaseOrder`. oneOf: - $ref: '#/components/schemas/TransactionPurchaseOrderRef' - type: 'null' TransactionContactRef: type: object description: Contact details included with a transaction. required: - id - name additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: - string - 'null' TransactionDocumentRef: type: object description: Document details included with a transaction. required: - id - name additionalProperties: false properties: id: $ref: '#/components/schemas/Id' name: type: - string - 'null' TransactionPurchaseOrderRef: type: object description: Purchase order details included with a transaction. required: - id - number additionalProperties: false properties: id: $ref: '#/components/schemas/Id' number: type: - string - 'null' TransactionManualCreate: type: object description: Fields for a new manual transaction. additionalProperties: false required: - type - amount - timestamp properties: type: $ref: '#/components/schemas/TransactionManualType' amount: $ref: '#/components/schemas/Money' timestamp: type: string format: date-time description: Transaction time. A date without a time is recorded at midnight UTC. status: allOf: - $ref: '#/components/schemas/TransactionStatus' description: Transaction status. Defaults to `posted`. description: type: string projectId: allOf: - $ref: '#/components/schemas/Id' description: Project ID or slug. Omit to leave the transaction unassigned. contactId: $ref: '#/components/schemas/Id' budgetLineId: allOf: - $ref: '#/components/schemas/Id' description: Budget line ID. Omit for an itemized transaction. fringeId: $ref: '#/components/schemas/Id' number: type: string ref: type: string notes: type: string actualized: type: boolean description: Whether to include the transaction in budget actuals. Defaults to the workspace setting. TransactionPatch: type: object description: Fields to update on a transaction. Financial fields are editable only on manual transactions. additionalProperties: false minProperties: 1 properties: projectId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' description: Project ID or slug. Set to `null` to unassign the transaction. contactId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' budgetLineId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' fringeId: anyOf: - $ref: '#/components/schemas/Id' - type: 'null' notes: type: - string - 'null' number: type: - string - 'null' ref: type: - string - 'null' amount: $ref: '#/components/schemas/Money' timestamp: type: string format: date-time description: Transaction time. A date without a time is recorded at midnight UTC. type: $ref: '#/components/schemas/TransactionType' status: $ref: '#/components/schemas/TransactionStatus' description: type: - string - 'null' merchant: type: - string - 'null' sourceLast4: type: - string - 'null' sourceName: type: - string - 'null' actualized: type: boolean description: Whether the transaction is included in budget actuals. TransactionBulkCreate: type: object description: Up to 500 manual transactions to create in one request. additionalProperties: false required: - transactions properties: transactions: type: array minItems: 1 maxItems: 500 description: Manual transactions to create. items: $ref: '#/components/schemas/TransactionManualCreate' TransactionCollection: type: object description: A page of transactions. additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Transaction' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total number of matches. Included when `withCount=true`. truncated: type: boolean description: Whether the page contains fewer results than requested. statusReachability: $ref: '#/components/schemas/StatusReachabilityMatrix' TransactionItemCollection: type: object description: The itemized lines of a transaction. additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/TransactionItem' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total number of matches. Included when `withCount=true`. truncated: type: boolean description: Whether the page contains fewer results than requested. TransactionStats: type: object description: Number and total amount of matching transactions. additionalProperties: false required: - total - amount properties: total: type: integer description: Number of matching transactions. examples: - 142 amount: $ref: '#/components/schemas/Money' StatusReachabilityMatrix: type: object description: Transaction statuses available for each source. additionalProperties: type: array items: $ref: '#/components/schemas/TransactionStatus' examples: - manual: - posted - void - projected plaid: - pending - posted - void - needs_review saturation_pay: - unpaid - pending - posted - void - rejected saturation_credit: - pending - posted - void - needs_review - rejected WebhookEvent: type: string description: Event types available for webhook subscriptions. enum: - transaction.created - transaction.updated - budget.changed - purchaseOrder.created - purchaseOrder.pending - purchaseOrder.approved - purchaseOrder.rejected - purchaseOrder.actualizing - purchaseOrder.paid - purchaseOrder.void - document.created - document.linked - document.unlinked - document.deleted - incentive.added - pack.installed - pack.uninstalled examples: - transaction.created WebhookDeliveryEvent: type: string description: Event recorded for a delivery. `ping` is used by test deliveries. enum: - transaction.created - transaction.updated - budget.changed - purchaseOrder.created - purchaseOrder.pending - purchaseOrder.approved - purchaseOrder.rejected - purchaseOrder.actualizing - purchaseOrder.paid - purchaseOrder.void - document.created - document.linked - document.unlinked - document.deleted - incentive.added - pack.installed - pack.uninstalled - ping WebhookDeliveryStatus: type: string description: Outcome of a delivery. `pending` may be retried. `success`, `failed`, `blocked`, and `dropped` are final. enum: - pending - success - failed - blocked - dropped Webhook: type: object description: A webhook subscription for a workspace or project. additionalProperties: false required: - id - url - events - isActive - workspaceId - createdAt - updatedAt properties: id: &id057 allOf: - $ref: '#/components/schemas/Id' description: "Subscription identifier (`whk_\u2026`)." examples: - whk_5c1a9e02 url: &id058 type: string format: uri description: HTTPS destination for deliveries. The host must resolve to a public address. examples: - https://hooks.example.com/saturation events: &id059 type: array description: Event types delivered to this endpoint. minItems: 1 items: $ref: '#/components/schemas/WebhookEvent' isActive: &id060 type: boolean description: Whether the subscription currently receives deliveries. Toggled via PATCH; a webhook continues to exist while paused. workspaceId: &id061 allOf: - $ref: '#/components/schemas/Id' description: Workspace ID. projectId: &id062 allOf: - $ref: '#/components/schemas/Id' description: Project ID when the subscription is limited to one project. lastDeliveryAt: &id063 type: string format: date-time description: Time of the most recent delivery attempt. lastDeliveryStatus: &id064 allOf: - $ref: '#/components/schemas/WebhookDeliveryStatus' description: Outcome of the most recent delivery attempt. createdAt: &id065 type: string format: date-time description: ISO-8601 creation timestamp. updatedAt: &id066 type: string format: date-time description: ISO-8601 last-update timestamp. WebhookWithSecret: type: object description: A newly created webhook subscription and its signing secret. additionalProperties: false required: - id - url - events - isActive - workspaceId - createdAt - updatedAt - secret properties: id: *id057 url: *id058 events: *id059 isActive: *id060 workspaceId: *id061 projectId: *id062 lastDeliveryAt: *id063 lastDeliveryStatus: *id064 createdAt: *id065 updatedAt: *id066 secret: type: string description: HMAC secret used to verify `X-Saturation-Signature`. Returned only when the subscription is created. examples: - whsec_example WebhookCreate: type: object description: Fields for a new webhook subscription. additionalProperties: false required: - url - events properties: url: type: string format: uri description: HTTPS destination. The host must resolve to a public address. examples: - https://hooks.example.com/saturation events: type: array description: One or more event types to subscribe to. minItems: 1 items: $ref: '#/components/schemas/WebhookEvent' secret: type: string description: Signing secret. When omitted, the create response includes a generated secret. minLength: 16 maxLength: 256 projectId: allOf: - $ref: '#/components/schemas/Id' description: Project ID when the subscription should receive events for one project only. WebhookUpdate: type: object description: Writable webhook subscription fields. additionalProperties: false minProperties: 1 properties: url: type: string format: uri description: New HTTPS destination. The host must resolve to a public address. examples: - https://hooks.example.com/saturation/v2 events: type: array description: Replacement event set. minItems: 1 items: $ref: '#/components/schemas/WebhookEvent' isActive: type: boolean description: Pause (`false`) or resume (`true`) deliveries. WebhookDelivery: type: object description: One webhook delivery and its retry state. additionalProperties: false required: - id - event - status - entityKind - entityId - attempts - occurredAt properties: id: allOf: - $ref: '#/components/schemas/Id' description: Delivery ID. It remains the same across retries. examples: - whd_9a02c1e5 event: $ref: '#/components/schemas/WebhookDeliveryEvent' status: $ref: '#/components/schemas/WebhookDeliveryStatus' entityKind: type: string description: The kind of entity the event concerns (e.g. `transaction`, `budget`, `purchaseOrder`, `document`). examples: - transaction entityId: allOf: - $ref: '#/components/schemas/Id' description: ID of the resource that changed. examples: - txn_8f2a1c9e requestUrl: type: string format: uri description: URL used for the delivery. examples: - https://hooks.example.com/saturation responseStatus: type: integer description: HTTP status returned by the endpoint, when available. examples: - 200 attempts: type: integer description: Number of delivery attempts. minimum: 1 examples: - 1 nextRetryAt: type: string format: date-time description: Time of the next retry. Present only while the delivery is pending. error: type: string description: Failure details when the delivery did not succeed. occurredAt: type: string format: date-time description: ISO-8601 timestamp of when the originating event occurred. deliveredAt: type: string format: date-time description: ISO-8601 timestamp of the terminal attempt. Absent while `pending`. WebhookEventPayload: type: object description: Webhook request body. Use `data` to fetch the current resource. additionalProperties: false required: - id - event - workspaceId - occurredAt - data properties: id: allOf: - $ref: '#/components/schemas/Id' description: Delivery ID for duplicate detection. event: $ref: '#/components/schemas/WebhookDeliveryEvent' workspaceId: allOf: - $ref: '#/components/schemas/Id' description: "The workspace the event belongs to (`ws_\u2026`)." workspaceName: type: string description: Workspace name when available. projectId: allOf: - $ref: '#/components/schemas/Id' description: Project ID for project-scoped events. projectName: type: string description: Project name when available. occurredAt: type: string format: date-time description: ISO-8601 timestamp of the originating change. data: type: object description: The record to fetch. additionalProperties: false required: - kind - id properties: kind: type: string description: Type of resource that changed. examples: - transaction id: allOf: - $ref: '#/components/schemas/Id' description: ID of the resource that changed. examples: - txn_8f2a1c9e WebhookCollection: type: object description: A paginated page of webhook subscriptions. additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/Webhook' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether inaccessible records shortened this page. WebhookDeliveryCollection: type: object description: A paginated page of delivery attempts for one subscription. additionalProperties: false required: - data properties: data: type: array items: $ref: '#/components/schemas/WebhookDelivery' nextCursor: $ref: '#/components/schemas/NextCursor' count: type: integer description: Total matching items; present only when `withCount=true` was requested. truncated: type: boolean description: Whether inaccessible records shortened this page.