{"openapi":"3.1.0","info":{"title":"AutoRFP.ai Public API","version":"1.0.0","description":"Public API for AutoRFP.ai"},"servers":[{"url":"https://api.autorfp.ai","description":"AU"},{"url":"https://api.us.autorfp.ai","description":"US"},{"url":"https://api.eu.autorfp.ai","description":"EU"}],"components":{"securitySchemes":{"bearerApiKey":{"type":"http","scheme":"bearer","description":"API key authentication for /v1/* endpoints. Use your API key as the Bearer token."}},"schemas":{"JsonApiError":{"type":"object","properties":{"errors":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"title":{"type":"string"},"detail":{"type":"string"},"code":{"type":"string"}},"required":["status","title"]}}},"required":["errors"]},"ProjectListItem":{"type":"object","properties":{"type":{"type":"string","enum":["projects"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Project name"},"status":{"type":"string","description":"Current project status"},"prospectName":{"type":"string","description":"Name of the prospect or issuer"},"projectType":{"type":["string","null"],"description":"Project type (e.g. \"rfp\", \"rfi\")"},"createdAt":{"type":["string","null"],"description":"ISO 8601 datetime when the project was created"},"dueDate":{"type":["string","null"],"description":"ISO 8601 datetime when the project is due"},"externalIds":{"type":"object","properties":{"salesforceId":{"type":["string","null"],"description":"Salesforce external ID"},"opportunityId":{"type":["string","null"],"description":"Salesforce opportunity ID"}},"required":["salesforceId","opportunityId"]}},"required":["name","status","prospectName","projectType","createdAt","dueDate","externalIds"]}},"required":["type","id","attributes"]},"ProjectSummary":{"type":"object","properties":{"type":{"type":"string","enum":["projects"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Project name"},"issuer":{"type":"string","description":"Name of the issuing organisation"},"status":{"type":"string","description":"Current project status"},"createdAt":{"type":"string","description":"ISO 8601 datetime when the project was created"},"dueDate":{"type":["string","null"],"description":"ISO 8601 datetime when the project is due"},"projectType":{"type":["string","null"],"description":"Same as list: value of the custom field with id project_type when present on the project; otherwise null"},"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Field id (pass as id in PATCH /v1/projects/{projectId})"},"label":{"type":"string","description":"Human-readable field label"},"type":{"type":"string","enum":["text","number","date","dropdown","multiselect","checkbox"],"description":"Field value type"},"externalId":{"type":["string","null"],"description":"Optional CRM/external key (pass as externalId in PATCH)"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]},"description":"Static options currently on the project snapshot. PATCH allowlists use the organisation template optionSource after refresh — prefer GET /v1/organisation for the live list."},"optionSource":{"type":"object","properties":{"type":{"type":"string","enum":["dynamic"]},"set":{"type":"string"}},"required":["type","set"],"description":"Dynamic option set on the project snapshot (e.g. users, usersAndTeams, teams). For known sets, PATCH values must be org members using user:<id> / team:<id> (bare id = legacy user)."},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"null"}],"description":"Scalar value for text, number, date, dropdown, or checkbox. Dates are ISO 8601 with offset (e.g. 2024-01-15T00:00:00.000+00:00)."},"values":{"type":"array","items":{"type":"string"},"description":"Multiselect values (clear with [])"}},"required":["id","label","type","externalId"]},"description":"Current custom field values on the project (empty when none are configured)"},"summary":{"type":"object","properties":{"requirementsCount":{"type":"number","description":"Total number of requirements"},"approvedCount":{"type":"number","description":"Number of approved requirements"},"submittedCount":{"type":"number","description":"Number of requirements submitted for review"}},"required":["requirementsCount","approvedCount","submittedCount"]}},"required":["name","issuer","status","createdAt","dueDate","projectType","customFields","summary"]}},"required":["type","id","attributes"]},"ContentListItem":{"type":"object","properties":{"type":{"type":"string","enum":["content"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"title":{"type":["string","null"],"description":"Content title — question text for QA, section heading for documentation"},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":["string","null"]}},"required":["id","label"]},"description":"Assigned tags: id plus resolved label (label null when the id is not in the current tag vocabulary — an orphan)"},"teamOwnerIds":{"type":"array","items":{"type":"string"},"description":"IDs of teams that own this content"},"createdAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was created"},"updatedAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was last updated"},"reviewedAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was last reviewed"},"projectUsageCount":{"type":"number","description":"Number of distinct non-deleted projects that currently reference this content. Live reverse-lookup, not the stored monotonic usageProjectCount."}},"required":["title","tags","teamOwnerIds","createdAt","updatedAt","reviewedAt","projectUsageCount"]}},"required":["type","id","attributes"]},"ContentUsageItem":{"type":"object","properties":{"type":{"type":"string","enum":["content-usage"]},"id":{"type":"string","description":"Response ID"},"attributes":{"type":"object","properties":{"projectId":{"type":"string","description":"ID of the project where the content was used"},"requirementId":{"type":"string","description":"ID of the requirement (response ID)"},"usageType":{"type":"string","enum":["verbatim","ai_generation","user_added"],"description":"How the content was used. 'verbatim' = the response engine used this content as the direct answer source. 'ai_generation' = the response engine used this content as supporting context. 'user_added' = a user explicitly inserted this content into the response while editing."}},"required":["projectId","requirementId","usageType"]}},"required":["type","id","attributes"]},"BulkTagRequest":{"type":"object","properties":{"type":{"type":"string","enum":["add","remove","replace"],"description":"How to apply the tags: 'add', 'remove', or 'replace'."},"items":{"type":"array","items":{"type":"object","properties":{"contentId":{"type":"string","minLength":1,"maxLength":128,"description":"Content embedding id to tag (max 128 chars)"},"tagIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":128},"maxItems":100,"description":"Tag ids to add/remove/replace on the item (max 100, each max 128 chars)"}},"required":["contentId","tagIds"]},"minItems":1,"maxItems":500,"description":"Content items to update (max 500 per request, unique contentId per item)"}},"required":["type","items"]},"BulkTagResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["content-tag-assignment-result"]},"id":{"type":"string","description":"Server-generated batch result id (not a content or tag id)"},"attributes":{"type":"object","properties":{"type":{"type":"string","enum":["add","remove","replace"],"description":"The operation type from the request"},"counts":{"type":"object","properties":{"totalItems":{"type":"number","description":"Number of items in the request"},"successfulItems":{"type":"number","description":"Number of items whose tags were updated"},"unsuccessfulItems":{"type":"number","description":"Number of items that were not updated"}},"required":["totalItems","successfulItems","unsuccessfulItems"]},"successfulContentIds":{"type":"array","items":{"type":"string"},"description":"Content ids whose tags were updated"},"failures":{"type":"array","items":{"type":"object","properties":{"contentId":{"type":"string"},"code":{"type":"string","enum":["content-not-found","no-edit-access","tag-not-found","write-failed"]},"tagIds":{"type":"array","items":{"type":"string"}}},"required":["contentId","code"]},"description":"Per-item outcomes that need attention. A contentId may appear here as tag-not-found while still being in successfulContentIds (valid tags were applied). content-not-found / no-edit-access mean the item was not updated. write-failed means the update did not fully succeed and may be partially applied (e.g. stored but the search index not yet updated); the operations are idempotent, so re-issue the same request to converge. tagIds is set for tag-not-found."}},"required":["type","counts","successfulContentIds","failures"]}},"required":["type","id","attributes"]}},"required":["data"]},"TagCategoryListItem":{"type":"object","properties":{"type":{"type":"string","enum":["tag-category"]},"id":{"type":"string","description":"Tag category id"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Tag category name"},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Tag id — pass in `tagIds` when calling POST /v1/content/tags"},"label":{"type":"string","description":"Human-readable tag label"},"parentId":{"type":["string","null"],"description":"Parent tag id for hierarchical tags, or null"}},"required":["id","label","parentId"]},"description":"Tags belonging to this category"}},"required":["name","tags"]}},"required":["type","id","attributes"]},"ListTagCategoriesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["tag-category"]},"id":{"type":"string","description":"Tag category id"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Tag category name"},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Tag id — pass in `tagIds` when calling POST /v1/content/tags"},"label":{"type":"string","description":"Human-readable tag label"},"parentId":{"type":["string","null"],"description":"Parent tag id for hierarchical tags, or null"}},"required":["id","label","parentId"]},"description":"Tags belonging to this category"}},"required":["name","tags"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"count":{"type":"number"}},"required":["count"]}},"required":["data","meta"]},"ListContentUsageResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["content-usage"]},"id":{"type":"string","description":"Response ID"},"attributes":{"type":"object","properties":{"projectId":{"type":"string","description":"ID of the project where the content was used"},"requirementId":{"type":"string","description":"ID of the requirement (response ID)"},"usageType":{"type":"string","enum":["verbatim","ai_generation","user_added"],"description":"How the content was used. 'verbatim' = the response engine used this content as the direct answer source. 'ai_generation' = the response engine used this content as supporting context. 'user_added' = a user explicitly inserted this content into the response while editing."}},"required":["projectId","requirementId","usageType"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"page":{"type":"object","properties":{"number":{"type":"number"},"size":{"type":"number"},"totalItems":{"type":"number"},"totalPages":{"type":"number"}},"required":["number","size","totalItems","totalPages"]}},"required":["page"]},"links":{"type":"object","properties":{"self":{"type":"string"},"first":{"type":"string"},"last":{"type":["string","null"]},"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["self","first","last","prev","next"]}},"required":["data","meta","links"]},"RequirementListItem":{"type":"object","properties":{"type":{"type":"string","enum":["requirements"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"status":{"type":"string","description":"Requirement status (drafted, assigned, submittedForReview, approved)"},"editorTeamIds":{"type":"array","items":{"type":"string"},"description":"Team IDs derived from assigned editors"},"reviewerTeamIds":{"type":"array","items":{"type":"string"},"description":"Team IDs derived from assigned reviewers"},"editPercentage":{"type":["number","null"],"description":"Edit percentage as a 0-1 value, null if no metrics available"}},"required":["status","editorTeamIds","reviewerTeamIds","editPercentage"]}},"required":["type","id","attributes"]},"ListRequirementsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["requirements"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"status":{"type":"string","description":"Requirement status (drafted, assigned, submittedForReview, approved)"},"editorTeamIds":{"type":"array","items":{"type":"string"},"description":"Team IDs derived from assigned editors"},"reviewerTeamIds":{"type":"array","items":{"type":"string"},"description":"Team IDs derived from assigned reviewers"},"editPercentage":{"type":["number","null"],"description":"Edit percentage as a 0-1 value, null if no metrics available"}},"required":["status","editorTeamIds","reviewerTeamIds","editPercentage"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"page":{"type":"object","properties":{"number":{"type":"number"},"size":{"type":"number"},"totalItems":{"type":"number"},"totalPages":{"type":"number"}},"required":["number","size","totalItems","totalPages"]}},"required":["page"]},"links":{"type":"object","properties":{"self":{"type":"string"},"first":{"type":"string"},"last":{"type":["string","null"]},"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["self","first","last","prev","next"]}},"required":["data","meta","links"]},"ListContentResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["content"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"title":{"type":["string","null"],"description":"Content title — question text for QA, section heading for documentation"},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":["string","null"]}},"required":["id","label"]},"description":"Assigned tags: id plus resolved label (label null when the id is not in the current tag vocabulary — an orphan)"},"teamOwnerIds":{"type":"array","items":{"type":"string"},"description":"IDs of teams that own this content"},"createdAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was created"},"updatedAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was last updated"},"reviewedAt":{"type":["string","null"],"description":"ISO 8601 datetime when the content was last reviewed"},"projectUsageCount":{"type":"number","description":"Number of distinct non-deleted projects that currently reference this content. Live reverse-lookup, not the stored monotonic usageProjectCount."}},"required":["title","tags","teamOwnerIds","createdAt","updatedAt","reviewedAt","projectUsageCount"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"page":{"type":"object","properties":{"number":{"type":"number"},"size":{"type":"number"},"totalItems":{"type":"number"},"totalPages":{"type":"number"}},"required":["number","size","totalItems","totalPages"]}},"required":["page"]},"links":{"type":"object","properties":{"self":{"type":"string"},"first":{"type":"string"},"last":{"type":["string","null"]},"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["self","first","last","prev","next"]}},"required":["data","meta","links"]},"ListProjectsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["projects"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Project name"},"status":{"type":"string","description":"Current project status"},"prospectName":{"type":"string","description":"Name of the prospect or issuer"},"projectType":{"type":["string","null"],"description":"Project type (e.g. \"rfp\", \"rfi\")"},"createdAt":{"type":["string","null"],"description":"ISO 8601 datetime when the project was created"},"dueDate":{"type":["string","null"],"description":"ISO 8601 datetime when the project is due"},"externalIds":{"type":"object","properties":{"salesforceId":{"type":["string","null"],"description":"Salesforce external ID"},"opportunityId":{"type":["string","null"],"description":"Salesforce opportunity ID"}},"required":["salesforceId","opportunityId"]}},"required":["name","status","prospectName","projectType","createdAt","dueDate","externalIds"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"page":{"type":"object","properties":{"number":{"type":"number"},"size":{"type":"number"},"totalItems":{"type":"number"},"totalPages":{"type":"number"}},"required":["number","size","totalItems","totalPages"]}},"required":["page"]},"links":{"type":"object","properties":{"self":{"type":"string"},"first":{"type":"string"},"last":{"type":["string","null"]},"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["self","first","last","prev","next"]}},"required":["data","meta","links"]},"TeamListItem":{"type":"object","properties":{"type":{"type":"string","enum":["teams"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Team name"}},"required":["name"]}},"required":["type","id","attributes"]},"ListTeamsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["teams"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Team name"}},"required":["name"]}},"required":["type","id","attributes"]}},"meta":{"type":"object","properties":{"page":{"type":"object","properties":{"number":{"type":"number"},"size":{"type":"number"},"totalItems":{"type":"number"},"totalPages":{"type":"number"}},"required":["number","size","totalItems","totalPages"]}},"required":["page"]},"links":{"type":"object","properties":{"self":{"type":"string"},"first":{"type":"string"},"last":{"type":["string","null"]},"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["self","first","last","prev","next"]}},"required":["data","meta","links"]},"GetProjectResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["projects"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Project name"},"issuer":{"type":"string","description":"Name of the issuing organisation"},"status":{"type":"string","description":"Current project status"},"createdAt":{"type":"string","description":"ISO 8601 datetime when the project was created"},"dueDate":{"type":["string","null"],"description":"ISO 8601 datetime when the project is due"},"projectType":{"type":["string","null"],"description":"Same as list: value of the custom field with id project_type when present on the project; otherwise null"},"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Field id (pass as id in PATCH /v1/projects/{projectId})"},"label":{"type":"string","description":"Human-readable field label"},"type":{"type":"string","enum":["text","number","date","dropdown","multiselect","checkbox"],"description":"Field value type"},"externalId":{"type":["string","null"],"description":"Optional CRM/external key (pass as externalId in PATCH)"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]},"description":"Static options currently on the project snapshot. PATCH allowlists use the organisation template optionSource after refresh — prefer GET /v1/organisation for the live list."},"optionSource":{"type":"object","properties":{"type":{"type":"string","enum":["dynamic"]},"set":{"type":"string"}},"required":["type","set"],"description":"Dynamic option set on the project snapshot (e.g. users, usersAndTeams, teams). For known sets, PATCH values must be org members using user:<id> / team:<id> (bare id = legacy user)."},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"null"}],"description":"Scalar value for text, number, date, dropdown, or checkbox. Dates are ISO 8601 with offset (e.g. 2024-01-15T00:00:00.000+00:00)."},"values":{"type":"array","items":{"type":"string"},"description":"Multiselect values (clear with [])"}},"required":["id","label","type","externalId"]},"description":"Current custom field values on the project (empty when none are configured)"},"summary":{"type":"object","properties":{"requirementsCount":{"type":"number","description":"Total number of requirements"},"approvedCount":{"type":"number","description":"Number of approved requirements"},"submittedCount":{"type":"number","description":"Number of requirements submitted for review"}},"required":["requirementsCount","approvedCount","submittedCount"]}},"required":["name","issuer","status","createdAt","dueDate","projectType","customFields","summary"]}},"required":["type","id","attributes"]}},"required":["data"]},"OrganisationResource":{"type":"object","properties":{"type":{"type":"string","enum":["organisation"]},"id":{"type":"string","description":"Organisation id"},"attributes":{"type":"object","properties":{"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable field id — pass as id in PATCH /v1/projects/{projectId}"},"label":{"type":"string","description":"Human-readable field label"},"type":{"type":"string","enum":["text","number","date","dropdown","multiselect","checkbox"],"description":"Field value type"},"required":{"type":"boolean","description":"Organisation-template required flag. PATCH uses each field.required on the project working set (cloned/appended from this template when missing; existing project flags are not rewritten). See PATCH docs for snapshot∪touched rules."},"section":{"type":["string","null"],"description":"UI section grouping, or null"},"manageOnly":{"type":"boolean","description":"Product UI may hide this field from non-managers. Ignored by PATCH (no write-deny; still counts when the project field is required)."},"externalId":{"type":["string","null"],"description":"Optional CRM/external key — pass as externalId in PATCH"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]},"description":"Static dropdown/multiselect options on the organisation template. Non-empty PATCH refreshes matched project optionSource from this template."},"optionSource":{"type":"object","properties":{"type":{"type":"string","enum":["dynamic"]},"set":{"type":"string"}},"required":["type","set"],"description":"Dynamic option set (e.g. users, usersAndTeams, teams). For known sets, PATCH requires org membership via user:<id> / team:<id> (bare id = legacy user). Non-empty PATCH refreshes matched project optionSource from this template."},"multiline":{"type":"boolean","description":"Present on text fields when multiline is enabled"}},"required":["id","label","type","required","section","manageOnly","externalId"]},"description":"Organisation custom project field definitions. Empty when no template is configured."}},"required":["customFields"]}},"required":["type","id","attributes"]},"GetOrganisationResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["organisation"]},"id":{"type":"string","description":"Organisation id"},"attributes":{"type":"object","properties":{"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stable field id — pass as id in PATCH /v1/projects/{projectId}"},"label":{"type":"string","description":"Human-readable field label"},"type":{"type":"string","enum":["text","number","date","dropdown","multiselect","checkbox"],"description":"Field value type"},"required":{"type":"boolean","description":"Organisation-template required flag. PATCH uses each field.required on the project working set (cloned/appended from this template when missing; existing project flags are not rewritten). See PATCH docs for snapshot∪touched rules."},"section":{"type":["string","null"],"description":"UI section grouping, or null"},"manageOnly":{"type":"boolean","description":"Product UI may hide this field from non-managers. Ignored by PATCH (no write-deny; still counts when the project field is required)."},"externalId":{"type":["string","null"],"description":"Optional CRM/external key — pass as externalId in PATCH"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]},"description":"Static dropdown/multiselect options on the organisation template. Non-empty PATCH refreshes matched project optionSource from this template."},"optionSource":{"type":"object","properties":{"type":{"type":"string","enum":["dynamic"]},"set":{"type":"string"}},"required":["type","set"],"description":"Dynamic option set (e.g. users, usersAndTeams, teams). For known sets, PATCH requires org membership via user:<id> / team:<id> (bare id = legacy user). Non-empty PATCH refreshes matched project optionSource from this template."},"multiline":{"type":"boolean","description":"Present on text fields when multiline is enabled"}},"required":["id","label","type","required","section","manageOnly","externalId"]},"description":"Organisation custom project field definitions. Empty when no template is configured."}},"required":["customFields"]}},"required":["type","id","attributes"]}},"required":["data"]},"PatchProjectCustomFieldsRequest":{"type":"object","properties":{"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"description":"Field id from GET /v1/organisation (or from the project customFields list)"},"externalId":{"type":"string","minLength":1,"maxLength":128,"description":"External/CRM key for the field; may be used instead of or with id"},"value":{"anyOf":[{"type":"string","maxLength":10000},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"null"}],"description":"Scalar value for text, number, date (ISO 8601), dropdown, or checkbox. Use null to clear. Dropdown empty/whitespace clears to null."},"values":{"type":"array","items":{"type":"string","maxLength":512},"maxItems":100,"description":"Multiselect values only (max 100). Use [] to clear. Do not send value for multiselect."}},"additionalProperties":false},"maxItems":50,"description":"Field value patches (max 50). Each entry needs id and/or externalId plus value or values. [] is a no-op: no write and no template sync; response matches GET."}},"required":["customFields"],"additionalProperties":false},"PatchProjectResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["projects"]},"id":{"type":"string"},"attributes":{"type":"object","properties":{"name":{"type":"string","description":"Project name"},"issuer":{"type":"string","description":"Name of the issuing organisation"},"status":{"type":"string","description":"Current project status"},"createdAt":{"type":"string","description":"ISO 8601 datetime when the project was created"},"dueDate":{"type":["string","null"],"description":"ISO 8601 datetime when the project is due"},"projectType":{"type":["string","null"],"description":"Same as list: value of the custom field with id project_type when present on the project; otherwise null"},"customFields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Field id (pass as id in PATCH /v1/projects/{projectId})"},"label":{"type":"string","description":"Human-readable field label"},"type":{"type":"string","enum":["text","number","date","dropdown","multiselect","checkbox"],"description":"Field value type"},"externalId":{"type":["string","null"],"description":"Optional CRM/external key (pass as externalId in PATCH)"},"options":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]},"description":"Static options currently on the project snapshot. PATCH allowlists use the organisation template optionSource after refresh — prefer GET /v1/organisation for the live list."},"optionSource":{"type":"object","properties":{"type":{"type":"string","enum":["dynamic"]},"set":{"type":"string"}},"required":["type","set"],"description":"Dynamic option set on the project snapshot (e.g. users, usersAndTeams, teams). For known sets, PATCH values must be org members using user:<id> / team:<id> (bare id = legacy user)."},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"null"}],"description":"Scalar value for text, number, date, dropdown, or checkbox. Dates are ISO 8601 with offset (e.g. 2024-01-15T00:00:00.000+00:00)."},"values":{"type":"array","items":{"type":"string"},"description":"Multiselect values (clear with [])"}},"required":["id","label","type","externalId"]},"description":"Current custom field values on the project (empty when none are configured)"},"summary":{"type":"object","properties":{"requirementsCount":{"type":"number","description":"Total number of requirements"},"approvedCount":{"type":"number","description":"Number of approved requirements"},"submittedCount":{"type":"number","description":"Number of requirements submitted for review"}},"required":["requirementsCount","approvedCount","submittedCount"]}},"required":["name","issuer","status","createdAt","dueDate","projectType","customFields","summary"]}},"required":["type","id","attributes"]}},"required":["data"]}},"parameters":{}},"paths":{"/v1/content":{"get":{"tags":["Content"],"security":[{"bearerApiKey":[]}],"summary":"List content","description":"Returns a paginated list of content library entries accessible via the API key.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number (1-indexed)"},"required":false,"description":"Page number (1-indexed)","name":"page[number]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page (1-100)"},"required":false,"description":"Items per page (1-100)","name":"page[size]","in":"query"},{"schema":{"type":"string","description":"Tag label to filter by"},"required":false,"description":"Tag label to filter by","name":"filter[tag]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[updatedAfter]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[updatedBefore]","in":"query"}],"responses":{"200":{"description":"Paginated list of content","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListContentResponse"}}}},"400":{"description":"Invalid query parameters","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient permissions","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"content:read"}},"/v1/content/{id}/usage":{"get":{"tags":["Content"],"security":[{"bearerApiKey":[]}],"summary":"List content usage","description":"Returns a paginated list of usage records showing where a content library entry has been used across projects.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number (1-indexed)"},"required":false,"description":"Page number (1-indexed)","name":"page[number]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page (1-100)"},"required":false,"description":"Items per page (1-100)","name":"page[size]","in":"query"}],"responses":{"200":{"description":"Paginated list of content usage records","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListContentUsageResponse"}}}},"400":{"description":"Invalid query parameters","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient permissions","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"404":{"description":"Content not found","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"content:read"}},"/v1/content/tags":{"post":{"tags":["Content"],"security":[{"bearerApiKey":[]}],"summary":"Bulk assign tags to content","description":"Adds, removes, or replaces tags across up to 500 content library items. Requires content:write. Well-formed batches always return 200 with per-item outcomes in successfulContentIds and failures[].","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTagRequest"}}}},"responses":{"200":{"description":"Bulk tag assignment result (partial success possible)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/BulkTagResponse"}}}},"400":{"description":"Malformed body, caps exceeded, or duplicate contentId","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient scope","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"content:write"}},"/v1/tag-categories":{"get":{"tags":["Tags"],"security":[{"bearerApiKey":[]}],"summary":"List tag categories","description":"Returns the organisation's full tag vocabulary (every category with its nested tags). Unpaginated — use to discover tagIds for POST /v1/content/tags. Requires tags:read.","responses":{"200":{"description":"Tag categories with nested tags","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListTagCategoriesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient scope","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"tags:read"}},"/v1/projects":{"get":{"tags":["Projects"],"security":[{"bearerApiKey":[]}],"summary":"List projects","description":"Returns a paginated list of projects accessible via the API key.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number (1-indexed)"},"required":false,"description":"Page number (1-indexed)","name":"page[number]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page (1-100)"},"required":false,"description":"Items per page (1-100)","name":"page[size]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[createdAfter]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[createdBefore]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[dueAfter]","in":"query"},{"schema":{"type":"string","format":"date-time","description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")"},"required":false,"description":"ISO 8601 datetime (e.g. \"2025-01-01T00:00:00Z\")","name":"filter[dueBefore]","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["intake","inProgress","completed","shortlisted","overdue","lost","won","stopped"]},"description":"Comma-separated list of statuses (e.g. \"inProgress,completed\")"},"required":false,"description":"Comma-separated list of statuses (e.g. \"inProgress,completed\")","name":"filter[status]","in":"query"}],"responses":{"200":{"description":"Paginated list of projects","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListProjectsResponse"}}}},"400":{"description":"Invalid query parameters","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient permissions","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"projects:read"}},"/v1/organisation":{"get":{"tags":["Organisation"],"security":[{"bearerApiKey":[]}],"summary":"Get organisation settings","description":"Returns the organisation's custom project field definitions (id, type, options, and flags). Use this to discover which fields you can set with PATCH /v1/projects/{projectId}. customFields is [] when no organisation template is configured. required on these definitions is the organisation-template flag; PATCH evaluates requiredness on the project working set (see PATCH docs). manageOnly is discovery-only and ignored by PATCH. Dynamic optionSource.set values such as users, usersAndTeams, or teams use user:<id> / team:<id> (bare id = legacy user); PATCH validates organisation membership for these known sets. Requires organisation:read. Rate limit: 100 requests / 60 seconds.","responses":{"200":{"description":"Organisation settings (custom field definitions)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/GetOrganisationResponse"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient scope (requires organisation:read)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"organisation:read"}},"/v1/projects/{projectId}":{"get":{"tags":["Projects"],"security":[{"bearerApiKey":[]}],"summary":"Get a project","description":"Returns one project: header fields, requirement summary counts, projectType, and custom field values. projectType matches GET /v1/projects list: value of the custom field with id project_type when present; otherwise null. customFields lists current values on the project. An empty array usually means none are configured; in rare cases it can briefly appear empty even when fields exist — confirm with GET /v1/organisation and retry if needed. Requires projects:read. Rate limit: 100 requests / 60 seconds.","parameters":[{"schema":{"type":"string","description":"Project id"},"required":true,"description":"Project id","name":"projectId","in":"path"}],"responses":{"200":{"description":"Project detail (includes customFields and projectType)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/GetProjectResponse"}}}},"400":{"description":"Invalid project id","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient scope (requires projects:read)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"404":{"description":"Project not found","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"projects:read"},"patch":{"tags":["Projects"],"security":[{"bearerApiKey":[]}],"summary":"Update project custom fields","description":"Updates custom project field values on one project. Request body is plain JSON (application/json), not a JSON:API envelope: { \"customFields\": [ { \"id\" and/or \"externalId\", \"value\" or \"values\" }, ... ] } (max 50). Match fields by id and/or externalId (case-insensitive, trimmed). If both are set and resolve to different fields, or the same field is patched twice, the request fails with 400 (field-invalid). Use value for text, number, date (ISO 8601 within 1970–2100 UTC), dropdown, and checkbox; use values (string array) for multiselect. Null clears a scalar field; dropdown empty/whitespace clears to null; values: [] clears multiselect. Static dropdown/multiselect options must match the organisation-template option list after refresh (values are trimmed). Dynamic option sources users / usersAndTeams / teams require organisation membership: user:<id> or bare id for users, team:<id> for teams (usersAndTeams allows both). Deactivated users and unknown ids fail with field-invalid. Unknown dynamic set names still accept any non-empty string. customFields: [] is a no-op (no write, no template sync, no required check); the 200 response matches the current project. A non-empty request adds any organisation-template fields missing from the project; project-only fields are kept. On a non-empty request, optionSource for matched dropdown/multiselect fields refreshes from the organisation template (static or dynamic; values and required/manageOnly flags on existing project fields are not rewritten). Required fields: after applying patches, required fields on the project working set must be non-empty. Requiredness uses each field.required flag already on the project (or on newly cloned/appended template fields); existing project required flags are not updated from the organisation template. When the project had no custom fields yet (full template clone), every required template field must be filled. Otherwise only required fields that already existed on the project or are touched in this request are checked (newly appended untouched template fields are exempt this request). Empty means: text/dropdown null or \"\"; number/date null; checkbox not true; multiselect []. manageOnly is ignored by PATCH (no write-deny); required manageOnly fields still must be filled when in scope. Updates are atomic: any unknown, invalid, or missing-required field rejects the whole request with no write (unlike POST /v1/content/tags, which allows partial success). Multiple semantic failures return multiple top-level errors[] entries with code field-not-found, field-invalid, or field-required; each detail names the field (for example, \"region: …\"). Body/schema problems (missing customFields, unknown keys, caps, empty ids) return 400 without errors[].code. Non-empty patches when neither the organisation template nor the project has any fields return 422 with code custom-fields-not-configured. On success, returns the full project summary in the same shape as GET /v1/projects/{projectId}. Requires projects:write. Rate limit: 30 requests / 60 seconds.","parameters":[{"schema":{"type":"string","description":"Project id"},"required":true,"description":"Project id","name":"projectId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchProjectCustomFieldsRequest"}}}},"responses":{"200":{"description":"Full project summary after update (same shape as GET /v1/projects/{projectId})","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/PatchProjectResponse"}}}},"400":{"description":"Invalid body/schema (no errors[].code), or one or more field errors with code field-not-found / field-invalid / field-required (no fields written)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient scope (requires projects:write)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"404":{"description":"Project not found","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"422":{"description":"No custom fields configured on the organisation or project (code: custom-fields-not-configured)","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"projects:write"}},"/v1/teams":{"get":{"tags":["Teams"],"security":[{"bearerApiKey":[]}],"summary":"List teams","description":"Returns a paginated list of teams accessible via the API key.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number (1-indexed)"},"required":false,"description":"Page number (1-indexed)","name":"page[number]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page (1-100)"},"required":false,"description":"Items per page (1-100)","name":"page[size]","in":"query"}],"responses":{"200":{"description":"Paginated list of teams","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListTeamsResponse"}}}},"400":{"description":"Invalid query parameters","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient permissions","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"teams:read"}},"/v1/projects/{projectId}/requirements":{"get":{"tags":["Projects"],"security":[{"bearerApiKey":[]}],"summary":"List project requirements","description":"Returns a paginated list of requirements within a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number (1-indexed)"},"required":false,"description":"Page number (1-indexed)","name":"page[number]","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page (1-100)"},"required":false,"description":"Items per page (1-100)","name":"page[size]","in":"query"}],"responses":{"200":{"description":"Paginated list of requirements","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/ListRequirementsResponse"}}}},"400":{"description":"Invalid query parameters","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"401":{"description":"Unauthorized","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"403":{"description":"Insufficient permissions","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"404":{"description":"Project not found","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}},"500":{"description":"Internal server error","content":{"application/vnd.api+json":{"schema":{"$ref":"#/components/schemas/JsonApiError"}}}}},"x-required-scope":"projects:read"}}},"webhooks":{}}