openapi: 3.0.3
info:
  title: Bring Your AI API
  description: |
    Public surface for Bring Your AI — the local-first AI agent harness migration,
    central Claude/Codex/Cursor sync, sanitized distill snapshot, and no-data
    remote MCP server.

    The primary programmable surface is the Model Context Protocol endpoint at
    `/mcp` (streamable-http JSON-RPC 2.0). REST endpoints below are for discovery
    and billing. The MCP discovery manifest is available at
    `/.well-known/mcp.json`.

    Remote MCP is no-data. It exposes discovery, preview, target listing, and
    local install handoff only. It does not accept harness files, generated
    memories, user rules, API keys, GitHub handles, or file contents. Actual
    moves, central sync, distill snapshots, and first-setup builds run through
    the local CLI or local MCP server on the user's machine. Central sync uses
    a local hub by default, can use a user-selected Git repo path, keeps auto
    sync disabled by default, never performs Git remote actions, and leaves
    platform-native config target-local by default during cross-tool sync.

    Commerce endpoints expose a machine-readable catalog, quote, and checkout.
    Stripe Payment Links are live for human handoff. Stripe shared payment token
    settlement is live for agents: submit a Link-issued token and buyer email to
    create a server-confirmed PaymentIntent and receive the signed license in JSON.
    x402/MPP is reserved for future per-call API endpoints.
  version: "1.2.0"
  contact:
    email: hello@bringyour.ai
  license:
    name: Proprietary — from $19 lifetime license
    url: https://bringyour.ai/buy
servers:
  - url: https://bringyour.ai
    description: Production
paths:
  /mcp:
    post:
      summary: Model Context Protocol JSON-RPC endpoint
      description: |
        Streamable-http MCP transport. The remote server exposes no-data tools:
        `preview_move`, `preview_build_setup`, `install_local_cli`,
        `list_targets`, `list_products`, `quote_lifetime_license`, and
        `start_checkout`. No license header is required because this server
        does not apply moves or process harness data.
      operationId: mcpJsonRpc
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [jsonrpc, method, id]
              properties:
                jsonrpc:
                  type: string
                  enum: ["2.0"]
                method:
                  type: string
                  example: tools/list
                id:
                  oneOf:
                    - type: string
                    - type: integer
                params:
                  type: object
      responses:
        "200":
          description: JSON-RPC 2.0 response
          content:
            application/json:
              schema:
                type: object
  /api/stripe/webhook:
    post:
      summary: Stripe webhook receiver
      description: |
        Verifies the `Stripe-Signature` header (HMAC-SHA256, ±5min replay
        window). On `checkout.session.completed`, mints a signed ed25519
        license envelope and emails it to the buyer via Resend.

        Not intended for public use.
      operationId: stripeWebhook
      responses:
        "200":
          description: Accepted
        "400":
          description: Signature failed verification
        "503":
          description: Secrets not configured yet
  /api/v1:
    get:
      summary: API catalog root
      description: Discovery endpoint listing the structured API surface.
      operationId: apiRoot
      responses:
        "200":
          description: JSON catalog
          content:
            application/json:
              schema:
                type: object
  /api/v1/ad-event:
    post:
      summary: First-party ad funnel event
      description: |
        Records non-PII ad funnel events such as `page_view` and
        `checkout_click` with UTM, gclid, first-party attribution ID, keyword,
        match type, campaign, and landing path metadata. The endpoint does not accept harness files,
        generated memories, user rules, API keys, repo paths, file contents, or
        buyer email.
      operationId: recordAdEvent
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
      responses:
        "204":
          description: Recorded
    get:
      summary: Pixel-style ad funnel event
      description: Records a non-PII ad event from query parameters.
      operationId: recordAdEventPixel
      responses:
        "204":
          description: Recorded
  /api/v1/admin/ad-events:
    get:
      summary: Admin ad funnel report
      description: Returns aggregate ad event counts, decision-eligible counts, health/test counts, top UTM/keyword cohorts, and client_reference_id mappings for Stripe attribution. Requires the admin bearer token.
      operationId: getAdEventReport
      responses:
        "200":
          description: Aggregate ad funnel report
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Unauthorized
  /api/v1/catalog:
    get:
      summary: Agent-readable product catalog
      description: Lists Bring Your AI lifetime-license products, prices, and truthful payment-mode support.
      operationId: listCatalog
      responses:
        "200":
          description: Commerce catalog
          content:
            application/json:
              schema:
                type: object
  /api/v1/products:
    get:
      summary: Alias for product catalog
      operationId: listProducts
      responses:
        "200":
          description: Commerce catalog
          content:
            application/json:
              schema:
                type: object
  /api/v1/quote:
    post:
      summary: Quote a lifetime license
      description: Returns a structured quote. USD is the only currently supported presentment currency.
      operationId: quoteProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [product_id]
              properties:
                product_id:
                  type: string
                  enum: [bringyour_founder_lifetime, bringyour_early_lifetime, bringyour_lifetime]
                quantity:
                  type: integer
                  enum: [1]
                buyer_country:
                  type: string
                  example: GB
                locale:
                  type: string
                  example: en-GB
                currency:
                  type: string
                  example: USD
                buyer_type:
                  type: string
                  example: individual
                tax_id:
                  type: string
                  nullable: true
      responses:
        "200":
          description: Quote
          content:
            application/json:
              schema:
                type: object
        "422":
          description: Unsupported currency
  /api/v1/checkout:
    get:
      summary: Start a human checkout handoff from query parameters
      description: |
        Browserless conversion route for agents and probers that follow the
        advertised checkout URL directly. Returns the same Stripe Payment Link
        handoff as POST when product_id is provided.
      operationId: getCheckoutHandoff
      parameters:
        - in: query
          name: product_id
          required: true
          schema:
            type: string
            enum: [bringyour_founder_lifetime, bringyour_early_lifetime, bringyour_lifetime]
        - in: query
          name: payment_mode
          schema:
            type: string
            enum: [stripe_payment_link, stripe_link, link, stripe_checkout, human_checkout]
        - in: query
          name: quantity
          schema:
            type: integer
            enum: [1]
      responses:
        "200":
          description: Stripe Payment Link handoff
          content:
            application/json:
              schema:
                type: object
        "400":
          description: Missing product_id
    post:
      summary: Start checkout or settle a Stripe SPT payment
      description: |
        For human checkout modes, returns a Stripe Payment Link checkout URL.
        For payment_mode=stripe_spt or spt, accepts a Link-issued
        shared_payment_granted_token and buyer_email, confirms a Stripe
        PaymentIntent server-side, then returns the signed Bring Your AI license
        directly in JSON. For x402/MPP, returns an explicit not-enabled response
        and the Payment Link fallback.
      operationId: startCheckout
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [product_id]
              properties:
                product_id:
                  type: string
                  enum: [bringyour_founder_lifetime, bringyour_early_lifetime, bringyour_lifetime]
                quantity:
                  type: integer
                  enum: [1]
                payment_mode:
                  type: string
                  enum: [stripe_payment_link, stripe_link, link, stripe_checkout, human_checkout, stripe_acp, acp, spt, stripe_spt, agentic_checkout, mpp, x402, mpp_x402, machine_payments_x402]
                shared_payment_granted_token:
                  type: string
                  description: Link-issued Stripe shared payment token. Required for stripe_spt settlement.
                buyer_email:
                  type: string
                  description: Email bound to the issued license. Required for stripe_spt settlement.
                email:
                  type: string
                  description: Alias for buyer_email.
                buyer_country:
                  type: string
                locale:
                  type: string
                currency:
                  type: string
      responses:
        "200":
          description: Stripe Payment Link handoff
          content:
            application/json:
              schema:
                type: object
        "201":
          description: Stripe SPT payment settled and signed license issued
          content:
            application/json:
              schema:
                type: object
        "501":
          description: Requested private-preview payment rail is not enabled
  /api/v1/license:
    get:
      summary: License fulfillment contract
      description: |
        Explains how paid Bring Your AI licenses are delivered, how the CLI
        verifies them locally without a remote account lookup, and which install
        commands an agent should hand to the buyer after checkout.
      operationId: getLicenseFulfillment
      responses:
        "200":
          description: Fulfillment, install, and local-verification contract
          content:
            application/json:
              schema:
                type: object
  /api/v1/updates:
    get:
      summary: Included updates and CLI upgrade contract
      description: |
        Machine-readable update surface for existing lifetime buyers and their
        agents. It states that new local features are included for existing
        paid users, preserves the no-phone-home license model, and returns the
        exact latest-channel upgrade command.
      operationId: getUpdates
      responses:
        "200":
          description: Included updates and upgrade instructions
          content:
            application/json:
              schema:
                type: object
  /license-verification.json:
    get:
      summary: Agent-readable license verification proof
      description: |
        Structured proof for agents and buyers validating Bring Your AI's paid
        license contract. The route is descriptive only and preserves the
        no-data remote invariant: it does not accept or process harness files,
        generated memories, user rules, API keys, GitHub handles, repo paths,
        MCP config files, or file contents. License verification is local after
        checkout fulfillment.
      operationId: licenseVerificationProof
      responses:
        "200":
          description: License verification proof
          content:
            application/json:
              schema:
                type: object
  /pricing.json:
    get:
      summary: Agent-readable pricing and checkout contract
      description: |
        Structured pricing, payment-mode, fulfillment, and no-data remote
        invariant metadata for agents evaluating whether a Bring Your AI
        lifetime license can be purchased safely.
      operationId: pricingContract
      responses:
        "200":
          description: Pricing and checkout contract
          content:
            application/json:
              schema:
                type: object
  /agent-setup-migration:
    get:
      summary: Google Ads landing page
      description: Buyer-facing landing page for high-intent searches around moving or syncing AI agent setup across Claude Code, Codex, and Cursor.
      operationId: agentSetupMigrationLandingPage
      responses:
        "200":
          description: HTML landing page
          content:
            text/html:
              schema:
                type: string
  /agent-buying-guide.json:
    get:
      summary: Agent buying guide
      description: Returns exact machine-readable catalog, quote, checkout, fulfillment, and proof routes for an agent buying a Bring Your AI license.
      operationId: getAgentBuyingGuide
      responses:
        "200":
          description: Agent buying guide
          content:
            application/json:
              schema:
                type: object
  /agent-recommendation-guide.json:
    get:
      summary: Agent recommendation guide
      description: Returns machine-readable criteria for when agents should recommend Bring Your AI and when they should not, including product boundaries and no-data remote guarantees.
      operationId: getAgentRecommendationGuide
      responses:
        "200":
          description: Agent recommendation guide
          content:
            application/json:
              schema:
                type: object
  /claude-code-to-codex.json:
    get:
      summary: Agent-readable Claude Code to Codex migration guide
      description: |
        Structured guide for agents helping a developer move a Claude Code
        setup to Codex. The route is descriptive only and preserves the no-data
        remote invariant: it does not accept or process harness files,
        generated memories, user rules, API keys, GitHub handles, repo paths,
        or file contents.
      operationId: claudeCodeToCodexMigrationGuide
      responses:
        "200":
          description: Claude Code to Codex migration guide
          content:
            application/json:
              schema:
                type: object
  /codex-import-checklist.json:
    get:
      summary: Agent-readable Codex import checklist
      description: |
        Structured checklist for agents validating a Claude Code to Codex
        migration after the first-party Codex import step. The route is
        descriptive only and preserves the no-data remote invariant: it does
        not accept or process harness files, generated memories, user rules,
        API keys, GitHub handles, or file contents.
      operationId: codexImportChecklist
      responses:
        "200":
          description: Codex import validation checklist
          content:
            application/json:
              schema:
                type: object
  /claude-code-limit-fallback.json:
    get:
      summary: Agent-readable Claude Code limit fallback runbook
      description: |
        Structured runbook for agents helping a developer continue work in
        Codex after Claude Code limits, outage, or plan interruption. The route
        is descriptive only and preserves the no-data remote invariant: it does
        not accept or process harness files, generated memories, user rules,
        API keys, GitHub handles, repo paths, or file contents.
      operationId: claudeCodeLimitFallback
      responses:
        "200":
          description: Claude Code to Codex fallback runbook
          content:
            application/json:
              schema:
                type: object
  /codex-import-audit.json:
    get:
      summary: Agent-readable Codex import audit
      description: |
        Structured audit for agents validating a Codex import after a Claude
        Code migration. The route is descriptive only and preserves the
        no-data remote invariant: it does not accept or process harness files,
        generated memories, user rules, API keys, GitHub handles, repo paths,
        MCP config files, or file contents.
      operationId: codexImportAudit
      responses:
        "200":
          description: Codex import audit checklist
          content:
            application/json:
              schema:
                type: object
  /mcp-config-migration.json:
    get:
      summary: Agent-readable MCP config migration checklist
      description: |
        Structured checklist for agents validating MCP config during a Claude
        Code to Codex migration. The route is descriptive only and preserves
        the no-data remote invariant: it does not accept or process MCP config
        files, generated memories, user rules, API keys, GitHub handles, local
        paths, or file contents.
      operationId: mcpConfigMigrationChecklist
      responses:
        "200":
          description: MCP config migration checklist
          content:
            application/json:
              schema:
                type: object
  /claude-code-to-codex-tools.json:
    get:
      summary: Agent-readable Claude Code to Codex migration tools comparison
      description: |
        Structured comparison for agents choosing between first-party Codex
        import, manual AGENTS.md edits, Bring Your AI local CLI validation,
        and no-data remote MCP discovery. The route is descriptive only and
        preserves the no-data remote invariant: it does not accept or process
        harness files, generated memories, user rules, API keys, GitHub
        handles, repo paths, MCP config files, or file contents.
      operationId: claudeCodeToCodexToolsComparison
      responses:
        "200":
          description: Claude Code to Codex migration tools comparison
          content:
            application/json:
              schema:
                type: object
  /agents-md-claude-md.json:
    get:
      summary: Agent-readable AGENTS.md vs CLAUDE.md migration audit
      description: |
        Structured checklist for agents validating instruction-file behavior
        during a Claude Code to Codex migration. The route is descriptive only
        and preserves the no-data remote invariant: it does not accept or
        process harness files, generated memories, user rules, API keys,
        GitHub handles, repo paths, or file contents.
      operationId: agentsMDClaudeMDMigrationAudit
      responses:
        "200":
          description: AGENTS.md vs CLAUDE.md migration audit checklist
          content:
            application/json:
              schema:
                type: object
  /codex-import-smoke.json:
    get:
      summary: Agent-readable Codex import smoke checklist
      description: |
        Structured local-only smoke checklist for agents validating a Claude
        Code to Codex migration before Codex edits production code. The route
        is descriptive only and preserves the no-data remote invariant: it
        does not accept or process harness files, generated memories, user
        rules, API keys, GitHub handles, repo paths, MCP config files, or file
        contents.
      operationId: codexImportSmokeChecklist
      responses:
        "200":
          description: Codex import smoke checklist
          content:
            application/json:
              schema:
                type: object
  /health:
    get:
      summary: Liveness probe
      operationId: health
      responses:
        "200":
          description: ok
          content:
            text/plain:
              schema:
                type: string
                example: "ok"
  /llms.txt:
    get:
      summary: llms.txt agent-discovery brief
      operationId: llmsTxt
      responses:
        "200":
          description: Plain-text description of the product for LLM agents.
  /.well-known/ai-plugin.json:
    get:
      summary: OpenAI-style AI Plugin manifest
      operationId: aiPlugin
      responses:
        "200":
          description: ai-plugin.json
          content:
            application/json:
              schema:
                type: object
  /.well-known/mcp.json:
    get:
      summary: MCP server discovery manifest
      operationId: mcpManifest
      responses:
        "200":
          description: MCP server manifest for the no-data remote MCP endpoint.
          content:
            application/json:
              schema:
                type: object
  /.well-known/commerce.json:
    get:
      summary: Commerce discovery manifest
      operationId: commerceManifest
      responses:
        "200":
          description: Agent-readable commerce manifest.
          content:
            application/json:
              schema:
                type: object
  /.well-known/agent.json:
    get:
      summary: Agent discovery manifest
      operationId: agentManifest
      responses:
        "200":
          description: Agent-readable product and commerce surface map.
          content:
            application/json:
              schema:
                type: object
