openapi: 3.1.0
info:
  title: LLM Hallucination Grounding API
  version: "1.0.0"
  description: >
    Detect LLM hallucinations. Submit an answer plus its source documents and get
    a 0-1 grounding score with per-claim labels: supported, partial, unsupported,
    or contradicted. Drop-in faithfulness check for RAG pipelines. Distributed via
    RapidAPI.
servers:
  - url: https://anchor.rgtz.dev
    description: RapidAPI gateway (replace with your RapidAPI host)
security:
  - rapidApiKey: []
paths:
  /v1/ground:
    post:
      operationId: groundAnswer
      summary: Score an answer's faithfulness to its sources
      description: >
        Provide an answer and >=1 sources (inline text or {url}). Returns a
        grounding_score and per-claim verdicts. Send Idempotency-Key for safe retries.
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GroundRequest'
            examples:
              basic:
                value:
                  answer: "The capital of France is Paris, population 12 million."
                  sources: ["Paris is the capital of France. About 2.1 million live in the city."]
      responses:
        "200":
          description: Grounding report.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroundResponse'
        "400": { $ref: '#/components/responses/Error' }
        "403": { $ref: '#/components/responses/Error' }
        "413": { $ref: '#/components/responses/Error' }
        "502": { $ref: '#/components/responses/Error' }
  /v1/usage:
    get:
      operationId: getUsage
      summary: Detected plan + per-plan limits
      responses:
        "200": { description: Plan info. }
        "403": { $ref: '#/components/responses/Error' }
  /v1/manifest:
    get:
      operationId: getManifest
      summary: Machine-readable capabilities (no auth)
      responses:
        "200": { description: Manifest. }
  /healthz:
    get:
      operationId: health
      summary: Health check (no auth)
      responses:
        "200": { description: OK. }
components:
  securitySchemes:
    rapidApiKey:
      type: apiKey
      in: header
      name: X-RapidAPI-Key
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema: { type: string }
  schemas:
    GroundRequest:
      type: object
      required: [answer, sources]
      properties:
        answer: { type: string, description: The LLM output to verify. }
        sources:
          type: array
          minItems: 1
          items:
            oneOf:
              - { type: string }
              - { type: object, properties: { text: { type: string } } }
              - { type: object, properties: { url: { type: string } } }
        question: { type: string, description: Optional question for context. }
    Claim:
      type: object
      properties:
        text: { type: string }
        status: { type: string, enum: [supported, partial, unsupported, contradicted] }
        score: { type: number }
        source_idx: { type: integer }
        reason: { type: string }
    GroundResponse:
      type: object
      properties:
        grounding_score: { type: number }
        supported: { type: boolean }
        claim_count: { type: integer }
        unsupported_count: { type: integer }
        method: { type: string, enum: [heuristic, llm] }
        claims: { type: array, items: { $ref: '#/components/schemas/Claim' } }
        source_count: { type: integer }
        plan: { type: string }
  responses:
    Error:
      description: Error envelope.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                properties:
                  code: { type: string }
                  message: { type: string }
                  hint: { type: string, nullable: true }
                  request_id: { type: string }
