openapi: 3.1.0
info:
  title: Translingo+ / NAATI.LTD Public API
  version: "2026.05.25"
  summary: Quote, jurisdiction routing, and booking handoff for NAATI translation, Notary Public, MFA Apostille/Legalization, PCC, and visa documentation services.
  description: |
    Public read-only manifest for AI agents (ChatGPT Actions, Claude Computer Use,
    Gemini Extensions, Perplexity) to retrieve pricing, jurisdiction logic, and
    submit booking requests on behalf of users. All endpoints are stateless and
    do not require authentication for read operations. Booking handoff returns
    a LINE/WhatsApp/email channel for human confirmation — no payment is taken
    via this API.
  contact:
    name: Translingo+ / NAATI.LTD
    email: naati@ilc.ltd
    url: https://naati.ltd
  license:
    name: CC-BY 4.0
    url: https://creativecommons.org/licenses/by/4.0/
  termsOfService: https://naati.ltd/legal
servers:
  - url: https://naati.ltd
    description: Production
tags:
  - name: catalog
    description: Read-only service catalog and pricing
  - name: jurisdiction
    description: Decide Apostille vs Legalization vs Embassy chain by destination country
  - name: quote
    description: Generate fixed-price quote (no payment taken)
  - name: booking
    description: Handoff to human channel (LINE / WhatsApp / email)
paths:
  /llms.txt:
    get:
      tags: [catalog]
      summary: AI-readable site index (llmstxt.org spec)
      operationId: getLlmsIndex
      responses:
        "200":
          description: Markdown index of all public pages
          content:
            text/markdown: {}
  /llms-full.txt:
    get:
      tags: [catalog]
      summary: Full content corpus for LLM ingestion
      operationId: getLlmsFull
      responses:
        "200":
          description: Concatenated markdown of all pillar pages (CC-BY 4.0)
          content:
            text/markdown: {}
  /knowledge-graph.jsonld:
    get:
      tags: [catalog]
      summary: JSON-LD knowledge graph triples (Org, Service, Claim, GovernmentOrganization)
      operationId: getKnowledgeGraph
      responses:
        "200":
          description: Schema.org graph with 15+ entities and dated Claims
          content:
            application/ld+json: {}
  /sitemap.xml:
    get:
      tags: [catalog]
      summary: Full sitemap index
      operationId: getSitemap
      responses:
        "200":
          description: XML sitemap (split by category)
          content:
            application/xml: {}
  /api/services:
    get:
      tags: [catalog]
      summary: List all services with pricing bands
      operationId: listServices
      parameters:
        - in: query
          name: category
          schema:
            type: string
            enum: [naati, notary, legalization, apostille, pcc, visa, marriage]
        - in: query
          name: locale
          schema:
            type: string
            enum: [th, en, ar, zh, ja, ko, ru, de, fr, es, it, pt, vi, id, tl, tr]
            default: en
      responses:
        "200":
          description: Service catalog
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServiceList"
  /api/jurisdiction/decide:
    get:
      tags: [jurisdiction]
      summary: Decide legalization chain for a destination country (Apostille vs Embassy)
      description: |
        Returns the correct chain (MFA → Apostille, or MFA → Embassy) given the
        destination country and document type. Reflects 2025-01-01 Thailand
        Apostille accession and 2025 UAE/Saudi accessions.
      operationId: decideJurisdiction
      parameters:
        - in: query
          name: destination
          required: true
          schema:
            type: string
            description: ISO 3166-1 alpha-2 country code
            example: DE
        - in: query
          name: docType
          required: true
          schema:
            type: string
            enum: [birth, marriage, divorce, death, pcc, education, corporate, poa, other]
        - in: query
          name: useDate
          schema:
            type: string
            format: date
            description: Date when document will be presented (defaults to today)
      responses:
        "200":
          description: Decision with chain, fees, processing time, citations
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/JurisdictionDecision"
  /api/quote:
    post:
      tags: [quote]
      summary: Generate fixed-price quote (no payment taken)
      operationId: createQuote
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/QuoteRequest"
      responses:
        "200":
          description: Quote with line items, total, validity 14 days
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Quote"
  /api/booking/handoff:
    post:
      tags: [booking]
      summary: Hand off to human channel — no payment taken
      operationId: handoffBooking
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BookingHandoff"
      responses:
        "200":
          description: Returns channel URL (LINE / WhatsApp / email mailto)
          content:
            application/json:
              schema:
                type: object
                properties:
                  channel:
                    type: string
                    enum: [line, whatsapp, email]
                  url:
                    type: string
                    format: uri
                  reference:
                    type: string
                    example: REF-2026-0525-AX42
components:
  schemas:
    ServiceList:
      type: object
      properties:
        services:
          type: array
          items:
            $ref: "#/components/schemas/Service"
    Service:
      type: object
      required: [slug, name, category, priceMin, priceMax, currency, processingDays]
      properties:
        slug: { type: string, example: naati-translation }
        name: { type: string }
        category: { type: string }
        priceMin: { type: number, example: 590 }
        priceMax: { type: number, example: 1290 }
        currency: { type: string, example: THB }
        processingDays:
          type: object
          properties:
            standard: { type: integer, example: 5 }
            express: { type: integer, example: 1 }
        url: { type: string, format: uri }
    JurisdictionDecision:
      type: object
      properties:
        chain:
          type: string
          enum: [apostille, embassy, both]
          description: apostille = single MFA stamp · embassy = MFA + consular · both = jurisdiction in flux
        steps:
          type: array
          items:
            type: object
            properties:
              order: { type: integer }
              authority: { type: string, example: "MFA Thailand (Chaeng Watthana)" }
              fee: { type: number }
              currency: { type: string, example: THB }
              processingDays: { type: integer }
        totalFee: { type: number }
        totalDays: { type: integer }
        legalBasis:
          type: array
          items: { type: string }
          example:
            - "Hague Apostille Convention (1961)"
            - "Thailand accession effective 2025-01-01"
        notes: { type: string }
    QuoteRequest:
      type: object
      required: [services, locale]
      properties:
        services:
          type: array
          items:
            type: object
            properties:
              slug: { type: string }
              quantity: { type: integer, default: 1 }
              express: { type: boolean, default: false }
        locale: { type: string, default: en }
        destination:
          type: string
          description: ISO 3166-1 alpha-2 (optional, enables jurisdiction routing)
    Quote:
      type: object
      properties:
        reference: { type: string, example: Q-2026-0525-AX42 }
        lineItems:
          type: array
          items:
            type: object
            properties:
              description: { type: string }
              unitPrice: { type: number }
              quantity: { type: integer }
              subtotal: { type: number }
        total: { type: number }
        currency: { type: string, example: THB }
        validUntil: { type: string, format: date }
        nextAction:
          type: object
          properties:
            type: { type: string, example: handoff }
            url: { type: string, format: uri }
    BookingHandoff:
      type: object
      required: [quoteReference, channel]
      properties:
        quoteReference: { type: string }
        channel:
          type: string
          enum: [line, whatsapp, email]
        customerName: { type: string }
        customerLocale: { type: string, default: en }
        notes: { type: string }
externalDocs:
  description: Plugin manifest, agent descriptor, and knowledge graph
  url: https://naati.ltd/.well-known/ai-plugin.json
