> ## Documentation Index
> Fetch the complete documentation index at: https://ttrpg.docs.kitefrost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk reject seeds (transition to REJECTED)

> Bulk reject: for each supplied seed UUID, transition ``TRIAGED → REJECTED`` via ``SeedLifecycleStore.transition``. REJECTED is a terminal state that also writes the dead-seed registry (C-SSD §2.2) so the same premise will not regenerate. Per-item failures are isolated.



## OpenAPI

````yaml /openapi.json post /v1/projects/{project_id}/seeds/batch/reject
openapi: 3.1.0
info:
  title: KiteFrost
  description: >
    ## KiteFrost API


    Persistent memory and queryable context for AI-powered products. Create

    projects, track entities and relationships, record events, and query context
    -

    stateful AI you can audit, with durable state across sessions, agents, and

    tools.


    ### What you get


    - **Persistent projects** - entities, relationships, and events live across
    sessions

    - **Context queries** - ask "what does this entity know right now?" and get
    a consistent answer

    - **Event sourcing** - every state transition is recorded and replayable

    - **BYOK** - bring your own LLM provider key per project


    ### Authentication


    All routes (except `/health` and `/ready`) require an `Authorization: Bearer
    <key>` header.

    Use publishable keys (`pk_...`) for read-only client calls and secret keys
    (`sk_...`) for

    write / generation / admin operations.


    ### Async generation pattern


    1. Call a `POST .../generate` endpoint → receive `{"session_id": "...",
    "status": "accepted"}`

    2. Poll `GET /v1/sessions/{session_id}/status` until `status` is `completed`
    or `error`

    3. If `status == "awaiting_human"`, submit a response via `POST
    /v1/sessions/{session_id}/respond`
  version: 1.0.0
servers:
  - url: https://api.kitefrost.ai
    description: Production
security: []
tags:
  - name: projects
    description: >-
      Project, entity, and event management: create projects, upsert entities,
      record events, query context, and generate content with project context.
  - name: npcs
    description: >-
      NPC (non-player character) CRUD, dialogue generation, and export. Supports
      the brainstorm → draft lifecycle.
  - name: sessions
    description: >-
      Poll generation session status, submit HITL responses, and create manual
      state snapshots for rollback/replay.
  - name: events
    description: >-
      Lightweight player-event ingestion path. Accepts player choices, quest
      triggers, and custom events without spinning up a full session.
  - name: players
    description: >-
      Player data management: GDPR erasure (right to be forgotten), data export
      (right of access), player context, facts, quests, and preferences.
  - name: keys
    description: >-
      API key lifecycle management: create publishable / secret keys, list,
      revoke, and rotate keys with scoped permissions.
  - name: byok
    description: >-
      Bring Your Own Key (BYOK) management. Store, revoke, and check the status
      of a tenant-supplied LLM provider API key per project.
  - name: ttrpg
    description: >-
      TTRPG GM pack endpoints: encounter CRUD and generation, session CRUD and
      async generation.
  - name: chapters
    description: >-
      Book Author pack endpoints: chapter CRUD, async generation, and markdown
      export.
  - name: ideas
    description: >-
      Idea Generation Engine: generate novel story ideas, list, fetch, mutate,
      blend, assign, and archive ideas.
  - name: seeds
    description: >-
      Story-seed discovery operations: list, detail, on-demand generate, promote
      (canonical assign per R127-C6), lifecycle transition, and soft-delete.
  - name: feedback
    description: >-
      Collect explicit feedback signals (thumbs, rating, A/B choice) and
      retrieve aggregated insights for model improvement.
  - name: webhooks
    description: >-
      Webhook subscription management: register HTTPS endpoints for async event
      delivery, list, delete, and test HMAC signatures.
  - name: audio
    description: >-
      Audio Story pack endpoints: async audio-story generation, list, fetch, and
      export (SSML / manifest / audio).
  - name: billing
    description: >-
      Billing integration: checkout, portal, subscription management, tier info,
      and usage stats.
  - name: demo
    description: >-
      Public demo endpoint - try the KiteFrost from the landing page without
      signing up. Limited to 5 messages per session and 20 requests per IP per
      hour. No authentication required.
  - name: health
    description: >-
      Health and readiness probes for load-balancer and orchestrator liveness
      checks.
  - name: score
    description: >-
      Content scoring: run craft-layer quality metrics (C10-C15) and humanness
      scoring (H2) on arbitrary text to get a per-dimension quality breakdown.
  - name: resilience
    description: >-
      Resilience Score: aggregate compliance, training, and education pack
      results into an overall project resilience score (0-100) with
      per-dimension breakdown and trend.
  - name: compliance-exercises
    description: >-
      Compliance Tabletop pack endpoints: create exercises, generate scenarios,
      evaluate participant responses, and produce after-action reviews.
  - name: training
    description: >-
      Training Simulation pack endpoints: create scenarios, generate branching
      scenario trees, and assess learner competency.
  - name: support
    description: >-
      Support Orchestration pack endpoints: create ticket contexts, generate
      response drafts, and escalate tickets.
  - name: story_bible
    description: >-
      Story Bible: assemble the Knowledge Graph into a structured canonical
      reference of characters, locations, events, factions, and items with their
      relationships. Supports point-in-time snapshots via at_seq.
  - name: gamification
    description: >-
      Gamification endpoints: player points, earned achievements, leaderboards
      with configurable visibility and weekly reset, and activity streaks.
  - name: conversations
    description: >-
      Multi-player conversation lifecycle: create, join, submit input, stream
      events (SSE), leave, and get conversation state.
  - name: images
    description: >-
      Image generation: create AI-generated images from text prompts with
      pack-configurable presets, safety controls, and audit logging.
paths:
  /v1/projects/{project_id}/seeds/batch/reject:
    post:
      tags:
        - seeds
      summary: Bulk reject seeds (transition to REJECTED)
      description: >-
        Bulk reject: for each supplied seed UUID, transition ``TRIAGED →
        REJECTED`` via ``SeedLifecycleStore.transition``. REJECTED is a terminal
        state that also writes the dead-seed registry (C-SSD §2.2) so the same
        premise will not regenerate. Per-item failures are isolated.
      operationId: batch_reject_seeds_v1_projects__project_id__seeds_batch_reject_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchSeedsRequest'
        required: true
      responses:
        '200':
          description: Batch processed (per-id verdicts in body)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchSeedsResponse'
        '400':
          description: Batch too large (> 100 ids) or empty
        '401':
          description: Invalid or missing tenant context
        '403':
          description: Forbidden - API key lacks the required scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
              example:
                error: Forbidden
                code: forbidden
                request_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                message: Your API key does not have the required scope.
                doc_url: https://docs.kitefrost.ai/errors/forbidden
        '404':
          description: Project not found
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          description: >-
            Too Many Requests - rate limit exceeded. Retry after the
            'Retry-After' header interval.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
              example:
                error: Rate limit exceeded
                code: rate_limited
                request_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                message: You have exceeded the rate limit for your plan.
                doc_url: https://docs.kitefrost.ai/errors/rate_limited
        '500':
          description: >-
            Internal Server Error - unexpected server-side failure. Retry with
            exponential back-off.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/APIError'
              example:
                error: Internal server error
                code: internal_error
                request_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                message: An unexpected error occurred.
                doc_url: https://docs.kitefrost.ai/errors/internal_error
        '503':
          description: Seed store not configured
components:
  schemas:
    BatchSeedsRequest:
      properties:
        seed_ids:
          items:
            type: string
            format: uuid
          type: array
          minItems: 1
          title: Seed Ids
          description: Seed UUIDs to operate on (slug not accepted in batch).
        triage_note:
          anyOf:
            - type: string
              maxLength: 500
            - type: 'null'
          title: Triage Note
          description: Optional shared note stamped on every successful transition.
      additionalProperties: false
      type: object
      required:
        - seed_ids
      title: BatchSeedsRequest
      description: |-
        Body of ``POST .../seeds/batch/{validate,reject}``.

        A flat list of seed UUIDs plus an optional shared note that gets
        stamped on every successful transition. The size cap is enforced
        inside the handler (explicit 400) rather than via Pydantic
        ``max_length`` so the failure mode is a clean ``400 Bad Request``
        with a stable schema, not the framework's default 422.
    BatchSeedsResponse:
      properties:
        succeeded:
          items:
            $ref: '#/components/schemas/SeedResponse'
          type: array
          title: Succeeded
        failed:
          items:
            $ref: '#/components/schemas/BatchFailure'
          type: array
          title: Failed
      additionalProperties: false
      type: object
      required:
        - succeeded
        - failed
      title: BatchSeedsResponse
      description: |-
        Response shape for both batch endpoints.

        ``succeeded`` carries the per-id verdicts that landed; ``failed``
        carries per-id reasons (``not_found``, ``cross_tenant``,
        ``invalid_transition``, ``error``). The HTTP status code is always
        ``200`` once the request has cleared validation - per-item failure
        does NOT abort the batch (per-item error isolation per design §
        Batch).
    APIError:
      properties:
        error:
          type: string
          title: Error
        code:
          type: string
          title: Code
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
        detail:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Detail
        message:
          anyOf:
            - type: string
            - type: 'null'
          title: Message
        doc_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Doc Url
        feedback_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Feedback Id
      type: object
      required:
        - error
        - code
      title: APIError
      example:
        code: not_found
        doc_url: https://docs.kitefrost.ai/errors/not_found
        error: Not found
        message: >-
          The requested resource does not exist or you do not have permission to
          access it. Verify the resource ID and your API key scopes.
        request_id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    SeedResponse:
      properties:
        seed_id:
          type: string
          format: uuid
          title: Seed Id
        tenant_id:
          type: string
          format: uuid
          title: Tenant Id
        slug:
          anyOf:
            - type: string
            - type: 'null'
          title: Slug
        state:
          $ref: '#/components/schemas/LifecycleState'
        state_changed_at:
          type: string
          format: date-time
          title: State Changed At
        promoted_project_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Promoted Project Id
        triaged_by:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Triaged By
        triage_note:
          anyOf:
            - type: string
            - type: 'null'
          title: Triage Note
        dramatic_premise:
          type: string
          title: Dramatic Premise
        dramatic_situation:
          type: string
          title: Dramatic Situation
        central_tension:
          additionalProperties: true
          type: object
          title: Central Tension
        human_tension_grounding:
          additionalProperties: true
          type: object
          title: Human Tension Grounding
        protagonist_shape:
          additionalProperties: true
          type: object
          title: Protagonist Shape
        stakes:
          additionalProperties: true
          type: object
          title: Stakes
        tone:
          type: string
          title: Tone
        pack_affinity:
          items:
            additionalProperties: true
            type: object
          type: array
          title: Pack Affinity
        provenance_class:
          $ref: '#/components/schemas/ProvenanceClass'
        risk_flags:
          items:
            $ref: '#/components/schemas/RiskFlag'
          type: array
          title: Risk Flags
        provenance:
          additionalProperties: true
          type: object
          title: Provenance
        quality_scores:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Quality Scores
        durability_class:
          type: string
          title: Durability Class
        freshness_ts:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Freshness Ts
        stale_after:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Stale After
        resonance_score:
          type: number
          title: Resonance Score
        created_at:
          type: string
          format: date-time
          title: Created At
        updated_at:
          type: string
          format: date-time
          title: Updated At
      type: object
      required:
        - seed_id
        - tenant_id
        - slug
        - state
        - state_changed_at
        - promoted_project_id
        - triaged_by
        - triage_note
        - dramatic_premise
        - dramatic_situation
        - central_tension
        - human_tension_grounding
        - protagonist_shape
        - stakes
        - tone
        - pack_affinity
        - provenance_class
        - risk_flags
        - provenance
        - quality_scores
        - durability_class
        - freshness_ts
        - stale_after
        - resonance_score
        - created_at
        - updated_at
      title: SeedResponse
      description: |-
        Response shape for a single seed row.

        A thin projection over :class:`StorySeedRecord` - JSONB columns
        surface as ``dict`` so dashboards can render them without a second
        round-trip; large list views can slim this down later if needed.
    BatchFailure:
      properties:
        seed_id:
          type: string
          format: uuid
          title: Seed Id
        error:
          type: string
          title: Error
          description: Stable machine-readable error code.
        detail:
          anyOf:
            - type: string
            - type: 'null'
          title: Detail
          description: Human-readable detail (optional, free-form).
      additionalProperties: false
      type: object
      required:
        - seed_id
        - error
      title: BatchFailure
      description: One per-item failure in a batch response.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    LifecycleState:
      type: string
      enum:
        - raw
        - triaged
        - promoted
        - used
        - rejected
        - dead
      title: LifecycleState
      description: |-
        The 6 seed lifecycle states.

        Source: ``mechanics/lifecycle-state-machine.md`` §1 - wire-form values
        match the DB ``CHECK (state IN ('raw',...))`` exactly.
    ProvenanceClass:
      type: string
      enum:
        - generated
        - public-domain
        - licensed
        - opt-in
        - operator-inspired
      title: ProvenanceClass
      description: |-
        Discrete provenance vocabulary (5 values) per R4 R127-C1.

        Source of truth:
          - ``docs/design/concepts/green-source-scout/mechanics/provenance-contract.md`` §2
          - ``docs/design/concepts/seed-lifecycle-store/mechanics/schema.md`` (CHECK constraint)
          - ``docs/design/concepts/story-seed-object/design.md`` §3.1

        Notable absence: there is NO ``scraped`` value - the gate enforces by
        absence. The DB-level ``CHECK`` constraint lists exactly these five.
    RiskFlag:
      type: string
      enum:
        - pii-present
        - sensitive-data
        - identifiable-real-event
        - copyrighted-phrasing-detected
        - platform-restriction
        - minor-or-sensitive-subject
      title: RiskFlag
      description: >-
        Controlled risk-flag vocabulary (C-SSD-7 contract §2).


        ANY flag set on a seed → mandatory human review (cannot auto-promote).

        Stored as ``TEXT[]`` with a GIN index so the SC8 audit

        (``WHERE risk_flags @> ARRAY[...]``) is a single index scan.


        Source:
        ``docs/design/concepts/green-source-scout/mechanics/provenance-contract.md``
        §2.

````