{"openapi":"3.1.0","info":{"title":"herramientas.lat API","version":"1.0.0","description":"API pública de herramientas.lat. Autenticación con API keys (`Authorization: Bearer hl_…`). Scopes por herramienta."},"servers":[{"url":"https://www.herramientas.lat/api/v1","description":"Producción v1","x-fern-server-name":"Production"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"hl_…","description":"Creá keys en /cuenta/api con scopes qr:read y/o qr:write"}},"schemas":{"QrDesign":{"type":"object","description":"Opciones visuales (mismas que el generador web).","properties":{"dotsStyle":{"type":"string","enum":["square","dots","rounded","extra-rounded","classy","classy-rounded"]},"cornerSquare":{"type":"string","enum":["square","dot","extra-rounded","classy","classy-rounded"]},"cornerDot":{"type":"string","enum":["square","dot","extra-rounded","classy","classy-rounded"]},"isGradient":{"type":"boolean"},"gradientType":{"type":"string","enum":["linear","radial"]},"gradientRotation":{"type":"number","minimum":0,"maximum":360},"color1":{"type":"string"},"color2":{"type":"string"},"bgColor":{"type":"string"},"bgTransparent":{"type":"boolean"},"customEyeColors":{"type":"boolean"},"eyeColor":{"type":"string"},"presetLogo":{"type":"string"},"customLogoUrl":{"type":["string","null"],"description":"Data URL de imagen o null"},"logoSize":{"type":"number","minimum":0.1,"maximum":0.5},"logoMargin":{"type":"number"},"hideDotsBehindLogo":{"type":"boolean"},"frameStyle":{"type":"string","enum":["none","bottom-banner","phone","badge"]},"frameText":{"type":"string"},"frameColor":{"type":"string"},"frameTextColor":{"type":"string"},"errorCorrectionLevel":{"type":"string","enum":["L","M","Q","H"]},"resolution":{"type":"integer","minimum":500,"maximum":2500}}},"QrItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"code":{"type":"string"},"contentType":{"type":"string","enum":["url","wifi","vcard","whatsapp","text","email"]},"payload":{"type":"string"},"active":{"type":"boolean"},"design":{"$ref":"#/components/schemas/QrDesign"},"shortUrl":{"type":"string","format":"uri"},"scanCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreateQrRequest":{"type":"object","required":["title"],"description":"Mismas opciones que el studio. Podés mandar `payload` crudo o campos tipados (`url`, `wifiSsid`, …). El diseño puede ir plano o en `design`.","properties":{"title":{"type":"string","maxLength":120},"tracking":{"type":"boolean","default":true,"description":"Equivale a “Activar seguimiento” del generador. En este endpoint debe ser true (o omitirse): crea link corto `/r/{code}` y métricas."},"contentType":{"type":"string","default":"url","enum":["url","wifi","vcard","whatsapp","text","email"]},"payload":{"type":"string","maxLength":4000,"description":"Opcional. Si falta, se calcula desde contentType + campos tipados."},"url":{"type":"string"},"wifiSsid":{"type":"string"},"wifiPass":{"type":"string"},"wifiEnc":{"type":"string","enum":["WPA","WEP","nopass"]},"vcardFirstName":{"type":"string"},"vcardLastName":{"type":"string"},"vcardPhone":{"type":"string"},"vcardEmail":{"type":"string"},"vcardOrg":{"type":"string"},"vcardWeb":{"type":"string"},"waNumber":{"type":"string"},"waMessage":{"type":"string"},"text":{"type":"string"},"emailTo":{"type":"string"},"emailSubject":{"type":"string"},"emailBody":{"type":"string"},"design":{"$ref":"#/components/schemas/QrDesign"},"dotsStyle":{"type":"string"},"cornerSquare":{"type":"string"},"cornerDot":{"type":"string"},"isGradient":{"type":"boolean"},"gradientType":{"type":"string"},"gradientRotation":{"type":"number"},"color1":{"type":"string"},"color2":{"type":"string"},"bgColor":{"type":"string"},"bgTransparent":{"type":"boolean"},"customEyeColors":{"type":"boolean"},"eyeColor":{"type":"string"},"presetLogo":{"type":"string"},"customLogoUrl":{"type":["string","null"]},"logoSize":{"type":"number"},"logoMargin":{"type":"number"},"hideDotsBehindLogo":{"type":"boolean"},"frameStyle":{"type":"string"},"frameText":{"type":"string"},"frameColor":{"type":"string"},"frameTextColor":{"type":"string"},"errorCorrectionLevel":{"type":"string"},"resolution":{"type":"integer"}}},"Error":{"type":"object","properties":{"error":{"type":"string"}}}}},"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"QR","description":"Códigos QR con seguimiento. Creá, pausá, eliminá y consultá métricas."}],"paths":{"/qr":{"get":{"tags":["QR"],"summary":"Listar QRs","description":"Requiere scope `qr:read`.","responses":{"200":{"description":"Lista","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/QrItem"}}}}}}},"401":{"description":"No autorizado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["QR"],"summary":"Crear QR con seguimiento","description":"Requiere `qr:write`. Acepta todas las opciones del generador web. El QR encodea el link corto `/r/{code}`; el destino real queda en `payload`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQrRequest"},"example":{"title":"Menú del local","tracking":true,"contentType":"url","url":"https://ejemplo.com/menu","dotsStyle":"rounded","cornerSquare":"extra-rounded","cornerDot":"dot","isGradient":true,"gradientType":"linear","gradientRotation":45,"color1":"#1d4ed8","color2":"#7c3aed","bgColor":"#ffffff","bgTransparent":false,"customEyeColors":false,"eyeColor":"#000000","presetLogo":"none","customLogoUrl":null,"logoSize":0.3,"logoMargin":4,"hideDotsBehindLogo":true,"frameStyle":"bottom-banner","frameText":"ESCANÉAME","frameColor":"#1d4ed8","frameTextColor":"#ffffff","errorCorrectionLevel":"H","resolution":1000}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"type":"object","properties":{"item":{"$ref":"#/components/schemas/QrItem"}}}}}},"403":{"description":"Scope insuficiente","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/qr/{id}":{"get":{"tags":["QR"],"summary":"Obtener QR","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"item":{"$ref":"#/components/schemas/QrItem"}}}}}},"404":{"description":"No encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["QR"],"summary":"Actualizar / pausar QR","description":"Usá `active: false` para pausar. También podés actualizar contenido y diseño. Requiere `qr:write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQrRequest"},"example":{"active":false}}}},"responses":{"200":{"description":"Actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"item":{"$ref":"#/components/schemas/QrItem"}}}}}}}},"delete":{"tags":["QR"],"summary":"Eliminar QR","description":"Requiere `qr:write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Eliminado","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}}}}},"/qr/{id}/stats":{"get":{"tags":["QR"],"summary":"Métricas de escaneos","description":"Requiere `qr:read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"days","in":"query","schema":{"type":"integer","default":14,"minimum":1,"maximum":90}}],"responses":{"200":{"description":"Totales, serie diaria y escaneos recientes"}}}}}}