openapi: 3.1.0
info:
  title: Haven Gateway API
  version: 0.2.0
paths:
  /catalog/contacts/export:
    get:
      summary: Proxy Contacts Export
      description: 'Proxy the contacts export NDJSON from the helper service through
        the gateway.


        This keeps the collector from needing direct access to the helper.'
      operationId: proxy_contacts_export_catalog_contacts_export_get
      parameters:
      - name: since_token
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Since Token
      - name: full
        in: query
        required: false
        schema:
          anyOf:
          - type: boolean
          - type: 'null'
          default: false
          title: Full
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /catalog/contacts/ingest:
    post:
      summary: Ingest Contacts
      operationId: ingest_contacts_catalog_contacts_ingest_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactIngestRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactIngestResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/ingest:
    post:
      summary: Ingest Document
      operationId: ingest_document_v1_ingest_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IngestRequestModel'
        required: true
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IngestSubmissionResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/ingest/file:
    post:
      summary: Ingest File
      operationId: ingest_file_v1_ingest_file_post
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/Body_ingest_file_v1_ingest_file_post'
        required: true
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileIngestResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/ingest/{submission_id}:
    get:
      summary: Get Ingest Status
      operationId: get_ingest_status_v1_ingest__submission_id__get
      parameters:
      - name: submission_id
        in: path
        required: true
        schema:
          type: string
          title: Submission Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IngestStatusResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/documents/{doc_id}:
    patch:
      summary: Update Document
      description: Update a document's metadata and text, optionally re-queuing for
        embedding.
      operationId: update_document_v1_documents__doc_id__patch
      parameters:
      - name: doc_id
        in: path
        required: true
        schema:
          type: string
          title: Doc Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentUpdateRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentUpdateResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/documents:
    get:
      summary: List Documents
      description: List documents with optional filtering.
      operationId: list_documents_v1_documents_get
      parameters:
      - name: source_type
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Source Type
      - name: has_attachments
        in: query
        required: false
        schema:
          type: boolean
          default: false
          title: Has Attachments
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          maximum: 200
          minimum: 1
          default: 50
          title: Limit
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          minimum: 0
          default: 0
          title: Offset
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentListResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /search/people:
    get:
      summary: Search People
      operationId: search_people_search_people_get
      parameters:
      - name: q
        in: query
        required: false
        schema:
          anyOf:
          - type: string
            minLength: 1
          - type: 'null'
          title: Q
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          maximum: 200
          minimum: 1
          default: 20
          title: Limit
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          minimum: 0
          default: 0
          title: Offset
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PeopleSearchResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/search:
    get:
      summary: Search Endpoint
      operationId: search_endpoint_v1_search_get
      parameters:
      - name: q
        in: query
        required: true
        schema:
          type: string
          minLength: 1
          title: Q
      - name: k
        in: query
        required: false
        schema:
          type: integer
          maximum: 50
          minimum: 1
          default: 20
          title: K
      - name: has_attachments
        in: query
        required: false
        schema:
          anyOf:
          - type: boolean
          - type: 'null'
          title: Has Attachments
      - name: source_type
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Source Type
      - name: person
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Person
      - name: start_date
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Start Date
      - name: end_date
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: End Date
      - name: thread_id
        in: query
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: Thread Id
      - name: context_window
        in: query
        required: false
        schema:
          type: integer
          maximum: 20
          minimum: 0
          default: 0
          title: Context Window
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/ask:
    post:
      summary: Ask Endpoint
      operationId: ask_endpoint_v1_ask_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AskRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AskResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/doc/{doc_id}:
    get:
      summary: Doc Endpoint
      description: 'Proxy document lookups to the Catalog service which owns record-wise
        access.


        The Catalog service is responsible for create/update/delete and record lookups.

        Gateway will forward the request and surface the same 404/200 behavior.'
      operationId: doc_endpoint_v1_doc__doc_id__get
      parameters:
      - name: doc_id
        in: path
        required: true
        schema:
          type: string
          title: Doc Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Doc Endpoint V1 Doc  Doc Id  Get
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
  /v1/context/general:
    get:
      summary: Context General
      operationId: context_general_v1_context_general_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                title: Response Context General V1 Context General Get
  /v1/healthz:
    get:
      summary: Health
      operationId: health_v1_healthz_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                additionalProperties:
                  type: string
                type: object
                title: Response Health V1 Healthz Get
components:
  schemas:
    AskRequest:
      properties:
        query:
          type: string
          title: Query
        k:
          type: integer
          title: K
          default: 5
      type: object
      required:
      - query
      title: AskRequest
    AskResponse:
      properties:
        query:
          type: string
          title: Query
        answer:
          type: string
          title: Answer
        citations:
          items:
            type: object
          type: array
          title: Citations
      type: object
      required:
      - query
      - answer
      - citations
      title: AskResponse
    Body_ingest_file_v1_ingest_file_post:
      properties:
        meta:
          type: string
          title: Meta
        upload:
          type: string
          format: binary
          title: Upload
      type: object
      required:
      - meta
      - upload
      title: Body_ingest_file_v1_ingest_file_post
    ContactAddressModel:
      properties:
        label:
          anyOf:
          - type: string
          - type: 'null'
          title: Label
        street:
          anyOf:
          - type: string
          - type: 'null'
          title: Street
        city:
          anyOf:
          - type: string
          - type: 'null'
          title: City
        region:
          anyOf:
          - type: string
          - type: 'null'
          title: Region
        postal_code:
          anyOf:
          - type: string
          - type: 'null'
          title: Postal Code
        country:
          anyOf:
          - type: string
          - type: 'null'
          title: Country
      type: object
      title: ContactAddressModel
    ContactAddressSummary:
      properties:
        label:
          anyOf:
          - type: string
          - type: 'null'
          title: Label
        city:
          anyOf:
          - type: string
          - type: 'null'
          title: City
        region:
          anyOf:
          - type: string
          - type: 'null'
          title: Region
        country:
          anyOf:
          - type: string
          - type: 'null'
          title: Country
      type: object
      title: ContactAddressSummary
    ContactIngestRequest:
      properties:
        source:
          type: string
          title: Source
          default: macos_contacts
        device_id:
          type: string
          title: Device Id
        since_token:
          anyOf:
          - type: string
          - type: 'null'
          title: Since Token
        batch_id:
          type: string
          title: Batch Id
        people:
          items:
            $ref: '#/components/schemas/PersonPayloadModel'
          type: array
          title: People
      type: object
      required:
      - device_id
      - batch_id
      title: ContactIngestRequest
    ContactIngestResponse:
      properties:
        accepted:
          type: integer
          title: Accepted
        upserts:
          type: integer
          title: Upserts
        deletes:
          type: integer
          title: Deletes
        conflicts:
          type: integer
          title: Conflicts
        skipped:
          type: integer
          title: Skipped
        since_token_next:
          anyOf:
          - type: string
          - type: 'null'
          title: Since Token Next
      type: object
      required:
      - accepted
      - upserts
      - deletes
      - conflicts
      - skipped
      title: ContactIngestResponse
    ContactUrlModel:
      properties:
        label:
          anyOf:
          - type: string
          - type: 'null'
          title: Label
        url:
          anyOf:
          - type: string
          - type: 'null'
          title: Url
      type: object
      title: ContactUrlModel
    ContactValueModel:
      properties:
        value:
          type: string
          title: Value
        value_raw:
          anyOf:
          - type: string
          - type: 'null'
          title: Value Raw
        label:
          anyOf:
          - type: string
          - type: 'null'
          title: Label
        priority:
          type: integer
          title: Priority
          default: 100
        verified:
          type: boolean
          title: Verified
          default: true
      type: object
      required:
      - value
      title: ContactValueModel
    DocumentListItem:
      properties:
        doc_id:
          type: string
          title: Doc Id
        metadata:
          type: object
          title: Metadata
        text:
          type: string
          title: Text
      type: object
      required:
      - doc_id
      - metadata
      - text
      title: DocumentListItem
    DocumentListResponse:
      properties:
        documents:
          items:
            $ref: '#/components/schemas/DocumentListItem'
          type: array
          title: Documents
        count:
          type: integer
          title: Count
      type: object
      required:
      - documents
      - count
      title: DocumentListResponse
    DocumentPerson:
      properties:
        identifier:
          type: string
          title: Identifier
        identifier_type:
          anyOf:
          - type: string
          - type: 'null'
          title: Identifier Type
        role:
          anyOf:
          - type: string
          - type: 'null'
          title: Role
        display_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Display Name
        metadata:
          type: object
          title: Metadata
      type: object
      required:
      - identifier
      title: DocumentPerson
    DocumentUpdateRequest:
      properties:
        metadata:
          type: object
          title: Metadata
        text:
          type: string
          title: Text
        requeue_for_embedding:
          type: boolean
          title: Requeue For Embedding
          default: true
      type: object
      required:
      - metadata
      - text
      title: DocumentUpdateRequest
    DocumentUpdateResponse:
      properties:
        doc_id:
          type: string
          title: Doc Id
        status:
          type: string
          title: Status
        chunks_requeued:
          type: integer
          title: Chunks Requeued
          default: 0
      type: object
      required:
      - doc_id
      - status
      title: DocumentUpdateResponse
    FileIngestResponse:
      properties:
        submission_id:
          type: string
          title: Submission Id
        doc_id:
          type: string
          title: Doc Id
        external_id:
          type: string
          title: External Id
        version_number:
          type: integer
          title: Version Number
        status:
          type: string
          title: Status
        thread_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Thread Id
        file_ids:
          items:
            type: string
          type: array
          title: File Ids
        duplicate:
          type: boolean
          title: Duplicate
          default: false
        total_chunks:
          type: integer
          title: Total Chunks
          default: 0
        file_sha256:
          type: string
          title: File Sha256
        object_key:
          type: string
          title: Object Key
        extraction_status:
          type: string
          enum:
          - ready
          - failed
          title: Extraction Status
      type: object
      required:
      - submission_id
      - doc_id
      - external_id
      - version_number
      - status
      - file_sha256
      - object_key
      - extraction_status
      title: FileIngestResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    IngestContentModel:
      properties:
        mime_type:
          type: string
          title: Mime Type
          default: text/plain
        data:
          type: string
          title: Data
        encoding:
          anyOf:
          - type: string
          - type: 'null'
          title: Encoding
      type: object
      required:
      - data
      title: IngestContentModel
    IngestRequestModel:
      properties:
        source_type:
          type: string
          title: Source Type
        source_id:
          type: string
          title: Source Id
        source_provider:
          anyOf:
          - type: string
          - type: 'null'
          title: Source Provider
        title:
          anyOf:
          - type: string
          - type: 'null'
          title: Title
        canonical_uri:
          anyOf:
          - type: string
          - type: 'null'
          title: Canonical Uri
        content:
          $ref: '#/components/schemas/IngestContentModel'
        metadata:
          type: object
          title: Metadata
        content_timestamp:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Content Timestamp
        content_timestamp_type:
          anyOf:
          - type: string
          - type: 'null'
          title: Content Timestamp Type
        content_created_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Content Created At
        content_modified_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Content Modified At
        people:
          items:
            $ref: '#/components/schemas/DocumentPerson'
          type: array
          title: People
        thread_id:
          anyOf:
          - type: string
            format: uuid
          - type: 'null'
          title: Thread Id
        thread:
          anyOf:
          - $ref: '#/components/schemas/ThreadPayloadModel'
          - type: 'null'
      type: object
      required:
      - source_type
      - source_id
      - content
      title: IngestRequestModel
    IngestStatusResponse:
      properties:
        submission_id:
          type: string
          title: Submission Id
        status:
          type: string
          title: Status
        document_status:
          anyOf:
          - type: string
          - type: 'null'
          title: Document Status
        doc_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Doc Id
        total_chunks:
          type: integer
          title: Total Chunks
          default: 0
        embedded_chunks:
          type: integer
          title: Embedded Chunks
          default: 0
        pending_chunks:
          type: integer
          title: Pending Chunks
          default: 0
        error:
          anyOf:
          - type: object
          - type: 'null'
          title: Error
      type: object
      required:
      - submission_id
      - status
      title: IngestStatusResponse
    IngestSubmissionResponse:
      properties:
        submission_id:
          type: string
          title: Submission Id
        doc_id:
          type: string
          title: Doc Id
        external_id:
          type: string
          title: External Id
        version_number:
          type: integer
          title: Version Number
        status:
          type: string
          title: Status
        thread_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Thread Id
        file_ids:
          items:
            type: string
          type: array
          title: File Ids
        duplicate:
          type: boolean
          title: Duplicate
          default: false
        total_chunks:
          type: integer
          title: Total Chunks
          default: 0
      type: object
      required:
      - submission_id
      - doc_id
      - external_id
      - version_number
      - status
      title: IngestSubmissionResponse
    PeopleSearchHit:
      properties:
        person_id:
          type: string
          title: Person Id
        display_name:
          type: string
          title: Display Name
        given_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Given Name
        family_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Family Name
        organization:
          anyOf:
          - type: string
          - type: 'null'
          title: Organization
        nicknames:
          items:
            type: string
          type: array
          title: Nicknames
        emails:
          items:
            type: string
          type: array
          title: Emails
        phones:
          items:
            type: string
          type: array
          title: Phones
        addresses:
          items:
            $ref: '#/components/schemas/ContactAddressSummary'
          type: array
          title: Addresses
      type: object
      required:
      - person_id
      - display_name
      - given_name
      - family_name
      - organization
      - nicknames
      - emails
      - phones
      - addresses
      title: PeopleSearchHit
    PeopleSearchResponse:
      properties:
        query:
          anyOf:
          - type: string
          - type: 'null'
          title: Query
        limit:
          type: integer
          title: Limit
        offset:
          type: integer
          title: Offset
        results:
          items:
            $ref: '#/components/schemas/PeopleSearchHit'
          type: array
          title: Results
      type: object
      required:
      - query
      - limit
      - offset
      - results
      title: PeopleSearchResponse
    PersonPayloadModel:
      properties:
        external_id:
          type: string
          title: External Id
        display_name:
          type: string
          title: Display Name
        given_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Given Name
        family_name:
          anyOf:
          - type: string
          - type: 'null'
          title: Family Name
        organization:
          anyOf:
          - type: string
          - type: 'null'
          title: Organization
        nicknames:
          items:
            type: string
          type: array
          title: Nicknames
        notes:
          anyOf:
          - type: string
          - type: 'null'
          title: Notes
        photo_hash:
          anyOf:
          - type: string
          - type: 'null'
          title: Photo Hash
        emails:
          items:
            $ref: '#/components/schemas/ContactValueModel'
          type: array
          title: Emails
        phones:
          items:
            $ref: '#/components/schemas/ContactValueModel'
          type: array
          title: Phones
        addresses:
          items:
            $ref: '#/components/schemas/ContactAddressModel'
          type: array
          title: Addresses
        urls:
          items:
            $ref: '#/components/schemas/ContactUrlModel'
          type: array
          title: Urls
        change_token:
          anyOf:
          - type: string
          - type: 'null'
          title: Change Token
        version:
          type: integer
          minimum: 0.0
          title: Version
          default: 1
        deleted:
          type: boolean
          title: Deleted
          default: false
      type: object
      required:
      - external_id
      - display_name
      title: PersonPayloadModel
    SearchHit:
      properties:
        document_id:
          type: string
          title: Document Id
        chunk_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Chunk Id
        title:
          anyOf:
          - type: string
          - type: 'null'
          title: Title
        url:
          anyOf:
          - type: string
          - type: 'null'
          title: Url
        snippet:
          anyOf:
          - type: string
          - type: 'null'
          title: Snippet
        score:
          type: number
          title: Score
        sources:
          items:
            type: string
          type: array
          title: Sources
        metadata:
          type: object
          title: Metadata
      type: object
      required:
      - document_id
      - chunk_id
      - title
      - url
      - snippet
      - score
      - sources
      - metadata
      title: SearchHit
    SearchResponse:
      properties:
        query:
          type: string
          title: Query
        results:
          items:
            $ref: '#/components/schemas/SearchHit'
          type: array
          title: Results
      type: object
      required:
      - query
      - results
      title: SearchResponse
    ThreadPayloadModel:
      properties:
        external_id:
          type: string
          title: External Id
        source_type:
          anyOf:
          - type: string
          - type: 'null'
          title: Source Type
        source_provider:
          anyOf:
          - type: string
          - type: 'null'
          title: Source Provider
        title:
          anyOf:
          - type: string
          - type: 'null'
          title: Title
        participants:
          items:
            $ref: '#/components/schemas/DocumentPerson'
          type: array
          title: Participants
        thread_type:
          anyOf:
          - type: string
          - type: 'null'
          title: Thread Type
        is_group:
          anyOf:
          - type: boolean
          - type: 'null'
          title: Is Group
        participant_count:
          anyOf:
          - type: integer
          - type: 'null'
          title: Participant Count
        metadata:
          type: object
          title: Metadata
        first_message_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: First Message At
        last_message_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Last Message At
      type: object
      required:
      - external_id
      title: ThreadPayloadModel
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
