openapi: "3.1.0"

info:
  title: "Prism — Document Generation API"
  version: "0.1.0"
  description: |
    Prism is the APEX Suite document generation engine. It assembles branded, professional
    documents — entity summaries, market briefings, due-diligence reports, engineering
    proposals, and more — from your data and the templates provisioned for your tenant,
    and renders them to Markdown, HTML, PDF, or Word. A chart engine produces
    chart configurations (and, on higher tiers, chart images) for embedding in your own
    interfaces.

    **Authentication.** Every request carries a single `Authorization: Bearer` header
    holding either a machine-to-machine access token or a platform-issued tenant API key.
    Your tenant is identified by the `tenantId` request-body field where the operation
    accepts one, or inferred from the credential when omitted; template listing and
    dashboard snapshots always take the tenant from the credential.

    **Tier entitlements.** Rendering volume and available output formats depend on your
    tenant's subscription tier. As an example of the shape of these entitlements: entry
    tiers render Markdown only with a modest hourly allowance; higher tiers add HTML, PDF,
    and Word output, chart and snapshot access, and progressively larger hourly volumes.
    A request for a format or volume beyond your tenant's entitlement is rejected with
    `403`. Your exact entitlements are part of your subscription agreement.

    **Branding.** Documents render with your tenant's provisioned branding (logo, colors,
    typography, footer); individual requests may override selected branding elements where
    permitted.

servers:
  - url: https://prism.dev.apex.reisiger.org
    description: Development
  - url: http://localhost:9150
    description: Local

security:
  - bearerAuth: []

tags:
  - name: Generation
    description: Assemble and render documents from templates and your data.
  - name: Charts
    description: Generate chart configurations and images.
  - name: Templates
    description: Read-only listing of the document templates available to your tenant.
  - name: Dashboards
    description: Dashboard catalog and snapshots (preview capability).
  - name: Service
    description: Service liveness.

paths:
  /generate:
    post:
      operationId: generateDocument
      tags: [Generation]
      summary: Generate a document
      x-apex-availability: available
      description: |
        Assembles a document from the requested template and your supplied data, applies
        tenant branding, and renders it in the requested output format.

        **Output behaviour by format:**
        - `markdown` and `html` return a JSON body with the rendered content in `content`.
        - `pdf` and `docx` return the document binary with an attachment
          `Content-Disposition` header.
        - `image` is planned but not yet implemented — requesting it returns an error in
          the current release.

        A format outside your tenant's entitlement returns `403`. A format your tenant is
        entitled to but which is not configured in your tenant's output set returns `400`
        with the available options.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/GenerateRequest"
            examples:
              markdownEntitySummary:
                summary: Default template and format — entity summary as Markdown
                value:
                  tenantId: your-tenant
                  template: entity-summary
                  format: markdown
                  entity: "Meridian Hydraulics"
                  title: "Meridian Hydraulics — Entity Summary"
              pdfEngineeringProposal:
                summary: Engineering proposal rendered to PDF with request data
                value:
                  tenantId: your-tenant
                  template: engineering-proposal
                  format: pdf
                  title: "Pump Station Upgrade — Proposal"
                  data:
                    project_name: "Pump Station Upgrade"
                    client_name: "Municipal Water Utility"
                    scope_summary: "Replacement of two intake pumps and control panel modernisation."
      responses:
        "200":
          description: >-
            The generated document. JSON for text formats; a binary attachment for
            `pdf` and `docx`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenerateResponse"
              examples:
                markdownResult:
                  value:
                    reportId: "rpt-1722951231843"
                    title: "Meridian Hydraulics — Entity Summary"
                    format: markdown
                    pages: 4
                    sections: [executive-summary, data-summary, risk-analysis, recommendations]
                    generatedAt: "2026-08-06T10:12:44.120Z"
                    durationMs: 1834
                    content: "# Meridian Hydraulics — Entity Summary\n\n..."
            application/pdf:
              schema:
                type: string
                format: binary
            application/vnd.openxmlformats-officedocument.wordprocessingml.document:
              schema:
                type: string
                format: binary
        "400":
          description: >-
            Missing tenant identifier, or the requested format is not in the tenant's
            configured output set (the error lists the available options).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: >-
            The requested output format or render volume exceeds the tenant's
            subscription tier.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          $ref: "#/components/responses/TenantNotFound"
        "500":
          description: >-
            Rendering failed. Requesting the planned `image` format also lands here in the
            current release, with a not-implemented status alongside the error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error: { type: string }
                  status:
                    type: string
                    enum: [FAILED, NOT_IMPLEMENTED]

  /chart:
    post:
      operationId: generateChart
      tags: [Charts]
      summary: Generate a chart
      x-apex-availability: available
      description: |
        Produces a chart from your data: a renderer-ready chart configuration
        (`output: config`), a rendered chart image (`output: image`), or both. Chart
        access, and chart image rendering in particular, are tier-gated — requests beyond
        the tenant's entitlement return `403`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ChartRequest"
            examples:
              barChartConfig:
                summary: Bar chart configuration from inline data
                value:
                  tenantId: your-tenant
                  chartType: bar
                  title: "Incidents by Site"
                  data:
                    labels: ["Site A", "Site B", "Site C"]
                    values: [12, 7, 3]
                  xAxis: "Site"
                  yAxis: "Incidents"
                  output: config
      responses:
        "200":
          description: The chart result.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ChartResult"
        "400":
          description: Missing tenant identifier or missing `chartType`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: Chart generation (or chart image rendering) is not included in the tenant's tier.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          $ref: "#/components/responses/TenantNotFound"

  /templates:
    get:
      operationId: listTemplates
      tags: [Templates]
      summary: List templates available to your tenant
      x-apex-availability: available
      description: >-
        Returns the document template identifiers your tenant may render, including any
        custom templates provisioned for you. Template definitions are provisioned and
        maintained by the platform operator — there are no create, update, or delete
        operations on this surface. The tenant is taken from the credential.
      responses:
        "200":
          description: Available template identifiers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  templates:
                    type: array
                    items:
                      type: string
                    description: Template identifiers accepted by `POST /generate`.
              examples:
                templates:
                  value:
                    templates: [entity-summary, entity-assessment, market-briefing, risk-report, engineering-proposal]
        "400":
          description: The credential carries no tenant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/TenantNotFound"

  /dashboards:
    get:
      operationId: listDashboards
      tags: [Dashboards]
      summary: List dashboards
      x-apex-availability: preview
      description: >-
        Catalog of dashboards with their filters and update cadence, optionally filtered
        by category. Preview capability: returns representative sample data in the
        current release.
      parameters:
        - name: category
          in: query
          schema: { type: string }
          description: Filter by dashboard category, e.g. `portfolio`, `market`.
      responses:
        "200":
          description: Dashboard catalog.
          content:
            application/json:
              schema:
                type: object
                properties:
                  dashboards:
                    type: array
                    items:
                      $ref: "#/components/schemas/DashboardInfo"
        "401":
          $ref: "#/components/responses/Unauthorized"

  /snapshot:
    post:
      operationId: snapshotDashboard
      tags: [Dashboards]
      summary: Take a dashboard snapshot
      x-apex-availability: preview
      description: >-
        Captures the current state of a dashboard as data (and, on entitled tiers, as an
        image). Tier-gated; the tenant is taken from the credential. Preview capability:
        returns representative sample data in the current release.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SnapshotRequest"
            examples:
              portfolioSnapshot:
                value:
                  dashboard: portfolio-overview
                  filters:
                    dateRange: "last-30-days"
                  output: data
      responses:
        "200":
          description: The snapshot.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SnapshotResult"
        "400":
          description: The credential carries no tenant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: Dashboard snapshots are not included in the tenant's tier.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          $ref: "#/components/responses/TenantNotFound"

  /health:
    get:
      operationId: getHealth
      tags: [Service]
      summary: Service liveness
      x-apex-availability: available
      security: []
      description: Liveness probe. No authentication required.
      responses:
        "200":
          description: Service status.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum: [ok]
                  service:
                    type: string
                  timestamp:
                    type: string
                    format: date-time

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Machine-to-machine access token issued by the platform identity provider, or a platform-issued tenant API key, sent as
        `Authorization: Bearer <credential>`.

  responses:
    Unauthorized:
      description: Missing or invalid credential.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    TenantNotFound:
      description: Unknown tenant.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Human-readable reason for the failure.

    TemplateId:
      type: string
      enum:
        - entity-summary
        - entity-assessment
        - market-briefing
        - portfolio-review
        - due-diligence
        - risk-report
        - engineering-proposal
        - custom
      description: >-
        Built-in document templates. `custom` selects a tenant-specific template
        provisioned by the platform operator. `GET /templates` returns the identifiers
        your tenant may actually render.

    OutputFormat:
      type: string
      enum: [markdown, html, pdf, docx, image]
      description: >-
        Rendering target. `markdown` and `html` return content inline; `pdf` and `docx`
        return a binary attachment. `image` is planned and not yet implemented — requesting
        it returns an error in the current release. Formats are tier-gated per tenant.

    SectionId:
      type: string
      enum:
        - executive-summary
        - data-summary
        - sentiment
        - verification
        - risk-analysis
        - prediction
        - financials
        - market-position
        - recommendations
        - project-scope
        - technical-approach
        - bill-of-quantities
        - project-team
        - project-timeline
        - references
      description: Document sections. Each template defines a default section set; override with `sections`.

    BrandingOverride:
      type: object
      description: Per-request overrides of the tenant's provisioned branding.
      properties:
        useClientBranding: { type: boolean }
        logoUrl: { type: string }
        primaryColor: { type: string }
        fontFamily: { type: string }
        footerText: { type: string }

    GenerateRequest:
      type: object
      description: >-
        All fields are optional except that a tenant must be resolvable: pass `tenantId`
        or use a tenant-scoped credential. `template` defaults to `entity-summary` and
        `format` to `markdown`.
      properties:
        tenantId:
          type: string
          description: Your tenant identifier. Falls back to the credential's tenant when omitted.
        template:
          $ref: "#/components/schemas/TemplateId"
        format:
          $ref: "#/components/schemas/OutputFormat"
        title:
          type: string
          description: Document title; a template-derived title is used when omitted.
        entity:
          type: string
          description: Subject entity of the document, used by entity-centric templates.
        sections:
          type: array
          items:
            $ref: "#/components/schemas/SectionId"
          description: Overrides the template's default section set.
        data:
          type: object
          additionalProperties: true
          description: Render context — your data, merged into the template's sections.
        variables:
          type: object
          additionalProperties: { type: string }
          description: Simple string substitutions available to the template.
        branding:
          $ref: "#/components/schemas/BrandingOverride"

    GenerateResponse:
      type: object
      description: JSON result for text output formats (`markdown`, `html`).
      properties:
        reportId: { type: string }
        title: { type: string }
        format:
          $ref: "#/components/schemas/OutputFormat"
        pages:
          type: integer
          description: Estimated page count.
        sections:
          type: array
          items:
            $ref: "#/components/schemas/SectionId"
        generatedAt:
          type: string
          format: date-time
        durationMs:
          type: integer
        content:
          type: string
          description: The rendered document.

    ChartType:
      type: string
      enum: [bar, line, pie, radar, scatter, gauge, heatmap, treemap, sankey]

    ChartRequest:
      type: object
      required: [chartType]
      description: >-
        Chart generation request. `output` selects a renderer-ready configuration, a
        rendered image, or both; it defaults to `config` when omitted.
      properties:
        tenantId:
          type: string
          description: Your tenant identifier. Falls back to the credential's tenant when omitted.
        chartType:
          $ref: "#/components/schemas/ChartType"
        data:
          type: object
          additionalProperties: true
          description: Chart data. The expected inner shape depends on the chart type.
          x-apex-note: "Schema partially documented — verify against the service."
        title:
          type: string
        xAxis:
          type: string
          description: Label for the horizontal axis.
        yAxis:
          type: string
          description: Label for the vertical axis.
        colorBy:
          type: string
          description: Data key used to color series or segments.
        output:
          type: string
          enum: [config, image, both]
          default: config

    ChartResult:
      type: object
      description: Chart generation result.
      x-apex-note: "Schema partially documented — verify against the service."
      properties:
        status:
          type: string
          enum: [SUCCESS, FAILED, NOT_IMPLEMENTED]
        chartId:
          type: string
        config:
          type: object
          additionalProperties: true
          description: Renderer-ready chart configuration, present for `config` and `both` outputs.
        image:
          description: Rendered chart image, present for `image` and `both` outputs on entitled tiers.
        error:
          type: string

    DashboardInfo:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
        description: { type: string }
        category: { type: string }
        filters:
          type: array
          items: { type: string }
          description: Filter dimensions the dashboard supports.
        updateFrequency:
          type: string
          description: How often the underlying data refreshes.

    SnapshotRequest:
      type: object
      description: >-
        Snapshot parameters. In the current preview release the service returns
        representative sample data regardless of the requested dashboard and filters.
      properties:
        dashboard:
          type: string
          description: Dashboard identifier from `GET /dashboards`.
        filters:
          type: object
          additionalProperties: true
        output:
          type: string
          enum: [data, image, both]
        imageFormat:
          type: string
          enum: [png, svg]

    SnapshotResult:
      type: object
      properties:
        status:
          type: string
          enum: [SUCCESS, FAILED, NOT_IMPLEMENTED]
        data:
          type: object
          additionalProperties: true
          description: Snapshot data payload.
        image:
          description: Rendered snapshot image, when requested and entitled.
        error:
          type: string
