{
  "openapi": "3.1.0",
  "info": {
    "title": "LoteríaYa — API de resultados de Colombia",
    "version": "1.0.0",
    "description": "Resultados de las loterías, el chance y el Baloto de Colombia. 44 sorteos activos, archivo desde 2024. JSON, UTF-8, fechas en hora de Colombia.\n\nPor defecto no recibes resultados en disputa ni con una sola fuente detrás. `status` distingue los verificados de los pendientes: **si notificas a personas, filtra por `confirmed`**. Con `?include=preliminary` recibes además lo que no llega a ese umbral.",
    "contact": {
      "name": "LoteríaYa",
      "url": "https://www.loteriaya.com.co/api-loterias"
    }
  },
  "servers": [
    {
      "url": "https://www.loteriaya.com.co"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Resultados",
      "description": "Lo que salió en cada sorteo."
    },
    {
      "name": "Catálogo",
      "description": "Qué sorteos hay y cuándo juegan."
    }
  ],
  "paths": {
    "/v1/draws": {
      "get": {
        "tags": [
          "Catálogo"
        ],
        "summary": "Catálogo de sorteos",
        "description": "Los sorteos que cubrimos, con su calendario y su hora. Sus identificadores son los que aceptan los demás endpoints.",
        "responses": {
          "200": {
            "description": "El catálogo completo.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrawList"
                }
              }
            }
          },
          "401": {
            "description": "Falta la clave o no es válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "value": {
                      "error": {
                        "code": "missing_key",
                        "message": "The X-Api-Key header is required."
                      }
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": {
                        "code": "invalid_key",
                        "message": "The API key is not valid or has been revoked."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite por minuto o cuota mensual agotada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Rate limit of 60 requests per minute exceeded."
                      }
                    }
                  },
                  "quota_exceeded": {
                    "value": {
                      "error": {
                        "code": "quota_exceeded",
                        "message": "Monthly quota of 50000 requests exhausted."
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Segundos que esperar: hasta el próximo minuto si el rechazo fue por el límite por minuto, y hasta el cambio de mes si fue por la cuota."
              }
            }
          },
          "500": {
            "description": "Error interno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal_error": {
                    "value": {
                      "error": {
                        "code": "internal_error",
                        "message": "Internal error."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/results": {
      "get": {
        "tags": [
          "Resultados"
        ],
        "summary": "Todos los resultados de un día",
        "description": "Un día sin resultados devuelve `200` con `results` vacío, no un `404`.",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Fecha en `YYYY-MM-DD`, hora de Colombia.",
            "example": "2026-08-25"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "preliminary"
              ]
            },
            "description": "Con `preliminary` recibes también los resultados en disputa y los de una sola fuente. Cualquier otro valor devuelve `invalid_parameter`."
          }
        ],
        "responses": {
          "200": {
            "description": "Los resultados de ese día. `results` vacío si aún no hay ninguno.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultsByDate"
                }
              }
            }
          },
          "400": {
            "description": "Parámetro ausente o con formato erróneo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_parameter": {
                    "value": {
                      "error": {
                        "code": "invalid_parameter",
                        "message": "The date parameter is required and must be in YYYY-MM-DD format."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falta la clave o no es válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "value": {
                      "error": {
                        "code": "missing_key",
                        "message": "The X-Api-Key header is required."
                      }
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": {
                        "code": "invalid_key",
                        "message": "The API key is not valid or has been revoked."
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La fecha es anterior al histórico que cubre tu plan. El dato existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "history_not_included": {
                    "value": {
                      "error": {
                        "code": "history_not_included",
                        "message": "Your plan covers the last 30 days (from 2026-07-30)."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite por minuto o cuota mensual agotada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Rate limit of 60 requests per minute exceeded."
                      }
                    }
                  },
                  "quota_exceeded": {
                    "value": {
                      "error": {
                        "code": "quota_exceeded",
                        "message": "Monthly quota of 50000 requests exhausted."
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Segundos que esperar: hasta el próximo minuto si el rechazo fue por el límite por minuto, y hasta el cambio de mes si fue por la cuota."
              }
            }
          },
          "500": {
            "description": "Error interno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal_error": {
                    "value": {
                      "error": {
                        "code": "internal_error",
                        "message": "Internal error."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/results/{draw}": {
      "get": {
        "tags": [
          "Resultados"
        ],
        "summary": "Serie histórica de un sorteo",
        "description": "Máximo **366 días por petición**. Se pagina por rango.",
        "parameters": [
          {
            "name": "draw",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del sorteo, tal y como lo devuelve `/v1/draws`.",
            "example": "loteria-del-huila"
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Primer día del rango, incluido.",
            "example": "2026-08-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Último día del rango, incluido. No puede ser anterior a `from`.",
            "example": "2026-08-25"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "preliminary"
              ]
            },
            "description": "Con `preliminary` recibes también los resultados en disputa y los de una sola fuente. Cualquier otro valor devuelve `invalid_parameter`."
          }
        ],
        "responses": {
          "200": {
            "description": "Los resultados del rango, del más reciente al más antiguo.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultsSeries"
                }
              }
            }
          },
          "400": {
            "description": "Parámetro con formato erróneo, `from` posterior a `to`, o rango de más de 366 días.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_parameter": {
                    "value": {
                      "error": {
                        "code": "invalid_parameter",
                        "message": "The date parameter is required and must be in YYYY-MM-DD format."
                      }
                    }
                  },
                  "range_too_large": {
                    "value": {
                      "error": {
                        "code": "range_too_large",
                        "message": "The range cannot exceed 366 days per request."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falta la clave o no es válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "value": {
                      "error": {
                        "code": "missing_key",
                        "message": "The X-Api-Key header is required."
                      }
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": {
                        "code": "invalid_key",
                        "message": "The API key is not valid or has been revoked."
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "El rango empieza antes del histórico que cubre tu plan.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "history_not_included": {
                    "value": {
                      "error": {
                        "code": "history_not_included",
                        "message": "Your plan covers the last 30 days (from 2026-07-30)."
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Ese identificador de sorteo no existe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_draw": {
                    "value": {
                      "error": {
                        "code": "unknown_draw",
                        "message": "Unknown draw identifier."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite por minuto o cuota mensual agotada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Rate limit of 60 requests per minute exceeded."
                      }
                    }
                  },
                  "quota_exceeded": {
                    "value": {
                      "error": {
                        "code": "quota_exceeded",
                        "message": "Monthly quota of 50000 requests exhausted."
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Segundos que esperar: hasta el próximo minuto si el rechazo fue por el límite por minuto, y hasta el cambio de mes si fue por la cuota."
              }
            }
          },
          "500": {
            "description": "Error interno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal_error": {
                    "value": {
                      "error": {
                        "code": "internal_error",
                        "message": "Internal error."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/results/{draw}/latest": {
      "get": {
        "tags": [
          "Resultados"
        ],
        "summary": "Último resultado de un sorteo",
        "description": "Si el sorteo de hoy aún no alcanza el umbral, recibes el de la sesión anterior. **Comprueba `draw_date` antes de notificar.**",
        "parameters": [
          {
            "name": "draw",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del sorteo, tal y como lo devuelve `/v1/draws`.",
            "example": "loteria-del-huila"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "preliminary"
              ]
            },
            "description": "Con `preliminary` recibes también los resultados en disputa y los de una sola fuente. Cualquier otro valor devuelve `invalid_parameter`."
          }
        ],
        "responses": {
          "200": {
            "description": "El último resultado publicado.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LotteryResult"
                }
              }
            }
          },
          "400": {
            "description": "Parámetro ausente o con formato erróneo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_parameter": {
                    "value": {
                      "error": {
                        "code": "invalid_parameter",
                        "message": "The date parameter is required and must be in YYYY-MM-DD format."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falta la clave o no es válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "value": {
                      "error": {
                        "code": "missing_key",
                        "message": "The X-Api-Key header is required."
                      }
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": {
                        "code": "invalid_key",
                        "message": "The API key is not valid or has been revoked."
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Ese sorteo no existe, o todavía no tiene ningún resultado publicado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_draw": {
                    "value": {
                      "error": {
                        "code": "unknown_draw",
                        "message": "Unknown draw identifier."
                      }
                    }
                  },
                  "no_result": {
                    "value": {
                      "error": {
                        "code": "no_result",
                        "message": "No result for that draw on that date."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite por minuto o cuota mensual agotada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Rate limit of 60 requests per minute exceeded."
                      }
                    }
                  },
                  "quota_exceeded": {
                    "value": {
                      "error": {
                        "code": "quota_exceeded",
                        "message": "Monthly quota of 50000 requests exhausted."
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Segundos que esperar: hasta el próximo minuto si el rechazo fue por el límite por minuto, y hasta el cambio de mes si fue por la cuota."
              }
            }
          },
          "500": {
            "description": "Error interno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal_error": {
                    "value": {
                      "error": {
                        "code": "internal_error",
                        "message": "Internal error."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/results/{draw}/{date}": {
      "get": {
        "tags": [
          "Resultados"
        ],
        "summary": "Resultado de un sorteo en una fecha",
        "description": "`pending_confirmation` y `no_result` comparten el `404` y no significan lo mismo: ante el primero reintenta en unos minutos, el dato existe. Ante el segundo, no.",
        "parameters": [
          {
            "name": "draw",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del sorteo, tal y como lo devuelve `/v1/draws`.",
            "example": "loteria-del-huila"
          },
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Fecha del sorteo en `YYYY-MM-DD`, hora de Colombia.",
            "example": "2026-08-25"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "preliminary"
              ]
            },
            "description": "Con `preliminary` recibes también los resultados en disputa y los de una sola fuente. Cualquier otro valor devuelve `invalid_parameter`."
          }
        ],
        "responses": {
          "200": {
            "description": "El resultado de ese sorteo en esa fecha.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LotteryResult"
                }
              }
            }
          },
          "400": {
            "description": "Parámetro ausente o con formato erróneo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_parameter": {
                    "value": {
                      "error": {
                        "code": "invalid_parameter",
                        "message": "The date parameter is required and must be in YYYY-MM-DD format."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falta la clave o no es válida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "missing_key": {
                    "value": {
                      "error": {
                        "code": "missing_key",
                        "message": "The X-Api-Key header is required."
                      }
                    }
                  },
                  "invalid_key": {
                    "value": {
                      "error": {
                        "code": "invalid_key",
                        "message": "The API key is not valid or has been revoked."
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "La fecha es anterior al histórico que cubre tu plan.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "history_not_included": {
                    "value": {
                      "error": {
                        "code": "history_not_included",
                        "message": "Your plan covers the last 30 days (from 2026-07-30)."
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Sorteo inexistente, día sin resultado, o resultado que todavía no alcanza el umbral de entrega.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_draw": {
                    "value": {
                      "error": {
                        "code": "unknown_draw",
                        "message": "Unknown draw identifier."
                      }
                    }
                  },
                  "no_result": {
                    "value": {
                      "error": {
                        "code": "no_result",
                        "message": "No result for that draw on that date."
                      }
                    }
                  },
                  "pending_confirmation": {
                    "value": {
                      "error": {
                        "code": "pending_confirmation",
                        "message": "The result exists but is not confirmed yet. Retry in a few minutes."
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Límite por minuto o cuota mensual agotada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Rate limit of 60 requests per minute exceeded."
                      }
                    }
                  },
                  "quota_exceeded": {
                    "value": {
                      "error": {
                        "code": "quota_exceeded",
                        "message": "Monthly quota of 50000 requests exhausted."
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que incluye tu plan este mes."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Peticiones que te quedan."
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Epoch del primer instante del mes siguiente, en hora de Colombia."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Segundos que esperar: hasta el próximo minuto si el rechazo fue por el límite por minuto, y hasta el cambio de mes si fue por la cuota."
              }
            }
          },
          "500": {
            "description": "Error interno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal_error": {
                    "value": {
                      "error": {
                        "code": "internal_error",
                        "message": "Internal error."
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Cabecera `X-Api-Key`. No hay query param ni Bearer.\n\nSolo guardamos el SHA-256 de tu clave, así que **no podemos reenviártela**. Si la pierdes, se revoca y se emite otra."
      }
    },
    "schemas": {
      "LotteryResult": {
        "type": "object",
        "description": "Un resultado. Las claves comunes salen siempre, con `null` cuando no aplican.",
        "required": [
          "draw",
          "name",
          "category",
          "draw_date",
          "draw_number",
          "winning_number",
          "winning_series",
          "top_prize",
          "secondary_prizes",
          "status",
          "published_at"
        ],
        "properties": {
          "draw": {
            "type": "string",
            "description": "Identificador del sorteo. No se traduce: es un nombre propio.",
            "example": "loteria-del-huila"
          },
          "name": {
            "type": "string",
            "description": "Nombre del sorteo.",
            "example": "Lotería del Huila"
          },
          "category": {
            "type": "string",
            "enum": [
              "loteria",
              "chance",
              "baloto"
            ],
            "description": "Categoría del sorteo. Determina qué campos adicionales trae."
          },
          "draw_date": {
            "type": "string",
            "format": "date",
            "description": "Fecha del sorteo en hora de Colombia.",
            "example": "2026-08-25"
          },
          "draw_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Número de sorteo que le da el operador, cuando lo publica.",
            "example": "4770"
          },
          "winning_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Número ganador. **Cadena, porque el cero a la izquierda es significativo**: \"0207\" no es 207. En Baloto y Revancha es `null`; el resultado está en `balls`.",
            "example": "7401"
          },
          "winning_series": {
            "type": [
              "string",
              "null"
            ],
            "description": "Serie ganadora. Cadena, por el mismo motivo.",
            "example": "168"
          },
          "top_prize": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Premio mayor en pesos colombianos, sin decimales.",
            "example": 2000000000
          },
          "secondary_prizes": {
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SecondaryPrize"
                }
              },
              {
                "type": "null"
              }
            ],
            "description": "Secos, aproximaciones y especiales. `null` si no hay."
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "preliminary",
              "disputed"
            ],
            "description": "`confirmed`: verificado contra la fuente oficial del sorteo.\n\n`preliminary`: pendiente de esa verificación. Puede cambiar.\n\n`disputed`: hay una discrepancia abierta. No lo uses.\n\nPor defecto recibes `confirmed` y `preliminary`, nunca `disputed`."
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "Cuándo entró el resultado en el archivo, con el offset de Colombia. **No es la hora del sorteo y no se actualiza**, ni siquiera al verificarse.",
            "example": "2026-08-25T23:01:02-05:00"
          },
          "fifth_digit": {
            "type": [
              "string",
              "null"
            ],
            "description": "Solo en `chance`: la quinta cifra, cuando el sorteo la tiene.",
            "example": "7"
          },
          "balls": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Solo en `baloto`: las balotas, en orden ascendente.",
            "example": [
              5,
              20,
              30,
              33,
              35,
              41
            ]
          },
          "super_ball": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Solo en `baloto`: la superbalota.",
            "example": 12
          },
          "no_draw": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Solo en los días declarados sin sorteo. Distingue «ese día no se jugó» de «todavía no ha salido»."
          }
        }
      },
      "SecondaryPrize": {
        "type": "object",
        "description": "Un premio menor del plan.",
        "required": [
          "number",
          "series"
        ],
        "properties": {
          "label": {
            "type": "string",
            "description": "El texto literal del operador. Para mostrar, no para decidir.",
            "example": "SECO DE $100 MILLONES"
          },
          "type": {
            "type": "string",
            "enum": [
              "secondary",
              "approximation",
              "special"
            ],
            "description": "La clasificación estable. Úsala tú en el `switch`, no `label`."
          },
          "number": {
            "type": "string",
            "example": "6567"
          },
          "series": {
            "type": "string",
            "example": "028"
          },
          "amount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Importe en pesos.",
            "example": 100000000
          }
        }
      },
      "DrawList": {
        "type": "object",
        "description": "La respuesta de `/v1/draws`.",
        "required": [
          "draws"
        ],
        "properties": {
          "draws": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Draw"
            }
          }
        }
      },
      "ResultsByDate": {
        "type": "object",
        "description": "La respuesta de `/v1/results`. `date` repite la fecha que pediste.",
        "required": [
          "date",
          "results"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "example": "2026-08-25"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LotteryResult"
            }
          }
        }
      },
      "ResultsSeries": {
        "type": "object",
        "description": "La respuesta de la serie histórica. Repite la consulta y añade `total`.",
        "required": [
          "draw",
          "from",
          "to",
          "total",
          "results"
        ],
        "properties": {
          "draw": {
            "type": "string",
            "example": "loteria-del-huila"
          },
          "from": {
            "type": "string",
            "format": "date",
            "example": "2026-08-01"
          },
          "to": {
            "type": "string",
            "format": "date",
            "example": "2026-08-25"
          },
          "total": {
            "type": "integer",
            "description": "Cuántos resultados trae `results`.",
            "example": 4
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LotteryResult"
            }
          }
        }
      },
      "Draw": {
        "type": "object",
        "description": "Un sorteo del catálogo.",
        "required": [
          "draw",
          "name",
          "category",
          "mode",
          "days",
          "time"
        ],
        "properties": {
          "draw": {
            "type": "string",
            "example": "loteria-del-huila"
          },
          "name": {
            "type": "string",
            "example": "Lotería del Huila"
          },
          "category": {
            "type": "string",
            "enum": [
              "loteria",
              "chance",
              "baloto"
            ]
          },
          "mode": {
            "type": [
              "string",
              "null"
            ],
            "description": "Modalidad, cuando el sorteo tiene varias al día.",
            "example": "noche"
          },
          "days": {
            "type": "string",
            "description": "Días en que se juega.",
            "example": "martes"
          },
          "time": {
            "type": "string",
            "description": "Hora local del sorteo.",
            "example": "22:30"
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "Todos los errores tienen esta forma. `code` es estable; `message` puede cambiar de redacción sin previo aviso.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "missing_key",
                  "invalid_key",
                  "rate_limited",
                  "quota_exceeded",
                  "unknown_draw",
                  "history_not_included",
                  "no_result",
                  "pending_confirmation",
                  "invalid_parameter",
                  "range_too_large",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}