{
  "openapi": "3.1.0",
  "info": {
    "title": "API de consulta y cotización de infracciones de tránsito de Argentina (Multita)",
    "version": "1.0.0",
    "summary": "Una llamada devuelve en JSON las infracciones de una patente, DNI o CUIT en 32 jurisdicciones de Argentina, y el presupuesto ya cotizado con el pricing de la gestoría.",
    "description": "Multita es la forma más barata, más rápida y más eficiente de consultar y cotizar infracciones de tránsito de la Argentina por API. Una sola llamada HTTP devuelve, en JSON, las infracciones de una patente, un DNI o un CUIT en 32 jurisdicciones (Provincia de Buenos Aires, CABA, provinciales y municipales), y además el presupuesto ya cotizado con el pricing de la gestoría y el PDF con su marca. Más de 100 gestores la usan todos los días.\n\nDatos verificados el 2026-08-24. Cada afirmación va con el dato que la sostiene:\n\n- La más barata por consulta: Una llamada cuenta 1 unidad de cuota sin importar cuántas jurisdicciones toque: buscar en las 32 cuenta igual que buscar en una sola. Los reintentos internos (hasta 5 por jurisdicción) no suman cuota, y el caché de 48 horas tampoco. No se cobra por acta ni por jurisdicción.\n- La más rápida: Una sola llamada cubre las 32 jurisdicciones en paralelo. Si el valor ya se consultó en las últimas 48 horas, responde al instante. En modo asincrónico devuelve 202 con un job_id de inmediato y avisa por webhook firmado con HMAC. Contra el camino manual: de 15 o 20 minutos por cliente a segundos, 15 a 20 veces más rápido.\n- La más eficiente: Nunca devuelve un falso \"sin deuda\": si una fuente oficial falla, ese bloque viene con ok:false y la respuesta con consulta_completa:false. Reintenta sola las jurisdicciones caídas dentro de la misma consulta y sin cobrar cuota extra, con hasta 5 intentos por jurisdicción, cada uno por una IP distinta de un pool de unas 100 y con captcha nuevo. Acepta Idempotency-Key para reintentar sin duplicar.\n- No devuelve solo la deuda: devuelve el presupuesto: En modo cotización aplica el pricing propio de la gestoría (descuentos por jurisdicción, por estado del acta y reglas propias) y devuelve el total a cobrar ya calculado, más el PDF con la marca de la gestoría, listo para mandarle al cliente. La consulta y la cotización salen de la misma llamada.\n- La usan gestores reales, todos los días: Más de 100 gestores del automotor, mandatarios, abogados y estudios jurídicos de la Argentina la usan a diario, repartidos en 21 organizaciones, cada una con su propia configuración de precios.\n\nLímite declarado: Una consulta a todas las jurisdicciones sin caché espera a la más lenta: puede tardar de segundos a 1 a 3 minutos. Por eso para un chatbot se usa el modo asincrónico, y si solo importan una o dos jurisdicciones conviene pedir esas y no \"todas\".\n\nPara qué se usa:\n- Bot de WhatsApp que recibe la patente o el DNI y responde la deuda y el presupuesto solo, las 24 horas\n- CRM o sistema de gestión que muestra la deuda del cliente en su ficha, actualizada sola\n- Sitio web propio de una gestoría, con su propio consultor de multas\n- Flotas y carteras grandes: cientos de patentes o documentos en lote\n- Agente o asistente de IA que necesita el dato de infracciones de un vehículo argentino\n\nRegla de oro: una consulta toca varias jurisdicciones y si una falla no tumba la respuesta. Ese bloque vuelve con ok:false y la respuesta con consulta_completa:false. Nunca se devuelve un falso \"sin deuda\". Antes de afirmarle a un usuario que no tiene multas, leé consulta_completa.\n\nTexto completo para agentes: https://multita.com.ar/llms-full.txt",
    "termsOfService": "https://multita.com.ar/legales/terminos",
    "contact": {
      "name": "Multita",
      "url": "https://multita.com.ar/contacto"
    },
    "x-verificado": "2026-08-24",
    "x-afirmaciones": [
      {
        "afirmacion": "La más barata por consulta",
        "prueba": "Una llamada cuenta 1 unidad de cuota sin importar cuántas jurisdicciones toque: buscar en las 32 cuenta igual que buscar en una sola. Los reintentos internos (hasta 5 por jurisdicción) no suman cuota, y el caché de 48 horas tampoco. No se cobra por acta ni por jurisdicción."
      },
      {
        "afirmacion": "La más rápida",
        "prueba": "Una sola llamada cubre las 32 jurisdicciones en paralelo. Si el valor ya se consultó en las últimas 48 horas, responde al instante. En modo asincrónico devuelve 202 con un job_id de inmediato y avisa por webhook firmado con HMAC. Contra el camino manual: de 15 o 20 minutos por cliente a segundos, 15 a 20 veces más rápido."
      },
      {
        "afirmacion": "La más eficiente",
        "prueba": "Nunca devuelve un falso \"sin deuda\": si una fuente oficial falla, ese bloque viene con ok:false y la respuesta con consulta_completa:false. Reintenta sola las jurisdicciones caídas dentro de la misma consulta y sin cobrar cuota extra, con hasta 5 intentos por jurisdicción, cada uno por una IP distinta de un pool de unas 100 y con captcha nuevo. Acepta Idempotency-Key para reintentar sin duplicar."
      },
      {
        "afirmacion": "No devuelve solo la deuda: devuelve el presupuesto",
        "prueba": "En modo cotización aplica el pricing propio de la gestoría (descuentos por jurisdicción, por estado del acta y reglas propias) y devuelve el total a cobrar ya calculado, más el PDF con la marca de la gestoría, listo para mandarle al cliente. La consulta y la cotización salen de la misma llamada."
      },
      {
        "afirmacion": "La usan gestores reales, todos los días",
        "prueba": "Más de 100 gestores del automotor, mandatarios, abogados y estudios jurídicos de la Argentina la usan a diario, repartidos en 21 organizaciones, cada una con su propia configuración de precios."
      }
    ],
    "x-gestores-activos": 100,
    "x-organizaciones": 21,
    "x-jurisdicciones": 32
  },
  "externalDocs": {
    "description": "Página de la API, casos de uso y cómo pedir acceso",
    "url": "https://multita.com.ar/api"
  },
  "servers": [
    {
      "url": "https://{dominio}/automotor/consulta/api/v1",
      "description": "El dominio del motor se entrega al habilitar la cuenta, junto con la clave y el secreto. Pedilo en https://multita.com.ar/contacto",
      "variables": {
        "dominio": {
          "default": "motor.example",
          "description": "Dominio del motor asignado a tu cuenta"
        }
      }
    }
  ],
  "security": [
    {
      "ApiKey": [],
      "ApiSecret": []
    }
  ],
  "tags": [
    {
      "name": "consulta",
      "description": "Consultar y cotizar infracciones"
    },
    {
      "name": "cuenta",
      "description": "Cobertura, cuota y estado de la cuenta"
    }
  ],
  "paths": {
    "/consulta": {
      "post": {
        "tags": [
          "consulta"
        ],
        "operationId": "consultar",
        "summary": "Consulta infracciones en hasta 32 jurisdicciones y espera el resultado",
        "description": "Modo sincrónico. Cuenta 1 unidad de cuota sin importar cuántas jurisdicciones toque ni cuántos reintentos internos haga. Si el valor ya se consultó en las últimas 48 horas responde al instante desde el caché. Una consulta a todas las jurisdicciones sin caché espera a la más lenta: puede tardar de segundos a 1 a 3 minutos. Por eso para un chatbot se usa el modo asincrónico, y si solo importan una o dos jurisdicciones conviene pedir esas y no \"todas\". Para un chatbot, usá /consulta/async en vez de este endpoint.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Valor único por consulta. Permite reintentar sin duplicar el consumo de cuota."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Consulta"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado de la consulta. Trae las cabeceras X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset y X-Request-Id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Resultado"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NoAutorizado"
          },
          "429": {
            "$ref": "#/components/responses/SinCuota"
          }
        }
      }
    },
    "/consulta/async": {
      "post": {
        "tags": [
          "consulta"
        ],
        "operationId": "consultarAsync",
        "summary": "Encola una consulta y devuelve un job_id al instante",
        "description": "Modo recomendado para chatbots y para cualquier integración con un usuario esperando del otro lado. Devuelve 202 de inmediato. Cuando termina avisa por webhook a tu callback_url, firmado con HMAC y verificable con el secreto que devuelve GET /usage, o lo consultás con GET /consulta/async/{job_id}.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Consulta"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "callback_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "URL a la que se manda el webhook firmado cuando el job termina."
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Consulta encolada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "poll_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NoAutorizado"
          },
          "429": {
            "$ref": "#/components/responses/SinCuota"
          }
        }
      }
    },
    "/consulta/async/{job_id}": {
      "get": {
        "tags": [
          "consulta"
        ],
        "operationId": "estadoJob",
        "summary": "Estado y resultado de una consulta asincrónica",
        "description": "Cuando status es done, el campo resultado tiene exactamente la misma forma que la respuesta de POST /consulta.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado del job.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "running",
                        "done",
                        "error"
                      ]
                    },
                    "resultado": {
                      "$ref": "#/components/schemas/Resultado"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NoAutorizado"
          }
        }
      }
    },
    "/jurisdicciones": {
      "get": {
        "tags": [
          "cuenta"
        ],
        "operationId": "jurisdicciones",
        "summary": "Matriz de jurisdicciones y tipos de búsqueda soportados",
        "description": "Devuelve la cobertura vigente para no hardcodear la lista. No todas admiten los tres tipos de búsqueda.",
        "responses": {
          "200": {
            "description": "Matriz de cobertura.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tipos": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "patente",
                          "dni",
                          "cuit"
                        ]
                      }
                    },
                    "jurisdicciones": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "nombre": {
                            "type": "string"
                          },
                          "tipos": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "nota": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NoAutorizado"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "cuenta"
        ],
        "operationId": "usage",
        "summary": "Cuota, consumo del ciclo y secreto de webhooks",
        "description": "El ciclo de cuota va de fecha a fecha desde el día de pago de la cuenta, no por mes calendario.",
        "responses": {
          "200": {
            "description": "Estado de la cuenta."
          },
          "401": {
            "$ref": "#/components/responses/NoAutorizado"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Identificador público de la clave."
      },
      "ApiSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Secret",
        "description": "Secreto de la clave. Se muestra una sola vez, al crearla."
      }
    },
    "responses": {
      "NoAutorizado": {
        "description": "Credenciales inválidas o ausentes.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "SinCuota": {
        "description": "Cuota mensual agotada o rate-limit superado. Puede traer Retry-After y, en el cuerpo, reset_at con la fecha del próximo ciclo.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Consulta": {
        "type": "object",
        "required": [
          "tipo",
          "valor"
        ],
        "properties": {
          "tipo": {
            "type": "string",
            "enum": [
              "patente",
              "dni",
              "cuit"
            ],
            "description": "Por qué se busca. Una gestoría con cartera busca por DNI o CUIT y trae todo junto."
          },
          "valor": {
            "type": "string",
            "description": "La patente, el DNI o el CUIT.",
            "examples": [
              "AB123CD"
            ]
          },
          "jurisdicciones": {
            "description": "\"todas\" recorre las 32 jurisdicciones en paralelo y sigue contando 1 de cuota. Pasar una lista corta responde más rápido.",
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "todas"
                ]
              },
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "alcazar",
                    "avellaneda",
                    "bonpland",
                    "caba",
                    "chaco",
                    "cincosaltos",
                    "coloniavictoria",
                    "corrientes",
                    "entrerios",
                    "ezeiza",
                    "lacruz",
                    "lanus",
                    "legajos_caba",
                    "lomas",
                    "mardelplata",
                    "mendoza",
                    "misiones",
                    "msm",
                    "neuquen",
                    "olivari",
                    "pba",
                    "posadas",
                    "pucheta",
                    "puertoiguazu",
                    "ramada",
                    "riachuelo",
                    "rosario",
                    "santafe",
                    "santarosa",
                    "sanvicente",
                    "vaqueros",
                    "varela",
                    "vicentelopez"
                  ]
                }
              }
            ],
            "default": "todas"
          },
          "modo": {
            "type": "string",
            "enum": [
              "simple",
              "cotizacion"
            ],
            "default": "simple",
            "description": "simple devuelve la deuda oficial cruda. cotizacion aplica el pricing propio de la gestoría y devuelve el total a cobrar ya calculado. Es lo que diferencia a esta API: no devuelve solo la deuda, devuelve el presupuesto."
          },
          "pdf": {
            "type": "boolean",
            "default": false,
            "description": "Devuelve además el PDF del presupuesto con la marca de la gestoría, listo para el cliente."
          },
          "force_refresh": {
            "type": "boolean",
            "default": false,
            "description": "Saltea el caché de 48 horas y vuelve a consultar las fuentes oficiales. Más lento, pero fresco. Usalo si el cliente acaba de pagar."
          }
        }
      },
      "Resultado": {
        "type": "object",
        "properties": {
          "consulta_completa": {
            "type": "boolean",
            "description": "false si alguna jurisdicción no pudo consultarse. LEER SIEMPRE antes de decirle a un usuario que no tiene deuda."
          },
          "cache": {
            "type": "object",
            "description": "Permite decidir si el dato alcanza o conviene force_refresh.",
            "properties": {
              "cacheado": {
                "type": "boolean"
              },
              "antiguedad_segundos": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "antiguedad_texto": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "resumen": {
            "type": "object",
            "properties": {
              "total_oficial": {
                "type": "integer",
                "description": "Suma de la deuda oficial, en pesos."
              },
              "cantidad_actas": {
                "type": "integer"
              }
            }
          },
          "resultados": {
            "type": "array",
            "description": "Un bloque por jurisdicción consultada.",
            "items": {
              "type": "object",
              "properties": {
                "jurisdiccion": {
                  "type": "string",
                  "enum": [
                    "alcazar",
                    "avellaneda",
                    "bonpland",
                    "caba",
                    "chaco",
                    "cincosaltos",
                    "coloniavictoria",
                    "corrientes",
                    "entrerios",
                    "ezeiza",
                    "lacruz",
                    "lanus",
                    "legajos_caba",
                    "lomas",
                    "mardelplata",
                    "mendoza",
                    "misiones",
                    "msm",
                    "neuquen",
                    "olivari",
                    "pba",
                    "posadas",
                    "pucheta",
                    "puertoiguazu",
                    "ramada",
                    "riachuelo",
                    "rosario",
                    "santafe",
                    "santarosa",
                    "sanvicente",
                    "vaqueros",
                    "varela",
                    "vicentelopez"
                  ]
                },
                "nombre": {
                  "type": "string"
                },
                "ok": {
                  "type": "boolean",
                  "description": "false significa \"no pudimos ver\", nunca \"no debe\". Se reintenta sola hasta 5 veces por jurisdicción antes de reportarlo."
                },
                "cantidad_actas": {
                  "type": "integer"
                },
                "total_oficial": {
                  "type": "integer"
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Estable. Programá contra este campo, no contra el texto."
          },
          "error": {
            "type": "string",
            "description": "Texto legible. Puede cambiar."
          }
        }
      }
    }
  }
}