info:
  description: 'Content Management API Endpoints '
  title: PostRFP Ref API
  version: 1.8.1
servers:
- url: https://re.postrfp.com/ref/api/
- url: http://localhost:9000/ref/api/
paths:
  /content:
    post:
      description: "Create a new content item\n\nCreates a new structured content
        item validated against its schema. The content\nis authored by the user's
        organization and can be associated with subjects,\ntags, and custom permission
        settings.\n\n**Returns:** Complete created content with assigned ID and metadata\n\
        \n**Schema Validation:**\nThe `content_doc` structure must conform to the
        JSON schema defined by `schema_id`.\nValidation errors will be returned if
        the content doesn't match the schema.\n\n\n\n**\n\nPermissions: REF_CONTENT_SAVE**"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentDocument'
      operationId: post_content
      tags:
      - Editors
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentDocument'
  /content/map:
    post:
      description: "Create a new content map with mapping pairs\n\nCreates a new mapping
        between questionnaire elements and content fields.\nThe map can include multiple
        pairs in a single request, defining how various\nquestion responses populate
        different fields in the content document.\n\n**Pair Structure:**\nEach pair
        in the `pairs` array must include:\n- `question_element_id`: ID of the question
        element\n- `content_reference`: JSONPointer expression for the content field\n\
        \n**Returns:** Created map with all pairs, assigned IDs, and complete structure\n\
        \n**JSON Pointer Requirements:**\n- Must be valid JSON Pointer expressions
        starting with `$`\n- Should reference fields that exist in the associated
        ContentSpec\n- Can target nested objects, arrays, and complex structures\n\
        - Examples: `$.name`, `$.address.city`, `$.items[0].quantity`\n\n**Validation:**\n\
        The system validates:\n- ContentSpec ID exists and belongs to user's organization\n\
        - Question element IDs exist (if provided)\n- JSON Pointer expressions are
        well-formed\n- No duplicate question elements in the same map\n\n**Ownership:**\n\
        - Map is associated with the ContentSpec's organization\n- Only users from
        the ContentSpec's organization can create/edit maps\n\n**\n\nPermissions:
        REF_CONTENT_SAVE**"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSpecMapDocument'
      operationId: post_content_map
      tags:
      - Editors
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentSpecMapDocument'
  /content/map/{map_id}:
    delete:
      description: "Delete a content map and all its mapping pairs\n\nPermanently
        removes a content map and all associated question-to-field mappings.\nThis
        action cannot be undone. The deletion only affects the mapping definition;\n\
        it does not affect existing content or questionnaires.\n\n**Path Parameters:**\n\
        - `content_map_id`: ID of the content map to delete\n\n**Returns:** None (204
        No Content status)\n\n**What Gets Deleted:**\n- The content map itself\n-
        All question-to-field mapping pairs\n- All mapping metadata and documentation\n\
        \n**What Is NOT Affected:**\n- Content items (existing content remains unchanged)\n\
        - ContentSpec (the schema remains intact)\n- Question elements (questions
        remain in questionnaires)\n- Questionnaire responses (answers are preserved)\n\
        \n**Impact:**\n- Future questionnaire responses cannot use this mapping to
        populate content\n- Existing content created via this mapping remains valid\n\
        - Manual content population is still possible\n- Other mappings for the same
        ContentSpec continue to work\n\n**Permission Requirements:**\n- User must
        have REF_CONTENT_SAVE permission\n- Map must belong to a ContentSpec owned
        by user's organization\n\n**Use Cases:**\n- Remove obsolete or incorrect mappings\n\
        - Clean up unused mapping definitions\n- Reorganize mapping structure (delete
        then recreate)\n\n**\n\nPermissions: REF_CONTENT_SAVE**"
      parameters:
      - in: path
        required: true
        name: map_id
        description: ID of the ContentSpecMap
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
      operationId: delete_content_map
      tags:
      - Editors
    get:
      description: "Get a single content map by ID\n\nRetrieves complete information
        about a content map including all question-to-field\nmapping pairs. Each pair
        specifies which question element maps to which field in\nthe content document
        via a JSON Pointer expression.\n\n**Path Parameters:**\n- `content_map_id`:
        Unique identifier of the content map\n\n**JSON Pointer Expression Examples:**\n\
        - `$.sla.uptime` → Maps to content_doc[\"sla\"][\"uptime\"]\n- `$.contact.email`
        → Maps to content_doc[\"contact\"][\"email\"]\n- `$.features[0].name` → Maps
        to content_doc[\"features\"][0][\"name\"]\n\n**Use Cases:**\n- Understand
        complete mapping structure\n- Review question-to-field connections\n- Debug
        content population issues\n- Document integration workflows\n\n**Raises:**\n\
        - `NoResultFound`: If the content map ID does not exist\n- `AuthorizationFailure`:
        If the map belongs to another organization's ContentSpec"
      parameters:
      - in: path
        required: true
        name: map_id
        description: ID of the ContentSpecMap
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSpecMapDocument'
      operationId: get_content_map
      tags:
      - Editors
    put:
      description: "Update an existing content map and replace all mapping pairs\n\
        \nModifies an existing content map with new data. This operation replaces
        ALL\nexisting mapping pairs with the new set provided in the request. Any
        pairs\nnot included in the update will be deleted.\n\n**Path Parameters:**\n\
        - `content_map_id`: ID of the content map to update\n\n**Returns:** Updated
        map with new structure and all pairs\n\n**Important - Pair Replacement Behavior:**\n\
        - ALL existing pairs are deleted\n- ALL pairs in the request are created as
        new\n- To keep a pair, include it in the update request\n- To remove a pair,
        omit it from the pairs array\n- To add a pair, include it in the pairs array\n\
        \n**Use Cases:**\n- Rename or re-describe the mapping\n- Add new question-to-field
        mappings\n- Remove obsolete mappings\n- Reorganize mapping structure\n- Move
        map to a different ContentSpec\n\n**Best Practices:**\n- Include all pairs
        you want to keep in the update\n- Review existing pairs before updating (use
        GET first)\n- Test mapping changes with sample questionnaire data\n- Document
        reasons for structural changes\n\n**\n\nPermissions: REF_CONTENT_SAVE**"
      parameters:
      - in: path
        required: true
        name: map_id
        description: ID of the ContentSpecMap
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSpecMapDocument'
      operationId: put_content_map
      tags:
      - Editors
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentSpecMapDocument'
  /content/maps:
    get:
      description: "List all content maps accessible to the user's organization\n\n\
        Content maps define how questionnaire responses populate structured content.\n\
        Each map connects question elements to specific fields in a content document\n\
        using JSON Pointer expressions. Maps are filtered to show only those belonging\n\
        to content schemas owned by the user's organization.\n\n**Query Parameters:**\n\
        - `q_name`: Filter maps by name (case-insensitive partial match)\n- `q_spec_id`:
        Filter by content schema/specification ID\n- Standard pagination parameters
        supported\n\n**Returns:** Paginated list of content maps accessible to the
        user\n\n**Access Control:**\nMaps are filtered to show only:\n- Maps associated
        with ContentSpecs owned by the user's organization\n- This ensures organizations
        only see mappings for their own content structures\n\n**Map Information Includes:**\n\
        - Map identification (ID, name, description)\n- Associated ContentSpec ID\n\
        - List of all question-to-field mapping pairs\n- JSON Pointer expressions
        for each field mapping\n\n**Use Cases:**\n- Browse available content population
        mappings\n- Find mappings for specific content types\n- Understand how questionnaires
        populate content\n- Manage organization's content integration workflows\n\n\
        **Examples:**\n- Get all maps: no query parameters\n- Search by name: `?q_name=vendor
        SLA`\n- Filter by schema: `?q_spec_id=5`"
      parameters:
      - in: query
        required: false
        name: qName
        description: Search for string inside a name
        schema:
          type: string
      - in: query
        required: false
        name: specId
        description: ID of the ContentSpec
        schema:
          type: integer
      - in: query
        required: false
        name: page_size
        description: The number of records to return in a single page,  maximum 
          200, minimum 1
        schema:
          type: integer
          default: 20
      - in: query
        required: false
        name: page
        description: Page number of records to show, beginning from 1
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse'
      operationId: get_content_maps
      tags:
      - Editors
  /content/{content_id}:
    delete:
      description: "Delete a content item\n\nPermanently removes a content item and
        all its associated data including\nrelationships, permissions, and revision
        history. This action cannot be undone.\nThe user's organization must have
        edit permissions for this content.\n\n**Path Parameters:**\n- `content_id`:
        ID of the content item to delete\n\n**Returns:** None (204 No Content status)\n\
        \n**What Gets Deleted:**\n- The content item itself\n- All tag associations\n\
        - All subject associations\n- All content relationships (both incoming and
        outgoing)\n- Complete revision history\n- Any comments or annotations\n\n\n\
        **Important Warnings:**\n- **This action is irreversible** - deleted content
        cannot be recovered\n- Other content items that reference this content will
        have broken relationships\n- Organizations that had access will lose that
        access immediately\n- Any workflows or external systems referencing this content
        may break\n\n**\n\nPermissions: REF_CONTENT_SAVE**"
      parameters:
      - in: path
        required: true
        name: content_id
        description: ID of the Content
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
      operationId: delete_content
      tags:
      - Editors
    get:
      description: "Get a single content item by ID\n\nRetrieves complete information
        about a content item including all structured\ndata, metadata, relationships,
        and associated tags and subjects. The user's\norganization must have appropriate
        permissions to view this content.\n\n**Path Parameters:**\n- `content_id`:
        Unique identifier of the content item\n\n**Raises:**\n- `NoResultFound`: If
        the content ID does not exist\n- `AuthorizationFailure`: If the user lacks
        permission to view this content"
      parameters:
      - in: path
        required: true
        name: content_id
        description: ID of the Content
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentDocument'
      operationId: get_content
      tags:
      - Editors
    put:
      description: "Update an existing content item\n\nModifies an existing content
        item with new data. The user's organization must\nhave edit permissions for
        this content. All changes are tracked in the revision\nhistory for auditing
        purposes.\n\n**Path Parameters:**\n- `content_id`: ID of the content item
        to update\n\n\n**Returns:** Updated content with new timestamps and metadata\n\
        \n\n**Schema Validation:**\nUpdated content must still conform to the original
        schema. Schema changes\nrequire updating the `schema_id` if needed.\n\n**Revision
        Tracking:**\nChanges are automatically tracked in the revision history, including:\n\
        - What fields changed\n- Who made the changes\n- When changes occurred\n-
        Optional change comments\n\n**\n\nPermissions: REF_CONTENT_SAVE**"
      parameters:
      - in: path
        required: true
        name: content_id
        description: ID of the Content
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentDocument'
      operationId: put_content
      tags:
      - Editors
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentDocument'
  /content/{content_id}/relationships:
    get:
      description: "Get all relationships for a specific content item\n\nReturns content
        items that are related to the specified content,\ngrouped by relationship
        type (parent, child, related, etc.).\nOnly returns content the user has permission
        to view."
      parameters:
      - in: path
        required: true
        name: content_id
        description: ID of the Content
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentRelationshipDoc'
      operationId: get_content_relationships
      tags:
      - Readers
  /contents:
    get:
      description: "List all content items accessible to the user's organization\n\
        \nReturns content items that the user's organization has permission to view,\n\
        including authored content, public content, and content with explicit permissions.\n\
        Results can be filtered by title and schema, and are paginated for performance.\n\
        \n**Query Parameters:**\n- `q_name`: Filter content by title (case-insensitive
        partial match)\n- `q_spec_id`: Filter by content schema/specification ID\n\
        - Standard pagination parameters supported\n\n**Returns:** Paginated list
        of content summaries accessible to the user\n\n\n**Content Summary includes:**\n\
        - Basic identification (ID, title, dates)\n- Schema information\n- Author
        organization\n- Associated tags and subjects\n\n**Examples:**\n- Get all content:
        no query parameters\n- Search by title: `?q_name=financial report`\n- Filter
        by schema: `?q_spec_id=5`"
      parameters:
      - in: query
        required: false
        name: qName
        description: Search for string inside a name
        schema:
          type: string
      - in: query
        required: false
        name: specId
        description: ID of the ContentSpec
        schema:
          type: integer
      - in: query
        required: false
        name: page_size
        description: The number of records to return in a single page,  maximum 
          200, minimum 1
        schema:
          type: integer
          default: 20
      - in: query
        required: false
        name: page
        description: Page number of records to show, beginning from 1
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse'
      operationId: get_contents
      tags:
      - Editors
  /policy:
    delete:
      description: "Remove a CEL authorization policy from an entity (sets policy
        to None).\n\n**Request Body:** Policy data including:\n- `entity`: Type of
        entity (\"Content\", \"ContentSpec\", or \"Subject\")\n- `entity_id`: ID of
        the entity to remove policy from\n\n**Returns:** Policy removal response with
        success status\n\n**\n\nPermissions: REF_MANAGE_PERMISSIONS**"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyResponse'
      operationId: delete_policy
      tags:
      - Administrators
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PolicyRequest'
    post:
      description: "Update a CEL authorization policy on a content item, content spec,
        or subject.\n\n**Request Body:** Policy data including:\n- `entity`: Type
        of entity (\"Content\", \"ContentSpec\", or \"Subject\")\n- `entity_id`: ID
        of the entity to update policy for\n- `policy`: CEL expression for authorization\n\
        \n**Returns:** Policy update response with success status and details\n\n\
        **Example CEL Policies:**\n- `entity.author_org_id == user.org.id`: Author
        organization access\n- `'admin' in user.roles`: Role-based access\n\n**\n\n\
        Permissions: REF_MANAGE_PERMISSIONS**"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyResponse'
      operationId: post_policy
      tags:
      - Administrators
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PolicyRequest'
  /search:
    get:
      description: "List content items related to a specific subject\n\nReturns a
        list of content items that are associated with the specified subject\nand
        that the current user has permission to view. Results can be filtered\nby
        content title and are paginated."
      parameters:
      - in: query
        required: false
        name: subject_id
        description: Subject ID to filter by
        schema:
          type: integer
      - in: query
        required: false
        name: q_term
        description: Search term to query by
        schema:
          type: string
      - in: query
        required: false
        name: page_size
        description: The number of records to return in a single page,  maximum 
          200, minimum 1
        schema:
          type: integer
          default: 20
      - in: query
        required: false
        name: page
        description: Page number of records to show, beginning from 1
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse'
      operationId: get_search
      tags:
      - Readers
  /spec:
    post:
      description: "Create a new content schema\n\nCreates a new JSON Schema definition
        that will control the structure and\nvalidation of content items. The schema
        becomes available for content creation\nwithin the user's organization and
        can define complex data structures.\n\n**Request Body:** Schema document including:\n\
        - `name`: Descriptive name for the schema (required)\n- `description`: Detailed
        explanation of the schema purpose\n- `spec_doc`: Complete JSON Schema definition
        (required)\n\n**Returns:** Created schema with assigned ID and metadata\n\n\
        **JSON Schema Requirements:**\nThe `spec_doc` must be a valid JSON Schema
        (Draft 7+ recommended) including:\n- Root `type` definition (typically \"\
        object\")\n- `properties` defining all available fields\n- `required` array
        listing mandatory fields\n- Field-level validation constraints\n- Proper data
        type specifications\n\n**Schema Validation:**\nThe system validates that:\n\
        - The JSON Schema syntax is correct\n- Required fields are properly defined\n\
        - Type definitions are valid\n- Constraints are logically consistent\n\n**Ownership:**\n\
        - Schema is owned by the user's organization\n- Only the owning organization
        can modify the schema\n- Content created with this schema will reference the
        organization\n\n**Best Practices:**\n- Use descriptive field names and documentation\n\
        - Define appropriate validation constraints\n- Consider backward compatibility
        for schema updates\n- Include examples in the schema description\n\n**\n\n\
        Permissions: REF_SPEC_SAVE**"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSchema'
      operationId: post_spec
      tags:
      - Designers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentSchema'
  /spec/{spec_id}:
    delete:
      description: "Delete a content schema\n\nPermanently removes a schema definition
        from the system. This is a destructive\noperation that will affect all content
        items using this schema and should be\nused with extreme caution.\n\n**Path
        Parameters:**\n- `spec_id`: ID of the schema to delete\n\n**Returns:** None
        (204 No Content status)\n\n**Critical Impact:**\n- **All content using this
        schema will become invalid**\n- Content items will no longer pass validation\n\
        - Existing content becomes uneditable (validation failures)\n- Content creation
        with this schema becomes impossible\n- API responses may include validation
        warnings\n\n**What Gets Deleted:**\n- The schema definition itself\n- All
        validation rules and field specifications\n- Schema metadata and documentation\n\
        - Workflow state information for the schema\n\n**Content Impact:**\nContent
        items using this schema will:\n- Remain accessible for viewing (existing data
        preserved)\n- Fail validation checks during editing attempts\n- Display warnings
        about missing schema\n- Require schema reassignment or recreation for continued
        use\n\n**Permission Requirements:**\n- User's organization must own the schema\n\
        - Only the schema owner can delete it\n- Cannot be deleted if it would violate
        system constraints\n\n**Recommended Alternatives:**\nInstead of deletion,
        consider:\n- Deprecating the schema (mark as inactive)\n- Creating a migration
        path to a new schema\n- Archiving content using the schema first\n- Updating
        the schema to a minimal valid state\n\n**\n\nPermissions: REF_SPEC_SAVE**"
      parameters:
      - in: path
        required: true
        name: spec_id
        description: ID of the ContentSpec
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
      operationId: delete_spec
      tags:
      - Designers
    get:
      description: "Get a single content schema by ID\n\nRetrieves the complete schema
        definition including all field specifications,\nvalidation rules, metadata,
        and documentation. Essential for understanding\ncontent structure requirements
        and implementing content creation interfaces.\n\n**Path Parameters:**\n- `spec_id`:
        Unique identifier of the content schema\n\n**Returns:** Complete schema definition
        including:\n- Schema identification and metadata\n- Full JSON Schema specification
        with all validation rules\n- Field definitions and constraints\n- Required
        vs optional field specifications\n- Data types and format requirements\n-
        Custom validation patterns\n- Creation and modification history\n\n**JSON
        Schema Features:**\nThe returned schema follows JSON Schema Draft 7+ specifications
        and may include:\n- Field type definitions (string, number, object, array,
        etc.)\n- Validation constraints (min/max length, patterns, enums)\n- Nested
        object structures\n- Array item specifications\n- Conditional field requirements\n\
        - Custom format validators\n\n**Use Cases:**\n- Generate content creation
        forms dynamically\n- Validate content before submission\n- Understand content
        structure for API integration\n- Document content requirements for users\n\
        \n**Raises:**\n- `NoResultFound`: If the schema ID does not exist\n- `AuthorizationFailure`:
        If the user lacks access to this schema"
      parameters:
      - in: path
        required: true
        name: spec_id
        description: ID of the ContentSpec
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSchema'
      operationId: get_spec
      tags:
      - Designers
    put:
      description: "Update an existing content schema\n\nModifies an existing schema
        definition with new validation rules and structure.\nThis is a potentially
        breaking change that may affect existing content items\nthat use this schema,
        so it should be used carefully.\n\n**Path Parameters:**\n- `spec_id`: ID of
        the schema to update\n\n**Request Body:** Complete schema document (all fields
        will be updated)\n- `name`: Updated descriptive name for the schema\n- `description`:
        Updated explanation of schema purpose\n- `spec_doc`: Complete updated JSON
        Schema definition\n\n**Returns:** Updated schema with new timestamps and metadata\n\
        \n**Breaking Change Considerations:**\n- Existing content may no longer validate
        against the updated schema\n- New required fields will cause validation failures
        for existing content\n- Changed field types or constraints may break existing
        content\n- Removed fields will be ignored in existing content but may cause
        confusion\n\n**Schema Evolution Best Practices:**\n- Add new optional fields
        rather than required ones\n- Avoid removing existing fields that contain data\n\
        - Use schema versioning for major structural changes\n- Consider deprecation
        warnings before removing fields\n- Test schema changes against existing content\n\
        \n**Validation Impact:**\n- Content validation occurs during content creation
        and updates\n- Existing content is not automatically re-validated\n- Invalid
        content may become accessible but not editable\n- New content must pass validation
        with the updated schema\n\n**\n\nPermissions: REF_SPEC_SAVE**"
      parameters:
      - in: path
        required: true
        name: spec_id
        description: ID of the ContentSpec
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentSchema'
      operationId: put_spec
      tags:
      - Designers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContentSchema'
  /spec/{spec_id}/pointers:
    get:
      description: "Get all valid JSON Pointer paths for a ContentSpec's schema\n\n\
        Returns a comprehensive list of all valid JSON Pointer expressions that can
        be\nused when creating ContentQElementPair mappings. This endpoint is designed
        to\nhelp UI developers provide auto-complete, validation, or selection interfaces\n\
        when users are configuring question-to-field mappings.\n\n**Path Parameters:**\n\
        - `spec_id`: The ID of the ContentSpec to get pointers for\n\n\n**Access Control:**\n\
        - Requires read access to the ContentSpec (must belong to user's organization)\n\
        - This ensures organizations only access pointer information for their own
        schemas\n\n**Pointer Extraction:**\n- Recursively extracts all valid paths
        from the JSON Schema\n- Handles nested objects, arrays, $ref definitions,
        and combinators\n- Array indices are normalized (e.g., `/items/0` represents
        any array element)\n- Paths are sorted alphabetically for consistent presentation\n\
        \n**Use Cases:**\n- Populate dropdowns or auto-complete fields in mapping
        UIs\n- Validate user input when creating/editing mappings\n- Display available
        fields when configuring content population\n- Document available fields for
        API consumers\n\n**Examples:**\nFor a schema with company and financial data,
        returns paths like:\n- `/company/name`\n- `/company/legal_status/jurisdiction`\n\
        - `/financial/auditing/external_auditor`\n- `/metadata/assessment_date`\n\n\
        **Raises:**\n- `NoResultFound`: If the content_spec_id does not exist\n- `AuthorizationFailure`:
        If the ContentSpec belongs to another organization\n\n**Performance Notes:**\n\
        - Pointers are cached by the validator for efficiency\n- Safe to call frequently
        in UI workflows\n\n**Access:** Requires authentication; no explicit permission
        needed for read operations"
      parameters:
      - in: path
        required: true
        name: spec_id
        description: ID of the ContentSpec
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SchemaPointersResponse'
      operationId: get_spec_pointers
      tags:
      - Editors
  /specs:
    get:
      description: "List all content schemas accessible to the user's organization\n\
        \nContent schemas define the structure, validation rules, and field definitions\n\
        for content items. Schemas are organization-owned and control how structured\n\
        content is created and validated within the system.\n\n**Query Parameters:**\n\
        - `q_name`: Filter schemas by name (case-insensitive partial match)\n- Standard
        pagination parameters supported\n\n**Returns:** Paginated list of schema definitions
        accessible to the user\n\n**Access Control:**\nSchemas are filtered to show
        only:\n- Schemas owned by the user's organization\n- Schemas shared with the
        user's organization (if sharing is implemented)\n\n**Schema Information Includes:**\n\
        - Schema identification (ID, name, description)\n- JSON Schema definition
        with validation rules\n- Creation and modification timestamps\n- Owning organization
        details\n- Current workflow status\n\n**Use Cases:**\n- Browse available content
        templates\n- Find schemas for specific content types\n- Understand validation
        requirements before content creation\n- Manage organization's content structure
        standards\n\n**Examples:**\n- Get all schemas: no query parameters\n- Search
        by name: `?q_name=financial report`"
      parameters:
      - in: query
        required: false
        name: qName
        description: Search for string inside a name
        schema:
          type: string
      - in: query
        required: false
        name: page_size
        description: The number of records to return in a single page,  maximum 
          200, minimum 1
        schema:
          type: integer
          default: 20
      - in: query
        required: false
        name: page
        description: Page number of records to show, beginning from 1
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse'
      operationId: get_specs
      tags:
      - Designers
  /subject:
    post:
      description: "Create a new subject\n\nCreates a new subject that can be used
        to categorize content items. Subjects\ncan have hierarchical relationships
        with other subjects and their own permission\nsystems for controlling access
        to related content.\n\n**Request Body:** Subject data including:\n- `name`:
        Display name for the subject (required)\n- `code`: Optional short identifier
        or symbol\n- `description`: Optional detailed description\n- `subject_type`:
        Type classification (required)\n- `parent_id`: Optional parent subject for
        hierarchical relationships\n- `managing_org_id`: Optional organization that
        manages this subject\n- `subject_metadata`: Optional key-value metadata (country
        codes, market identifiers, etc.)\n\n**Returns:** Created subject with assigned
        ID and timestamps\n\n**Permission Impact:**\nWhen content references this
        subject, the subject's permissions may affect\ncontent access depending on
        the content's permission inheritance mode.\n\n**Hierarchical Relationships:**\n\
        Use `parent_id` to create hierarchies like:\n- City → State → Country\n- Subsidiary
        → Parent Company\n- Sub-sector → Industry Sector"
      parameters: []
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectDocument'
      operationId: post_subject
      tags:
      - Subjects
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubjectDocument'
  /subject/{subject_id}:
    delete:
      description: "Delete a subject\n\nPermanently removes a subject from the system.
        This operation is protected\nby referential integrity checks to prevent data
        inconsistency.\n\n**Path Parameters:**\n- `subject_id`: ID of the subject
        to delete\n\n**Returns:** Success confirmation with deletion details\n\n**Raises:**\n\
        - `NoResultFound`: If the subject ID does not exist\n- `ValueError`: If the
        subject has dependencies that prevent deletion:\n  - Subject has child subjects
        in the hierarchy\n  - Subject is referenced as primary subject by content
        items\n  - Subject is referenced in content subject associations\n\n**Protection
        Mechanisms:**\nThe system prevents deletion of subjects that would break data
        integrity:\n\n1. **Hierarchical Protection:** Cannot delete subjects with
        children\n2. **Content Protection:** Cannot delete subjects referenced by
        content\n3. **Permission Protection:** Associated permissions are cascade-deleted\n\
        \n**Recommendation:**\nBefore deleting, consider if the subject should be:\n\
        - Marked as inactive/deprecated instead of deleted\n- Replaced by transferring
        references to another subject\n- Have its child subjects reassigned to a different
        parent"
      parameters:
      - in: path
        required: true
        name: subject_id
        description: ID of the Subject
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletionResponse'
      operationId: delete_subject
      tags:
      - Subjects
    get:
      description: "Get a specific subject by ID\n\nRetrieves complete information
        about a subject including its name, type,\ndescription, hierarchical position,
        managing organization, and metadata.\n\n**Path Parameters:**\n- `subject_id`:
        Unique identifier of the subject\n\n**Returns:** Complete subject information\n\
        \n**Raises:**\n- `NoResultFound`: If the subject ID does not exist\n\n**Subject
        Types:**\n- `country`: Geographic countries or regions\n- `organization`:
        Companies, banks, institutions\n- `market`: Stock exchanges, trading venues\n\
        - `sector`: Industry classifications\n- `product`: Financial products or services\n\
        - `other`: Custom subject types"
      parameters:
      - in: path
        required: true
        name: subject_id
        description: ID of the Subject
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectDocument'
      operationId: get_subject
      tags:
      - Subjects
    put:
      description: "Update an existing subject\n\nModifies all fields of an existing
        subject. Changes to subject properties\nmay affect access to content that
        references this subject, depending on\nthose content items' permission inheritance
        settings.\n\n**Path Parameters:**\n- `subject_id`: ID of the subject to update\n\
        \n**Request Body:** Complete subject data (all fields will be updated)\n\n\
        **Returns:** Updated subject information\n\n**Raises:**\n- `NoResultFound`:
        If the subject ID does not exist\n- `ValueError`: If invalid subject_type
        provided\n\n**Important Notes:**\n- Changing hierarchical relationships (`parent_id`)
        affects content categorization\n- Updates to managing organization may impact
        permission inheritance\n- Metadata changes can affect external system integrations"
      parameters:
      - in: path
        required: true
        name: subject_id
        description: ID of the Subject
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectDocument'
      operationId: put_subject
      tags:
      - Subjects
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubjectDocument'
  /subject/{subject_id}/children:
    get:
      description: "Get all direct children of a subject\n\nRetrieves subjects that
        have the specified subject as their direct parent\nin the hierarchical relationship.
        This is useful for building tree views\nor navigation interfaces.\n\n**Path
        Parameters:**\n- `subject_id`: ID of the parent subject\n\n**Returns:** List
        of direct child subjects (not recursive)\n\n**Use Cases:**\n- Building hierarchical
        navigation menus\n- Showing organizational structure\n- Geographic drill-down
        (country → states → cities)\n- Industry classification browsing\n\n**Note:**\n\
        This endpoint only returns direct children. For the complete hierarchy,\n\
        you may need to make recursive calls or use the main subjects list endpoint\n\
        with appropriate filtering.\n\n**Example Hierarchies:**\n- Geographic: USA
        → California → San Francisco\n- Corporate: Holding Company → Subsidiaries
        → Divisions\n- Market: Region → Exchange → Trading Segments"
      parameters:
      - in: path
        required: true
        name: subject_id
        description: ID of the Subject
        schema:
          type: integer
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SubjectDocument'
      operationId: get_subject_children
      tags:
      - Subjects
  /subjects:
    get:
      description: "List subjects with optional filtering\n\nSubjects represent entities
        that content items can be about, such as countries,\norganizations, markets,
        industry sectors, or products. They can have hierarchical\nrelationships and
        carry their own metadata and permission systems.\n\n**Query Parameters:**\n\
        - `q_name`: Filter subjects by name (case-insensitive partial match)\n- `q_type`:
        Filter by subject type (country, organization, market, sector, product, other)\n\
        - `q_parent_id`: Filter to show only direct children of the specified parent
        subject\n- Standard pagination parameters supported\n\n**Returns:** Paginated
        list of subjects matching the filter criteria\n\n**Examples:**\n- Get all
        banking organizations: `?q_type=organization&q_name=bank`\n- Get all cities
        in a country: `?q_parent_id=123&q_type=location`"
      parameters:
      - in: query
        required: false
        name: qName
        description: Search for string inside a name
        schema:
          type: string
      - in: query
        required: false
        name: q_type
        description: Filter subjects by type (country, organization, market, 
          sector, product, other)
        schema:
          type: string
      - in: query
        required: false
        name: q_parent_id
        description: Filter to show only direct children of the specified parent
          subject
        schema:
          type: integer
      - in: query
        required: false
        name: page_size
        description: The number of records to return in a single page,  maximum 
          200, minimum 1
        schema:
          type: integer
          default: 20
      - in: query
        required: false
        name: page
        description: Page number of records to show, beginning from 1
        schema:
          type: integer
          default: 1
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse'
      operationId: get_subjects
      tags:
      - Subjects
tags:
- name: Administrators
  description: HTTP endpoints for administrative functions, including CEL policy
    management
- name: Designers
  description: HTTP endpoints for managing ContentSchema objects
- name: Editors
  description: HTTP endpoints for managing Content objects
- name: Readers
  description: "HTTP handler functions supporting a consumer of the content\nmanaged
    by this system"
- name: Subjects
  description: HTTP endpoints for Subject CRUD operations
openapi: 3.1.1
components:
  schemas:
    ContentDocument:
      description: Unified content model - adapts based on usage context
      properties:
        id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Id
        date_created:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Created
        date_updated:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Updated
        title:
          title: Title
          type: string
        schema_id:
          title: Schema Id
          type: integer
        content_doc:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          default:
          title: Content Doc
        primary_subject_id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Primary Subject Id
        auth_policy:
          anyOf:
          - description: Authorization policy - CEL expression
            maxLength: 4000
            type: string
          - type: 'null'
          default:
          title: Auth Policy
        tags:
          items:
            $ref: '#/components/schemas/TagSummary'
          title: Tags
          type: array
        subjects:
          items:
            $ref: '#/components/schemas/SubjectSummary'
          title: Subjects
          type: array
        author_org_id:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Author Org Id
        last_updated_by_id:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Last Updated By Id
      required:
      - title
      - schema_id
      title: ContentDocument
      type: object
    ContentQElementPairDocument:
      description: Mapping between a question element and a content field via 
        JSON Pointer
      properties:
        id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Id
        question_element_id:
          title: Question Element Id
          type: integer
        content_reference:
          description: JSON Pointer expression to locate field in content 
            document (e.g., '$.sla.uptime')
          title: Content Reference
          type: string
        content_map_id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Content Map Id
      required:
      - question_element_id
      - content_reference
      title: ContentQElementPairDocument
      type: object
    ContentRelationshipDoc:
      description: Content with its relationships
      properties:
        content_id:
          title: Content Id
          type: integer
        content_title:
          title: Content Title
          type: string
        relationships:
          $ref: '#/components/schemas/ContentRelationships'
      required:
      - content_id
      - content_title
      - relationships
      title: ContentRelationshipDoc
      type: object
    ContentRelationships:
      description: Content relationship data using the unified Content model
      properties:
        children:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Children
          type: array
        parents:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Parents
          type: array
        references:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: References
          type: array
        related:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Related
          type: array
        superseded_by:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Superseded By
          type: array
        supersedes:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Supersedes
          type: array
        derived_from:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Derived From
          type: array
        derived:
          items:
            $ref: '#/components/schemas/ContentDocument'
          title: Derived
          type: array
      title: ContentRelationships
      type: object
    ContentSchema:
      description: Unified content schema model - works for create, update, and 
        response
      properties:
        id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Id
        date_created:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Created
        date_updated:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Updated
        name:
          title: Name
          type: string
        description:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Description
        spec_doc:
          additionalProperties: true
          title: Spec Doc
          type: object
        auth_policy:
          anyOf:
          - description: Authorization policy - CEL expression
            maxLength: 4000
            type: string
          - type: 'null'
          default:
          title: Auth Policy
        tags:
          items:
            type: string
          title: Tags
          type: array
        org_id:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Org Id
      required:
      - name
      - spec_doc
      title: ContentSchema
      type: object
    ContentSpecMapDocument:
      description: Mapping between question elements and content fields
      properties:
        id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          description: Unique ID of the content spec map, assigned by the system
          title: Id
        name:
          title: Name
          type: string
        description:
          title: Description
          type: string
        content_spec_id:
          title: Content Spec Id
          type: integer
        content_spec_name:
          anyOf:
          - type: string
          - type: 'null'
          default:
          description: Name of the associated content spec, not required for 
            input
          title: Content Spec Name
        pairs:
          items:
            $ref: '#/components/schemas/ContentQElementPairDocument'
          title: Pairs
          type: array
      required:
      - name
      - description
      - content_spec_id
      title: ContentSpecMapDocument
      type: object
    DeletionResponse:
      description: Standard deletion response
      properties:
        success:
          title: Success
          type: boolean
        message:
          title: Message
          type: string
      required:
      - success
      - message
      title: DeletionResponse
      type: object
    ListResponse:
      description: Generic list response that works with any item type
      properties:
        items:
          anyOf:
          - items:
              $ref: '#/components/schemas/ContentDocument'
            type: array
          - items:
              $ref: '#/components/schemas/SubjectSummary'
            type: array
          - items:
              $ref: '#/components/schemas/ContentSchema'
            type: array
          - items:
              $ref: '#/components/schemas/ContentSpecMapDocument'
            type: array
          title: Items
        pagination:
          $ref: '#/components/schemas/Pagination'
      required:
      - items
      - pagination
      title: ListResponse
      type: object
    Pagination:
      description: Schema for pagination information.
      properties:
        current_page:
          title: Current Page
          type: integer
        page_size:
          title: Page Size
          type: integer
        total_count:
          title: Total Count
          type: integer
        total_pages:
          title: Total Pages
          type: integer
        has_next:
          title: Has Next
          type: boolean
        current_page_count:
          default: 0
          description: Number of records in the current page
          title: Current Page Count
          type: integer
      required:
      - current_page
      - page_size
      - total_count
      - total_pages
      - has_next
      title: Pagination
      type: object
    PolicyRequest:
      description: Request to update/delete a policy
      properties:
        entity_type:
          enum:
          - Content
          - ContentSpec
          - Subject
          title: Entity Type
          type: string
        entity_id:
          title: Entity Id
          type: integer
        policy:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Policy
      required:
      - entity_type
      - entity_id
      title: PolicyRequest
      type: object
    PolicyResponse:
      description: Response from policy operations
      properties:
        entity_type:
          enum:
          - Content
          - ContentSpec
          - Subject
          title: Entity Type
          type: string
        entity_id:
          title: Entity Id
          type: integer
        policy:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Policy
        success:
          title: Success
          type: boolean
        entity_name:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Entity Name
        error:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Error
        operation_performed:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Operation Performed
      required:
      - entity_type
      - entity_id
      - success
      title: PolicyResponse
      type: object
    SchemaPointersResponse:
      description: Response containing valid JSON Pointer paths for a schema
      properties:
        content_spec_id:
          title: Content Spec Id
          type: integer
        content_spec_name:
          title: Content Spec Name
          type: string
        pointers:
          description: List of valid JSON Pointer paths that can be used in 
            ContentQElementPair mappings
          items:
            type: string
          title: Pointers
          type: array
      required:
      - content_spec_id
      - content_spec_name
      - pointers
      title: SchemaPointersResponse
      type: object
    SubjectDocument:
      description: Unified subject model - works for create, update, and 
        response
      properties:
        id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Id
        date_created:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Created
        date_updated:
          anyOf:
          - format: date-time
            type: string
          - type: 'null'
          default:
          title: Date Updated
        name:
          title: Name
          type: string
        subject_type:
          title: Subject Type
          type: string
        code:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Code
        description:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Description
        auth_policy:
          anyOf:
          - description: Authorization policy - CEL expression
            maxLength: 4000
            type: string
          - type: 'null'
          default:
          title: Auth Policy
        parent_id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Parent Id
        managing_org_id:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Managing Org Id
        subject_metadata:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          default:
          title: Subject Metadata
      required:
      - name
      - subject_type
      title: SubjectDocument
      type: object
    SubjectSummary:
      description: Subject reference - can be minimal for lists or full for 
        details
      properties:
        id:
          title: Id
          type: integer
        parent_id:
          anyOf:
          - type: integer
          - type: 'null'
          default:
          title: Parent Id
        name:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Name
        code:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Code
        description:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Description
        subject_type:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Subject Type
      required:
      - id
      title: SubjectSummary
      type: object
    TagSummary:
      description: Tag reference - can be minimal for lists or full for details
      properties:
        id:
          title: Id
          type: integer
        name:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Name
        description:
          anyOf:
          - type: string
          - type: 'null'
          default:
          title: Description
      required:
      - id
      title: TagSummary
      type: object
