{"openapi":"3.1.0","info":{"title":"Roles · Profiles · Flows Public API","version":"1.0.0","description":"Read-side public API for the RPF catalogue. Multilingual (EN, PT-BR, FR, ES); pass `?locale=` to flatten to a single language.\n\n**Stability: stable.** Documented response shapes will not change incompatibly within v1. Additive change is not breaking: new properties may appear on any response, so ignore unknown properties. A breaking change means a new major version and a new vendor media type; v1 keeps answering. If an endpoint is ever withdrawn it is announced first, marked `deprecated` in this document, and served for at least six months after that mark appears.\n\n**Version boundary.** Send `Accept: application/vnd.rpf.v1+json` to pin the major version. Every response also carries `x-rpf-api-stability`.\n\n**Cross-origin use.** The action-statement, package and specification endpoints answer cross-origin browser requests (`GET`, `HEAD` and preflight). Credentials are never accepted cross-origin, so a browser will not attach a session; an API key header is accepted, because it is a token you hold deliberately rather than an ambient credential. The catalogue lists, registers, search and metro map do NOT answer cross-origin: they are the bulk surface, and opening them is a separate decision.\n\n**Licence and bulk use.** Anonymous list endpoints are paginated and return a teaser projection; slug-level detail returns full rows to everyone. Reads are metered per identity per day, in ROWS rather than requests, so the response format cannot become the cheap way round a page limit. Higher volumes are available with an API key; see the terms link below.\n\n**What this document does not promise.** Detail endpoints return more properties than are described here, and say so per endpoint. Ignore unknown properties. Where a package publishes its own `schema.json`, validate against that: it ships with the payload and moves with it.","license":{"name":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International","identifier":"CC-BY-NC-SA-4.0"},"contact":{"name":"BIMe Initiative, by ChangeAgents AEC","email":"support@bimexcellence.org","url":"/developers"},"termsOfService":"https://rpf.bimexcellence.org/licence","x-stability":"stable"},"servers":[{"url":"/"}],"tags":[{"name":"action-statements","description":"Action statements (DB-internal name: `items`)."},{"name":"roles","description":"Roles and their generated Flows."},{"name":"profiles","description":"Profiles."},{"name":"information-uses","description":"Information Uses."},{"name":"workflows","description":"Flows."},{"name":"sources","description":"Sources and source materials."},{"name":"source-references","description":"Source references."},{"name":"packages","description":"Composed cross-journey documents."},{"name":"registers","description":"Composed register views. Capped, not paginated."},{"name":"search","description":"Cross-entity search."},{"name":"showcase","description":"The metro map."},{"name":"feed","description":"Cursor-based change feed."},{"name":"citations","description":"Citations."},{"name":"projection","description":"Per-organisation published-scenario projection. Requires an organisation-scoped API key."},{"name":"meta","description":"This document."}],"components":{"securitySchemes":{"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-rpf-api-key","description":"Optional. Raises the daily ROW budget, not just the request ceiling. An invalid or revoked key is not an error: it falls back to anonymous treatment, so a stale credential degrades to the public allowance rather than becoming an outage."},"bearerApiKey":{"type":"http","scheme":"bearer","description":"The same key as `Authorization: Bearer rpf_…`. Identical treatment; use whichever suits your client."}},"schemas":{"LangText":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"},"es":{"type":"string"}},"required":["en"],"description":"Multilingual text bundle. `en` is required and is the fallback for every other language; the rest are present only where a translation exists."},"ApiError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"]}},"required":["error"]},"PageMeta":{"type":"object","properties":{"nextCursor":{"type":["string","null"],"description":"Opaque. Pass back as `?cursor=`. `null` is the ONLY end-of-list signal: do not infer the end from a short page."}},"required":["nextCursor"]},"RoleTeaser":{"type":"object","properties":{"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"summary":{"$ref":"#/components/schemas/LangText"},"type":{"type":"string","description":"The role rank (`roleRank`). Role types are recorded separately as an array, such as ['Qr','Or']."}},"required":["slug","title","summary","type"]},"ProfileTeaser":{"type":"object","properties":{"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"summary":{"$ref":"#/components/schemas/LangText"},"type":{"type":"string","description":"`profileType`."}},"required":["slug","title","summary","type"]},"InformationUseTeaser":{"type":"object","properties":{"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"summary":{"allOf":[{"$ref":"#/components/schemas/LangText"},{"type":["object","null"],"description":"NULLABLE on this entity alone."}]},"type":{"type":"string","description":"`useType`."}},"required":["slug","title","summary","type"]},"WorkflowTeaser":{"type":"object","properties":{"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"summary":{"$ref":"#/components/schemas/LangText"},"type":{"type":"string","description":"`journeyKind`."}},"required":["slug","title","summary","type"]},"SourceTeaser":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string","description":"`displayName`. Not multilingual."},"type":{"type":["string","null"],"description":"`publisherKind`."}},"required":["slug","title","type"],"description":"Sources have no summary column, so the key is ABSENT rather than null."},"SourceReferenceTeaser":{"type":"object","properties":{"id":{"type":"string","description":"Present BECAUSE this entity has no slug: without it an anonymous caller could not cite or resolve a single row."},"title":{"type":"string"},"type":{"type":["string","null"]}},"required":["id","title","type"]},"LegacyRefs":{"type":"object","properties":{"xlsx":{"type":"integer"},"matriz":{"type":"string"}},"additionalProperties":{},"description":"Provenance map of external IDs (e.g. xlsx row id, matriz block id)."},"ActionStatement":{"type":"object","properties":{"id":{"type":"string","pattern":"^CI-[A-Z0-9-]+$"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"actionStatement":{"$ref":"#/components/schemas/LangText"},"summary":{"allOf":[{"$ref":"#/components/schemas/LangText"},{"type":["object","null"]}]},"itemType":{"type":"string","enum":["action","enquiry","capability","unclassified"],"description":"Action statement category"},"labels":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["draft","validated","published","archived"],"description":"Lifecycle state"},"version":{"type":"string"},"owner":{"type":"string"},"sourceRefs":{"type":"array","items":{"type":"string"}},"lastUpdated":{"type":"string"},"legacyRefs":{"allOf":[{"$ref":"#/components/schemas/LegacyRefs"},{"type":["object","null"]}]},"asCode":{"type":["string","null"],"description":"The master-list alias: `AS` and the statement's `legacyRefs.xlsx` row, unpadded (`AS121`), the code MAD tags its survey items with. Canonical catalogue statements only; null for an organisation's or a practitioner's statement and where no row is recorded. An alias, not the join key.","example":"AS121"},"ontIri":{"type":["string","null"],"description":"The statement's permanent ONT IRI (`https://w3id.org/bimei/{type}/{slug}`), the preferred join key across BIMei apps when present. Null for every statement until RPF reads ONT's versioned snapshot.","example":null}},"required":["id","slug","title","actionStatement","summary","itemType","labels","status","version","owner","sourceRefs","lastUpdated","legacyRefs","asCode","ontIri"],"description":"Action statement (DB-internal name: `item`). Use the `?locale=` query parameter to receive the flattened single-language variant instead."},"ActionStatementFlattened":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"locale":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Locale code","example":"fr"},"title":{"type":"string"},"actionStatement":{"type":"string"},"summary":{"type":["string","null"]},"itemType":{"type":"string","enum":["action","enquiry","capability","unclassified"],"description":"Action statement category"},"labels":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["draft","validated","published","archived"],"description":"Lifecycle state"},"version":{"type":"string"},"owner":{"type":"string"},"sourceRefs":{"type":"array","items":{"type":"string"}},"lastUpdated":{"type":"string"},"legacyRefs":{"allOf":[{"$ref":"#/components/schemas/LegacyRefs"},{"type":["object","null"]}]},"asCode":{"type":["string","null"],"description":"The master-list alias: `AS` and the statement's `legacyRefs.xlsx` row, unpadded (`AS121`), the code MAD tags its survey items with. Canonical catalogue statements only; null for an organisation's or a practitioner's statement and where no row is recorded. An alias, not the join key.","example":"AS121"},"ontIri":{"type":["string","null"],"description":"The statement's permanent ONT IRI (`https://w3id.org/bimei/{type}/{slug}`), the preferred join key across BIMei apps when present. Null for every statement until RPF reads ONT's versioned snapshot.","example":null}},"required":["id","slug","locale","title","actionStatement","summary","itemType","labels","status","version","owner","sourceRefs","lastUpdated","legacyRefs","asCode","ontIri"],"description":"Action statement with `title`/`actionStatement`/`summary` flattened to a single locale's string."},"ActionStatementListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ActionStatementVariant"}},"meta":{"$ref":"#/components/schemas/ActionStatementListMeta"}},"required":["data","meta"]},"ActionStatementVariant":{"anyOf":[{"$ref":"#/components/schemas/ActionStatement"},{"$ref":"#/components/schemas/ActionStatementFlattened"}]},"ActionStatementListMeta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]},"total":{"type":"integer"},"locale":{"type":["string","null"],"enum":["en","pt-BR","fr","es",null],"description":"Locale code","example":"fr"}},"required":["nextCursor","total","locale"]},"ActionStatementResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ActionStatementVariant"}},"required":["data"]},"ActionStatementSearchResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/LangText"}]}},"required":["id","title"]}}},"required":["hits"]}},"required":["data"]},"ActionStatementLineageResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"profiles":{"type":"array","items":{"type":"object","properties":{}}},"roles":{"type":"array","items":{"type":"object","properties":{}}},"infoUses":{"type":"array","items":{"type":"object","properties":{}}},"sourceRefs":{"type":"array","items":{"type":"object","properties":{}}}},"required":["item","profiles","roles","infoUses","sourceRefs"]}},"required":["data"],"description":"Where this statement is used: the Profiles, Roles and Information Uses that reference it, plus its source references."},"RoleListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RoleTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"ProfileListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProfileTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"InformationUseListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InformationUseTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"WorkflowListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"SourceListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"SourceReferenceListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceReferenceTeaser"}},"meta":{"$ref":"#/components/schemas/PageMeta"}},"required":["data","meta"]},"RoleDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"role":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"},"summary":{"$ref":"#/components/schemas/LangText"}},"required":["id","slug","title","summary"],"description":"Role row. Carries further columns."},"profiles":{"type":"array","items":{"type":"object","properties":{"edge":{"type":"object","properties":{},"description":"Role-to-Profile edge row."},"profile":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"}},"required":["id","slug","title"]}},"required":["edge","profile"]}}},"required":["role","profiles"]}},"required":["data"]},"ProfileDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"}},"required":["id","slug","title"]}},"required":["data"]},"InformationUseDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"}},"required":["id","slug","title"]}},"required":["data"]},"WorkflowDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"$ref":"#/components/schemas/LangText"}},"required":["id","slug","title"]}},"required":["data"]},"SourceDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}},"required":["data"]},"SourceReferenceDetailResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}},"required":["data"]},"GeneratedFlowResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"stages":{"type":"array","items":{"type":"object","properties":{}},"description":"Ordered stages of the generated flow."}},"required":["stages"]}},"required":["data"]},"SearchHit":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/LangText"}]}},"required":["id","title"],"description":"`title` is a plain string on the surfaces that flatten it and a LangText bundle on those that do not. Handle both."},"SearchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchHit"}}},"required":["data"]},"RegisterRow":{"type":"object","properties":{},"description":"One composed register row. Shape differs per register."},"RegisterResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RegisterRow"}}},"required":["data"]},"MetroMapResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"stations":{"type":"array","items":{"type":"object","properties":{}},"description":"Stations on the map. One per role in the filtered set."}},"required":["stations"]}},"required":["data"]},"ChangeEvent":{"type":"object","properties":{"event_id":{"type":"string","description":"`<kind>:<id>`. STABLE across re-delivery: the same change re-delivered at the boundary carries the same id, which is what makes deduplication possible.","example":"role:0f3c..."},"event_type":{"type":"string","example":"role.changed"},"target_kind":{"type":"string","enum":["role","profile","information_use","action_statement","flow"]},"target_key":{"type":"string","description":"The entity's public slug. Resolve it against that entity's endpoint."},"occurred_at":{"type":"string","description":"RFC 3339, microsecond precision."},"as_code":{"type":["string","null"],"description":"`action_statement` events only: the statement's master-list alias (`AS121`), as on `/api/action-statements`. Null for a statement with no master-list row or outside the canonical catalogue. Absent on every other kind.","example":"AS121"},"ont_iri":{"type":["string","null"],"description":"`action_statement` events only: the statement's ONT IRI, the preferred join key when present. Null until RPF reads ONT's snapshot. Absent on every other kind.","example":null}},"required":["event_id","event_type","target_kind","target_key","occurred_at"]},"ChangeFeedResponse":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/ChangeEvent"}},"cursor_at":{"type":["string","null"],"description":"Send back as `since` on the next poll. `null` only when you have never polled and there is nothing to report."},"has_more":{"type":"boolean","description":"The page filled. Poll again immediately rather than waiting for your interval, or you will fall behind."}},"required":["events","cursor_at","has_more"]},"JsonSchemaDocument":{"type":"object","properties":{"$schema":{"type":"string"},"$id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"}},"description":"A JSON Schema document describing the sibling package payload. Carries the full schema; the properties named here are the stable ones."},"PackageLicenceEnvelope":{"type":"object","properties":{"licence":{"type":"object","properties":{"spdx":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"}},"required":["spdx","name","url"]},"termsUrl":{"type":"string"}},"required":["licence","termsUrl"],"description":"Embedded in every package payload, not only sent as a header, because a package is saved to disk and passed on without its headers."},"PackageResponse":{"type":"object","properties":{"data":{"type":"object","properties":{}}},"required":["data"],"description":"Composed package document. Validate against the sibling `schema.json` where one exists."},"ProjectionResourceCard":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","description":"material | course | reference: the catalogue item kind."},"title":{"type":"string"},"summary":{"type":["string","null"]},"provider":{"type":["string","null"]},"externalUrl":{"type":["string","null"]}},"required":["id","kind","title","summary","provider","externalUrl"],"description":"A published Resources card: exactly the public card fields, nothing else."},"ProjectionScenario":{"type":"object","properties":{"code":{"type":"string","description":"The SP- scenario code: the identity to key on."},"reportSlug":{"type":"string","description":"The published report's slug. Stable across re-publishes."},"title":{"type":"string"},"publication":{"type":"string","description":"The RPB- publication code of the active publication."},"version":{"type":"integer","description":"Bumped on every re-publish."},"tier":{"type":"string","enum":["final","interim"],"description":"An interim publication carries its caveat on the published page; consumers decide what to list by this field."},"recordVisibility":{"type":"string","enum":["members","public"],"description":"Who may open the Full Scenario Record on the published page."},"publishedAt":{"type":"string","description":"ISO 8601."},"updatedAt":{"type":"string","description":"ISO 8601."},"urls":{"type":"object","properties":{"canonical":{"type":"string","description":"The published report page, org-scoped."},"embed":{"type":"string","description":"The navigator embed focused on this report."},"drawio":{"type":["string","null"],"description":"The one-way .drawio extract, or null when the publication froze no diagram."}},"required":["canonical","embed","drawio"],"description":"Site-relative URLs."},"subtitle":{"type":["string","null"],"description":"The line under the published Report's title, or null when it shows none."},"keyFacts":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"]},"description":"The key facts the published Report lists under its heading (organisation, appointment, project value, jurisdiction), in its order. The role is the title. Empty when the Report hides them."},"mandate":{"type":["object","null"],"properties":{"result":{"type":"string","enum":["applies","does_not_apply","cannot_determine"]},"label":{"type":"string"}},"required":["result","label"],"description":"The published Report's answer to \"Does the mandate apply?\", or null when it shows none."},"resources":{"type":"object","properties":{"materials":{"type":"array","items":{"$ref":"#/components/schemas/ProjectionResourceCard"},"description":"Cards derived from the frozen rollup's approved evidence keys."},"extras":{"type":"array","items":{"$ref":"#/components/schemas/ProjectionResourceCard"},"description":"Approved scenario-level supplements."}},"required":["materials","extras"],"description":"The published Resources band."}},"required":["code","reportSlug","title","publication","version","tier","recordVisibility","publishedAt","updatedAt","urls","subtitle","keyFacts","mandate","resources"],"description":"One published scenario as identity, status, links and the heading facts its published Report shows. Deliberately NO section content, evidence bodies or rollups: content stays on the published pages this projection points at."},"ProjectionScenarioListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectionScenario"}}},"required":["data"]},"ProjectionScenarioResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProjectionScenario"}},"required":["data"]},"PersonaPackage":{"type":"object","properties":{"package":{"type":"object","properties":{"id":{"type":"string"},"schemaVersion":{"type":"string","enum":["1.0.0"]},"generatedAt":{"type":"string","format":"date-time"},"generatorVersion":{"type":"string"},"locale":{"type":"string","enum":["en","pt-BR","fr","es"]},"licence":{"type":"object","properties":{"spdx":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["spdx","name","url"]},"termsUrl":{"type":"string"},"citation":{"type":"object","properties":{"doi":{"type":["string","null"]},"url":{"type":["string","null"],"format":"uri"}},"required":["doi","url"]}},"required":["id","schemaVersion","generatedAt","generatorVersion","citation"]},"role":{"type":"object","properties":{"id":{"type":"string","pattern":"^DR-"},"slug":{"type":"string"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"description":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"rank":{"type":["string","null"]},"scale":{"type":"array","items":{"type":"string"}},"type":{"type":"array","items":{"type":"string"}},"discipline":{"type":"array","items":{"type":"string"}},"region":{"type":["string","null"]},"countryCode":{"type":["string","null"]},"subregionCode":{"type":["string","null"]},"regionLabel":{"type":["string","null"]},"owner":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"version":{"type":"string"},"lastUpdated":{"type":"string"},"createdBy":{"type":["object","null"],"properties":{"email":{"type":["string","null"],"format":"email"},"userId":{"type":["string","null"],"format":"uuid"}},"required":["email","userId"]}},"required":["id","slug","title","summary","description","rank","scale","type","discipline","region","countryCode","subregionCode","regionLabel","owner","visibility","version","lastUpdated","createdBy"]},"organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"displayName":{"type":"string"}},"required":["id","slug","displayName"]},"jurisdiction":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"alpha3":{"type":"string"},"name":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]}},"required":["id","code","alpha3","name"]},"profiles":{"type":"array","items":{"type":"object","properties":{"profile":{"type":"object","properties":{"id":{"type":"string","pattern":"^CP-"},"slug":{"type":"string"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"description":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"profileType":{"type":"string","enum":["core","specialized"]},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]}},"required":["id","slug","title","summary","description","profileType","version","owner","lastUpdated","visibility"]},"edge":{"type":"object","properties":{"classification":{"type":"string","enum":["core","primary","supporting"]},"iri":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]},"ici":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]},"sortOrder":{"type":"integer"}},"required":["classification","iri","ici","sortOrder"]}},"required":["profile","edge"]}},"actionStatements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^CI-"},"slug":{"type":"string"},"profileId":{"type":"string","pattern":"^CP-"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"actionStatement":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"itemType":{"type":"string","enum":["action","enquiry","capability","unclassified"]},"labels":{"type":"array","items":{"type":"string"}},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"edge":{"type":"object","properties":{"sortOrder":{"type":"integer"},"groupLabel":{"type":["string","null"]},"iri":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]},"ici":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]}},"required":["sortOrder","groupLabel","iri","ici"]}},"required":["id","slug","profileId","title","actionStatement","summary","itemType","labels","version","owner","lastUpdated","visibility","edge"]}},"informationUses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^IU-"},"slug":{"type":"string"},"profileId":{"type":"string","pattern":"^CP-"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"useType":{"type":"string","enum":["model","document","data"]},"taxonomyCode":{"type":["string","null"]},"bimDictionaryUrl":{"type":["string","null"]},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"edge":{"type":"object","properties":{"relevance":{"type":"string","enum":["primary","supporting","reference"]}},"required":["relevance"]}},"required":["id","slug","profileId","title","summary","useType","taxonomyCode","bimDictionaryUrl","version","owner","lastUpdated","visibility","edge"]}},"linkedMaterials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^(EM|SM)-"},"slug":{"type":["string","null"]},"sourceSlug":{"type":"string"},"kind":{"type":["string","null"]},"source":{"type":"string"},"title":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"citation":{"type":["string","null"]},"url":{"type":["string","null"]},"countryCode":{"type":["string","null"]},"subregionCode":{"type":["string","null"]},"version":{"type":"string"},"edge":{"type":"object","properties":{"linkedFrom":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["role"]},"roleId":{"type":"string"}},"required":["kind","roleId"]},{"type":"object","properties":{"kind":{"type":"string","enum":["item"]},"itemId":{"type":"string"}},"required":["kind","itemId"]},{"type":"object","properties":{"kind":{"type":"string","enum":["informationUse"]},"informationUseId":{"type":"string"}},"required":["kind","informationUseId"]}]},"relevance":{"type":"string","enum":["primary","supporting","reference"]},"note":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"sortOrder":{"type":"integer"}},"required":["linkedFrom","relevance","note","sortOrder"]}},"required":["id","slug","sourceSlug","kind","source","title","summary","citation","url","countryCode","subregionCode","version","edge"]}},"flows":{"type":"array","items":{"type":"object","properties":{"source":{"type":"object","properties":{"type":{"type":"string","enum":["role","profile"]},"id":{"type":"string"}},"required":["type","id"]},"label":{"type":"string"},"disclaimer":{"type":"string"},"steps":{"type":"array","items":{"type":"object","properties":{"stepNumber":{"type":"integer"},"sourceType":{"type":"string","enum":["profile","item","informationUse"]},"sourceId":{"type":"string"},"display":{"type":"string"}},"required":["stepNumber","sourceType","sourceId","display"]}},"truncated":{"type":"boolean"}},"required":["source","label","disclaimer","steps","truncated"]}},"sourceReferences":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"},"url":{"type":["string","null"]},"file":{"type":["string","null"]}},"required":["id","title","type"]}}},"required":["package","role","jurisdiction","profiles"],"description":"Versioned, citable export package for an RPF role/persona. Schema URL: /api/packages/personas/schema.json. Strategy doc §10.1 is the contract."},"InformationUsePackage":{"type":"object","properties":{"package":{"type":"object","properties":{"id":{"type":"string"},"schemaVersion":{"type":"string","enum":["1.0.0"]},"generatedAt":{"type":"string","format":"date-time"},"generatorVersion":{"type":"string"},"locale":{"type":"string","enum":["en","pt-BR","fr","es"]},"licence":{"type":"object","properties":{"spdx":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["spdx","name","url"]},"termsUrl":{"type":"string"},"citation":{"type":"object","properties":{"doi":{"type":["string","null"]},"url":{"type":["string","null"],"format":"uri"}},"required":["doi","url"]}},"required":["id","schemaVersion","generatedAt","generatorVersion","citation"]},"informationUse":{"type":"object","properties":{"id":{"type":"string","pattern":"^IU-"},"slug":{"type":"string"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"useType":{"type":"string","enum":["model","document","data"]},"taxonomyCode":{"type":["string","null"]},"bimDictionaryUrl":{"type":["string","null"]},"countryCode":{"type":["string","null"]},"subregionCode":{"type":["string","null"]},"regionLabel":{"type":["string","null"]},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"createdBy":{"type":["object","null"],"properties":{"email":{"type":["string","null"],"format":"email"},"userId":{"type":["string","null"],"format":"uuid"}},"required":["email","userId"]}},"required":["id","slug","title","summary","useType","taxonomyCode","bimDictionaryUrl","countryCode","subregionCode","regionLabel","version","owner","lastUpdated","visibility","createdBy"]},"jurisdiction":{"$ref":"#/components/schemas/InformationUsePackageJurisdiction"},"bimDictionary":{"type":["object","null"],"properties":{"url":{"type":"string","format":"uri"},"iri":{"type":"string","format":"uri"},"title":{"type":"string"},"summary":{"type":["string","null"]},"labels":{"type":"array","items":{"type":"string"}},"version":{"type":["string","null"]},"authorship":{"type":["string","null"]},"linkedTerms":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string"},"iri":{"type":"string","format":"uri"}},"required":["url","title"]}},"fetchedAt":{"type":"string","format":"date-time"},"release":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"}},"required":["id","version"]},"lang":{"type":"string"}},"required":["url","title","summary","labels","version","authorship","linkedTerms","fetchedAt"]},"profiles":{"type":"array","items":{"type":"object","properties":{"profile":{"type":"object","properties":{"id":{"type":"string","pattern":"^CP-"},"slug":{"type":"string"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"description":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"profileType":{"type":"string","enum":["core","specialized"]},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]}},"required":["id","slug","title","summary","description","profileType","version","owner","lastUpdated","visibility"]},"edge":{"type":"object","properties":{"relevance":{"type":"string","enum":["primary","supporting","reference"]}},"required":["relevance"]}},"required":["profile","edge"]}},"relatedRoles":{"type":"array","items":{"type":"object","properties":{"role":{"type":"object","properties":{"id":{"type":"string","pattern":"^DR-"},"slug":{"type":"string"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"rank":{"type":["string","null"]},"scale":{"type":"array","items":{"type":"string"}},"type":{"type":"array","items":{"type":"string"}},"discipline":{"type":"array","items":{"type":"string"}},"region":{"type":["string","null"]},"version":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"lastUpdated":{"type":"string"}},"required":["id","slug","title","summary","rank","scale","type","discipline","region","version","visibility","lastUpdated"]},"via":{"type":"object","properties":{"profileIds":{"type":"array","items":{"type":"string","pattern":"^CP-"}}},"required":["profileIds"]}},"required":["role","via"]}},"actionStatements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^CI-"},"slug":{"type":"string"},"profileId":{"type":"string","pattern":"^CP-"},"title":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"actionStatement":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"itemType":{"type":"string","enum":["action","enquiry","capability","unclassified"]},"labels":{"type":"array","items":{"type":"string"}},"version":{"type":"string"},"owner":{"type":"string"},"lastUpdated":{"type":"string"},"visibility":{"type":"string","enum":["private","unlisted","public_draft","submitted","formal_published","archived","system_draft"]},"edge":{"type":"object","properties":{"sortOrder":{"type":"integer"},"groupLabel":{"type":["string","null"]},"iri":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]},"ici":{"type":"object","properties":{"value":{"type":["integer","null"],"minimum":0,"maximum":4},"label":{"type":["string","null"]}},"required":["value","label"]}},"required":["sortOrder","groupLabel","iri","ici"]},"doaLevel":{"type":["integer","null"],"minimum":0,"maximum":4}},"required":["id","slug","profileId","title","actionStatement","summary","itemType","labels","version","owner","lastUpdated","visibility","edge"]}},"linkedMaterials":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^(EM|SM)-"},"slug":{"type":["string","null"]},"sourceSlug":{"type":"string"},"kind":{"type":["string","null"]},"source":{"type":"string"},"title":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"summary":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"citation":{"type":["string","null"]},"url":{"type":["string","null"]},"countryCode":{"type":["string","null"]},"subregionCode":{"type":["string","null"]},"version":{"type":"string"},"edge":{"type":"object","properties":{"linkedFrom":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["role"]},"roleId":{"type":"string"}},"required":["kind","roleId"]},{"type":"object","properties":{"kind":{"type":"string","enum":["item"]},"itemId":{"type":"string"}},"required":["kind","itemId"]},{"type":"object","properties":{"kind":{"type":"string","enum":["informationUse"]},"informationUseId":{"type":"string"}},"required":["kind","informationUseId"]}]},"relevance":{"type":"string","enum":["primary","supporting","reference"]},"note":{"type":["object","null"],"properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]},"sortOrder":{"type":"integer"}},"required":["linkedFrom","relevance","note","sortOrder"]}},"required":["id","slug","sourceSlug","kind","source","title","summary","citation","url","countryCode","subregionCode","version","edge"]}},"sourceReferences":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"},"url":{"type":["string","null"]},"file":{"type":["string","null"]}},"required":["id","title","type"]}}},"required":["package","informationUse","jurisdiction"],"description":"Versioned, citable export package for an RPF Information Use. Schema URL: /api/packages/information-uses/schema.json. Strategy doc §10.2 is the contract."},"InformationUsePackageJurisdiction":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"alpha3":{"type":"string"},"name":{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]}},"required":["id","code","alpha3","name"],"description":"Jurisdiction the Information Use is scoped to. Same shape as the persona-package version; defined locally for OpenAPI naming isolation."},"ProfileGapPackage":{"type":"object","properties":{"package":{"type":"object","properties":{"id":{"type":"string"},"schemaVersion":{"type":"string","enum":["1.0.0"]},"generatedAt":{"type":"string","format":"date-time"},"generatorVersion":{"type":"string"},"locale":{"type":"string","enum":["en","pt-BR","fr","es"]},"licence":{"type":"object","properties":{"spdx":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["spdx","name","url"]},"termsUrl":{"type":"string"},"citation":{"type":"object","properties":{"doi":{"type":["string","null"]},"url":{"type":["string","null"],"format":"uri"}},"required":["doi","url"]}},"required":["id","schemaVersion","generatedAt","generatorVersion","citation"]},"org":{"type":"object","properties":{"id":{"type":"string","pattern":"^CP-"},"slug":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]}]},"countryCode":{"type":["string","null"]},"orgId":{"type":["string","null"]}},"required":["id","slug","title","countryCode","orgId"]},"canonical":{"type":"object","properties":{"id":{"type":"string","pattern":"^CP-"},"slug":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"object","properties":{"en":{"type":"string"},"pt-BR":{"type":"string"},"fr":{"type":"string"}},"required":["en"]}]},"countryCode":{"type":["string","null"]},"orgId":{"type":["string","null"]}},"required":["id","slug","title","countryCode","orgId"]},"jurisdictionCode":{"type":["string","null"]},"itemDeltas":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","pattern":"^CI-"},"itemTitle":{"type":"string"},"iriDelta":{"type":["number","null"]},"iciDelta":{"type":["number","null"]},"canonical":{"type":"object","properties":{"iri":{"type":["integer","null"],"minimum":0,"maximum":4},"ici":{"type":["integer","null"],"minimum":0,"maximum":4}},"required":["iri","ici"]},"org":{"type":"object","properties":{"iri":{"type":["integer","null"],"minimum":0,"maximum":4},"ici":{"type":["integer","null"],"minimum":0,"maximum":4}},"required":["iri","ici"]}},"required":["itemId","itemTitle","iriDelta","iciDelta","canonical","org"]}},"addedItems":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","pattern":"^CI-"},"itemTitle":{"type":"string"},"iri":{"type":["integer","null"],"minimum":0,"maximum":4},"ici":{"type":["integer","null"],"minimum":0,"maximum":4}},"required":["itemId","itemTitle","iri","ici"]}},"removedItems":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","pattern":"^CI-"},"itemTitle":{"type":"string"},"iri":{"type":["integer","null"],"minimum":0,"maximum":4},"ici":{"type":["integer","null"],"minimum":0,"maximum":4}},"required":["itemId","itemTitle","iri","ici"]}},"iuDeltas":{"type":"array","items":{"type":"object","properties":{"informationUseId":{"type":"string","pattern":"^IU-"},"informationUseTitle":{"type":"string"},"canonicalRelevance":{"type":"string","enum":["primary","supporting","reference"]},"orgRelevance":{"type":"string","enum":["primary","supporting","reference"]}},"required":["informationUseId","informationUseTitle","canonicalRelevance","orgRelevance"]}},"addedIus":{"type":"array","items":{"type":"object","properties":{"informationUseId":{"type":"string","pattern":"^IU-"},"informationUseTitle":{"type":"string"},"relevance":{"type":"string","enum":["primary","supporting","reference"]}},"required":["informationUseId","informationUseTitle","relevance"]}},"removedIus":{"type":"array","items":{"type":"object","properties":{"informationUseId":{"type":"string","pattern":"^IU-"},"informationUseTitle":{"type":"string"},"relevance":{"type":"string","enum":["primary","supporting","reference"]}},"required":["informationUseId","informationUseTitle","relevance"]}},"substitutions":{"type":"array","items":{"type":"object","properties":{"canonicalRef":{"type":"string"},"canonicalTitle":{"type":"string"},"orgRef":{"type":["string","null"]},"orgTitle":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["canonicalRef","canonicalTitle","orgRef","orgTitle","note"]}},"summary":{"type":"object","properties":{"commonItemCount":{"type":"integer","minimum":0},"missingItemCount":{"type":"integer","minimum":0},"extraItemCount":{"type":"integer","minimum":0},"iriGapTotal":{"type":"number"},"iciGapTotal":{"type":"number"},"missingIuCount":{"type":"integer","minimum":0},"extraIuCount":{"type":"integer","minimum":0},"changedIuCount":{"type":"integer","minimum":0},"substitutionCount":{"type":"integer","minimum":0}},"required":["commonItemCount","missingItemCount","extraItemCount","iriGapTotal","iciGapTotal","missingIuCount","extraIuCount","changedIuCount","substitutionCount"]}},"required":["package","org","canonical","jurisdictionCode","itemDeltas","addedItems","removedItems","iuDeltas","addedIus","removedIus","substitutions","summary"],"description":"Profile Gap Analysis package — per-item IRI/ICI deltas, missing/extra item + IU sets, and material substitutions between an org-scoped Profile and its canonical future-ready counterpart. Schema URL: /api/packages/profile-gaps/schema.json. Strategy memo §4.1 + roadmap Phase 18 / M18.1."}},"parameters":{}},"paths":{"/api/action-statements":{"get":{"tags":["action-statements"],"description":"Paginated list of published action statements. Cursor-based; pass `meta.nextCursor` from each response back as `?cursor=…` to walk the catalog.","parameters":[{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"When set, response items return `title`/`actionStatement`/`summary` flattened to that locale; omitted returns the full `LangText` bundle."},"required":false,"description":"When set, response items return `title`/`actionStatement`/`summary` flattened to that locale; omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Opaque cursor returned in `meta.nextCursor` from a previous page."},"required":false,"description":"Opaque cursor returned in `meta.nextCursor` from a previous page.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size (1–200, default 50)."},"required":false,"description":"Page size (1–200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Substring search against title (EN) and action statement (EN)."},"required":false,"description":"Substring search against title (EN) and action statement (EN).","name":"q","in":"query"},{"schema":{"type":"string","enum":["action","enquiry","capability","unclassified"],"description":"Filter by category."},"required":false,"description":"Filter by category.","name":"itemType","in":"query"},{"schema":{"type":"string","description":"Comma-separated label codes; matches items whose `labels` overlap any of the given labels."},"required":false,"description":"Comma-separated label codes; matches items whose `labels` overlap any of the given labels.","name":"labels","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionStatementListResponse"}}}},"304":{"description":"Not Modified (matched If-None-Match)"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/action-statements/{id}":{"get":{"tags":["action-statements"],"description":"Fetch a single published action statement by ID.","parameters":[{"schema":{"type":"string","description":"Action statement ID (e.g. CI-AS-0456)"},"required":true,"description":"Action statement ID (e.g. CI-AS-0456)","name":"id","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"When set, response items return `title`/`actionStatement`/`summary` flattened to that locale; omitted returns the full `LangText` bundle."},"required":false,"description":"When set, response items return `title`/`actionStatement`/`summary` flattened to that locale; omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionStatementResponse"}}}},"304":{"description":"Not Modified"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/action-statements/search":{"get":{"tags":["action-statements"],"summary":"Search action statements","description":"Trigram search. Bounded by `limit` and NOT cursor-paginated: there is no way to walk past the limit, by design.\n\nAn empty or absent `q` returns an empty `hits` array rather than the whole catalogue.","parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Defaults to 25."},"required":false,"description":"Defaults to 25.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionStatementSearchResponse"}}}},"429":{"description":"Rate limited or row budget exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/action-statements/{id}/lineage":{"get":{"tags":["action-statements"],"summary":"Where one action statement is used","description":"Usage lineage for a single statement. Visibility-filtered: a caller sees only the referencing entities they may read, so an empty array means 'none you can see' rather than 'none'.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionStatementLineageResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/action-statements/{id}/raw":{"get":{"tags":["action-statements"],"summary":"One action statement, unflattened","description":"The stored row without locale flattening, for authoring tools that need the full `LangText` bundles.\n\nFEATURE-FLAGGED: served only while `ITEM_BUILDER_ENABLED` is not `false`. It defaults to on and is unset in production, so it answers today; but this is the one documented endpoint whose availability is a deployment setting rather than a property of the data. Confirmed answering in production on 17/08/2026.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionStatementResponse"}}}},"404":{"description":"Not found, or the item builder is disabled. The two are deliberately indistinguishable by status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/roles":{"get":{"tags":["roles"],"summary":"Roles (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/profiles":{"get":{"tags":["profiles"],"summary":"Profiles (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/information-uses":{"get":{"tags":["information-uses"],"summary":"Information Uses (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InformationUseListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/workflows":{"get":{"tags":["workflows"],"summary":"Flows (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sources":{"get":{"tags":["sources"],"summary":"Sources (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/source-references":{"get":{"tags":["source-references"],"summary":"Source references (paginated)","description":"Keyset-paginated list. Walk it by passing `meta.nextCursor` back as `?cursor=`; `nextCursor: null` is the only end-of-list signal.\n\nANONYMOUS callers receive the teaser shape documented here. A caller with a session receives the full row from this same endpoint, which is a superset. Build against the teaser and ignore unknown properties.\n\nThere is deliberately no `meta.total`.","parameters":[{"schema":{"type":"string","description":"Keyset cursor from the previous response's `meta.nextCursor`."},"required":false,"description":"Keyset cursor from the previous response's `meta.nextCursor`.","name":"cursor","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceReferenceListResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/roles/{slug}":{"get":{"tags":["roles"],"summary":"One Role, with its Profiles","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/profiles/{slug}":{"get":{"tags":["profiles"],"summary":"One Profile","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/information-uses/{slug}":{"get":{"tags":["information-uses"],"summary":"One Information Use","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InformationUseDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/workflows/by-slug/{slug}":{"get":{"tags":["workflows"],"summary":"One Flow, by slug","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sources/{id}":{"get":{"tags":["sources"],"summary":"One Source","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/source-references/{id}":{"get":{"tags":["source-references"],"summary":"One source reference","description":"Returns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.\n\nNON-DISCLOSING: a row that exists but is not readable by this caller is a 404, identical to a row that does not exist. Do not infer existence from the status code.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceReferenceDetailResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/flows/role/{slug}":{"get":{"tags":["roles"],"summary":"Generated Flow for one Role","description":"DERIVED, not stored. Generated from the Role at read time, so it can change without the Role having been edited.\n\nReturns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedFlowResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/flows/profile/{slug}":{"get":{"tags":["profiles"],"summary":"Generated Flow for one Profile","description":"DERIVED, not stored. Generated from the Profile at read time, so it can change without the Profile having been edited.\n\nReturns the FULL row to every caller, anonymous included. The reduced teaser shape applies to bulk lists, not single-item reads. The properties documented here are the confirmed ones; more are present. Ignore unknown properties.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratedFlowResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/roles":{"get":{"tags":["roles"],"summary":"Search Roles","description":"Trigram search over Roles. Bounded by `limit`, NOT cursor-paginated: there is no way to walk past the limit, by design.\n\nResults are visibility-filtered for the caller, so the same query returns more to a signed-in member than to an anonymous caller.","parameters":[{"schema":{"type":"string","description":"Search term. An empty term returns an empty result set."},"required":false,"description":"Search term. An empty term returns an empty result set.","name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/profiles":{"get":{"tags":["profiles"],"summary":"Search Profiles","description":"Trigram search over Profiles. Bounded by `limit`, NOT cursor-paginated: there is no way to walk past the limit, by design.\n\nResults are visibility-filtered for the caller, so the same query returns more to a signed-in member than to an anonymous caller.","parameters":[{"schema":{"type":"string","description":"Search term. An empty term returns an empty result set."},"required":false,"description":"Search term. An empty term returns an empty result set.","name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/information-uses":{"get":{"tags":["information-uses"],"summary":"Search Information Uses","description":"Trigram search over Information Uses. Bounded by `limit`, NOT cursor-paginated: there is no way to walk past the limit, by design.\n\nResults are visibility-filtered for the caller, so the same query returns more to a signed-in member than to an anonymous caller.","parameters":[{"schema":{"type":"string","description":"Search term. An empty term returns an empty result set."},"required":false,"description":"Search term. An empty term returns an empty result set.","name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/source-materials":{"get":{"tags":["sources"],"summary":"Search source materials","description":"Trigram search over source materials. Bounded by `limit`, NOT cursor-paginated: there is no way to walk past the limit, by design.\n\nResults are visibility-filtered for the caller, so the same query returns more to a signed-in member than to an anonymous caller.","parameters":[{"schema":{"type":"string","description":"Search term. An empty term returns an empty result set."},"required":false,"description":"Search term. An empty term returns an empty result set.","name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/entities":{"get":{"tags":["search"],"summary":"Search across entity types","description":"Cross-entity search. Same bounding and visibility filtering as the per-entity searches.","parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":["integer","null"],"description":"Page size, clamped to [1, 200]. Defaults to 50."},"required":false,"description":"Page size, clamped to [1, 200]. Defaults to 50.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Narrow to one organisation. Ignored where the caller has no visibility of it."},"required":false,"description":"Narrow to one organisation. Ignored where the caller has no visibility of it.","name":"orgId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/registers/gaps":{"get":{"tags":["registers"],"summary":"Gap register","description":"CAPPED, NOT PAGINATED. There is no cursor. When the cap is reached the response is truncated and says so, in this order of reliability:\n\n- `x-rpf-truncated`, `x-rpf-row-limit` and `x-rpf-rows-available` response headers\n- for `?format=csv`, a trailing `# TRUNCATED: ...` comment row, because headers do not survive a file being saved to disk and emailed on\n\nTruncation is never silent. Treat a response without the header as complete.","parameters":[{"schema":{"type":"string"},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"profileId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"proposedSupportKind","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/registers/cross-reference":{"get":{"tags":["registers"],"summary":"Cross-reference register","description":"CAPPED, NOT PAGINATED. There is no cursor. When the cap is reached the response is truncated and says so, in this order of reliability:\n\n- `x-rpf-truncated`, `x-rpf-row-limit` and `x-rpf-rows-available` response headers\n- for `?format=csv`, a trailing `# TRUNCATED: ...` comment row, because headers do not survive a file being saved to disk and emailed on\n\nTruncation is never silent. Treat a response without the header as complete.\n\n`?format=csv` returns `text/csv` instead of the `{ data }` envelope. The row budget charges the same either way: metering is priced in ROWS precisely so the response format cannot become the cheap way round it.","parameters":[{"schema":{"type":"string"},"required":false,"name":"source","in":"query"},{"schema":{"type":"string"},"required":false,"name":"kind","in":"query"},{"schema":{"type":"string"},"required":false,"name":"workflowId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"profileId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"relevance","in":"query"},{"schema":{"type":"string","enum":["csv"],"description":"Set to `csv` for a CSV download instead of JSON."},"required":false,"description":"Set to `csv` for a CSV download instead of JSON.","name":"format","in":"query"}],"responses":{"200":{"description":"OK. JSON by default, `text/csv` when `?format=csv`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/showcase/metro-map":{"get":{"tags":["showcase"],"summary":"Metro map data","description":"The role set as a metro map. Charged at `stations.length` rows, not 1: a rendered map is a bulk export of the role set in visual form, and pricing it as a single read would make it the cheap way round the list metering.","parameters":[{"schema":{"type":"string"},"required":false,"name":"discipline","in":"query"},{"schema":{"type":"string"},"required":false,"name":"jurisdiction","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Defaults to `latest`."},"required":false,"description":"Defaults to `latest`.","name":"version","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetroMapResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/showcase/metro-map/render":{"get":{"tags":["showcase"],"summary":"Metro map, rendered","description":"The same map rasterised. Binary response, charged identically at `stations.length`.","parameters":[{"schema":{"type":"string"},"required":false,"name":"discipline","in":"query"},{"schema":{"type":"string"},"required":false,"name":"jurisdiction","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Defaults to `latest`."},"required":false,"description":"Defaults to `latest`.","name":"version","in":"query"},{"schema":{"type":"string","description":"Output format, for example `svg`, `png` or `pdf`."},"required":false,"description":"Output format, for example `svg`, `png` or `pdf`.","name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"size","in":"query"}],"responses":{"200":{"description":"Rendered map.","content":{"image/svg+xml":{"schema":{"type":"string"}},"image/png":{"schema":{"type":"string"}},"application/pdf":{"schema":{"type":"string"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/changes":{"get":{"tags":["feed"],"summary":"What changed, since when","description":"A cursor-based feed of catalogue changes, so you do not have to re-crawl. It mirrors the SMC mutations contract, so an existing SMC poller works against it with the URL changed.\n\n**How to poll.** First call with no `since`; you receive the oldest page and a `cursor_at`. Send that back as `since` next time, with `after_event_id` set to the last `event_id` you processed. Repeat while `has_more` is true.\n\n**Boundary events are RE-DELIVERED on purpose.** Events whose `occurred_at` equals the `cursor_at` you were given come back on the next poll. That is the contract, not a bug: it is what guarantees no event is skipped when several share a timestamp. Deduplicate on `event_id`, which is stable across re-delivery.\n\n**Empty polls do not rewind you.** With nothing new, `cursor_at` echoes the value you sent.\n\n**What an event means, and what it does not.** `<kind>.changed` says the entity is at a NEW STATE, not what was done to it: there is no actor, no before/after and no action verb, because the feed is derived from entity state rather than from the audit log, which is what keeps operator identities and internal notes out of a public surface by construction rather than by projection.\n\n**DELETIONS ARE NOT REPRESENTED.** A withdrawn entity simply stops appearing; no tombstone is emitted. A consumer reconciling removals must still compare sets periodically. This is a known limitation of deriving from state.\n\n**Visibility applies.** You see changes to entities you can read. An anonymous caller sees canonical published content only, so a change to an organisation's private row is not merely redacted, it is absent.\n\n**Metered in rows**, like every other bulk read: a page of 100 events costs 100.","parameters":[{"schema":{"type":"string","description":"RFC 3339 timestamp, normally the previous response's `cursor_at`. Malformed values are a 400, never a silent reset to the beginning of the catalogue."},"required":false,"description":"RFC 3339 timestamp, normally the previous response's `cursor_at`. Malformed values are a 400, never a silent reset to the beginning of the catalogue.","name":"since","in":"query"},{"schema":{"type":"string","description":"The last `event_id` you processed, used as the tiebreaker among events sharing `since`. Omit it and you receive everything at or after that instant."},"required":false,"description":"The last `event_id` you processed, used as the tiebreaker among events sharing `since`. Omit it and you receive everything at or after that instant.","name":"after_event_id","in":"query"},{"schema":{"type":["integer","null"],"description":"Events per page, clamped to 100. Defaults to 50."},"required":false,"description":"Events per page, clamped to 100. Defaults to 50.","name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeFeedResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/iu-stacks/schema.json":{"get":{"tags":["packages"],"summary":"IU Stack JSON Schema","description":"JSON Schema for the IU Stack package payload. Validate against this rather than against this specification's prose: it ships with the payload and moves with it.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonSchemaDocument"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/jurisdictional-flows/schema.json":{"get":{"tags":["packages"],"summary":"Jurisdictional Flow JSON Schema","description":"JSON Schema for the Jurisdictional Flow package payload. Validate against this rather than against this specification's prose: it ships with the payload and moves with it.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonSchemaDocument"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/persona-plans/schema.json":{"get":{"tags":["packages"],"summary":"Persona Plan JSON Schema","description":"JSON Schema for the Persona Plan package payload. Validate against this rather than against this specification's prose: it ships with the payload and moves with it.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonSchemaDocument"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/iu-stacks":{"get":{"tags":["packages"],"summary":"IU Stack package","description":"Composed stack for a set of Information Uses. Validate against `/api/packages/iu-stacks/schema.json`.","parameters":[{"schema":{"type":"string","description":"Comma-separated Information Use slugs."},"required":false,"description":"Comma-separated Information Use slugs.","name":"ius","in":"query"},{"schema":{"type":"string"},"required":false,"name":"include","in":"query"},{"schema":{"type":"string"},"required":false,"name":"doaMin","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Serialisation variant where the package offers more than one."},"required":false,"description":"Serialisation variant where the package offers more than one.","name":"format","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/jurisdictional-flows":{"get":{"tags":["packages"],"summary":"Jurisdictional Flow package","description":"Composed flow for a jurisdiction. Validate against `/api/packages/jurisdictional-flows/schema.json`.","parameters":[{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Serialisation variant where the package offers more than one."},"required":false,"description":"Serialisation variant where the package offers more than one.","name":"format","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/persona-plans":{"get":{"tags":["packages"],"summary":"Persona Plan package","description":"Plan from a current Persona to a target one. Validate against `/api/packages/persona-plans/schema.json`.","parameters":[{"schema":{"type":"string"},"required":false,"name":"current","in":"query"},{"schema":{"type":"string"},"required":false,"name":"target","in":"query"},{"schema":{"type":"string"},"required":false,"name":"jurisdiction","in":"query"},{"schema":{"type":"string"},"required":false,"name":"discipline","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"},{"schema":{"type":"string","description":"Serialisation variant where the package offers more than one."},"required":false,"description":"Serialisation variant where the package offers more than one.","name":"format","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/organizations/{orgSlug}/personas/{roleSlug}":{"get":{"tags":["packages"],"summary":"Organisation Persona package","description":"One organisation's Persona for a Role. Answers only where the organisation has published it; otherwise 404, which does not distinguish unpublished from non-existent.","parameters":[{"schema":{"type":"string"},"required":true,"name":"orgSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"roleSlug","in":"path"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle."},"required":false,"description":"Flatten multilingual fields to a single language. Omitted returns the full `LangText` bundle.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/verification-rounds/{id}":{"get":{"tags":["packages"],"summary":"Verification round package","description":"One verification round. `?scope=aggregate` returns aggregate figures instead of per-participant detail; panellist identities are never in the anonymous projection.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["aggregate"]},"required":false,"name":"scope","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/credentials/{recognitionId}/{objectType}/{objectSlug}":{"get":{"tags":["packages"],"summary":"Credential package","description":"A credential asserting that an object meets a recognition.\n\nThe alignment block carries canonical URLs for the aligned objects. Credentials issued before bundle 4B minted those on the legacy `/items/{id}` path, which 308-redirects to `/action-statements/{id}`; a consumer resolving an older credential must follow redirects.","parameters":[{"schema":{"type":"string"},"required":true,"name":"recognitionId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"objectType","in":"path"},{"schema":{"type":"string"},"required":true,"name":"objectSlug","in":"path"},{"schema":{"type":"string","description":"Serialisation variant where the package offers more than one."},"required":false,"description":"Serialisation variant where the package offers more than one.","name":"format","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}}},"400":{"description":"Bad request. A malformed cursor is a 400, never a silent reset to page one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found, or not visible to this caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/openapi.json":{"get":{"tags":["meta"],"summary":"This document","description":"The OpenAPI 3.1 description of this API, regenerated per request from the same Zod schemas the handlers validate against, so it cannot describe a shape the code does not implement.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/public/orgs/{orgSlug}/v1/scenarios":{"get":{"tags":["projection"],"summary":"Published scenarios of one organisation","description":"Every active published scenario of the organisation, as identity, status and links: the index card, not the document. Interim publications are included; filter on `tier` to list only client-ready reports.\n\nThe `/v1/` segment is the contract: within it, changes are additive only. New properties may appear on any response; ignore ones you do not recognise.\n\nResponses carry a weak `ETag`; send `If-None-Match` to poll cheaply (a matching tag answers 304).","security":[{"apiKeyHeader":[]},{"bearerApiKey":[]}],"parameters":[{"schema":{"type":"string","description":"The organisation's slug."},"required":true,"description":"The organisation's slug.","name":"orgSlug","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectionScenarioListResponse"}}}},"401":{"description":"No valid API key. This surface has no anonymous tier: it requires an organisation-scoped key for the organisation being read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key is valid but not scoped to this organisation (platform-wide keys are deliberately not enough).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such organisation, or one the public eligibility gate excludes; on the single-item route, also an unknown scenario code. Indistinguishable on purpose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/orgs/{orgSlug}/v1/scenarios/{code}":{"get":{"tags":["projection"],"summary":"One published scenario by its SP- code","description":"The list item for one scenario, addressed by the SP- code consumers key on. Same shape and same contract as the list route.\n\nThe `/v1/` segment is the contract: within it, changes are additive only. New properties may appear on any response; ignore ones you do not recognise.","security":[{"apiKeyHeader":[]},{"bearerApiKey":[]}],"parameters":[{"schema":{"type":"string","description":"The organisation's slug."},"required":true,"description":"The organisation's slug.","name":"orgSlug","in":"path"},{"schema":{"type":"string","description":"The SP- scenario code, matching ^SP-[A-Z0-9-]+$."},"required":true,"description":"The SP- scenario code, matching ^SP-[A-Z0-9-]+$.","name":"code","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectionScenarioResponse"}}}},"401":{"description":"No valid API key. This surface has no anonymous tier: it requires an organisation-scoped key for the organisation being read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key is valid but not scoped to this organisation (platform-wide keys are deliberately not enough).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such organisation, or one the public eligibility gate excludes; on the single-item route, also an unknown scenario code. Indistinguishable on purpose.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or the daily row budget is exhausted. `details.reason = \"READ_BUDGET_EXCEEDED\"` distinguishes the budget from the request limiter, and means an API key would raise the ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/packages/personas/schema.json":{"get":{"tags":["packages"],"description":"Returns the JSON Schema (draft-07) for the RPF Role/Persona Package. Public, cacheable. Stable contract — schema version is encoded inside `package.schemaVersion`.","responses":{"200":{"description":"OK — the JSON Schema document.","content":{"application/schema+json":{"schema":{"type":"object","properties":{},"additionalProperties":{},"description":"JSON Schema (draft-07) describing the PersonaPackage object."}}}},"304":{"description":"Not Modified (matched If-None-Match)"},"500":{"description":"Server misconfiguration (e.g. NEXT_PUBLIC_SITE_URL unset)."}}}},"/api/packages/personas/{slug}":{"get":{"tags":["packages"],"description":"Returns a populated RPF Role/Persona Package for the role identified by `slug`. Visibility is enforced at the data layer — public callers see only formal-published rows. `?include=` (csv) controls which optional slots are populated; default is the full package. `?locale=` selects the language used for flow rendering and is recorded in `package.locale`. Body matches the JSON Schema served at `/api/packages/personas/schema.json`.","parameters":[{"schema":{"type":"string","description":"Role slug. Same value used by `/api/roles/{slug}` and the role detail page.","example":"bim-coordinator"},"required":true,"description":"Role slug. Same value used by `/api/roles/{slug}` and the role detail page.","name":"slug","in":"path"},{"schema":{"type":"string","description":"Comma-separated subset of: profiles, statements, informationUses, materials, flows, sources. Omit to receive the full package.","example":"profiles,statements"},"required":false,"description":"Comma-separated subset of: profiles, statements, informationUses, materials, flows, sources. Omit to receive the full package.","name":"include","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Locale used for flow rendering (label/disclaimer/step display). Defaults to en. LangText fields on role/profile/material rows are preserved as-is regardless."},"required":false,"description":"Locale used for flow rendering (label/disclaimer/step display). Defaults to en. LangText fields on role/profile/material rows are preserved as-is regardless.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK — the populated package.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonaPackage"}}}},"304":{"description":"Not Modified (matched If-None-Match)"},"400":{"description":"Bad request (unknown ?include token, a ?format= other than rpf-json, or ?jurisdiction= on this endpoint)."},"404":{"description":"Role not found, or not visible to the current viewer (responses are unified to avoid leaking row existence)."}}}},"/api/packages/information-uses/schema.json":{"get":{"tags":["packages"],"description":"Returns the JSON Schema (draft-07) for the RPF Information Use Package. Public, cacheable. Stable contract — schema version is encoded inside `package.schemaVersion`.","responses":{"200":{"description":"OK — the JSON Schema document.","content":{"application/schema+json":{"schema":{"type":"object","properties":{},"additionalProperties":{},"description":"JSON Schema (draft-07) describing the InformationUsePackage object."}}}},"304":{"description":"Not Modified (matched If-None-Match)"},"500":{"description":"Server misconfiguration (e.g. NEXT_PUBLIC_SITE_URL unset)."}}}},"/api/packages/information-uses/{slug}":{"get":{"tags":["packages"],"description":"Returns a populated RPF Information Use Package. Cacheable (Cache-Control max-age=60, weak ETag). Use ?include= to control which optional sections are populated.","parameters":[{"schema":{"type":"string","example":"clash-detection"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","description":"Comma-separated subset of: profiles, relatedRoles, statements, materials, sources. Omit for the full package."},"required":false,"description":"Comma-separated subset of: profiles, relatedRoles, statements, materials, sources. Omit for the full package.","name":"include","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"]},"required":false,"name":"locale","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InformationUsePackage"}}}},"304":{"description":"Not Modified"},"400":{"description":"Bad request (unknown ?include token, a ?format= other than rpf-json, or ?jurisdiction=)"},"404":{"description":"Information Use not found, or not visible to the current viewer"}}}},"/api/packages/profile-gaps/{slug}":{"get":{"tags":["packages"],"description":"Returns a Profile Gap Analysis package comparing the org-scoped Profile identified by path `slug` against the canonical Profile identified by `?vs=<canonical-slug>`. Visibility is enforced at the data layer — public callers see only formal-published rows on both sides. `?locale=` selects the language used for item / IU title rendering. Body matches the JSON Schema served at `/api/packages/profile-gaps/schema.json`.","parameters":[{"schema":{"type":"string","description":"Org-scoped Profile slug (the subject of the comparison). Same value used by `/api/profiles/{slug}`.","example":"acme-architect"},"required":true,"description":"Org-scoped Profile slug (the subject of the comparison). Same value used by `/api/profiles/{slug}`.","name":"slug","in":"path"},{"schema":{"type":"string","description":"Canonical Profile slug to compare against (typically a future-ready canonical profile). Required.","example":"architect-future-ready"},"required":true,"description":"Canonical Profile slug to compare against (typically a future-ready canonical profile). Required.","name":"vs","in":"query"},{"schema":{"type":"string","enum":["en","pt-BR","fr","es"],"description":"Locale used for item / IU title rendering. Defaults to en."},"required":false,"description":"Locale used for item / IU title rendering. Defaults to en.","name":"locale","in":"query"}],"responses":{"200":{"description":"OK — the gap-analysis package.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileGapPackage"}}}},"304":{"description":"Not Modified (matched If-None-Match)"},"400":{"description":"Bad request (missing ?vs= or both slugs refer to the same profile)."},"404":{"description":"Either profile not found, or not visible to the current viewer."}}}}},"webhooks":{}}