openapi: 3.1.0
info:
    title: UXBERT Labs Public API
    version: 1.0.0
    summary: Agent-friendly public surface for uxbert.com
    description: |
        Programmatic access to UXBERT's public content (services, case studies,
        articles, careers) and a single write endpoint for submitting a
        contact / project enquiry.

        All "list" endpoints are HTML pages by default but support
        `Accept: text/markdown` for token-efficient consumption by language
        models and agents.
    contact:
        name: UXBERT Labs
        email: hello@uxbert.com
        url: https://uxbert.com/en/contact
    license:
        name: Proprietary content — see /en/terms-of-service
        url: https://uxbert.com/en/terms-of-service
servers:
    - url: https://uxbert.com
      description: Production
    - url: https://beta.uxbert.com
      description: Beta / staging
paths:
    /llms.txt:
        get:
            operationId: getLlmsIndex
            summary: Curated llms.txt index of the site
            responses:
                '200':
                    description: OK
                    content:
                        text/plain: {}
                        text/markdown: {}
    /llms-full.txt:
        get:
            operationId: getLlmsFull
            summary: Full markdown dump of key pages
            responses:
                '200':
                    description: OK
                    content:
                        text/plain: {}
                        text/markdown: {}
    /sitemap.xml:
        get:
            operationId: getSitemap
            summary: XML sitemap of all public pages
            responses:
                '200':
                    description: OK
                    content:
                        application/xml: {}
    /{locale}/digital-services:
        get:
            operationId: listServices
            summary: List the full UXBERT services catalogue
            parameters:
                - $ref: '#/components/parameters/Locale'
            responses:
                '200':
                    description: HTML page (or markdown when negotiated)
                    content:
                        text/html: {}
                        text/markdown: {}
    /{locale}/digital-services/{slug}:
        get:
            operationId: getService
            summary: Get a single service by slug
            parameters:
                - $ref: '#/components/parameters/Locale'
                - name: slug
                  in: path
                  required: true
                  schema:
                      type: string
                  example: user-research-usability-testing
            responses:
                '200':
                    description: HTML page (or markdown when negotiated)
                    content:
                        text/html: {}
                        text/markdown: {}
                '404':
                    description: Service not found
    /{locale}/case-studies:
        get:
            operationId: listCaseStudies
            summary: List published case studies
            parameters:
                - $ref: '#/components/parameters/Locale'
            responses:
                '200':
                    description: HTML page (or markdown when negotiated)
                    content:
                        text/html: {}
                        text/markdown: {}
    /{locale}/articles:
        get:
            operationId: listArticles
            summary: List published articles
            parameters:
                - $ref: '#/components/parameters/Locale'
            responses:
                '200':
                    description: HTML page (or markdown when negotiated)
                    content:
                        text/html: {}
                        text/markdown: {}
    /{locale}/careers:
        get:
            operationId: listCareers
            summary: List open careers
            parameters:
                - $ref: '#/components/parameters/Locale'
            responses:
                '200':
                    description: HTML page (or markdown when negotiated)
                    content:
                        text/html: {}
                        text/markdown: {}
    /api/contact:
        post:
            operationId: submitContact
            summary: Submit a contact / project enquiry
            description: |
                Forwards the message to UXBERT's lead pipeline (CRM + email).
                A consultant follows up by email. The endpoint is rate-limited
                and protected by reCAPTCHA v3 in interactive contexts; agents
                should include `X-Source: agent` for visibility.
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/ContactRequest'
            responses:
                '200':
                    description: Submission accepted
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/ContactResponse'
                '400':
                    description: Validation error
                '429':
                    description: Rate limit exceeded
components:
    parameters:
        Locale:
            name: locale
            in: path
            required: true
            schema:
                type: string
                enum: [en, ar]
                default: en
    schemas:
        ContactRequest:
            type: object
            required: [name, email, message]
            properties:
                name:
                    type: string
                    description: Full name. Supports Latin and Arabic characters.
                email:
                    type: string
                    format: email
                message:
                    type: string
                    minLength: 10
                company:
                    type: string
                phone:
                    type: string
                services:
                    type: array
                    items:
                        type: string
                    description: Optional UXBERT service slugs of interest.
        ContactResponse:
            type: object
            properties:
                ok:
                    type: boolean
                message:
                    type: string
