{
  "openapi": "3.1.0",
  "info": {
    "title": "oPOS Public API",
    "version": "1.0.0",
    "description": "API pública de lectura para consultar conocimiento de producto y respuestas por rubro de oPOS, el sistema de punto de venta para comercios de Argentina. La versión estable actual es v1 y se publica bajo /api/v1. Las rutas sin versión son aliases de compatibilidad. Los cambios incompatibles se anuncian con una nueva versión y una política de deprecación publicada en /developers.",
    "x-api-version": "1",
    "x-api-versioning": {
      "strategy": "URL path versioning",
      "current": "v1",
      "basePath": "https://opos.lat/api/v1",
      "deprecationPolicy": "Unversioned routes remain compatibility aliases for the current major version. A breaking change requires a new URL version and advance documentation."
    },
    "contact": {
      "name": "Equipo oPOS",
      "email": "contacto@opos.lat",
      "url": "https://opos.lat/contacto"
    },
    "license": {
      "name": "Uso sujeto a los términos de oPOS",
      "url": "https://opos.lat/terminos"
    }
  },
  "servers": [
    {
      "url": "https://opos.lat",
      "description": "Producción"
    }
  ],
  "externalDocs": {
    "description": "Documentación de uso de oPOS",
    "url": "https://docs.opos.lat"
  },
  "tags": [
    {
      "name": "Discovery",
      "description": "Superficies para descubrir el API y sus recursos."
    },
    {
      "name": "Knowledge",
      "description": "Respuestas públicas y verificables sobre oPOS."
    },
    {
      "name": "Quotes",
      "description": "Consulta de presupuestos compartidos mediante token."
    }
  ],
  "paths": {
    "/ask": {
      "get": {
        "operationId": "askNlWeb",
        "summary": "Consultar oPOS en lenguaje natural",
        "description": "Endpoint NLWeb de solo lectura. Devuelve resultados estructurados sobre producto, rubros y recursos públicos de oPOS.",
        "tags": [
          "Discovery"
        ],
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Pregunta o necesidad que se quiere consultar.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Modo de respuesta NLWeb.",
            "schema": {
              "type": "string",
              "enum": [
                "list",
                "summarize",
                "generate"
              ],
              "default": "list"
            }
          },
          {
            "name": "streaming",
            "in": "query",
            "required": false,
            "description": "Solicita eventos SSE cuando es true.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resultados NLWeb en JSON o SSE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NlWebResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Falta query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postNlWebQuery",
        "summary": "Consultar oPOS en lenguaje natural por POST",
        "description": "Versión JSON de la consulta NLWeb para clientes que prefieren POST.",
        "tags": [
          "Discovery"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "list",
                      "summarize",
                      "generate"
                    ]
                  },
                  "streaming": {
                    "type": "boolean"
                  },
                  "query_id": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultados NLWeb en JSON o SSE.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NlWebResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Falta query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "Descubrir las superficies públicas de oPOS",
        "description": "Devuelve enlaces al OpenAPI, al contenido para agentes, a la documentación y al servidor MCP de oPOS.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Índice de recursos públicos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/faq/{industry}": {
      "get": {
        "operationId": "getIndustryFaq",
        "summary": "Consultar preguntas frecuentes de un rubro",
        "description": "Devuelve preguntas frecuentes, criterios y fuentes registradas para un rubro de comercio argentino.",
        "tags": [
          "Knowledge"
        ],
        "parameters": [
          {
            "name": "industry",
            "in": "path",
            "required": true,
            "description": "Identificador del rubro, por ejemplo kioscos o almacenes.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "pattern": "^[a-z0-9-]+$",
              "example": "kioscos"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preguntas frecuentes y fuentes del rubro.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndustryFaq"
                }
              }
            }
          },
          "404": {
            "description": "El rubro no existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Se superó el límite de consultas.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/quotes/{token}": {
      "get": {
        "operationId": "getPublicQuote",
        "summary": "Consultar un presupuesto compartido",
        "description": "Devuelve un presupuesto publicado cuando se cuenta con su token de acceso. El token debe tratarse como secreto.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token de acceso incluido en el enlace compartido del presupuesto.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "example": "quote-token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Presupuesto compartido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Token inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Presupuesto no encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Se superó el límite de consultas.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1": {
      "get": {
        "operationId": "getApiV1Index",
        "summary": "Descubrir la API pública v1 de oPOS",
        "description": "Índice versionado de la API pública estable. Las rutas sin /v1 son aliases de compatibilidad.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "Índice de la API pública v1.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/faq/{industry}": {
      "get": {
        "operationId": "getV1IndustryFaq",
        "summary": "Consultar preguntas frecuentes por rubro en la API v1",
        "description": "Devuelve preguntas frecuentes y fuentes para un rubro de comercio argentino usando la versión estable v1.",
        "tags": [
          "Knowledge"
        ],
        "parameters": [
          {
            "name": "industry",
            "in": "path",
            "required": true,
            "description": "Identificador del rubro, por ejemplo kioscos o almacenes.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "pattern": "^[a-z0-9-]+$",
              "example": "kioscos"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preguntas frecuentes y fuentes del rubro.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IndustryFaq"
                }
              }
            }
          },
          "404": {
            "description": "El rubro no existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Se superó el límite de consultas.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/quotes/{token}": {
      "get": {
        "operationId": "getV1PublicQuote",
        "summary": "Consultar un presupuesto compartido en la API v1",
        "description": "Devuelve un presupuesto publicado mediante su token de acceso usando la versión estable v1.",
        "tags": [
          "Quotes"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "Token secreto incluido en el enlace compartido del presupuesto.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "example": "quote-token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Presupuesto compartido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicQuote"
                }
              }
            }
          },
          "400": {
            "description": "Token inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Presupuesto no encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Se superó el límite de consultas.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ApiIndex": {
        "type": "object",
        "description": "Enlaces canónicos a los recursos de integración de oPOS.",
        "required": [
          "name",
          "description",
          "openapi",
          "llms",
          "documentation",
          "mcp",
          "agentInstructions",
          "developerResources",
          "versioning",
          "rateLimits"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nombre del producto.",
            "example": "oPOS"
          },
          "description": {
            "type": "string",
            "description": "Descripción del producto.",
            "example": "Software de punto de venta para comercios de Argentina con ventas, stock, caja, facturación electrónica ARCA y reportes."
          },
          "openapi": {
            "type": "string",
            "format": "uri",
            "description": "Especificación OpenAPI."
          },
          "ask": {
            "type": "string",
            "format": "uri",
            "description": "Endpoint NLWeb de consulta en lenguaje natural."
          },
          "llms": {
            "type": "string",
            "format": "uri",
            "description": "Guía compacta para agentes."
          },
          "documentation": {
            "type": "string",
            "format": "uri",
            "description": "Documentación de uso."
          },
          "mcp": {
            "type": "string",
            "format": "uri",
            "description": "Endpoint MCP Streamable HTTP."
          },
          "agentInstructions": {
            "type": "string",
            "format": "uri",
            "description": "Instrucciones para agentes."
          },
          "developerResources": {
            "type": "string",
            "format": "uri",
            "description": "Portal de recursos para desarrolladores."
          },
          "versioning": {
            "type": "object",
            "required": [
              "current",
              "basePath",
              "compatibility"
            ],
            "properties": {
              "current": {
                "type": "string",
                "example": "v1"
              },
              "basePath": {
                "type": "string",
                "format": "uri"
              },
              "compatibility": {
                "type": "string"
              }
            },
            "additionalProperties": false
          },
          "rateLimits": {
            "type": "object",
            "required": [
              "headers",
              "documentation"
            ],
            "properties": {
              "headers": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "documentation": {
                "type": "string",
                "format": "uri"
              }
            },
            "additionalProperties": false
          },
          "pricing": {
            "type": "string",
            "format": "uri",
            "description": "Precios en Markdown."
          },
          "authentication": {
            "type": "string",
            "format": "uri",
            "description": "Guía de autenticación."
          },
          "agentCatalog": {
            "type": "string",
            "format": "uri",
            "description": "Catálogo de recursos de agentes."
          },
          "agentSkills": {
            "type": "string",
            "format": "uri",
            "description": "Índice de Agent Skills."
          },
          "agentCard": {
            "type": "string",
            "format": "uri",
            "description": "A2A agent card."
          }
        },
        "additionalProperties": false
      },
      "IndustryFaq": {
        "type": "object",
        "description": "Respuesta de conocimiento por rubro.",
        "required": [
          "schemaVersion",
          "industry",
          "faq"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "description": "Versión del contrato de conocimiento."
          },
          "industry": {
            "type": "object",
            "required": [
              "id",
              "name",
              "path",
              "url",
              "criteria",
              "claimIds",
              "sourceIds"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "path": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "criteria": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "claimIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "sourceIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "additionalProperties": false
          },
          "faq": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "question",
                "answer"
              ],
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              },
              "additionalProperties": false
            }
          }
        },
        "additionalProperties": false
      },
      "PublicQuote": {
        "type": "object",
        "description": "Presupuesto compartido; sus campos pueden variar según la configuración comercial.",
        "additionalProperties": true
      },
      "ApiError": {
        "type": "object",
        "required": [
          "error",
          "code",
          "message",
          "resolution",
          "status"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Código estable del error."
          },
          "code": {
            "type": "string",
            "description": "Código legible por agentes."
          },
          "message": {
            "type": "string",
            "description": "Descripción del problema."
          },
          "resolution": {
            "type": "string",
            "description": "Siguiente acción sugerida."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          }
        },
        "additionalProperties": true
      },
      "NlWebResponse": {
        "type": "object",
        "description": "Respuesta NLWeb v0.5 de solo lectura.",
        "required": [
          "query",
          "query_id",
          "totalResults",
          "results",
          "_meta"
        ],
        "properties": {
          "query": {
            "type": "string"
          },
          "query_id": {
            "type": "string"
          },
          "totalResults": {
            "type": "integer",
            "minimum": 0
          },
          "summary": {
            "type": "string"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "description",
                "url"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "additionalProperties": false
            }
          },
          "_meta": {
            "type": "object",
            "required": [
              "response_type",
              "version"
            ],
            "properties": {
              "response_type": {
                "type": "string"
              },
              "version": {
                "type": "string",
                "example": "0.5"
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      }
    }
  }
}