openapi: 3.1.0
info:
  title: busom.com — agente vendedor (Agentic Commerce Protocol)
  version: "2026-04-17"
  description: |
    Venta directa de los libros de Rais Busom a agentes de IA. Sigue las formas del Agentic Commerce
    Protocol (ACP, Stripe + OpenAI, versión 2026-04-17): sesiones de checkout con line_items, totals,
    fulfillment_options y status. Diferencia con el estándar: no hay pago delegado (Shared Payment
    Token). `complete` devuelve en `links` un `payment_url` de Stripe Checkout que una persona debe
    abrir y autorizar. Precios en EUR con IVA incluido y fijos por ley (Ley 10/2007 del libro).
    Envío de papel solo a España. También disponible como servidor MCP en https://busom.com/mcp.
  contact: { name: Rais Busom, email: rais@busom.com, url: https://busom.com/agentes }
  termsOfService: https://busom.com/condiciones
servers:
  - url: https://busom.com
paths:
  /agent/catalog.json:
    get:
      summary: Catálogo para máquinas (estático)
      responses: { "200": { description: Catálogo, content: { application/json: {} } } }
  /acp/checkout_sessions:
    post:
      summary: Crear una sesión de checkout
      parameters:
        - { name: API-Version, in: header, schema: { type: string, example: "2026-04-17" } }
        - { name: Idempotency-Key, in: header, schema: { type: string } }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/CheckoutSessionCreateRequest" }
            examples:
              ebook: { value: { items: [ { id: ebook, quantity: 1 } ], buyer: { first_name: Ana, last_name: Lectora, email: ana@example.com } } }
              papel: { value: { items: [ { id: espia, quantity: 1 } ], fulfillment_details: { name: Ana Lectora, address: { line_one: "Calle Mayor 1", city: Madrid, postal_code: "28013", country: ES } } } }
      responses:
        "201": { description: Sesión creada, content: { application/json: { schema: { $ref: "#/components/schemas/CheckoutSession" } } } }
        "400": { $ref: "#/components/responses/Error" }
  /acp/checkout_sessions/{checkout_session_id}:
    parameters: [ { name: checkout_session_id, in: path, required: true, schema: { type: string } } ]
    get:
      summary: Estado de la sesión
      responses:
        "200": { description: Sesión, content: { application/json: { schema: { $ref: "#/components/schemas/CheckoutSession" } } } }
        "404": { $ref: "#/components/responses/Error" }
    post:
      summary: Actualizar items, comprador o dirección
      requestBody: { content: { application/json: { schema: { $ref: "#/components/schemas/CheckoutSessionCreateRequest" } } } }
      responses:
        "200": { description: Sesión, content: { application/json: { schema: { $ref: "#/components/schemas/CheckoutSession" } } } }
  /acp/checkout_sessions/{checkout_session_id}/complete:
    post:
      summary: Cerrar la sesión y obtener el enlace de pago
      description: Sin `payment_data` devuelve 202 y `links[type=payment_url]`. Con un Shared Payment Token (`credential.type=spt`) responde 501.
      parameters: [ { name: checkout_session_id, in: path, required: true, schema: { type: string } } ]
      responses:
        "202": { description: Pendiente de que una persona pague en payment_url }
        "200": { description: Ya pagada, con order }
        "501": { $ref: "#/components/responses/Error" }
  /acp/checkout_sessions/{checkout_session_id}/cancel:
    post:
      summary: Cancelar la sesión
      parameters: [ { name: checkout_session_id, in: path, required: true, schema: { type: string } } ]
      responses:
        "200": { description: Sesión cancelada }
  /mcp:
    post:
      summary: Servidor MCP (JSON-RPC 2.0, Streamable HTTP)
      description: "Tools: list_books, get_book, quote, create_checkout, checkout_status. Sin autenticación."
      requestBody: { content: { application/json: { example: { jsonrpc: "2.0", id: 1, method: tools/list } } } }
      responses: { "200": { description: Respuesta JSON-RPC } }
components:
  responses:
    Error:
      description: Error con la forma ACP
      content: { application/json: { schema: { $ref: "#/components/schemas/Error" } } }
  schemas:
    Error:
      type: object
      properties: { type: { type: string }, code: { type: string }, message: { type: string }, param: { type: string } }
    Item:
      type: object
      required: [id]
      properties:
        id: { type: string, enum: [ebook, espia] }
        quantity: { type: integer, minimum: 1, maximum: 3, default: 1 }
        proposed_amount: { type: integer, description: "Extensión: oferta en céntimos. Se ignora con aviso: precio fijo por ley." }
    Buyer:
      type: object
      properties: { first_name: { type: string }, last_name: { type: string }, email: { type: string, format: email }, phone_number: { type: string } }
    Address:
      type: object
      properties: { name: { type: string }, line_one: { type: string }, line_two: { type: string }, city: { type: string }, state: { type: string }, postal_code: { type: string }, country: { type: string, description: "Solo ES" } }
    CheckoutSessionCreateRequest:
      type: object
      required: [items]
      properties:
        items: { type: array, items: { $ref: "#/components/schemas/Item" } }
        buyer: { $ref: "#/components/schemas/Buyer" }
        fulfillment_details: { type: object, properties: { name: { type: string }, address: { $ref: "#/components/schemas/Address" } } }
    CheckoutSession:
      type: object
      properties:
        id: { type: string, example: acs_0123456789abcdef01234567 }
        status: { type: string, enum: [not_ready_for_payment, ready_for_payment, requires_escalation, completed, canceled] }
        currency: { type: string, example: eur }
        line_items: { type: array, items: { type: object } }
        totals: { type: array, items: { type: object, properties: { type: { type: string }, display_text: { type: string }, amount: { type: integer, description: céntimos } } } }
        fulfillment_options: { type: array, items: { type: object } }
        fulfillment_details: { type: object }
        buyer: { $ref: "#/components/schemas/Buyer" }
        links: { type: array, items: { type: object, properties: { type: { type: string, enum: [terms_of_use, privacy_policy, seller_shop_policies, payment_url] }, url: { type: string } } } }
        messages: { type: array, items: { type: object } }
        order: { type: object, nullable: true }
