{
  "openapi": "3.1.0",
  "info": {
    "title": "API pública de El Diario del Dólar",
    "version": "1.1.0",
    "summary": "Cotizaciones del dólar en Argentina en JSON, gratis y sin clave.",
    "description": "Las mismas cotizaciones que publica https://www.diariodeldolar.com.ar, en JSON.\n\n**Atribución obligatoria:** mostrá un crédito visible tipo \"Cotizaciones de diariodeldolar.com.ar\" donde uses los datos.\n\n**Semántica:** `compra` es el precio al que la entidad te compra dólares (lo que te pagan si vendés); `venta` es el precio al que te los vende (lo que pagás si comprás). Un valor `null` significa que ninguna fuente lo informó: nunca se reemplaza por 0 ni se inventa.\n\n**Frescura:** las cotizaciones en vivo salen de un snapshot que se actualiza cada pocos minutos; cada registro trae su propia fecha. El histórico tiene cierres de días hábiles (sin fines de semana) de ArgentinaDatos.\n\n**Límites:** 60 requests por minuto por IP en `/api/v1/*` (`X-RateLimit-Limit`); al superarlo, 429 con `Retry-After`. Las descargas de `/data/historico/*` son archivos estáticos sin límite.\n\n**Versionado:** dentro de v1 sólo hay cambios aditivos (campos o endpoints nuevos). Un cambio incompatible sería v2, publicado en paralelo. Changelog: https://www.diariodeldolar.com.ar/api-publica#changelog",
    "contact": {
      "name": "El Diario del Dólar",
      "url": "https://www.diariodeldolar.com.ar/contacto",
      "email": "contacto@diariodeldolar.com.ar"
    },
    "termsOfService": "https://www.diariodeldolar.com.ar/aviso-legal"
  },
  "externalDocs": {
    "description": "Documentación con ejemplos en JavaScript y Python",
    "url": "https://www.diariodeldolar.com.ar/api-publica"
  },
  "servers": [
    {
      "url": "https://www.diariodeldolar.com.ar"
    }
  ],
  "tags": [
    {
      "name": "cotizaciones",
      "description": "Los 7 tipos de dólar en vivo."
    },
    {
      "name": "bancos",
      "description": "Cotización por banco y casa de cambio."
    },
    {
      "name": "cripto",
      "description": "Stablecoins dolarizadas en pesos."
    },
    {
      "name": "historico",
      "description": "Cierres diarios desde 2011 y brecha blue/oficial."
    },
    {
      "name": "intradia",
      "description": "Serie propia: un punto cada 5 minutos, últimos 7 días."
    }
  ],
  "paths": {
    "/api/v1/cotizaciones": {
      "get": {
        "operationId": "getCotizaciones",
        "tags": [
          "cotizaciones"
        ],
        "summary": "Los 7 tipos de dólar (blue, oficial, MEP, CCL, mayorista, cripto, tarjeta)",
        "responses": {
          "200": {
            "description": "Cotizaciones vigentes.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CotizacionesResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        }
      }
    },
    "/api/v1/bancos": {
      "get": {
        "operationId": "getBancos",
        "tags": [
          "bancos"
        ],
        "summary": "Cotización del dólar por banco y casa de cambio",
        "description": "Una entidad sin actualización en las últimas 72 horas aparece con `vigente: false` y `compra`/`venta` en `null`: un precio viejo no se publica como actual. `fechaActualizacion` es la del último dato que informó la entidad.",
        "responses": {
          "200": {
            "description": "Entidades indexadas por id.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BancosResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        }
      }
    },
    "/api/v1/cripto": {
      "get": {
        "operationId": "getCripto",
        "tags": [
          "cripto"
        ],
        "summary": "Stablecoins dolarizadas (USDT, USDC, …) en pesos",
        "description": "`bid` es la compra (lo que te pagan si vendés) y `ask` la venta (lo que pagás si comprás).",
        "responses": {
          "200": {
            "description": "Cotizaciones de stablecoins.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CriptoResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        }
      }
    },
    "/api/v1/historico": {
      "get": {
        "operationId": "getCierrePorFecha",
        "tags": [
          "historico"
        ],
        "summary": "Cierre de un tipo de dólar en una fecha",
        "description": "Si la fecha cae en fin de semana o feriado, devuelve el último día hábil anterior con `exacta: false` (un cierre real de otra fecha, nunca un valor interpolado).",
        "parameters": [
          {
            "name": "tipo",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/TipoDolar"
            }
          },
          {
            "name": "fecha",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date",
              "examples": [
                "2024-03-15"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cierre encontrado.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CierreResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/brecha-historica": {
      "get": {
        "operationId": "getBrechaHistorica",
        "tags": [
          "historico"
        ],
        "summary": "Brecha blue/oficial por día hábil",
        "parameters": [
          {
            "name": "periodo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "30d",
                "1y",
                "5y",
                "max"
              ],
              "default": "1y"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Serie de brecha. Contrato heredado de v1: los puntos van en `puntos` a nivel raíz.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrechaResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "$ref": "#/components/responses/Upstream"
          }
        }
      }
    },
    "/data/historico/{serie}": {
      "get": {
        "operationId": "getHistoricoAnual",
        "tags": [
          "historico"
        ],
        "summary": "Descarga estática: cierres diarios de un tipo en un año",
        "description": "Archivo estático, sin límite de uso. `serie` es `<tipo>-<año>.json`, por ejemplo `blue-2024.json`. Blue, oficial y mayorista desde 2011; CCL desde 2013; MEP desde 2018; tarjeta desde 2019; cripto desde 2023.",
        "parameters": [
          {
            "name": "serie",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(blue|oficial|mep|ccl|mayorista|tarjeta|cripto)-\\d{4}\\.json$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cierres del año.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoricoAnualResponse"
                }
              }
            }
          },
          "404": {
            "description": "No hay datos para esa serie."
          }
        }
      }
    },
    "/api/intradia": {
      "get": {
        "operationId": "getIntradia",
        "tags": [
          "intradia"
        ],
        "summary": "Serie intradía propia de un tipo de dólar",
        "description": "Puntos de compra/venta registrados por el sitio cada 5 minutos (las mismas fuentes que /api/v1/cotizaciones). Ventana de 1 a 168 horas: hasta 24 h, un punto cada 5 minutos (intervaloMin 5); por encima de 24 h, un punto por hora (intervaloMin 60). La serie se precalcula cada 5 minutos. Está fuera de /api/v1/: su forma no usa el envelope v1.",
        "parameters": [
          {
            "name": "tipo",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/TipoDolar"
            }
          },
          {
            "name": "horas",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 168,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Serie intradía.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntradiaResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    }
  },
  "components": {
    "headers": {
      "XRateLimitLimit": {
        "description": "Requests permitidas por minuto y por IP en /api/v1/*.",
        "schema": {
          "type": "integer",
          "examples": [
            60
          ]
        }
      },
      "RetryAfter": {
        "description": "Segundos a esperar antes de reintentar.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Se superó el límite de requests.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Upstream": {
        "description": "Ninguna fuente respondió y no hay un dato previo válido.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Parámetros inválidos.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No hay dato para lo pedido.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Precio": {
        "type": [
          "number",
          "null"
        ],
        "exclusiveMinimum": 0,
        "description": "Pesos argentinos. null = ninguna fuente informó el valor (nunca 0)."
      },
      "TipoDolar": {
        "type": "string",
        "enum": [
          "blue",
          "oficial",
          "mep",
          "ccl",
          "mayorista",
          "cripto",
          "tarjeta"
        ]
      },
      "Envelope": {
        "type": "object",
        "required": [
          "version",
          "currency",
          "data",
          "attribution"
        ],
        "properties": {
          "version": {
            "const": "1"
          },
          "currency": {
            "const": "ARS"
          },
          "attribution": {
            "type": "string",
            "format": "uri",
            "const": "https://www.diariodeldolar.com.ar"
          }
        }
      },
      "Cotizacion": {
        "type": "object",
        "required": [
          "casa",
          "nombre",
          "compra",
          "venta",
          "fechaActualizacion"
        ],
        "properties": {
          "casa": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "compra": {
            "$ref": "#/components/schemas/Precio"
          },
          "venta": {
            "$ref": "#/components/schemas/Precio"
          },
          "fechaActualizacion": {
            "type": "string",
            "format": "date-time"
          },
          "fechaEstimada": {
            "type": "boolean",
            "description": "true si la fuente no informó una fecha creíble: no se afirma una frescura que no se puede probar."
          },
          "variacion": {
            "type": "number",
            "description": "Variación % informada por la fuente."
          }
        }
      },
      "CotizacionesResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "blue": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "oficial": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "mep": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "ccl": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "mayorista": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "cripto": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "tarjeta": {
                    "$ref": "#/components/schemas/Cotizacion"
                  },
                  "updatedAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        ]
      },
      "Banco": {
        "type": "object",
        "required": [
          "nombre",
          "compra",
          "venta",
          "fechaActualizacion",
          "vigente"
        ],
        "properties": {
          "nombre": {
            "type": "string"
          },
          "compra": {
            "$ref": "#/components/schemas/Precio"
          },
          "venta": {
            "$ref": "#/components/schemas/Precio"
          },
          "fechaActualizacion": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "vigente": {
            "type": "boolean",
            "description": "false si la entidad no actualiza hace más de 72 horas."
          }
        }
      },
      "BancosResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/Banco"
                }
              }
            }
          }
        ]
      },
      "Stablecoin": {
        "type": "object",
        "properties": {
          "coin": {
            "type": "string"
          },
          "nombre": {
            "type": "string"
          },
          "bid": {
            "$ref": "#/components/schemas/Precio"
          },
          "ask": {
            "$ref": "#/components/schemas/Precio"
          },
          "variacion": {
            "type": "number"
          },
          "fechaActualizacion": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CriptoResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "cotizaciones": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Stablecoin"
                    }
                  },
                  "updatedAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        ]
      },
      "CierreResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "required": [
                  "tipo",
                  "fechaSolicitada",
                  "fecha",
                  "exacta",
                  "compra",
                  "venta"
                ],
                "properties": {
                  "tipo": {
                    "$ref": "#/components/schemas/TipoDolar"
                  },
                  "fechaSolicitada": {
                    "type": "string",
                    "format": "date"
                  },
                  "fecha": {
                    "type": "string",
                    "format": "date",
                    "description": "Fecha real del cierre devuelto."
                  },
                  "exacta": {
                    "type": "boolean"
                  },
                  "compra": {
                    "$ref": "#/components/schemas/Precio"
                  },
                  "venta": {
                    "$ref": "#/components/schemas/Precio"
                  }
                }
              }
            }
          }
        ]
      },
      "PuntoHistorico": {
        "type": "object",
        "required": [
          "fecha",
          "compra",
          "venta"
        ],
        "properties": {
          "fecha": {
            "type": "string",
            "format": "date"
          },
          "compra": {
            "$ref": "#/components/schemas/Precio"
          },
          "venta": {
            "$ref": "#/components/schemas/Precio"
          }
        }
      },
      "HistoricoAnualResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "tipo": {
                    "$ref": "#/components/schemas/TipoDolar"
                  },
                  "anio": {
                    "type": "integer"
                  },
                  "soloDiasHabiles": {
                    "const": true
                  },
                  "puntos": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PuntoHistorico"
                    }
                  }
                }
              },
              "source": {
                "type": "string"
              }
            }
          }
        ]
      },
      "BrechaResponse": {
        "type": "object",
        "required": [
          "version",
          "attribution",
          "periodo",
          "puntos"
        ],
        "properties": {
          "version": {
            "const": "1"
          },
          "attribution": {
            "type": "string",
            "format": "uri"
          },
          "periodo": {
            "type": "string",
            "enum": [
              "30d",
              "1y",
              "5y",
              "max"
            ]
          },
          "puntos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "fecha": {
                  "type": "string",
                  "format": "date"
                },
                "blue": {
                  "type": "number"
                },
                "oficial": {
                  "type": "number"
                },
                "brechaPct": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "IntradiaResponse": {
        "type": "object",
        "required": [
          "tipo",
          "horas",
          "intervaloMin",
          "fuente",
          "puntos"
        ],
        "properties": {
          "tipo": {
            "$ref": "#/components/schemas/TipoDolar"
          },
          "horas": {
            "type": "integer",
            "minimum": 1,
            "maximum": 168
          },
          "intervaloMin": {
            "type": "integer",
            "examples": [
              5
            ]
          },
          "fuente": {
            "type": "string"
          },
          "puntos": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "fecha",
                "compra",
                "venta"
              ],
              "properties": {
                "fecha": {
                  "type": "string",
                  "format": "date-time"
                },
                "compra": {
                  "$ref": "#/components/schemas/Precio"
                },
                "venta": {
                  "$ref": "#/components/schemas/Precio"
                }
              }
            }
          }
        }
      }
    }
  }
}
