openapi: 3.1.0
info:
  title: kura public content API
  version: "1.0.0"
  description: >
    Read a kura project's published content. Token-authed, read-only. Schema is managed in the kura admin / via the kura MCP
    server; this API serves content to a website frontend.
  license:
    name: MIT
servers:
  - url: https://kuracms.com
    description: Hosted kura
security:
  - bearerAuth: []
paths:
  /api/v1/{project}/types:
    get:
      summary: List content types and their field schemas
      operationId: listTypes
      parameters:
        - $ref: "#/components/parameters/Project"
      responses:
        "200":
          description: The project's content types.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        slug: {type: string}
                        name: {type: string}
                        schema:
                          type: object
                          description: Content-type schema (fields and their kinds).
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/PaymentRequired"}
        "404": {$ref: "#/components/responses/NotFound"}
  /api/v1/{project}/{type}:
    get:
      summary: List published entries of a content type
      operationId: listEntries
      parameters:
        - $ref: "#/components/parameters/Project"
        - $ref: "#/components/parameters/Type"
        - name: limit
          in: query
          schema: {type: integer, default: 20, minimum: 1, maximum: 100}
        - name: offset
          in: query
          schema: {type: integer, default: 0, minimum: 0}
        - name: fields
          in: query
          description: Comma-separated field keys to include.
          schema: {type: string}
        - name: exclude
          in: query
          description: Comma-separated field keys to drop.
          schema: {type: string}
        - name: sort
          in: query
          description: Comma-separated field or -field (descending), e.g. -published_at.
          schema: {type: string}
        - name: group
          in: query
          description: Named content version; defaults to the live one.
          schema: {type: string}
        - name: preview
          in: query
          description: Include unpublished drafts (still token-authed).
          schema: {type: boolean}
      responses:
        "200":
          description: A page of entries.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items: {$ref: "#/components/schemas/Entry"}
                  meta:
                    type: object
                    properties:
                      count: {type: integer}
                      limit: {type: integer}
                      offset: {type: integer}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/PaymentRequired"}
        "404": {$ref: "#/components/responses/NotFound"}
  /api/v1/{project}/{type}/{entry}:
    get:
      summary: Get one entry by slug
      operationId: getEntry
      parameters:
        - $ref: "#/components/parameters/Project"
        - $ref: "#/components/parameters/Type"
        - name: entry
          in: path
          required: true
          schema: {type: string}
      responses:
        "200":
          description: The entry.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data: {$ref: "#/components/schemas/Entry"}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/PaymentRequired"}
        "404": {$ref: "#/components/responses/NotFound"}
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: A kura project API token, e.g. kr_live_... (test tokens kr_test_).
  parameters:
    Project:
      name: project
      in: path
      required: true
      description: Project slug.
      schema: {type: string}
    Type:
      name: type
      in: path
      required: true
      description: Content-type slug.
      schema: {type: string}
  schemas:
    Entry:
      type: object
      description: >
        An entry. Always has id and slug; the rest of the keys are the content type's own fields. Rich-text fields are returned
        as HTML strings.
      properties:
        id: {type: string}
        slug: {type: string}
      additionalProperties: true
    Problem:
      type: object
      properties:
        type: {type: string}
        title: {type: string}
        status: {type: integer}
        detail: {type: string}
        instance: {type: string}
  responses:
    Unauthorized:
      description: Missing or invalid API token.
      content:
        application/problem+json:
          schema: {$ref: "#/components/schemas/Problem"}
    PaymentRequired:
      description: The project has no active subscription.
      content:
        application/problem+json:
          schema: {$ref: "#/components/schemas/Problem"}
    NotFound:
      description: Unknown project, type, or entry.
      content:
        application/problem+json:
          schema: {$ref: "#/components/schemas/Problem"}
