{
  "openapi": "3.1.0",
  "info": {
    "title": "Alimenta Data API",
    "version": "1.0.0",
    "description": "Prețuri ANRE observate, numai citire. Nu garantează prețul sau stocul la pompă în timp real."
  },
  "servers": [
    {
      "url": "https://alimenta.md"
    }
  ],
  "paths": {
    "/api/v1/stations": {
      "get": {
        "summary": "Listează stațiile active și prețurile publicate",
        "operationId": "listStations",
        "security": [
          {
            "BearerKey": []
          }
        ],
        "parameters": [
          {
            "name": "fuel",
            "in": "query",
            "description": "Returnează numai stațiile cu preț publicat pentru produsul ales.",
            "schema": {
              "type": "string",
              "enum": [
                "gasoline95",
                "diesel",
                "lpg"
              ]
            }
          },
          {
            "name": "district",
            "in": "query",
            "description": "Denumirea exactă a raionului/localității în catalog.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Pagina de rezultate, ordonată stabil după ID.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Numărul maxim de stații pe pagină.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stații, paginare, sursă, plafonul e-Carburanți și, dacă există, plafonul publicat de ANRE pentru o dată ulterioară.",
            "headers": {
              "X-RateLimit-Remaining-Minute": {
                "description": "Cereri rămase în minutul UTC curent.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining-Day": {
                "description": "Cereri rămase în ziua UTC curentă.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StationPage"
                }
              }
            }
          },
          "400": {
            "description": "Parametru invalid sau duplicat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Cheie lipsă, invalidă sau revocată.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Cota pe minut sau pe zi a fost depășită.",
            "headers": {
              "Retry-After": {
                "description": "Secunde până la următoarea fereastră.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Cheie emisă manual, cu prefix alim_live_; nu o include în URL sau în clientul public."
      }
    },
    "schemas": {
      "PriceObservation": {
        "type": "object",
        "required": [
          "value",
          "currency",
          "unit",
          "source",
          "source_url",
          "observed_at",
          "effective_at",
          "pump_verified"
        ],
        "properties": {
          "value": {
            "type": "number",
            "description": "MDL per litru, conform sursei."
          },
          "currency": {
            "type": "string",
            "const": "MDL"
          },
          "unit": {
            "type": "string",
            "const": "litre"
          },
          "source": {
            "type": "string"
          },
          "source_url": {
            "type": "string",
            "format": "uri"
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "effective_at": {
            "type": "null",
            "description": "Ora schimbării la pompă nu este disponibilă."
          },
          "pump_verified": {
            "type": "boolean",
            "const": false
          }
        }
      },
      "Station": {
        "type": "object",
        "required": [
          "id",
          "name",
          "operator",
          "address",
          "district",
          "latitude",
          "longitude",
          "prices"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "operator": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "district": {
            "type": "string"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "prices": {
            "type": "object",
            "description": "Produsele fără preț publicat lipsesc; lipsa nu indică stoc zero.",
            "properties": {
              "gasoline95": {
                "$ref": "#/components/schemas/PriceObservation"
              },
              "diesel": {
                "$ref": "#/components/schemas/PriceObservation"
              },
              "lpg": {
                "$ref": "#/components/schemas/PriceObservation"
              }
            },
            "additionalProperties": false
          }
        }
      },
      "Source": {
        "type": "object",
        "required": [
          "name",
          "url",
          "observed_at",
          "source_updated_at",
          "note"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "source_updated_at": {
            "type": "null"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "StationPage": {
        "type": "object",
        "required": [
          "data",
          "pagination",
          "source",
          "national_price_caps"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Station"
            }
          },
          "pagination": {
            "type": "object",
            "required": [
              "page",
              "limit",
              "total",
              "has_next"
            ],
            "properties": {
              "page": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              },
              "has_next": {
                "type": "boolean"
              }
            }
          },
          "source": {
            "$ref": "#/components/schemas/Source"
          },
          "national_price_caps": {
            "type": "object",
            "description": "Plafon ANRE național, separat de prețul stației.",
            "required": [
              "source_url",
              "retrieved_at",
              "effective_date",
              "prices",
              "currency",
              "unit"
            ],
            "properties": {
              "source_url": {
                "type": "string",
                "format": "uri"
              },
              "retrieved_at": {
                "type": "string",
                "format": "date-time"
              },
              "effective_date": {
                "type": "string",
                "format": "date"
              },
              "prices": {
                "type": "object",
                "properties": {
                  "gasoline95": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "diesel": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "currency": {
                "type": "string",
                "const": "MDL"
              },
              "unit": {
                "type": "string",
                "const": "l"
              }
            }
          },
          "published_price_caps": {
            "type": "object",
            "description": "Plafonul publicat pe pagina oficială ANRE pentru o dată de aplicare mai nouă decât plafonul e-Carburanți. Câmp opțional; nu reprezintă prețul practicat azi de stații.",
            "required": [
              "source_url",
              "retrieved_at",
              "effective_date",
              "prices",
              "currency",
              "unit",
              "published_date"
            ],
            "properties": {
              "source_url": {
                "type": "string",
                "format": "uri"
              },
              "retrieved_at": {
                "type": "string",
                "format": "date-time"
              },
              "effective_date": {
                "type": "string",
                "format": "date"
              },
              "prices": {
                "type": "object",
                "properties": {
                  "gasoline95": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "diesel": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              },
              "currency": {
                "type": "string",
                "const": "MDL"
              },
              "unit": {
                "type": "string",
                "const": "l"
              },
              "published_date": {
                "type": "string",
                "format": "date"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
