{"openapi":"3.0.3","info":{"title":"DigitALL API","version":"1.0.0","description":"Plataforma colombiana de consulta de antecedentes. Consulta 18 fuentes (12 colombianas + 6 listas internacionales de sanciones) con una sola llamada API. Resolucion automatica de CAPTCHA, rotacion de proxy, y recoleccion de evidencia.\n\n## 🚀 Demo Rapido — Verificacion Financiera\nUse **`POST /query/batch`** con las 14 fuentes de seguridad financiera:\n\n```bash\ncurl -X POST /api/v1/query/batch \\\n  -H \"Authorization: Bearer <TOKEN>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"sources\": [\"policia\",\"procuraduria\",\"contraloria\",\"rama-judicial\",\"peps\",\"defuncion\",\"inpec\",\"interpol\",\"ofac\",\"us-non-sdn\",\"us-csl\",\"eu-csl\",\"uk-csl\",\"un-csl\"],\n    \"documentType\": \"cedula\",\n    \"documentNumber\": \"1020741686\"\n  }'\n```\n\n**Fuentes incluidas (14):** Policia, Procuraduria, Contraloria, Rama Judicial, PEPs, Defuncion, INPEC, INTERPOL + 6 listas de sanciones.\n\n**Excluidas (3):** Registro Civil, ADRES, SIMIT (no relevantes para seguridad financiera).\n\nConsulte resultados con `GET /query/{queryId}`.\n\n---\n\n## Autenticacion (JWT)\nTodos los endpoints requieren un JWT Bearer token:\n```\nAuthorization: Bearer <JWT_ACCESS_TOKEN>\n```\nObtenga su token con `POST /auth/login` usando email + contrasena. El token expira en 2h — use `POST /auth/refresh` para renovar.\n\n**Roles:** `super_admin` (todo), `admin` (gestiona su cuenta), `manager` (ve consultas de su cuenta), `user` (solo sus consultas)\n\n## Patron Asincrono de Consulta\n1. Enviar consulta → recibir `queryId`\n2. Consultar `GET /query/{queryId}` hasta que `status` sea `completed`, `partial`, o `failed`\n3. Resultados indexados por nombre de fuente\n\n## Fuentes\n**Colombianas (11):** Policia, Contraloria, Procuraduria, PEPs, Defuncion, Rama Judicial, Registro Civil, ADRES, SIMIT, INTERPOL, INPEC\n\n**Sanciones Internacionales (6, via Watchman):** OFAC SDN, Non-SDN, US CSL, EU CSL, UK CSL, UN CSL"},"servers":[{"url":"https://api.digitall.io/api/v1","description":"Production (api.digitall.io)"},{"url":"/api/v1","description":"Current host (auto-detect)"}],"tags":[{"name":"Auth","description":"JWT authentication (login, refresh, password reset)"},{"name":"Admin","description":"Account, user, pricing, and consumption management"},{"name":"Query","description":"Background check queries"},{"name":"Sources","description":"Available sources and capabilities"},{"name":"Evidence","description":"Screenshots, network logs, and documents"},{"name":"Metrics","description":"Platform metrics and monitoring (super_admin only)"},{"name":"Health","description":"Server and proxy health monitoring"},{"name":"Learn","description":"AI learning mode (admin only)"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT access token obtained from POST /auth/login"}},"schemas":{"SourceName":{"type":"string","enum":["policia","contraloria","procuraduria","ofac","us-non-sdn","us-csl","eu-csl","uk-csl","un-csl","peps","defuncion","rama-judicial","registro-civil","adres","simit","interpol","inpec","rndc"],"description":"Available source identifiers"},"DocumentType":{"type":"string","enum":["cedula","pasaporte","nit","cedula_extranjeria"],"description":"Document type identifiers"},"QueryStatus":{"type":"string","enum":["processing","completed","partial","failed"]},"ResultStatus":{"type":"string","enum":["found","clean","error","timeout","unavailable"]},"SourceResult":{"type":"object","properties":{"source":{"type":"string"},"status":{"$ref":"#/components/schemas/ResultStatus"},"data":{"type":"object","description":"Source-specific response data"},"duration":{"type":"number","description":"Duration in milliseconds"},"timestamp":{"type":"string","format":"date-time"},"error":{"type":"string","description":"Error message (if status is error)"},"connectionType":{"type":"string","enum":["proxy","direct"]}}},"QueryResult":{"type":"object","properties":{"queryId":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/QueryStatus"},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"duration":{"type":"number","description":"Total duration in ms"},"input":{"type":"object","properties":{"documentType":{"$ref":"#/components/schemas/DocumentType"},"documentNumber":{"type":"string"},"fullName":{"type":"string"}}},"results":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SourceResult"},"description":"Results keyed by source name"}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"error":{"type":"string","example":"Validation error"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}}}},"security":[{"BearerAuth":[]}],"paths":{"/auth/login":{"post":{"tags":["Auth"],"summary":"Login with email + password","description":"Returns JWT access token (2h), refresh token (7d), and user profile.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":1}}},"example":{"email":"andres@digitall.io","password":"your-password"}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"fullName":{"type":"string"},"role":{"type":"string","enum":["super_admin","admin","manager","user"]},"accountId":{"type":"string","format":"uuid"},"accountName":{"type":"string"},"allowedSources":{"type":"array","items":{"type":"string"}}}}}}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/refresh":{"post":{"tags":["Auth"],"summary":"Refresh access token","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string"}}}}}},"responses":{"200":{"description":"New access token","content":{"application/json":{"schema":{"type":"object","properties":{"accessToken":{"type":"string"}}}}}},"401":{"description":"Invalid refresh token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/forgot-password":{"post":{"tags":["Auth"],"summary":"Request password reset email","description":"Sends a reset link via email. Rate limited to 3 per hour per email.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Reset link sent (if email exists)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"429":{"description":"Rate limit exceeded"}}}},"/auth/reset-password":{"post":{"tags":["Auth"],"summary":"Reset password with token","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","password"],"properties":{"token":{"type":"string"},"password":{"type":"string","minLength":8}}}}}},"responses":{"200":{"description":"Password reset successful"},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/me":{"get":{"tags":["Auth"],"summary":"Get current user profile","description":"Returns user info, account, allowed sources, and pricing (if manager+).","responses":{"200":{"description":"User profile"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/change-password":{"post":{"tags":["Auth"],"summary":"Change current password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["currentPassword","newPassword"],"properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string","minLength":8}}}}}},"responses":{"200":{"description":"Password changed"},"401":{"description":"Current password incorrect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/admin/accounts":{"get":{"tags":["Admin"],"summary":"List accounts (super_admin)","responses":{"200":{"description":"Accounts list"},"403":{"description":"Forbidden"}}},"post":{"tags":["Admin"],"summary":"Create account (super_admin)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","slug","allowedSources"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"allowedSources":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Account created"},"403":{"description":"Forbidden"},"409":{"description":"Slug already exists"}}}},"/admin/accounts/{id}":{"get":{"tags":["Admin"],"summary":"Get account details","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Account with users and pricing"},"403":{"description":"Forbidden"},"404":{"description":"Not found"}}},"put":{"tags":["Admin"],"summary":"Update account (super_admin)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"allowedSources":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Account updated"},"403":{"description":"Forbidden"}}}},"/admin/users":{"get":{"tags":["Admin"],"summary":"List users (scoped by role)","responses":{"200":{"description":"Users list"}}},"post":{"tags":["Admin"],"summary":"Create user","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","fullName","accountId","role"],"properties":{"email":{"type":"string"},"fullName":{"type":"string"},"accountId":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["admin","manager","user"]},"password":{"type":"string"}}}}}},"responses":{"201":{"description":"User created (includes tempPassword if auto-generated)"},"409":{"description":"Email already exists"}}}},"/admin/users/{id}":{"put":{"tags":["Admin"],"summary":"Update user","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fullName":{"type":"string"},"role":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"User updated"}}}},"/admin/users/{id}/reset-password":{"post":{"tags":["Admin"],"summary":"Admin reset user password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Returns temp password"}}}},"/admin/accounts/{id}/pricing":{"get":{"tags":["Admin"],"summary":"Get account pricing","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Pricing per source"}}},"put":{"tags":["Admin"],"summary":"Set account pricing (super_admin)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"pricePerQuery":{"type":"number"}}}}}}},"responses":{"200":{"description":"Pricing updated"}}}},"/admin/consumption":{"get":{"tags":["Admin"],"summary":"Query consumption data","description":"Total queries, cost by source, by user. Scoped by role.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":168}},{"name":"accountId","in":"query","schema":{"type":"string","format":"uuid"},"description":"super_admin only"}],"responses":{"200":{"description":"Consumption data"}}}},"/admin/consumption/export":{"get":{"tags":["Admin"],"summary":"Export consumption as CSV","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":168}},{"name":"accountId","in":"query","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"CSV file","content":{"text/csv":{"schema":{"type":"string"}}}}}}},"/query":{"post":{"tags":["Query"],"summary":"Single source query","description":"Execute a background check against a single source. Returns immediately with a queryId; poll `GET /query/{queryId}` for results.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source","documentType","documentNumber"],"properties":{"source":{"$ref":"#/components/schemas/SourceName"},"documentType":{"$ref":"#/components/schemas/DocumentType"},"documentNumber":{"type":"string","minLength":1,"maxLength":20},"fullName":{"type":"string","description":"Required for some sources (interpol, rama-judicial, sanctions)"},"responseMode":{"type":"string","enum":["json","evidence"],"default":"json"}}},"example":{"source":"policia","documentType":"cedula","documentNumber":"1020741686","responseMode":"json"}}}},"responses":{"202":{"description":"Query accepted","content":{"application/json":{"schema":{"type":"object","properties":{"queryId":{"type":"string","format":"uuid"},"status":{"type":"string","example":"processing"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/query/batch":{"post":{"tags":["Query"],"summary":"Batch query (multiple sources)","description":"Execute a background check across 1–18 sources in parallel. Returns immediately; poll `GET /query/{queryId}` for results.\n\n**🚀 Demo — Verificacion Financiera (14 fuentes):**\nPolicia, Procuraduria, Contraloria, Rama Judicial, PEPs, Defuncion, INPEC, INTERPOL + 6 listas de sanciones.\nExcluidas: Registro Civil, ADRES, SIMIT.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sources","documentType","documentNumber"],"properties":{"sources":{"type":"array","items":{"$ref":"#/components/schemas/SourceName"},"minItems":1,"maxItems":17},"documentType":{"$ref":"#/components/schemas/DocumentType"},"documentNumber":{"type":"string","minLength":1,"maxLength":20},"fullName":{"type":"string"},"responseMode":{"type":"string","enum":["json","evidence"],"default":"json"}}},"examples":{"demo-financial":{"summary":"🚀 Demo — Verificacion Financiera (14 fuentes)","value":{"sources":["policia","procuraduria","contraloria","rama-judicial","peps","defuncion","inpec","interpol","ofac","us-non-sdn","us-csl","eu-csl","uk-csl","un-csl"],"documentType":"cedula","documentNumber":"1020741686"}},"custom":{"summary":"Consulta personalizada (seleccionar fuentes)","value":{"sources":["policia","peps","contraloria","ofac"],"documentType":"cedula","documentNumber":"1020741686","fullName":"ORLANDO ANDRES FAJARDO TEJADA"}}}}}},"responses":{"202":{"description":"Batch query accepted","content":{"application/json":{"schema":{"type":"object","properties":{"queryId":{"type":"string","format":"uuid"},"status":{"type":"string","example":"processing"},"sources":{"type":"number","description":"Number of sources queried"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/query/{queryId}":{"get":{"tags":["Query"],"summary":"Get query results","description":"Poll this endpoint until `status` is `completed`, `partial`, or `failed`. Results are keyed by source name.","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Query result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryResult"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Query not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/query/history/{documentNumber}":{"get":{"tags":["Query"],"summary":"Query history by document","description":"Returns past queries for a given document number, sorted by most recent.","parameters":[{"name":"documentNumber","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Max results to return"}],"responses":{"200":{"description":"Array of query results","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/QueryResult"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sources":{"get":{"tags":["Sources"],"summary":"List available sources","description":"Returns all sources with supported document types, required fields, browser requirements, and CAPTCHA type. Optionally filter by document type.","parameters":[{"name":"documentType","in":"query","schema":{"$ref":"#/components/schemas/DocumentType"},"description":"Filter sources that support this document type"}],"responses":{"200":{"description":"Source list","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"displayName":{"type":"string"},"supportedDocumentTypes":{"type":"array","items":{"type":"object","properties":{"documentType":{"type":"string"},"inputMethod":{"type":"string"},"requiresName":{"type":"boolean"}}}},"requiredFields":{"type":"array","items":{"type":"string"}},"requiresBrowser":{"type":"boolean"},"captchaType":{"type":"string","enum":["recaptcha_v2","recaptcha_v3","image","text","none"]}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/evidence/{queryId}/{source}":{"get":{"tags":["Evidence"],"summary":"Get evidence bundle","description":"Returns screenshots, network logs, documents, and cookies collected during query execution.","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"source","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Evidence bundle","content":{"application/json":{"schema":{"type":"object","properties":{"queryId":{"type":"string"},"source":{"type":"string"},"screenshots":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"path":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}},"networkLogs":{"type":"array","items":{"type":"object"}},"documents":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"base64":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}},"collectedAt":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Evidence not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/evidence/{queryId}/{source}/screenshot/{index}":{"get":{"tags":["Evidence"],"summary":"Get screenshot image","description":"Returns a specific screenshot file by index.","parameters":[{"name":"queryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"source","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Screenshot image (PNG/JPEG)","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Screenshot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health":{"get":{"tags":["Health"],"summary":"Basic health check","description":"Returns server status, uptime, and proxy configuration.","security":[],"responses":{"200":{"description":"Server healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"timestamp":{"type":"string","format":"date-time"},"uptime":{"type":"number","description":"Uptime in seconds"},"proxy":{"type":"object","properties":{"enabled":{"type":"boolean"},"country":{"type":"string"},"protocol":{"type":"string"}}}}}}}}}}},"/health/proxy":{"get":{"tags":["Health"],"summary":"Proxy pool health","description":"Detailed proxy pool status including per-proxy health.","responses":{"200":{"description":"Proxy pool status","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"country":{"type":"string"},"protocol":{"type":"string"},"connectionCount":{"type":"number"},"pool":{"type":"object"},"proxies":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health/sources":{"get":{"tags":["Health"],"summary":"Source health status","description":"Real-time health status for all sources based on recent query success/failure.","responses":{"200":{"description":"Source health list","content":{"application/json":{"schema":{"type":"object","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"displayName":{"type":"string"},"url":{"type":"string"},"requiresBrowser":{"type":"boolean"},"captchaType":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health/playbooks":{"get":{"tags":["Health"],"summary":"Playbook status","description":"Shows which sources have AI-generated playbooks available.","responses":{"200":{"description":"Playbook statuses","content":{"application/json":{"schema":{"type":"object","properties":{"playbooks":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/summary":{"get":{"tags":["Metrics"],"summary":"Dashboard summary KPIs","description":"Key performance indicators: total queries, success rate, avg duration, active sources, CAPTCHA balance, proxy health.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168},"description":"Lookback window in hours"}],"responses":{"200":{"description":"Dashboard summary","content":{"application/json":{"schema":{"type":"object","properties":{"totalQueries":{"type":"integer"},"completedQueries":{"type":"integer"},"failedQueries":{"type":"integer"},"avgDurationMs":{"type":"integer"},"successRate":{"type":"integer","description":"0-100"},"activeSources":{"type":"integer"},"captchaBalance":{"type":"number","description":"USD"},"proxyPoolHealth":{"type":"integer","description":"0-100"},"uptimeSeconds":{"type":"integer"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/sources":{"get":{"tags":["Metrics"],"summary":"Per-source metrics","description":"Success rate, latency (avg/p95), error count, connection type breakdown per source.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}}],"responses":{"200":{"description":"Source metrics array","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"totalExecutions":{"type":"integer"},"successRate":{"type":"integer"},"avgDurationMs":{"type":"integer"},"p95DurationMs":{"type":"integer"},"errorCount":{"type":"integer"},"lastError":{"type":"string","nullable":true},"proxyPercent":{"type":"integer"},"directPercent":{"type":"integer"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/timeline":{"get":{"tags":["Metrics"],"summary":"Query timeline","description":"Time-bucketed query counts, avg duration, and error counts for charting.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}},{"name":"bucket","in":"query","schema":{"type":"integer","default":15,"minimum":5,"maximum":60},"description":"Bucket size in minutes"}],"responses":{"200":{"description":"Timeline buckets","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string","format":"date-time"},"queryCount":{"type":"integer"},"avgDurationMs":{"type":"integer"},"errorCount":{"type":"integer"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/errors":{"get":{"tags":["Metrics"],"summary":"Recent errors","description":"Latest source execution errors with source name, error message, duration, and timestamp.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Error list","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"error":{"type":"string"},"durationMs":{"type":"integer"},"recordedAt":{"type":"string","format":"date-time"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/captcha":{"get":{"tags":["Metrics"],"summary":"CAPTCHA metrics","description":"2captcha balance, solve statistics (success rate, avg time), breakdown by type, and cost estimates.","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}}],"responses":{"200":{"description":"CAPTCHA metrics","content":{"application/json":{"schema":{"type":"object","properties":{"currentBalance":{"type":"number"},"totalSolves":{"type":"integer"},"successRate":{"type":"integer"},"avgSolveTimeMs":{"type":"integer"},"estimatedDailyCost":{"type":"number"},"byType":{"type":"array","items":{"type":"object","properties":{"captchaType":{"type":"string"},"count":{"type":"integer"},"successRate":{"type":"integer"},"avgMs":{"type":"integer"}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/metrics/proxy":{"get":{"tags":["Metrics"],"summary":"Proxy metrics","description":"Proxy pool stats, per-proxy health, and proxy vs direct connection usage ratio.","responses":{"200":{"description":"Proxy metrics","content":{"application/json":{"schema":{"type":"object","properties":{"pool":{"type":"object","description":"Pool statistics (total, residential, healthy, refresh info)"},"proxies":{"type":"array","items":{"type":"object"},"description":"Per-proxy health details"},"usage":{"type":"object","properties":{"proxy":{"type":"integer"},"direct":{"type":"integer"},"total":{"type":"integer"},"proxyPercent":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/learn/{source}":{"post":{"tags":["Learn"],"summary":"Trigger AI learning mode","description":"Admin-only. AI (Claude) navigates the source site, records steps, and generates a reusable playbook. Takes 30–120s. High token cost — use sparingly.","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["documentNumber"],"properties":{"documentType":{"$ref":"#/components/schemas/DocumentType","default":"cedula"},"documentNumber":{"type":"string","minLength":1},"fullName":{"type":"string"}}},"example":{"documentType":"cedula","documentNumber":"1020741686"}}}},"responses":{"200":{"description":"Playbook generated","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"learned"},"source":{"type":"string"},"playbook":{"type":"object"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}