{"openapi":"3.1.0","info":{"title":"EMPEDIAcloud API","version":"2.0.0","description":"REST API of EMPEDIAcloud (website audits, code audits, monitoring, reports).\n\n**Authentication** (always as `Authorization: Bearer <token>`):\n- **OAuth 2.0 Client Credentials** (server to server, recommended for integrations): create a service client under “API access” and obtain short-lived tokens via `POST /oauth/token`.\n- **OAuth 2.0 Authorization Code + PKCE**: for apps where a person signs in (e.g. Claude/ChatGPT connector).\n- Endpoints with `x-auth-note` “Dashboard session” belong to the web interface and cannot be reached with access tokens.\n\nAll responses are JSON with a `success` field unless stated otherwise. Amounts are in cents, times in UTC (ISO 8601).","contact":{"name":"urbanstudio GmbH","email":"service@urbanstudio.de","url":"https://urbanstudio.de"}},"servers":[{"url":"https://empedia.cloud"}],"tags":[{"name":"Domains"},{"name":"Scans"},{"name":"Code Audit"},{"name":"Monitoring"},{"name":"Jobs"},{"name":"Reports & AI"},{"name":"Compliance"},{"name":"OIDC Provider"},{"name":"Async jobs"},{"name":"Webhooks & Badges"},{"name":"Email security (DMARC and TLS-RPT)"},{"name":"Domain management (domains, DNS, certificates)"},{"name":"Search engines (Search Console, Bing, CrUX)"},{"name":"EMPEDIAcaptcha (domains, rules, statistics)"}],"paths":{"/api/domains":{"get":{"tags":["Domains"],"operationId":"domains-list","summary":"Domains of the organization","description":"Lists the domains with expiry date, nameserver set, auto-renewal and deletion mark. Filters `quick` (expiring, cancelled, nozone), `ns_set`, `renew`; sorting via `sort` (name, ns, expire, renew) and `dir`. The \"Domains\" area must be enabled for the organization, otherwise 404.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsListResponse"},"example":{"success":true,"domains":[{"domain":"example.com","verified_at":"2026-04-01T10:00:00Z","method":"dns","token":"abc123..."}]}}}},"401":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]}],"x-required-scopes":{"scopes":["scan:read"],"mode":"all"}},"post":{"tags":["Domains"],"operationId":"domains-register","summary":"Register domain","description":"Registers a domain. **Billable:** the amount is deducted from the credit balance in advance (prepayment, no credit limit) and automatically refunded on failure; on success the invoice follows on the same day. The order runs asynchronously (response 202); the result is delivered via webhook `domain.order.completed` or `domain.order.failed`, or via `GET /orders`. With the `Idempotency-Key` header (8–128 characters), a retry within 24 hours is neither executed nor charged twice. TLDs with special rules (proofs, trustee …) are handled via a request (`POST /requests`).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRegisterResponse"},"example":{"domain":"example.com","token":"a1b2c3d4...","verification_methods":[{"method":"dns","instruction":"Legen Sie einen DNS-TXT-Eintrag …","values":[{"label":"Hostname","value":"_empedia"},{"label":"Wert","value":"empedia-verify=a1b2c3d4..."}]},{"method":"file","instruction":"Laden Sie die Verifizierungsdatei herunter …","values":[{"label":"URL","value":"https://example.com/.well-known/empedia-a1b2c3d4....txt"}],"download_url":"/api/domains/example.com/verification-file"},{"method":"meta","instruction":"Fügen Sie diesen Meta-Tag … ein.","values":[{"label":"Meta-Tag","value":"<meta name=\"empedia-site-verification\" content=\"a1b2c3d4...\">"}]}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Insufficient credit balance (prepayment, no credit limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRegisterRequest"},"example":{"domain":"example.com"}}}}}},"/api/domains/{domain}/verify":{"post":{"tags":["Domains"],"operationId":"domains-verify","summary":"Check verification","description":"Checks DNS TXT record, verification file and meta tag. Returns which method succeeded.","parameters":[{"name":"domain","in":"path","required":true,"description":"Domain name, e.g. example.com","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsVerifyResponse"},"example":{"verified":true,"method":"dns"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/domains/{domain}/verification-file":{"get":{"tags":["Domains"],"operationId":"domains-file","summary":"Download verification file","description":"Returns the verification file as a download. Place the file under /.well-known/.","parameters":[{"name":"domain","in":"path","required":true,"description":"Domain name","schema":{"type":"string"}}],"responses":{"200":{"description":"auditcollector-verify=a1b2c3d4...  (text/plain, Content-Disposition: attachment","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]}],"x-required-scopes":{"scopes":["scan:read"],"mode":"all"}}},"/api/audit/short":{"post":{"tags":["Scans"],"operationId":"scan-short","summary":"Quick Scan","description":"Quick scan of up to 5 pages. Score + grade + key findings. ~5–15 seconds.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanShortResponse"},"example":{"success":true,"mode":"short","score":78,"grade":"C","findings_summary":{"total":12,"high":1,"medium":4,"low":7},"duration_ms":8420}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified (security scans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Scan timeout or page unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanShortRequest"},"example":{"url":"https://example.com","options":{"maxPages":5,"screenshot":true}}}}}}},"/api/audit/scan":{"post":{"tags":["Scans"],"operationId":"scan-full","summary":"Full Scan","description":"Complete audit. Page limit from plan (20–all pages). All analyzers including Lighthouse and infection check of every page (field `infection`: malware traces in the delivered HTML/JS, cloaking comparison). The field `coverage` lists discovered, checked, unreachable and unchecked pages together with the reason (`limit_reason`: complete | max_pages | time | no_links — `no_links` reports that despite a multi-page scan no further link was found anywhere, usually an unrecognized bot/security interstitial instead of the real website; crawl time limit 30 minutes, the pages checked up to then remain the result). ~60–180 s. Large scans are started automatically as a background job.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanFullResponse"},"example":{"success":true,"mode":"scan","score":72,"grade":"C","tls":{"valid":true,"days_remaining":62},"findings_summary":{"total":18,"high":2,"medium":8,"low":8},"coverage":{"discovered":148,"crawled":120,"skipped":3,"unscanned":25,"sitemap_urls":140,"max_pages":200,"limit_reason":"max_pages"},"infection":{"pages_checked":120,"pages_with_indicators":0,"indicators":0,"items":[],"cloaking_checked":true,"cloaking_hits":0},"duration_ms":62400}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified (security scans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Scan timeout or page unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanFullRequest"},"example":{"url":"https://example.com","options":{"maxPages":50,"maxDepth":2,"concurrency":3,"screenshot":true,"lighthouse":true,"simulateConsent":true}}}}}}},"/api/audit/scan/stream":{"post":{"tags":["Scans"],"operationId":"scan-stream","summary":"Streaming Scan (SSE)","description":"Like Full Scan, but with real-time progress via Server-Sent Events. Accepts the same request body as Full Scan. The client receives events: progress, start_page, result, done.","parameters":[],"responses":{"200":{"description":"event: progress\\ndata: {\"step\":\"tls\",\"message\":\"Checking TLS...\",\"percent\":5}\\n\\nevent: result\\ndata: {\"success\":true,\"mode\":\"scan\",...}\\n\\nevent: done\\ndata: {\"message\":\"Scan complete\"}","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified (security scans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanStreamRequest"},"example":{"url":"https://example.com","options":{"maxPages":50,"maxDepth":2,"concurrency":3,"screenshot":true,"lighthouse":true,"simulateConsent":true}}}}}}},"/api/audit/dns-check":{"post":{"tags":["Scans"],"operationId":"scan-dns","summary":"DNS & email security","description":"SPF, DKIM, DMARC, DNSSEC, MTA-STS, TLSRPT, BIMI. DNSBL checks (Spamhaus, CBL, SpamCop) for IPv4/IPv6. Open relay test. Optional: AbuseIPDB IP reputation.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanDnsResponse"},"example":{"success":true,"domain":"example.com","score":70,"email_security":{"spf":{"exists":true,"has_all_fail":true},"dkim":{"found":true},"dmarc":{"exists":true,"policy":"reject"}},"reputation":{"ips":{"93.184.216.34":{"dnsbl":[],"abuseipdb":{"abuse_score":0}}},"open_relay":{"open_relay":false}}}}}},"400":{"description":"Invalid URL or domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanDnsRequest"},"example":{"url":"https://example.com"}}}}}},"/api/audit/gdpr":{"post":{"tags":["Scans"],"operationId":"scan-gdpr","summary":"GDPR single page","description":"GDPR check on a single page: cookies, consent banner, trackers, dark patterns. No domain verification required.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanGdprResponse"},"example":{"success":true,"mode":"gdpr","gdpr_score":62,"findings_summary":{"total":7,"high":2,"medium":3,"low":2}}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanGdprRequest"},"example":{"url":"https://example.com"}}}}}},"/api/audit/gdpr-full":{"post":{"tags":["Scans"],"operationId":"scan-gdpr-full","summary":"GDPR full site","description":"GDPR scan across all crawled pages including consent rejection test.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanGdprFullResponse"},"example":{"success":true,"mode":"gdpr-full","gdpr_score":58,"pages_scanned":12}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanGdprFullRequest"},"example":{"url":"https://example.com","options":{"maxPages":50}}}}}}},"/api/audit/wp-emergency":{"post":{"tags":["Scans"],"operationId":"scan-wp","summary":"WP Emergency Check","description":"In-depth WordPress check: core version, plugins, themes, exposed files, xmlrpc, REST API, user enumeration, infection check of the start page (malware traces in the delivered HTML/JS, cloaking comparison). With AI action plan. The multi-page emergency check (infection check of every page, WordPress emergency report) runs via the preset `wp-emergency` in `POST /api/audit/start-async`.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanWpResponse"},"example":{"success":true,"wordpress":{"version":"6.4.2","is_latest":false},"findings_summary":{"total":5,"high":2},"ai_action_plan":"1. WordPress sofort auf 6.5 aktualisieren..."}}}},"400":{"description":"Invalid URL or WordPress not detected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanWpRequest"},"example":{"url":"https://example.com"}}}}}},"/api/code/scans/{id}/sarif":{"get":{"tags":["Code Audit"],"operationId":"code-scan-sarif","summary":"Export code audit as SARIF 2.1.0","description":"Returns the findings of a completed code audit in SARIF format (`application/sarif+json`) — directly usable for GitHub Code Scanning (`github/codeql-action/upload-sarif`), GitLab, Azure DevOps and IDEs. Severities: high → error, medium → warning, low/info → note; `security-severity` for the GitHub display.","parameters":[{"name":"id","in":"path","required":true,"description":"Public UUID of the code audit","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScanSarifResponse"},"example":{"$schema":"https://json.schemastore.org/sarif-2.1.0.json","version":"2.1.0","runs":[{"tool":{"driver":{"name":"EMPEDIAcloud Code-Audit","rules":[{"id":"sast-xss","shortDescription":{"text":"Reflected XSS"},"defaultConfiguration":{"level":"error"}}]}},"results":[{"ruleId":"sast-xss","level":"error","message":{"text":"Reflected XSS: src/a.php:12 — Empfehlung: Ausgabe escapen"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"src/a.php"},"region":{"startLine":12}}}]}]}]}}}},"404":{"description":"Audit not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Audit not yet completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/analyze":{"post":{"tags":["Code Audit"],"operationId":"code-upload","summary":"Upload ZIP/TAR","description":"Uploads a ZIP or TAR.GZ and analyzes the source code. Multipart/form-data. Optional: system parameter for framework-specific rules.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeUploadResponse"},"example":{"success":true,"mode":"upload","files_scanned":142,"findings_summary":{"total":18,"high":3,"medium":7,"low":8},"wordpress":{"version":"6.4.2","plugins":["woocommerce"]}}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Archive too large for the current plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CodeUploadRequest"}}}}}},"/api/code/ssh-public-key":{"get":{"tags":["Code Audit"],"operationId":"code-ssh-key","summary":"Get system SSH public key","description":"Returns the system's public key. Add this key to ~/.ssh/authorized_keys on the target server to enable passwordless SFTP connections.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeSshKeyResponse"},"example":{"success":true,"publicKey":"ssh-ed25519 AAAA... auditcollector-code-audit"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"SSH key could not be generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/connect":{"post":{"tags":["Code Audit"],"operationId":"code-connect","summary":"Remote connection (SFTP/FTP/Git)","description":"Connects to the server and analyzes the source code directly. Supports SFTP with password, SSH key or the system key (if neither password nor privateKey is given, the system SSH key is used automatically). FTP and Git are also supported.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectResponse"},"example":{"success":true,"mode":"sftp","files_scanned":312,"findings_summary":{"total":9,"high":1,"medium":4,"low":4}}}}},"400":{"description":"Connection failed or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectRequest"},"example":{"method":"sftp","host":"server.example.com","port":22,"username":"deploy","remotePath":"/var/www/html","ai":true,"system":"wordpress"}}}}}},"/api/code/scans":{"get":{"tags":["Code Audit"],"operationId":"code-scan-list","summary":"Code audit history","description":"Lists all code audits of the organization, paginated.","parameters":[{"name":"page","in":"query","required":false,"description":"Page (default: 1)","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"Entries per page (default: 20, max 100)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScanListResponse"},"example":{"success":true,"scans":[{"id":"uuid","target":"sftp://server.example.com/var/www","status":"completed","findings_summary":{"total":18,"high":3,"medium":7,"low":8},"created_at":"2026-04-22T03:00:01Z"}],"total":42,"page":1,"limit":20}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/scans/{id}":{"get":{"tags":["Code Audit"],"operationId":"code-scan-detail","summary":"Code audit detail","description":"Returns the complete result of a code audit (findings, WordPress analysis, AI result).","parameters":[{"name":"id","in":"path","required":true,"description":"Public UUID of the scan","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScanDetailResponse"},"example":{"success":true,"scan":{"id":"uuid","mode":"git","target":"https://github.com/org/repo.git","status":"completed","findings":[{"id":"sast-sqli-a3f2","severity":"high","title":"SQL Injection","file":"db-helper.php","line":42}],"findings_summary":{"total":18,"high":3,"medium":7,"low":8},"wordpress":null,"ai":{"available":true,"findings_count":4,"provider":"Claude (Anthropic)"},"duration_ms":12340}}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found or no access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/scans/{id}/pdf":{"get":{"tags":["Code Audit"],"operationId":"code-scan-pdf","summary":"Download code audit PDF","description":"Generates a PDF report for the code audit. With ?lang=en an English report is generated. Contains findings tables by severity, WordPress analysis, file statistics and AI result block.","parameters":[{"name":"id","in":"path","required":true,"description":"Public UUID of the scan","schema":{"type":"string"}},{"name":"lang","in":"query","required":false,"description":"Language: de (default) | en","schema":{"type":"string"}}],"responses":{"200":{"description":"PDF binary, Content-Type: application/pdf, Content-Disposition: attachment; filename=\"code-audit-example-com-2026-04-22.pdf\"","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found or no access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"PDF generation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/schedules":{"get":{"tags":["Code Audit"],"operationId":"code-schedule-list","summary":"List scheduled code audits","description":"Lists all scheduled code audits of the organization. Credentials are not returned — has_credentials (0/1) is set instead.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleListResponse"},"example":{"success":true,"schedules":[{"id":"uuid","label":"Nightly Git Audit","method":"git","cron":"0 3 * * *","enabled":true,"last_run_at":"2026-04-22T03:00:01Z","next_run_at":"2026-04-23T03:00:00Z","has_credentials":1}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["Code Audit"],"operationId":"code-schedule-create","summary":"Create scheduled code audit","description":"Creates a new scheduled code audit. Credentials (token, password, SSH key) are stored AES-256-GCM encrypted. Max. 20 schedules per organization.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleCreateResponse"},"example":{"success":true,"schedule":{"id":"uuid","label":"Nightly Git Audit","method":"git","cron":"0 3 * * *","enabled":true,"next_run_at":"2026-04-23T03:00:00Z"}}}}},"400":{"description":"Invalid cron expression or missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No code audit quota available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Maximum number of schedules (20) reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleCreateRequest"},"example":{"label":"Nightly Git Audit","method":"git","repo_url":"https://github.com/org/repo.git","branch":"main","token":"ghp_...","cron":"0 3 * * *","use_ai":true,"system_hint":"laravel","notify_on":"new_high"}}}}}},"/api/code/scans/{id}/retry-ai":{"post":{"tags":["Code Audit"],"operationId":"code-retry-ai","summary":"Retry AI analysis","description":"Restarts the AI analysis of an existing scan — e.g. after an error or with a different model. Uses code snippets stored with the scan.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRetryAiResponse"},"example":{"success":true,"status":"running"}}}},"402":{"description":"AI quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRetryAiRequest"},"example":{"provider_id":"uuid-des-providers"}}}}}},"/api/code/scans/{id}/retry-ai-status":{"get":{"tags":["Code Audit"],"operationId":"code-retry-ai-status","summary":"Get AI retry status","description":"Polling endpoint for the status of a running AI retry.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRetryAiStatusResponse"},"example":{"success":true,"status":"done"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/estimate-full-scan":{"post":{"tags":["Code Audit"],"operationId":"code-estimate-full-scan","summary":"Estimate cost of full AI analysis","description":"Estimates the token cost of a full AI analysis based on file count and selected model.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeEstimateFullScanResponse"},"example":{"success":true,"estimated_files":347,"estimated_tokens_in":297000,"estimated_tokens_out":138800,"estimated_cost_cents":12.5,"provider_name":"Claude Sonnet 4.6","model":"claude-sonnet-4-6"}}}},"500":{"description":"No AI provider available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeEstimateFullScanRequest"},"example":{"provider_id":"uuid","file_count":347,"avg_file_size":3000}}}}}},"/api/code/scans/{id}/remediations":{"get":{"tags":["Code Audit"],"operationId":"code-list-remediations","summary":"List remediation jobs","description":"Lists all remediation jobs for a scan (max. 10, newest first). Useful for showing the latest job status on the scan detail page.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeListRemediationsResponse"},"example":{"success":true,"remediations":[{"id":"rem-uuid","status":"completed","mode":"automatic","method":"sftp","findings_fixed":12,"findings_skipped":3,"findings_failed":0,"created_at":"2026-06-20T14:00:00Z"}]}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/scans/{id}/start-remediation":{"post":{"tags":["Code Audit"],"operationId":"code-start-remediation","summary":"Start AI remediation","description":"Starts an autonomous remediation job. Creates a backup (SFTP/FTP), generates fixes with AI, verifies them adversarially, and applies approved fixes. Three modes: automatic, interactive, review.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeStartRemediationResponse"},"example":{"success":true,"job_id":"job-uuid","remediation_id":"rem-uuid","mode":"interactive","method":"sftp"}}}},"400":{"description":"No relevant findings or missing credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeStartRemediationRequest"},"example":{"mode":"interactive"}}}}}},"/api/code/remediation/{id}":{"get":{"tags":["Code Audit"],"operationId":"code-remediation-status","summary":"Remediation status","description":"Returns the current status, progress and cost of a remediation job.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationStatusResponse"},"example":{"success":true,"remediation":{"id":"rem-uuid","status":"running","mode":"interactive","findings_fixed":3,"findings_skipped":1,"ai_tokens_in":12438,"ai_cost_cents":8.9}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/remediation/{id}/messages":{"get":{"tags":["Code Audit"],"operationId":"code-remediation-messages","summary":"Get agent messages","description":"Returns the message history between agent and user. Supports polling with the since parameter.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"description":"ISO timestamp — only messages after this point in time","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationMessagesResponse"},"example":{"success":true,"messages":[{"role":"agent","content":"Backup erstellt: 1247 Dateien","message_type":"success","options":null,"created_at":"2026-06-20T14:00:00Z"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/remediation/{id}/respond":{"post":{"tags":["Code Audit"],"operationId":"code-remediation-respond","summary":"Answer agent question","description":"Sends a reply to a question from the remediation agent (interactive mode).","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationRespondResponse"},"example":{"success":true,"delivered":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationRespondRequest"},"example":{"answer":"Anwenden"}}}}}},"/api/code/remediation/{id}/actions":{"get":{"tags":["Code Audit"],"operationId":"code-remediation-actions","summary":"List fix actions","description":"Returns all individual actions of a remediation job with diffs, status and AI assessments.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationActionsResponse"},"example":{"success":true,"actions":[{"id":"action-uuid","finding_id":"F001","file_path":"wp-config.php","action_type":"patch","status":"applied","ai_fix_approved":1,"ai_verify_approved":1,"ai_fix_reasoning":"SQL-Injection-Risiko behoben durch Prepared Statement","ai_verify_reasoning":"Fix korrekt, keine Seiteneffekte","user_approved":null,"patch_diff":"--- a/wp-config.php\n+++ b/wp-config.php\n@@ -42 @@\n-$wpdb->query($sql)\n+$wpdb->prepare($sql)","applied_at":"2026-06-20T14:05:00Z","created_at":"2026-06-20T14:04:00Z"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/remediation/{id}/approve-fixes":{"post":{"tags":["Code Audit"],"operationId":"code-remediation-approve","summary":"Apply approved fixes (review mode)","description":"Applies the fixes approved by the user. Only available in review mode.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationApproveResponse"},"example":{"success":true,"applied":2,"failed":0}}}},"400":{"description":"Job not in review mode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationApproveRequest"},"example":{"action_ids":["action-uuid-1","action-uuid-2"]}}}}}},"/api/code/remediation/{id}/rollback":{"post":{"tags":["Code Audit"],"operationId":"code-remediation-rollback","summary":"Rollback — revert all changes","description":"Restores all files from the backup. Only for SFTP/FTP remediation with an existing backup.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRemediationRollbackResponse"},"example":{"success":true,"message":"Rollback erfolgreich — alle Dateien wiederhergestellt"}}}},"400":{"description":"No backup available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/remediation/{id}/download":{"get":{"tags":["Code Audit"],"operationId":"code-remediation-download","summary":"Download archive","description":"Downloads the backup or patched archive. SFTP/FTP/SSH: pre-remediation backup (backup-*.tar.gz). Upload: patched archive (remediated-*.tar.gz). Requires `has_backup: true` in the status endpoint.","parameters":[{"name":"id","in":"path","required":true,"description":"Remediation UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Binary tar.gz, Content-Type: application/gzip, Content-Disposition: attachment; filename=\"backup-<id8>.tar.gz\"","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No archive available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"}}},"/api/code/connections":{"get":{"tags":["Code Audit"],"operationId":"code-connections-list","summary":"List saved connections","description":"Lists all saved code audit connections of the user (Git, SFTP, FTP, SSH). Credentials are not returned — only a `has_credentials` boolean.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsListResponse"},"example":{"success":true,"connections":[{"id":"conn-uuid","label":"Mein Server","method":"sftp","host":"server.example.com","port":22,"username":"deploy","remote_path":"/var/www","system_hint":"wordpress","has_credentials":1,"last_used_at":"2026-06-20T14:00:00Z","created_at":"2026-06-01T10:00:00Z"}]}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["Code Audit"],"operationId":"code-connections-create","summary":"Save connection","description":"Saves a new code audit connection. Credentials (token, password, SSH key) are stored AES-256-GCM encrypted. Max. 50 connections per user.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsCreateResponse"},"example":{"success":true,"id":"conn-uuid"}}}},"400":{"description":"Max. 50 connections or invalid method","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsCreateRequest"},"example":{"label":"Mein Server","method":"sftp","host":"server.example.com","username":"deploy","password":"secret","remote_path":"/var/www","system_hint":"wordpress"}}}}}},"/api/code/connections/{id}":{"patch":{"tags":["Code Audit"],"operationId":"code-connections-update","summary":"Update connection","description":"Updates a saved connection. Only the submitted fields are changed. New credentials are stored encrypted.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsUpdateResponse"},"example":{"success":true}}}},"404":{"description":"Connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsUpdateRequest"},"example":{"label":"Neuer Name","host":"new-server.example.com"}}}}},"delete":{"tags":["Code Audit"],"operationId":"code-connections-delete","summary":"Delete connection","description":"Deletes a saved connection and the associated encrypted credentials.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectionsDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/code/schedules/{id}":{"patch":{"tags":["Code Audit"],"operationId":"code-schedule-update","summary":"Update scheduled code audit","description":"Updates an existing schedule. Only the fields you send are changed. To delete credentials, send null.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the schedule","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleUpdateResponse"},"example":{"success":true,"schedule":{"id":"uuid","enabled":false,"cron":"0 4 * * 1"}}}}},"400":{"description":"Invalid cron expression","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Schedule not found or no access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleUpdateRequest"},"example":{"enabled":false,"cron":"0 4 * * 1","notify_on":"always"}}}}},"delete":{"tags":["Code Audit"],"operationId":"code-schedule-delete","summary":"Delete scheduled code audit","description":"Permanently deletes a schedule. Past scan results remain in the history.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the schedule","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleDeleteResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Schedule not found or no access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/code/schedules/{id}/run":{"post":{"tags":["Code Audit"],"operationId":"code-schedule-run","summary":"Run schedule immediately","description":"Triggers a scheduled code audit immediately, regardless of the cron schedule. Useful for testing or manual triggering.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the schedule","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeScheduleRunResponse"},"example":{"success":true,"message":"Audit gestartet."}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Schedule not found or no access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/monitoring/servers":{"get":{"tags":["Monitoring"],"operationId":"mon-servers-list","summary":"List servers","description":"Returns all registered server agents of the organization, including the latest metrics (CPU, RAM, disk, load).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersListResponse"},"example":{"success":true,"servers":[{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Webserver Produktion","hostname":"web01.example.com","status":"active","last_heartbeat":"2026-04-20T08:00:00Z","cpu_percent":34.2,"memory_percent":61.8,"disk_percent":48,"load_1m":0.82}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"post":{"tags":["Monitoring"],"operationId":"mon-servers-register","summary":"Register server","description":"Registers a new server and returns an installation token. The token is inserted into the curl install command. Fails with **402 limit_reached** if the plan limit is reached.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersRegisterResponse"},"example":{"success":true,"agent_token":"a1b2c3d4e5f6...","install_cmd":"curl -sSL https://empedia.cloud/api/monitoring/install.sh | bash -s -- a1b2c3d4e5f6...","server":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Webserver Produktion"}}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"limit_reached — plan limit for servers reached; response contains upgrade_options[]","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersRegisterRequest"},"example":{"name":"Webserver Produktion","alert_email":"ops@example.com"}}}}}},"/api/monitoring/servers/{id}":{"delete":{"tags":["Monitoring"],"operationId":"mon-servers-delete","summary":"Remove server","description":"Removes the server from monitoring. A server whose agent has reported at least once disappears immediately from the list, queries and quota and no longer triggers alerts; **the agent uninstalls itself on the next heartbeat** (`uninstall.pending: true`, the heartbeat response then contains `uninstall: true`, after which the record is deleted). If the agent no longer reports (server off), it removes itself on its own after more than 24 h and 5 failed attempts (response `401` with `code: invalid_token`); manually: `curl -sL <instance>/api/monitoring/install.sh | sudo bash -s -- --uninstall` or, on Windows, `Uninstall-AuditCollectorAgent`. A server that has never reported is deleted immediately (`uninstall.pending: false`).","parameters":[{"name":"id","in":"path","required":true,"description":"Server ID (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersDeleteResponse"},"example":{"success":true,"uninstall":{"pending":true}}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}},"get":{"tags":["Monitoring"],"operationId":"mon-servers-get","summary":"Get server","description":"Returns a server with its settings, the last 288 measurements (`metrics`), the linked website monitors (`websites`: id, name, url, status), the last 100 alerts (`alerts`; `resolved_at` is set once the corresponding recovery notice has been sent, per service for services, otherwise `null`; for alerts with `snapshot`: load, RAM, file systems and top processes at the time of the alert) and the known kernel vulnerabilities (`kernel_cves`). `server.extras` contains the latest state of the agent's additional data: `filesystems`, `top_processes`, `services_running`, `gpus`, `cpu_cores` and `updates` (pending updates: `security` counted by security advisories, `total`, `method` = `advisories|packages`, `reboot`, `kernel` with `running`, `available`, `advisories`, `livepatch`, and the list `items`). `server.blacklist_detail` contains the result of the spam list check (`listed`, `unknown`, `results`). The installation token is only included for dashboard sessions.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the server","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersGetResponse"},"example":{"success":true,"server":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Webserver Produktion","hostname":"web01.example.com","agent_version":"1.4.9","scheduler":"systemd-timer","extras":{"cpu_cores":8,"filesystems":[{"mount":"/","fs":"ext4","total_gb":98,"used_gb":47,"pct":48}],"top_processes":[{"name":"php-fpm","cpu":12.5,"mem":8.1}],"updates":{"manager":"dnf","method":"advisories","security":0,"total":0,"reboot":true,"kernel":{"running":"4.18.0-553.139.1.el8_10.x86_64","available":null,"advisories":0,"livepatch":"kernelcare"},"items":[],"checked_at":1791600000}},"blacklist_detail":{"listed":[],"unknown":[],"results":[{"list":"Spamhaus ZEN","target":"203.0.113.10","state":"clean"}]}},"metrics":[],"alerts":[{"id":"7b1e9c4a-0d52-4b0a-9a55-2f9c1d3e8a10","type":"service","severity":"critical","message":"Dienst „nginx“ ausgefallen (gestoppt)","metric_value":null,"threshold":null,"snapshot":null,"resolved_at":"2026-04-20T09:42:11.000Z","created_at":"2026-04-20T09:31:02.000Z"}],"kernel_cves":null}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"patch":{"tags":["Monitoring"],"operationId":"mon-servers-update","summary":"Update server settings","description":"Changes name, alert channels and thresholds, the offline threshold, the blacklist check (`blacklist`, from Monitor Pro) and the monitored services (`watch_services`, from Monitor Basic) of a server.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the server","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersUpdateResponse"},"example":{"success":true}}}},"400":{"description":"Invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Feature not included in the plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersUpdateRequest"},"example":{"name":"web-01","offline_threshold_min":10,"blacklist":true}}}}}},"/api/monitoring/servers/{id}/metrics":{"get":{"tags":["Monitoring"],"operationId":"mon-servers-metrics","summary":"Server metrics (time series)","description":"Returns historical CPU/RAM/disk/load metrics as a time series. The time range can be selected via query parameter. If the server has GPUs (NVIDIA/AMD), each data row contains `gpus`: `[{ \"i\": 0, \"util\": 83, \"mem\": 61.2, \"temp\": 71, \"power_w\": 312 }]` (utilization %, VRAM usage %, °C, watts; otherwise `null`). The detail endpoint `GET /servers/:id` additionally returns the latest state with names and VRAM size in `server.extras.gpus`.","parameters":[{"name":"id","in":"path","required":true,"description":"Server ID (UUID)","schema":{"type":"string"}},{"name":"range","in":"query","required":false,"description":"1h | 6h | 24h | 7d | 30d (default: 24h)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonServersMetricsResponse"},"example":{"success":true,"metrics":[{"ts":"2026-04-20T07:00:00Z","cpu_percent":28.4,"memory_percent":59.1,"disk_percent":47.8,"load_1m":0.61}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites":{"get":{"tags":["Monitoring"],"operationId":"mon-websites-list","summary":"List websites","description":"Returns all monitored websites of the organization, including current status, last response time and SSL expiry date. With `kind=heartbeat` and `limit`, only heartbeat monitors are returned, paginated (plus `total` and `used` = all monitors of the organization).","parameters":[{"name":"kind","in":"query","required":false,"description":"`heartbeat` = heartbeat monitors only (together with `limit`)","schema":{"type":"string","enum":["heartbeat"]}},{"name":"limit","in":"query","required":false,"description":"Entries per page (1–200); only with `kind=heartbeat`","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start position","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search in name","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"description":"Filter: `ok`, `late`, `failed`, `wait`","schema":{"type":"string","enum":["ok","late","failed","wait"]}},{"name":"sort","in":"query","required":false,"description":"Sort: `state`, `name`, `every`, `last`, `due`","schema":{"type":"string"}},{"name":"dir","in":"query","required":false,"description":"`asc` or `desc`","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesListResponse"},"example":{"success":true,"websites":[{"id":"550e8400-e29b-41d4-a716-446655440000","url":"https://example.com","name":"Produktiv-Website","status":"up","last_check":"2026-04-20T08:00:00Z","response_time_ms":312,"ssl_expires_in_days":62,"check_interval_sec":60,"check_types":["uptime","ssl","response-time"]}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"post":{"tags":["Monitoring"],"operationId":"mon-websites-add","summary":"Add website","description":"Adds a website to monitoring. The check interval is limited to the plan minimum (Monitor Free: 900 s, Basic: 300 s, Pro and higher: 60 s; websites are checked at most once per minute). Fails with **402 limit_reached** if the plan limit is reached.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesAddResponse"},"example":{"success":true,"website":{"id":"550e8400-e29b-41d4-a716-446655440000","url":"https://example.com","name":"Produktiv-Website","check_interval_sec":60}}}}},"400":{"description":"URL missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"limit_reached — plan limit for websites reached; response contains upgrade_options[]","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesAddRequest"},"example":{"url":"https://example.com","name":"Produktiv-Website","check_interval_sec":60,"check_types":["uptime","ssl","response-time","dns"]}}}}}},"/api/monitoring/websites/{id}":{"patch":{"tags":["Monitoring"],"operationId":"mon-websites-update","summary":"Update website","description":"Updates name, check interval, check types or alert configuration of a monitored website. Only the fields you send are overwritten.","parameters":[{"name":"id","in":"path","required":true,"description":"Website ID (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesUpdateResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesUpdateRequest"},"example":{"check_interval_sec":30,"alert_channels":{"slack_webhook":"https://hooks.slack.com/..."}}}}}},"delete":{"tags":["Monitoring"],"operationId":"mon-websites-delete","summary":"Remove website","description":"Removes a website from monitoring. The entire check history is deleted.","parameters":[{"name":"id","in":"path","required":true,"description":"Website ID (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesDeleteResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}},"get":{"tags":["Monitoring"],"operationId":"mon-websites-get","summary":"Get website monitor","description":"Returns a monitor with its latest results per check type (`uptime`, `ssl`, `dns`, `blacklist`, `mail-auth` …), availability over the last 30 days (`uptimeDays`) and, for heartbeat monitors, the ping history including `next_due_at`. For the `mail-auth` check, `detail` contains the score (0–100) and findings `{ id, severity, title, fix, params }` (texts in German; `id` + `params` are suitable for your own translations). For the `blacklist` check, `detail` contains `listed`, `unknown` and `results` (per query `list`, `target`, `state` = `clean|listed|unknown`). For the `domain-expiry` check, `detail.unavailable: true` is set if the registry of the TLD (e.g. .de) does not publish an expiry date.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the monitor","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesGetResponse"},"example":{"success":true,"website":{"id":"550e8400-e29b-41d4-a716-446655440000","url":"https://example.com","name":"Produktiv-Website","monitor_kind":"http","status":"up","check_interval_sec":60,"check_types":["uptime","ssl","response-time","mail-auth"]},"results":[{"check_type":"uptime","status":"up","checked_at":"2026-10-02T08:00:00Z","detail":{"response_time_ms":312}},{"check_type":"mail-auth","status":"up","checked_at":"2026-10-02T03:00:00Z","detail":{"score":92,"issues":[{"id":"dmarc-no-rua","severity":"low","title":"DMARC ohne Berichts-Adresse (rua)"}]}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites/{id}/ping-stats":{"get":{"tags":["Monitoring"],"operationId":"mon-heartbeat-stats","summary":"Get heartbeat history","description":"Reports of a heartbeat monitor per time bucket. `day` = 24 hours, `week` = 7 days, `month` = 30 days (from the individual reports, day boundaries in the time zone passed with `tz`), `year` = 365 days (UTC daily values). Buckets without a report are missing from `buckets` (count and grid are given in `from`, `size`, `count`).","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the heartbeat monitor","schema":{"type":"string"}},{"name":"range","in":"query","required":false,"description":"`day`, `week` (default), `month` or `year`","schema":{"type":"string","enum":["day","week","month","year"]}},{"name":"tz","in":"query","required":false,"description":"Time zone offset in minutes as in `Date.getTimezoneOffset()` (Berlin in summer: -120)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonHeartbeatStatsResponse"},"example":{"success":true,"range":"week","from":1775512800,"size":86400,"count":7,"buckets":[{"ts":1775944800,"ok":3,"fail":1}]}}}},"404":{"description":"Heartbeat not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites/{id}/log":{"get":{"tags":["Monitoring"],"operationId":"mon-websites-log","summary":"Check log of a website","description":"Individual check results (uptime, SSL, domain expiry, blacklist …), newest first, paginated. With `grouped=1`, results are combined per check run (status, response time, status code) and filtered/sorted server-side.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the monitor","schema":{"type":"string"}},{"name":"grouped","in":"query","required":false,"description":"`1` = combined per check run (returns `runs`, `total`)","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Entries per page (grouped: 1–200, default 25; otherwise 10–500, default 100)","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start position (grouped only)","schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"description":"Page number (without grouped only)","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search text in status, check type and detail (grouped only)","schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"description":"Sort (grouped): `time`, `status`, `response`, `code`","schema":{"type":"string"}},{"name":"dir","in":"query","required":false,"description":"`asc` or `desc`","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesLogResponse"},"example":{"success":true,"rows":[{"check_type":"uptime","status":"up","response_ms":182,"status_code":200,"detail":null,"checked_at":"2026-10-10T09:00:02.000Z"}],"total":1440,"page":1,"limit":100}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites/{id}/history":{"get":{"tags":["Monitoring"],"operationId":"mon-websites-history","summary":"History of a website (chart data)","description":"Check results of the last hours, per check type as series `timestamps`, `values` (response time in ms) and `statuses`, ascending by time — basis for response time charts.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the monitor","schema":{"type":"string"}},{"name":"hours","in":"query","required":false,"description":"Time range in hours (1–720, default 24)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesHistoryResponse"},"example":{"success":true,"hours":24,"history":{"uptime":{"timestamps":["2026-10-10T09:00:02.000Z"],"values":[182],"statuses":["up"]}}}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites/{id}/dns":{"get":{"tags":["Monitoring"],"operationId":"mon-websites-dns","summary":"DNS records of the website domain","description":"Reads the current DNS records (A, AAAA, MX, NS) of the monitor's domain; types that cannot be resolved are returned as an empty list.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the monitor","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonWebsitesDnsResponse"},"example":{"success":true,"dns":{"a":["203.0.113.10"],"aaaa":[],"mx":[{"exchange":"mail.example.com","priority":10}],"ns":["ns1.example.com"]}}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/websites/{id}/pings":{"get":{"tags":["Monitoring"],"operationId":"mon-heartbeat-pings","summary":"List heartbeat reports","description":"Report log of a heartbeat monitor (30 days), paginated. The per-day history is available as `ping_days` in `GET /api/monitoring/websites/:id`.","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of the heartbeat monitor","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Entries per page (1–200, default 25)","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start position","schema":{"type":"integer"}},{"name":"result","in":"query","required":false,"description":"Filter: `ok` or `fail`","schema":{"type":"string","enum":["ok","fail"]}},{"name":"sort","in":"query","required":false,"description":"Sort: `time` or `result`","schema":{"type":"string"}},{"name":"dir","in":"query","required":false,"description":"`asc` or `desc`","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonHeartbeatPingsResponse"},"example":{"success":true,"total":2,"pings":[{"ok":1,"pinged_at":"2026-04-20T03:00:02.000Z"},{"ok":0,"pinged_at":"2026-04-19T03:00:01.000Z"}]}}}},"404":{"description":"Heartbeat not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/monitoring/heartbeat/{token}":{"post":{"tags":["Monitoring"],"operationId":"mon-heartbeat-ping","summary":"Report heartbeat (backup, cron job, script)","description":"Public endpoint for heartbeat monitors: the job calls the URL after each run (GET or POST, e.g. `curl -fsS https://…/api/monitoring/heartbeat/TOKEN`). With the suffix `/fail` (or `?status=fail` or `?code=<exit code>` with a value ≠ 0), the job reports a failure. Optionally, a short message can be sent along (`?msg=…`, as form field `msg` or as text in the body, at most 300 characters); it appears in the report log and in the alert for a reported failure. If the call fails to arrive for longer than interval + grace period, an alert is raised. The token is part of the monitor's URL.","parameters":[{"name":"token","in":"path","required":true,"description":"Heartbeat token of the monitor","schema":{"type":"string"}},{"name":"msg","in":"query","required":false,"description":"Short message from the job (at most 300 characters)","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"fail = report a failure","schema":{"type":"string"}},{"name":"code","in":"query","required":false,"description":"Exit code of the job (0 = ok, otherwise failure)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonHeartbeatPingResponse"},"example":{"success":true}}}},"404":{"description":"Unknown token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/jobs":{"get":{"tags":["Jobs"],"operationId":"jobs-list","summary":"List jobs","description":"Returns all of your own background jobs (max. 50, newest first).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsListResponse"},"example":{"success":true,"jobs":[{"id":"uuid","type":"scan","status":"completed","progress":100,"created_at":"2026-04-18T10:00:00Z"}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]},{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]},{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["scan:read","scan:write","code:audit"],"mode":"any"}}},"/api/jobs/{id}":{"get":{"tags":["Jobs"],"operationId":"jobs-status","summary":"Job status","description":"Status, progress and result of a job.","parameters":[{"name":"id","in":"path","required":true,"description":"Job UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsStatusResponse"},"example":{"success":true,"job":{"id":"550e8400-e29b-41d4-a716-446655440000","status":"completed","progress":100,"scan_id":"550e8400-e29b-41d4-a716-446655440001","error":null}}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]},{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]},{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["scan:read","scan:write","code:audit"],"mode":"any"}}},"/api/jobs/{id}/stream":{"get":{"tags":["Jobs"],"operationId":"jobs-stream","summary":"SSE progress","description":"Server-Sent Events stream for real-time progress. Sends progress events until the job is complete.","parameters":[{"name":"id","in":"path","required":true,"description":"Job UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"event: progress\\ndata: {\"percent\":45,\"pages_done\":9,\"pages_total\":20}\\n\\nevent: done\\ndata: {\"scan_id\":\"550e8400-e29b-41d4-a716-446655440001\"}","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]},{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]},{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["scan:read","scan:write","code:audit"],"mode":"any"}}},"/api/user/scans/summary":{"get":{"tags":["Reports & AI"],"operationId":"scan-summary","summary":"Summary of the latest check of a domain","description":"Compact overview for widgets, plugins and dashboards: overall grade, trend compared to the previous audit, findings, **category index** per area (`gdpr` privacy, `a11y` accessibility, `seo` SEO & GEO, `security` security; 100 minus weighted findings, only for areas the audit checked), link to the online report and to the PDF. Uses the domain's latest completed audit.","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain, e.g. example.com (with or without https:// / www.)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanSummaryResponse"},"example":{"success":true,"summary":{"domain":"example.com","scan_id":"550e8400-e29b-41d4-a716-446655440001","scanned_at":"2026-10-02T10:00:00.000Z","age_days":3,"score":82,"grade":"B","trend":{"previous_score":76,"previous_grade":"C","delta":6,"direction":"up"},"findings":{"total":14,"high":1,"medium":5,"low":8},"categories":{"gdpr":{"index":88,"high":0,"medium":2,"low":4},"a11y":{"index":71,"high":1,"medium":2,"low":3},"seo":{"index":93,"high":0,"medium":1,"low":0},"security":{"index":90,"high":0,"medium":1,"low":2}},"report_url":"https://empedia.cloud/scans-detail.html?id=550e8400-e29b-41d4-a716-446655440001","pdf_url":"https://empedia.cloud/api/user/scans/550e8400-e29b-41d4-a716-446655440001/pdf"}}}}},"400":{"description":"Parameter domain is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No completed audit exists for this domain yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]}],"x-required-scopes":{"scopes":["scan:read"],"mode":"all"}}},"/api/audit/report":{"post":{"tags":["Reports & AI"],"operationId":"report-pdf","summary":"PDF report from scan result","description":"Creates a branded PDF report from an existing scan JSON. No new scan — ideal if the result is already available. Optional aiAnalysis field for an AI-assisted section.","parameters":[],"responses":{"200":{"description":"PDF binary, Content-Type: application/pdf, Content-Disposition: attachment","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"scanResult is missing or not a valid scan JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportPdfRequest"}}}}}},"/api/audit/report/html":{"post":{"tags":["Reports & AI"],"operationId":"report-html","summary":"HTML report from scan result","description":"Like /report, but as a complete HTML document with embedded CSS. For direct display in the browser or embedding in your own portals.","parameters":[],"responses":{"200":{"description":"text/html; charset=utf-8 — complete HTML page with CSS","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"scanResult is missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportHtmlRequest"}}}}}},"/api/audit/scan-and-report":{"post":{"tags":["Reports & AI"],"operationId":"scan-and-report","summary":"Scan + PDF in one call","description":"Runs a complete scan and returns the PDF report directly. With \"ai\":true, an AI analysis report is also included (takes longer, ~30–60 s extra).","parameters":[],"responses":{"200":{"description":"PDF binary, Content-Type: application/pdf","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified (security scans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanAndReportRequest"},"example":{"url":"https://example.com","options":{"ai":false,"customerName":"Musterfirma GmbH","language":"de","screenshot":true}}}}}}},"/api/audit/scan-and-report/html":{"post":{"tags":["Reports & AI"],"operationId":"scan-and-report-html","summary":"Scan + HTML report in one call","description":"Like scan-and-report, but returns an HTML document instead of a PDF. Useful for web display or email integration.","parameters":[],"responses":{"200":{"description":"text/html; charset=utf-8","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"Invalid URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified (security scans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanAndReportHtmlRequest"},"example":{"url":"https://example.com","options":{"ai":false,"customerName":"Musterfirma GmbH","language":"de"}}}}}}},"/api/user/scans/{id}/analyze":{"post":{"tags":["Reports & AI"],"operationId":"ai-analyze","summary":"Start AI analysis","description":"Starts the AI-assisted evaluation of a stored scan asynchronously. Immediate response — poll the status via /analyze-status. Returns \"ready\" directly if an analysis already exists.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan ID (UUID) from the scan history","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAnalyzeResponse"},"example":{"success":true,"status":"generating"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"No AI provider configured or analysis failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"}}},"/api/user/scans/{id}/analyze-status":{"get":{"tags":["Reports & AI"],"operationId":"ai-analyze-status","summary":"AI analysis status","description":"Polls the status of the running AI analysis. Status: \"generating\" (in progress), \"ready\" (done), \"idle\" (not started yet), \"error\" (failed).","parameters":[{"name":"id","in":"path","required":true,"description":"Scan ID (UUID)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAnalyzeStatusResponse"},"example":{"status":"ready"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]}],"x-required-scopes":{"scopes":["scan:read"],"mode":"all"}}},"/api/user/scans/{id}/pdf":{"get":{"tags":["Reports & AI"],"operationId":"ai-pdf","summary":"Download PDF report (8 types)","description":"Downloads a specialized PDF report. The query parameter `type` determines which sections are included. If an AI analysis exists, it is embedded automatically. For `nis2` and `dora`, the compliance mappers are run on the fly (including the latest questionnaire context). **Scoped scans:** If only a subset of modules was scanned (purchased single product such as `seo-geo-audit`/`bfsg-audit`, or manually deselected modules), the server enforces the report type matching the scan — the `type` parameter is then ignored, so `?type=full` cannot unlock areas that were not scanned.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan ID (UUID)","schema":{"type":"string"}},{"name":"type","in":"query","required":false,"description":"full (default) | security | gdpr | accessibility | seo_geo | wordpress | individual | nis2 | dora — wordpress (WordPress emergency report) is used automatically for WP Emergency Check scans, individual is used automatically for scans with several, but not all, topic areas","schema":{"type":"string"}}],"responses":{"200":{"description":"PDF binary, Content-Type: application/pdf, Content-Disposition: attachment; filename=\"empediacloud-example-com-security-abc123.pdf\"","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["report:read"]},{"oauth2":["report:read"]}],"x-required-scopes":{"scopes":["report:read"],"mode":"all"}}},"/api/user/scans/{id}/findings":{"get":{"tags":["Reports & AI"],"operationId":"scan-findings-export","summary":"Export findings (JSON, CSV, SARIF)","description":"Machine-readable export of all findings of a website scan with the **location per page and element** (page URL, CSS path of the element, text, detail, HTML snippet). Accessibility and SEO findings are merged per rule for the whole website: `pages_affected`/`pages_checked`/`count_total`, `pages[]` (affected pages with elements) and `template_elements[]` (elements that occur identically on a large share of the pages – header, footer, navigation – and need to be fixed once in the template). `format=json` returns the schema `auditcollector.findings/1` including area grades (`scan.scores`) and coverage; `format=csv` one row per location (UTF-8 with BOM, formula characters are neutralized); `format=sarif` SARIF 2.1.0 for developer tools. For a restricted scope (single audit), the export contains only the findings of the scanned area.","parameters":[{"name":"id","in":"path","required":true,"description":"Scan ID (UUID)","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"json (default) | csv | sarif","schema":{"type":"string","enum":["json","csv","sarif"]}}],"responses":{"200":{"description":"{\"schema\":\"auditcollector.findings/1\",\"scan\":{\"id\":\"3f1c…\",\"target\":\"https://example.com\",\"score\":86,\"grade\":\"B\",\"scores\":{\"version\":2,\"score\":86,\"grade\":\"B\",\"buckets\":{\"a11y\":{\"score\":86,\"grade\":\"B\"}}}},\"coverage\":{\"discovered\":413,\"crawled\":274,\"skipped\":138},\"findings\":[{\"rule\":\"a11y-empty-button","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Scope report:read missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["report:read"]},{"oauth2":["report:read"]}],"x-required-scopes":{"scopes":["report:read"],"mode":"all"}}},"/api/user/ai-consent":{"get":{"tags":["Reports & AI"],"operationId":"ai-consent-get","summary":"Get AI consent","description":"Returns whether the user has permanently consented to AI data sharing (remember=true) and when the consent was given.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiConsentGetResponse"},"example":{"remembered":true,"consent_at":"2026-04-19T10:00:00.000Z"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["Reports & AI"],"operationId":"ai-consent-save","summary":"Save AI consent","description":"Saves the permanent consent to AI data sharing. After that, the consent dialog no longer appears before AI analyses.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiConsentSaveResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"delete":{"tags":["Reports & AI"],"operationId":"ai-consent-revoke","summary":"Revoke AI consent","description":"Revokes the stored AI consent. The consent dialog appears again before the next AI analysis.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiConsentRevokeResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/compliance/overview":{"get":{"tags":["Compliance"],"operationId":"compliance-overview","summary":"GDPR and accessibility status per domain","description":"Summarizes, per domain (without www, across all spellings of the target URL), the latest GDPR and BFSG status from all scans of the organization that include the area: full scans, scheduled scans and GDPR/BFSG audits. Quick checks, WordPress and consent watchers are not counted. The value is the GDPR score of a GDPR scan, otherwise an index derived from the area's findings (100 − 8 per high, 3 per medium, 1 per low). Levels: ok ≥ 90, partial ≥ 70, otherwise critical.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplianceOverviewResponse"},"example":{"success":true,"domains":[{"domain":"example.org","last_scan_at":"2026-10-10T09:00:00.000Z","statement_at":null,"gdpr":{"score":89,"level":"partial","high":1,"medium":0,"scan_id":"1fe76b67-c53e-11f1-89b4-02fc00000001","at":"2026-10-10T09:00:00.000Z","native":false},"a11y":null}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read"]},{"oauth2":["scan:read"]}],"x-required-scopes":{"scopes":["scan:read"],"mode":"all"}}},"/.well-known/openid-configuration":{"get":{"tags":["OIDC Provider"],"operationId":"oidc-discovery","summary":"Discovery document","description":"OpenID Connect discovery document with all endpoint URLs, supported scopes, algorithms and claims.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcDiscoveryResponse"},"example":{"issuer":"https://empedia.cloud","authorization_endpoint":"https://empedia.cloud/oauth/authorize","token_endpoint":"https://empedia.cloud/oauth/token","userinfo_endpoint":"https://empedia.cloud/oauth/userinfo","jwks_uri":"https://empedia.cloud/.well-known/jwks.json","revocation_endpoint":"https://empedia.cloud/oauth/revoke","introspection_endpoint":"https://empedia.cloud/oauth/introspect","registration_endpoint":"https://empedia.cloud/oauth/register","response_types_supported":["code"],"grant_types_supported":["authorization_code","refresh_token"],"id_token_signing_alg_values_supported":["RS256"],"scopes_supported":["openid","profile","email","offline_access","scan:read","scan:write","report:read","code:audit"],"code_challenge_methods_supported":["S256"]}}}}},"security":[]}},"/.well-known/jwks.json":{"get":{"tags":["OIDC Provider"],"operationId":"oidc-jwks","summary":"JWKS (public keys)","description":"JSON Web Key Set — public RSA-2048 keys for verifying ID tokens (RS256).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcJwksResponse"},"example":{"keys":[{"kty":"RSA","n":"...","e":"AQAB","kid":"a1b2c3d4","use":"sig","alg":"RS256"}]}}}}},"security":[]}},"/oauth/token":{"post":{"tags":["OIDC Provider"],"operationId":"oidc-token","summary":"Token exchange","description":"Issues access tokens. **`grant_type=client_credentials`** (server-to-server, recommended for integrations): exchange the client ID and secret of a service client (Settings → API access) for a short-lived access token (default 1 hour, no refresh token); optional `scope` (space-separated, subset of the allowed scopes). **`authorization_code`**: exchanges an authorization code for access token + ID token + (optional) refresh token; PKCE (`code_verifier`) for public clients. **`refresh_token`**: renews tokens. Client authentication via HTTP Basic (`client_secret_basic`) or in the body (`client_secret_post`). Body: application/x-www-form-urlencoded.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcTokenResponse"},"example":{"access_token":"a1b2c3...","token_type":"Bearer","expires_in":3600,"scope":"scan:read scan:write"}}}},"400":{"description":"invalid_grant (code/refresh token invalid), invalid_scope (scope not allowed), unauthorized_client (client is not a service client) or unsupported_grant_type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_client — client authentication failed (client_id/secret)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/oauth/userinfo":{"get":{"tags":["OIDC Provider"],"operationId":"oidc-userinfo","summary":"Userinfo","description":"Returns user info (depending on the granted scopes: `email`, `profile`). Requires an OIDC access token in the `Authorization: Bearer` header.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcUserinfoResponse"},"example":{"sub":"42","email":"jane@example.com","email_verified":true,"name":"Jane Doe","given_name":"Jane","family_name":"Doe"}}}},"401":{"description":"OIDC access token invalid or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["openid"]},{"oauth2":["openid"]}],"x-required-scopes":{"scopes":["openid"],"mode":"all"}}},"/oauth/revoke":{"post":{"tags":["OIDC Provider"],"operationId":"oidc-revoke","summary":"Revoke token","description":"Immediately revokes an access token or refresh token. Afterwards, all API calls with this token are rejected with 401.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRevokeResponse"},"example":{}}}},"400":{"description":"Token missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/oauth/introspect":{"post":{"tags":["OIDC Provider"],"operationId":"oidc-introspect","summary":"Token introspection","description":"Checks whether an access token is active and returns metadata (sub, scope, exp). Useful for server-to-server communication.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcIntrospectResponse"},"example":{"active":true,"scope":"openid scan:read","client_id":"oidc_abc123","sub":"42","email":"jane@example.com","exp":1714000000,"iat":1713996400}}}},"400":{"description":"Token missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Client authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/oauth/register":{"post":{"tags":["OIDC Provider"],"operationId":"oidc-register","summary":"Dynamic Client Registration (RFC 7591)","description":"Space-separated; trimmed to the allowlist: openid, profile, email, offline_access, scan:read, scan:write, report:read, monitor:read (excludes code:audit, monitor:write and domain:*)","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRegisterResponse"},"example":{"client_id":"mcp_a1b2c3...","client_id_issued_at":1714000000,"client_name":"Claude","redirect_uris":["https://claude.ai/api/mcp/auth_callback"],"scope":"openid profile scan:read scan:write report:read","token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"]}}}},"400":{"description":"redirect_uris missing or contains a disallowed URI","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit reached (10 registrations/hour/IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRegisterRequest"},"example":{"client_name":"Claude","redirect_uris":["https://claude.ai/api/mcp/auth_callback"],"scope":"openid profile scan:read scan:write report:read","token_endpoint_auth_method":"none"}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["OIDC Provider"],"operationId":"oidc-protected-resource","summary":"Protected Resource Metadata (for /mcp)","description":"Tells MCP clients which authorization server is responsible for the `/mcp` endpoint — referenced by a `401` response on `/mcp` via the `WWW-Authenticate` header so that the client can start the OAuth flow automatically.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProtectedResourceResponse"},"example":{"resource":"https://empedia.cloud/mcp","authorization_servers":["https://empedia.cloud"],"scopes_supported":["scan:read","scan:write","report:read"]}}}}},"security":[]}},"/mcp":{"post":{"tags":["OIDC Provider"],"operationId":"mcp-endpoint","summary":"MCP endpoint (Model Context Protocol)","description":"Not a regular REST/JSON endpoint, but an MCP server over the Streamable HTTP transport (JSON-RPC 2.0) — intended for AI agents such as Claude or ChatGPT, not for direct calls from your own code. Auth via OAuth access token (`Authorization: Bearer`), no API key. Provides 8 tools: start_scan, get_job_status, list_scans, get_scan, get_scan_pdf, generate_ai_report, get_ai_report_status, list_available_presets. Setup details: see `mcp-server/README.md` (repo) or the guide \"Connect EMPEDIAcloud to Claude/ChatGPT\".","parameters":[],"responses":{"200":{"description":"JSON-RPC 2.0 over Streamable HTTP — no simple JSON example","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid access token (WWW-Authenticate points to /.well-known/oauth-protected-resource)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:read","scan:write","report:read"]},{"oauth2":["scan:read","scan:write","report:read"]}],"x-required-scopes":{"scopes":["scan:read","scan:write","report:read"],"mode":"all"}}},"/api/user/oidc-clients":{"get":{"tags":["OIDC Provider"],"operationId":"oidc-clients-list","summary":"List OIDC clients","description":"Lists all OIDC client apps of your own organization.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcClientsListResponse"},"example":{"clients":[{"id":"550e8400-e29b-41d4-a716-446655440000","client_id":"oidc_abc123","name":"My App","is_public":false,"allowed_scopes":["openid","email","scan:read"],"enabled":true,"created_at":"2026-04-19T10:00:00.000Z"}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["OIDC Provider"],"operationId":"oidc-clients-create","summary":"Register OIDC client","description":"Registers a new OIDC app. The `client_secret` is returned **once** in the response — it cannot be retrieved afterwards. For public clients (SPAs, mobile), set `is_public: true` — then there is no secret and PKCE is required instead. For **server-to-server integrations**, set `service_client: true` (no `redirect_uris` needed, API scopes only): the client obtains short-lived tokens via `client_credentials`. The token acts on behalf of the user who created the client.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcClientsCreateResponse"},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","client_id":"oidc_a1b2c3d4e5f6a1b2c3d4e5f6","client_secret":"secret-shown-once-store-securely"}}}},"400":{"description":"name or redirect_uris missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcClientsCreateRequest"},"example":{"name":"My Integration","redirect_uris":["https://myapp.example.com/callback"],"is_public":false,"allowed_scopes":["openid","email","scan:read"]}}}}}},"/api/user/oidc-clients/{id}/rotate-secret":{"post":{"tags":["OIDC Provider"],"operationId":"oidc-clients-rotate","summary":"Rotate client secret","description":"Generates a new client secret. The old secret becomes invalid immediately. Confidential clients only (not public).","parameters":[{"name":"id","in":"path","required":true,"description":"Client ID (UUID) from the list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcClientsRotateResponse"},"example":{"client_secret":"new-secret-shown-once"}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/user/oidc-clients/{id}":{"delete":{"tags":["OIDC Provider"],"operationId":"oidc-clients-delete","summary":"Delete OIDC client","description":"Deletes the app registration. All issued tokens become invalid.","parameters":[{"name":"id","in":"path","required":true,"description":"Client ID (UUID) from the list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcClientsDeleteResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/user/connected-apps":{"get":{"tags":["OIDC Provider"],"operationId":"connected-apps-list","summary":"List connected apps","description":"Consumer view (counterpart to the oidc-clients endpoints above, which manage the apps provided by your own account): lists third-party apps to which the current user has granted access via the OAuth consent screen — e.g. an MCP connector such as Claude or ChatGPT. Reachable only via a dashboard session (JWT), not via API keys or OAuth tokens themselves.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAppsListResponse"},"example":{"success":true,"apps":[{"client_id":"mcp_a1b2c3...","name":"Claude","description":null,"logo_url":null,"registration_type":"dynamic","scope":"openid scan:read scan:write report:read","granted_at":"2026-09-01T10:00:00.000Z"}]}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access via API key or OAuth token (dashboard session only)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/user/connected-apps/{clientId}":{"delete":{"tags":["OIDC Provider"],"operationId":"connected-apps-revoke","summary":"Revoke access of a connected app","description":"Deletes the granted consent (oidc_consents) and immediately revokes all still-valid access/refresh tokens of this app for the current user. The app must then go through the full OAuth flow (including the consent screen) again to regain access.","parameters":[{"name":"clientId","in":"path","required":true,"description":"The OAuth client_id string (not the internal app UUID) from the connected-apps list","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAppsRevokeResponse"},"example":{"success":true}}}},"401":{"description":"No valid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Access via API key or OAuth token (dashboard session only)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No consent found for this app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/audit/start-async":{"post":{"tags":["Async jobs"],"operationId":"audit-start-async","summary":"Start scan as background job","description":"Starts a (possibly multi-step) scan asynchronously and returns a job_id. Progress via GET /api/jobs/:id/stream (SSE). Requires the scan:write scope and a verified domain. **Safely retryable:** with the `Idempotency-Key` header (8–128 characters, e.g. a UUID), a repeated request within 24 hours returns the same response (header `Idempotent-Replayed: true`) without starting a second scan or consuming quota. Different body with the same key → 422, request still in progress → 409.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key per intended action (e.g. UUID); valid for 24 hours","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditStartAsyncResponse"},"example":{"success":true,"job_id":"550e8400-e29b-41d4-a716-446655440000","status":"pending"}}}},"400":{"description":"No module selection (`no_modules_selected`) or unknown module","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Scan quota exhausted, module not in the plan, or preset neither in the plan nor purchased","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Domain not verified / missing scan:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many queued scans (at most 5 per organization and no more than the remaining quota)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["scan:write"]},{"oauth2":["scan:write"]}],"x-required-scopes":{"scopes":["scan:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditStartAsyncRequest"},"example":{"url":"https://example.com","checks":{"security":[],"dns":[]},"maxPages":20}}}}}},"/api/code/analyze-async":{"post":{"tags":["Async jobs"],"operationId":"code-analyze-async","summary":"Code audit (upload) as job","description":"Uploads an archive (.zip/.tar/.tar.gz, multipart/form-data field \"file\") and starts the analysis as a background job. Optional fullAiScan=true.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeAnalyzeAsyncResponse"},"example":{"success":true,"job_id":"uuid"}}}},"400":{"description":"No file / invalid format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CodeAnalyzeAsyncRequest"}}}}}},"/api/code/connect-async":{"post":{"tags":["Async jobs"],"operationId":"code-connect-async","summary":"Code audit (Git/SFTP/FTP) as job","description":"Fetches source code via Git/SFTP/FTP and starts the analysis as a background job. Target hosts are checked against private/internal addresses (SSRF).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectAsyncResponse"},"example":{"success":true,"job_id":"uuid"}}}},"400":{"description":"Invalid connection data / private address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeConnectAsyncRequest"},"example":{"method":"git","repoUrl":"https://github.com/org/repo.git","branch":"main"}}}}}},"/api/code/test-connection":{"post":{"tags":["Async jobs"],"operationId":"code-test-connection","summary":"Test connection","description":"Checks Git/SFTP/FTP reachability (rate-limited). On failure, HTTP 500 with {success:false} is returned.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeTestConnectionResponse"},"example":{"success":true,"message":"SFTP-Verbindung erfolgreich"}}}},"429":{"description":"Rate limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["code:audit"]},{"oauth2":["code:audit"]}],"x-required-scopes":{"scopes":["code:audit"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeTestConnectionRequest"},"example":{"method":"sftp","host":"sftp.example.com","port":22,"username":"user","password":"..."}}}}}},"/api/webhooks":{"get":{"tags":["Webhooks & Badges"],"operationId":"webhooks-list","summary":"List webhooks","description":"All webhook endpoints of the organization and the available event types. The signing secrets cannot be retrieved.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksListResponse"},"example":{"success":true,"webhooks":[{"id":"…","url":"https://example.com/hooks/auditcollector","enabled":true,"events":["scan.completed","score.degraded"],"failure_count":0,"last_success_at":"2026-10-02T10:00:00.000Z","last_failure_at":null,"created_at":"2026-10-01T09:00:00.000Z"}],"events":{"scan.completed":"Ein Website-Audit wurde abgeschlossen","monitor.down":"Ein Monitor meldet einen Ausfall bzw. eine Störung"}}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["Webhooks & Badges"],"operationId":"webhooks-create","summary":"Create webhook","description":"Creates an endpoint (https only, no internal addresses; at most 10). The signing secret (`secret`, prefix `whsec_`) is returned **only once**. Empty `events` list = all events. Delivery, signature and retries: see the \"Webhooks\" guide.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksCreateResponse"},"example":{"success":true,"webhook":{"id":"…","url":"https://example.com/hooks/auditcollector","enabled":true,"events":["scan.completed"]},"secret":"whsec_…nur-einmal-sichtbar"}}}},"400":{"description":"Invalid or internal URL, limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksCreateRequest"},"example":{"url":"https://example.com/hooks/auditcollector","events":["scan.completed","score.degraded","monitor.down"]}}}}}},"/api/webhooks/{id}":{"patch":{"tags":["Webhooks & Badges"],"operationId":"webhooks-update","summary":"Update webhook","description":"Changes the URL, events, or enables/disables the endpoint. Re-enabling resets the failure counter.","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksUpdateResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksUpdateRequest"},"example":{"enabled":true}}}}},"delete":{"tags":["Webhooks & Badges"],"operationId":"webhooks-delete","summary":"Delete webhook","description":"Removes the endpoint including its delivery log.","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/webhooks/{id}/rotate-secret":{"post":{"tags":["Webhooks & Badges"],"operationId":"webhooks-rotate","summary":"Rotate signing secret","description":"Generates a new secret (visible only once); the old one becomes invalid immediately.","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksRotateResponse"},"example":{"success":true,"secret":"whsec_…"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/webhooks/{id}/test":{"post":{"tags":["Webhooks & Badges"],"operationId":"webhooks-test","summary":"Send test event","description":"Synchronously sends a signed `ping` event and returns the HTTP status of your server.","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksTestResponse"},"example":{"success":true,"result":{"ok":true,"status":200}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks & Badges"],"operationId":"webhooks-deliveries","summary":"Delivery log","description":"The last 30 deliveries with status (`pending`, `delivered`, `failed`), attempts and response code.","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksDeliveriesResponse"},"example":{"success":true,"deliveries":[{"id":"…","event":"scan.completed","status":"delivered","attempts":1,"response_code":200,"error":null,"created_at":"2026-10-02T10:00:00.000Z"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/user/badges":{"get":{"tags":["Webhooks & Badges"],"operationId":"badges-list","summary":"List badges","description":"All badges of the organization with embed code.","parameters":[],"responses":{"200":{"description":"{\"success\":true,\"badges\":[{\"id\":\"…\",\"domain\":\"example.com\",\"embed\":{\"image_url\":\"https://empedia.cloud/api/public/badge/TOKEN.svg\",\"json_url\":\"https://empedia.cloud/api/public/badge/TOKEN.json\",\"html\":\"<img src=\"…\" alt=\"Website-Check example.com\" width=\"220\" height=\"64\">\"}}]}","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"},"post":{"tags":["Webhooks & Badges"],"operationId":"badges-create","summary":"Create badge for a domain","description":"Creates a public badge, revocable at any time, for a **verified** domain of your organization. It shows the grade of the latest check; after 35 days without a new check it shows \"Check expired\".","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadgesCreateResponse"},"example":{"success":true,"badge":{"id":"…","domain":"example.com","embed":{"image_url":"https://empedia.cloud/api/public/badge/TOKEN.svg","html":"<img …>"}}}}}},"400":{"description":"Domain not verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Badge already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadgesCreateRequest"},"example":{"domain":"example.com"}}}}}},"/api/user/badges/{id}":{"delete":{"tags":["Webhooks & Badges"],"operationId":"badges-delete","summary":"Delete badge","description":"Revokes the badge immediately; embedded images show nothing afterwards.","parameters":[{"name":"id","in":"path","required":true,"description":"Badge UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadgesDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionToken":[]}],"x-auth-note":"Dashboard session (login) only, not available with access tokens"}},"/api/public/badge/{token}.svg":{"get":{"tags":["Webhooks & Badges"],"operationId":"badge-public","summary":"Get badge (SVG)","description":"Public image for websites (`<img>`); cached for 15 minutes. With `.json` instead of `.svg`, the raw data is returned: `domain`, `grade`, `score`, `scanned_at`, `valid`.","parameters":[{"name":"token","in":"path","required":true,"description":"Badge token","schema":{"type":"string"}}],"responses":{"200":{"description":"SVG, Content-Type: image/svg+xml","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Badge unknown or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/email-security":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-list","summary":"Domains with email reports (DMARC, TLS-RPT)","description":"Lists the organization's domains with their report address (applies to DMARC and TLS-RPT), quota, and metrics for the last 30 days (DMARC emails, TLS sessions, status of both setups). Report reception is a server feature (`enabled`); the quota comes from the plan (Monitor Pro 1, Business 3, Agency 5, Agency Pro 15, more via add-on).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityListResponse"},"example":{"success":true,"enabled":true,"rua_domain":"rua.empedia.cloud","quota":5,"used":1,"domains":[{"id":"uuid","domain":"kunde.de","rua":"r-0123456789abcdef@rua.empedia.cloud","last_report_at":"2026-10-02T06:10:00Z","total_30d":1480,"pass_30d":1390,"alert":{"enabled":true,"min_mails":10,"pass_below":90}}]}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"post":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-create","summary":"Add domain","description":"Creates a domain and generates the report address `r-<token>@<rua-domain>`. Enter this address in the domain's DMARC record under `rua=` (append to existing addresses with a comma). Reports usually arrive after 24–48 hours.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityCreateResponse"},"example":{"success":true,"domain":{"id":"uuid","domain":"kunde.de","rua":"r-0123456789abcdef@rua.empedia.cloud"}}}}},"400":{"description":"Invalid domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not included in the plan or quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Domain already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Reception not enabled on this server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityCreateRequest"},"example":{"domain":"kunde.de"}}}}}},"/api/email-security/{id}/summary":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-summary","summary":"Domain analysis","description":"Totals, daily trend, and sender sources (with reverse DNS name; `is_new` marks sources that did not appear before the period). \"Passed\" means SPF or DKIM passed and aligned with the domain.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"7 | 30 | 90 | 365 (default 30)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecuritySummaryResponse"},"example":{"success":true,"summary":{"days":30,"reports":42,"totals":{"total":1480,"pass":1390,"quarantined":12,"rejected":3},"daily":[{"day":"2026-09-30","total":52,"pass":49}],"sources":[{"ip":"209.85.220.41","ptr":"mail-sor-f41.google.com","total":900,"pass":900,"fail":0,"is_new":false}]}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-get","summary":"Domain with setup and settings","description":"Master data, report address (`rua`), setup status (`setup`: status, last checked, existing record, other `rua` recipients, ready-made suggestion), alert thresholds, and notification channels.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityGetResponse"},"example":{"success":true,"domain":{"id":"uuid","domain":"kunde.de","rua":"r-0123456789abcdef@rua.empedia.cloud","setup":{"status":"rua_missing","checked_at":"2026-10-03T08:00:00.000Z","record":"v=DMARC1; p=reject; rua=mailto:dmarc@kunde.de","existing_rua":["dmarc@kunde.de"],"authorized":true,"suggested_record":"v=DMARC1; p=reject; rua=mailto:dmarc@kunde.de,mailto:r-0123456789abcdef@rua.empedia.cloud"},"alert":{"enabled":true,"min_mails":10,"pass_below":90,"setup_lost":true,"no_report_days":7},"alert_channels":{"email":{"enabled":true,"recipients":["raw:it@kunde.de"],"notify_on":"always"}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"patch":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-update","summary":"Configure alerting and notifications","description":"Enables or disables alerting per domain and sets the thresholds. Alerts on a new source without passing SPF/DKIM (from `alert_min_mails` emails; the first three reports of a domain do not trigger an alert) and on a daily pass rate below `alert_pass_below` percent (from 20 emails per day).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityUpdateResponse"},"example":{"success":true,"domain":{"id":"uuid","domain":"kunde.de","alert":{"enabled":true,"min_mails":10,"pass_below":90}}}}}},"400":{"description":"Value outside the allowed range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityUpdateRequest"},"example":{"alert_enabled":true,"alert_min_mails":10,"alert_pass_below":90}}}}},"delete":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-delete","summary":"Remove domain","description":"Removes the domain including all stored reports.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}}},"/api/email-security/{id}/reports":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-reports","summary":"Report log","description":"Received aggregate reports, newest first: reporter (e.g. google.com), period, emails, of which passed, policy.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page (default 1)","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"5–100 (default 20)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityReportsResponse"},"example":{"success":true,"total":42,"page":1,"per_page":20,"reports":[{"id":"uuid","org_name":"google.com","report_id":"1234567890","begin_at":"2026-10-02T00:00:00.000Z","end_at":"2026-10-03T00:00:00.000Z","policy_p":"none","total_count":112,"pass":112}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/reports/{rid}":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-report","summary":"Single report","description":"All rows (sources) of a report with hostname, emails, disposition, DKIM/SPF alignment, and domains.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"description":"Report UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityReportResponse"},"example":{"success":true,"report":{"id":"uuid","org_name":"google.com","report_id":"1234567890","policy_p":"none","total":112},"rows":[{"ip":"209.85.220.41","ptr":"mail-sor-f41.google.com","count":112,"disposition":"none","dkim":true,"spf":true,"header_from":"kunde.de","dkim_domain":"kunde.de","dkim_selector":"s1","spf_domain":"kunde.de"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/tlsrpt/summary":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-tlsrpt-summary","summary":"TLS-RPT: domain analysis","description":"TLS-RPT reports (RFC 8460): total sessions, daily trend, failure types (`result_type` with hint text), affected mail servers (MX), policy types (MTA-STS, DANE, none), and reporters. Same report address as for DMARC; the TXT record `_smtp._tls.<domain>` is available with status and suggestion in `GET /api/email-security/:id` under `tlsrpt`.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"7 | 30 | 90 | 365 (default 30)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityTlsrptSummaryResponse"},"example":{"success":true,"summary":{"days":30,"totals":{"success":900,"failure":100},"daily":[{"day":"2026-10-07","success":180,"failure":10}],"by_type":[{"result_type":"certificate-expired","count":60,"mx_count":1,"last_day":"2026-10-06","advice":"…"}],"by_mx":[{"mx":"mx1.kunde.de","count":80,"types":["certificate-expired"]}],"by_policy":[{"policy_type":"sts","success":800,"failure":90}],"reporters":[{"org_name":"Google Inc.","reports":5,"success":600,"failure":50,"last_at":"2026-10-08T01:00:00.000Z"}],"reports":10,"last_report_at":"2026-10-08T01:05:00.000Z"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/tlsrpt/reports":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-tlsrpt-reports","summary":"TLS-RPT: report log","description":"Received TLS-RPT reports, paginated (newest first).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–200 (default 25)","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Default 0","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search in reporter and report ID","schema":{"type":"string"}},{"name":"result","in":"query","required":false,"description":"`failed` = only reports with failures, `ok` = without failures","schema":{"type":"string","enum":["failed","ok"]}},{"name":"sort","in":"query","required":false,"description":"`from`, `period`, `sessions`, `failed`","schema":{"type":"string"}},{"name":"dir","in":"query","required":false,"description":"`asc` or `desc`","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityTlsrptReportsResponse"},"example":{"success":true,"total":10,"limit":25,"offset":0,"reports":[{"id":"uuid","org_name":"Google Inc.","report_id":"2026-10-07T00:00:00Z_kunde.de","begin_at":"2026-10-07T00:00:00.000Z","end_at":"2026-10-07T23:59:59.000Z","success_count":90,"failure_count":10}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/tlsrpt/reports/{rid}":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-tlsrpt-report","summary":"TLS-RPT: single report","description":"One report with policies (type, domain, sessions) and failure rows (failure type, sending IP, receiving MX, count, reason).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"description":"Report UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityTlsrptReportResponse"},"example":{"success":true,"report":{"id":"uuid","org_name":"Google Inc.","report_id":"…","begin_at":"…","end_at":"…","contact":"smtp-tls-reporting@google.com","success":90,"failure":10},"policies":[{"type":"sts","domain":"kunde.de","success":90,"failure":10}],"failures":[{"policy_type":"sts","result_type":"certificate-expired","sending_ip":"209.85.220.41","receiving_mx":"mx1.kunde.de","receiving_ip":"203.0.113.5","count":10,"reason":null}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/export.csv":{"get":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-export","summary":"CSV export","description":"Sources (`kind=sources`, with `days`) or report log (`kind=reports`) as CSV (semicolon, UTF-8 with BOM, cells protected against formula injection).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"sources (default) | reports","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"7 | 30 | 90 | 365 (sources only)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Quelle (IP);Hostname;E-Mails;DMARC bestanden;…","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/check":{"post":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-check","summary":"Check setup","description":"Checks live via DNS (the check otherwise runs automatically: hourly until setup is complete, daily afterwards; calls within 20 seconds return the stored result). `status`: ok | waiting (set up, no report yet) | record_missing | rua_missing | unauthorized | unknown. `setup.suggested_record` is the ready-made TXT value for `_dmarc.<domain>`: for an existing record, our address is added to `rua=`, never replaced. Additionally, the rest of the previous description: checks live via DNS whether the domain's DMARC record contains the report address and whether the authorization of the report domain is reachable.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityCheckResponse"},"example":{"success":true,"status":"ok","record":"v=DMARC1; p=none; rua=mailto:r-0123456789abcdef@rua.empedia.cloud","authorized":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/email-security/{id}/token":{"post":{"tags":["Email security (DMARC and TLS-RPT)"],"operationId":"email-security-token","summary":"Renew report address","description":"Generates a new report address. The old one becomes invalid immediately (emails to it are rejected) — the `rua=` record in DNS must be changed afterwards, otherwise no more reports will arrive. Stored reports are retained.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSecurityTokenResponse"},"example":{"success":true,"domain":{"id":"uuid","domain":"kunde.de","rua":"r-fedcba9876543210@rua.empedia.cloud"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}}},"/api/domain-portfolio/domains":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-list_","summary":"Domains of the organization","description":"Lists the domains with expiry date, nameserver set, auto-renewal and deletion mark. Filters `quick` (expiring, cancelled, nozone), `ns_set`, `renew`; sorting via `sort` (name, ns, expire, renew) and `dir`. The \"Domains\" area must be enabled for the organization, otherwise 404.","parameters":[{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsList_Response"},"example":{"success":true,"total":1,"domains":[{"id":"uuid","name":"kunde.de","ns_set":"urbandomains","expire_at":"2027-03-01","cancelation":null,"auto_renew":"TRUE","has_zone":true,"zone_records":12}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/domains/{id}":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-get","summary":"Domain details","description":"Shows contacts (handles), name servers, DNSSEC state, and zone of a domain belonging to the own organization.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsGetResponse"},"example":{"success":true,"domain":{"id":"uuid","name":"kunde.de","ns_set":"urbandomains","nameservers":["ns1.urbandomains.de","ns2.urbandomains.de"],"expire_at":"2027-03-01","auto_renew":"TRUE","has_zone":true}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}},"patch":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-update","summary":"Change domain","description":"Changes auto-renewal (`auto_renew`), name servers (`ns_profile` or `nameservers`, 2–13), and owner/admin contact. For TLDs that charge for changes (e.g. owner change), the fee is deducted from the credit balance in advance. Changes are only possible when write access is enabled by the operator (otherwise 409).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsUpdateResponse"},"example":{"success":true}}}},"409":{"description":"Change not possible (e.g. dnssec_active, order_pending, fee_unknown)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsUpdateRequest"},"example":{"auto_renew":"TRUE"}}}}}},"/api/domain-portfolio/orders/quote":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-quote","summary":"Price and availability of a registration","description":"Returns the current net price (from the price list, never from memory), the minimum term, and the credit balance. Pass the price as `expect_net_cents` when ordering; if it has changed, the order is rejected with `price_changed`.","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain name","schema":{"type":"string"}},{"name":"years","in":"query","required":false,"description":"Term in years","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsQuoteResponse"},"example":{"success":true,"quote":{"domain":"kunde.de","years":1,"net_cents":1290,"balance_cents":5000}}}}},"409":{"description":"Price missing (price_missing) or on request only (price_on_request)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/orders/register":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-register_","summary":"Register domain","description":"Registers a domain. **Billable:** the amount is deducted from the credit balance in advance (prepayment, no credit limit) and automatically refunded on failure; on success the invoice follows on the same day. The order runs asynchronously (response 202); the result is delivered via webhook `domain.order.completed` or `domain.order.failed`, or via `GET /orders`. With the `Idempotency-Key` header (8–128 characters), a retry within 24 hours is neither executed nor charged twice. TLDs with special rules (proofs, trustee …) are handled via a request (`POST /requests`).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRegister_Response"},"example":{"success":true,"order":{"id":"uuid","kind":"register","domain":"kunde.de","status":"processing"}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credit balance (prepayment, no credit limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed), order already in progress (order_pending), or price missing (price_missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Idempotency-Key used with a different request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRegister_Request"},"example":{"domain":"kunde.de","years":1,"expect_net_cents":1290,"contacts":{"owner":{}}}}}}}},"/api/domain-portfolio/orders":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-orders","summary":"Orders","description":"Lists orders (registration, renewal, restoration, transfer, paid change) with status `processing`, `completed`, `failed`, or `simulated`, amount, and refund.","parameters":[{"name":"status","in":"query","required":false,"description":"processing | completed | failed | simulated","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsOrdersResponse"},"example":{"success":true,"total":1,"orders":[{"id":"uuid","kind":"register","domain":"kunde.de","status":"completed","net_cents":1290,"charged_cents":1535,"refunded":0}]}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/domains/{id}/renew":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-renew","summary":"Renew domain","description":"Renews the domain at the current list price, charged to the credit balance. With the `Idempotency-Key` header (8–128 characters), a retry within 24 hours is neither executed nor charged twice. ","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRenewResponse"},"example":{"success":true}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credit balance (prepayment, no credit limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed), order already in progress (order_pending), or price missing (price_missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Idempotency-Key used with a different request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRenewRequest"},"example":{"years":1}}}}}},"/api/domain-portfolio/domains/{id}/restore":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-restore","summary":"Restore deleted domain","description":"Restores a domain in its deletion grace period (restoration fee, plus renewal depending on the TLD), charged to the credit balance. With the `Idempotency-Key` header (8–128 characters), a retry within 24 hours is neither executed nor charged twice. ","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsRestoreResponse"},"example":{"success":true}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credit balance (prepayment, no credit limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed), order already in progress (order_pending), or price missing (price_missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Idempotency-Key used with a different request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/domains/{id}/cancel":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-cancel","summary":"Cancel at expiry","description":"Marks the domain for deletion at its expiry date (free of charge). Requires `confirm: true`. The cancellation can be revoked at any time until then (`/uncancel`). Immediate deletion is not available.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsCancelResponse"},"example":{"success":true}}}},"400":{"description":"confirm missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsCancelRequest"},"example":{"confirm":true}}}}}},"/api/domain-portfolio/domains/{id}/uncancel":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"domains-uncancel","summary":"Revoke cancellation","description":"Revokes the deletion mark.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainsUncancelResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/zones/{id}/records":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"zones-records","summary":"Records of a zone","description":"Reads the resource records live. Filter `q`, `quick` (type), sorting `sort`, `dir`. Zones exist only for domains on our name servers.","parameters":[{"name":"id","in":"path","required":true,"description":"Zone ID","schema":{"type":"string"}},{"name":"quick","in":"query","required":false,"description":"Type, e.g. MX","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesRecordsResponse"},"example":{"success":true,"total":2,"records":[{"name":"www","type":"CNAME","value":"kunde.de.","ttl":3600}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}},"patch":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"zones-patch","summary":"Change zone","description":"Adds and removes records in a single step; everything is validated before writing (CNAME conflicts, structure of SRV/CAA/TXT, protected NS at the apex). Warnings (e.g. last MX removed) are returned with the response. Every change is recorded in the change log and can be reverted.","parameters":[{"name":"id","in":"path","required":true,"description":"Zone ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesPatchResponse"},"example":{"success":true}}}},"400":{"description":"Invalid record","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict (e.g. CNAME)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesPatchRequest"},"example":{"add":[{"name":"www","type":"CNAME","value":"kunde.de.","ttl":3600}],"remove":[]}}}}}},"/api/domain-portfolio/zones/{id}/changes":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"zones-changes","summary":"Zone change log","description":"Lists the changes with timestamp, author, source, and affected records.","parameters":[{"name":"id","in":"path","required":true,"description":"Zone ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesChangesResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/zones/{id}/changes/{cid}/rollback":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"zones-rollback","summary":"Revert zone change","description":"Reverts a change as far as the current state allows; skipped records are reported.","parameters":[{"name":"id","in":"path","required":true,"description":"Zone ID","schema":{"type":"string"}},{"name":"cid","in":"path","required":true,"description":"Change ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesRollbackResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/zones/{id}/export":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"zones-export","summary":"Zone as BIND file","description":"Returns the zone in BIND zone file format (backup).","parameters":[{"name":"id","in":"path","required":true,"description":"Zone ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZonesExportResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/certificates/catalog":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-catalog","summary":"Orderable certificates","description":"Lists the orderable products (DV single and wildcard) with terms and net prices. OV, EV, S/MIME, code signing, and other types are handled via a request.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsCatalogResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/certificates/prepare":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-prepare","summary":"Prepare certificate order","description":"Validates the **CSR** (Certificate Signing Request) and returns the name, price, and available validation methods (DNS, email). **Private keys are never accepted or stored** – a private key in the field is rejected with `private_key_rejected`.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsPrepareResponse"},"example":{"success":true}}}},"400":{"description":"Invalid CSR or private key (private_key_rejected)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsPrepareRequest"},"example":{"product_id":12,"months":12,"csr":"-----BEGIN CERTIFICATE REQUEST-----…"}}}}}},"/api/domain-portfolio/certificates/orders":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-order","summary":"Order certificate","description":"Orders the prepared certificate (method `DNS` or `EMAIL`, `confirm: true`; the price comes from the preparation step). Contact: either `contact_id` of a stored certificate contact or `contact` with the details (for this order only). **Chargeable:** prepayment from the credit balance, refunded on failure. If the zone is on our name servers, the validation record is set automatically. Result via webhook `certificate.issued` or `certificate.failed`. With the `Idempotency-Key` header (8–128 characters), a retry within 24 hours is neither executed nor charged twice. ","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsOrderResponse"},"example":{"success":true}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credit balance (prepayment, no credit limit)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed), order already in progress (order_pending), or price missing (price_missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Idempotency-Key used with a different request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsOrderRequest"},"example":{"order_id":"uuid","method":"DNS","confirm":true,"contact":{"fname":"Max","lname":"Muster","email":"max@kunde.de","phone":"+49301234567","address":"Musterstr. 1","pcode":"10115","city":"Berlin","country":"DE"},"expect_net_cents":1990}}}}},"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-orders-list","summary":"Certificate orders","description":"Lists the orders with status and validation hints.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsOrdersListResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/certificates/smime":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-smime","summary":"Order email certificate (S/MIME)","description":"Orders an email certificate without a CSR. **Chargeable:** prepayment from the credit balance, refunded on failure. The certificate authority confirms the email address by email and then makes the certificate available for download (password `password`, only forwarded to the certificate authority, never stored). Result via webhook `certificate.issued` or `certificate.failed`. With `Idempotency-Key`. Contact: `contact_id` or `contact`.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsSmimeResponse"},"example":{"success":true,"order":{"id":"uuid","status":"validating","email":"max.muster@kunde.de","charged_cents":2368}}}}},"400":{"description":"Invalid details (invalid_contact with field errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient credit balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed) or order in progress (order_pending)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsSmimeRequest"},"example":{"product_id":42,"months":12,"email":"max.muster@kunde.de","firstname":"Max","lastname":"Muster","organization_unit":"Vertrieb","password":"Geheim Wort 12","contact_id":"uuid","confirm":true,"expect_net_cents":1990}}}}}},"/api/domain-portfolio/certificates/{id}/download":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"certs-download","summary":"Download certificate","description":"Returns the certificate and chain (never a key).","parameters":[{"name":"id","in":"path","required":true,"description":"Certificate ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertsDownloadResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/orders/aftermarket/quote":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"aftermarket-quote","summary":"Purchase price of a domain for sale","description":"Returns the purchase price (net and gross) of a domain offered on the sales platform, and whether the purchase requires prior approval (`requires_approval`, from the organization's threshold). The purchase price is already included in the search results (`aftermarket: true`, `price_cents`).","parameters":[{"name":"domain","in":"query","required":true,"description":"Domain name","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketQuoteResponse"},"example":{"success":true,"quote":{"domain":"beispiel.de","net_cents":6590,"gross_cents":7842,"requires_approval":false,"approval_limit_cents":200000}}}}},"409":{"description":"No longer for sale (not_for_sale) or price missing (price_missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/orders/aftermarket":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"aftermarket-start","summary":"Buy a domain on the aftermarket","description":"Starts the purchase. **Payment is made in advance by card (Stripe)**: without an approval requirement, the response contains `order.checkout_url`; the domain is only bought after payment is received. From the threshold (global, overridable per organization), our approval is required first (`status: awaiting_approval`, notification on decision); then `POST …/:id/pay`. If the price changes, the domain is not bought. The result is delivered via webhook `domain.order.completed` or `domain.order.failed` (type `buy`). With `Idempotency-Key`.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketStartResponse"},"example":{"success":true,"order":{"id":"uuid","domain":"beispiel.de","status":"awaiting_payment","gross_cents":7842,"checkout_url":"https://checkout.stripe.com/…"}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Price changed (price_changed), not for sale (not_for_sale), or order in progress (order_pending)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Card payment unavailable (stripe_off)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketStartRequest"},"example":{"domain":"beispiel.de","expect_net_cents":6590,"confirm":true,"owner":{"handle":"uuid"},"ns_profile":"urbandomains"}}}}},"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"aftermarket-list","summary":"Organization's domain purchases","description":"Lists the purchases with status `awaiting_approval`, `awaiting_payment`, `paid`, `processing`, `completed`, `failed`, `declined`, `expired`, `cancelled`.","parameters":[{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketListResponse"},"example":{"success":true,"total":1,"orders":[{"id":"uuid","domain":"beispiel.de","status":"awaiting_approval","net_cents":250000,"gross_cents":297500,"requires_approval":true}]}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/orders/aftermarket/{id}/pay":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"aftermarket-pay","summary":"Pay an approved purchase","description":"Creates the payment link (Stripe, card) for an approved purchase. The price is re-checked beforehand; if it has changed, nothing is charged.","parameters":[{"name":"id","in":"path","required":true,"description":"Purchase ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketPayResponse"},"example":{"success":true,"checkout_url":"https://checkout.stripe.com/…"}}}},"409":{"description":"Not payable (not_payable), expired (expired), or price changed (price_changed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/orders/aftermarket/{id}/cancel":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"aftermarket-cancel","summary":"Cancel purchase","description":"Cancels a purchase that has not been paid yet.","parameters":[{"name":"id","in":"path","required":true,"description":"Purchase ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AftermarketCancelResponse"},"example":{"success":true}}}},"409":{"description":"No longer cancellable (not_cancellable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/certificate-contacts":{"get":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"cert-contacts-list","summary":"Certificate contacts","description":"Lists the stored contacts for certificates.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsListResponse"},"example":{"success":true,"contacts":[{"id":"uuid","fname":"Erika","lname":"Muster","organization":"Muster GmbH","email":"e@example.com","phone":"+49 30 123456","address":"Weg 1","pcode":"10115","city":"Berlin","country":"DE"}]}}}}},"security":[{"oauth2ClientCredentials":["domain:read"]},{"oauth2":["domain:read"]}],"x-required-scopes":{"scopes":["domain:read"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}},"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"cert-contacts-create","summary":"Create certificate contact","description":"Creates a contact for certificates (at the provider and on our side). Usable as `contact_id` when ordering a certificate.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsCreateResponse"},"example":{"success":true}}}},"400":{"description":"Invalid details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Maximum number reached (too_many)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsCreateRequest"},"example":{"fname":"Erika","lname":"Muster","organization":"Muster GmbH","address":"Weg 1","pcode":"10115","city":"Berlin","country":"DE","email":"e@example.com","phone":"+49 30 123456"}}}}}},"/api/domain-portfolio/certificate-contacts/{id}":{"put":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"cert-contacts-update","summary":"Update certificate contact","description":"Updates a stored contact (at the provider and on our side).","parameters":[{"name":"id","in":"path","required":true,"description":"Contact ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsUpdateResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsUpdateRequest"},"example":{"fname":"Erika","lname":"Muster","address":"Weg 1","pcode":"10115","city":"Berlin","country":"DE","email":"e@example.com","phone":"+49 30 999999"}}}}},"delete":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"cert-contacts-delete","summary":"Delete certificate contact","description":"Deletes the contact. Certificates already issued remain unaffected.","parameters":[{"name":"id","in":"path","required":true,"description":"Contact ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertContactsDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":["string","null"]},"example":null}}}}},"/api/domain-portfolio/requests":{"post":{"tags":["Domain management (domains, DNS, certificates)"],"operationId":"requests-create","summary":"Submit request","description":"For TLDs and certificates with special rules: the request goes to the operator, who will get in touch.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestsCreateResponse"},"example":{"success":true}}}}},"security":[{"oauth2ClientCredentials":["domain:write"]},{"oauth2":["domain:write"]}],"x-required-scopes":{"scopes":["domain:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestsCreateRequest"},"example":{"kind":"domain","subject":"kunde.es","message":"…"}}}}}},"/api/search-console/config":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-config","summary":"Availability and service account address","description":"Shows whether the plan includes the integration (`feature`), whether the Google integration is set up on the server, and which **service account address** the customer must add as a user in their Search Console (the \"Restricted\" permission is sufficient). Bing needs no address (customer's API key); `crux.enabled` shows whether field measurement (Chrome UX Report) is available.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleConfigResponse"},"example":{"success":true,"feature":true,"google":{"enabled":true,"service_account_email":"auditcollector@projekt.iam.gserviceaccount.com"},"bing":{"enabled":true},"crux":{"enabled":true}}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-links","summary":"Connected domains","description":"Lists the connections (per domain and search engine) with status (`ok`, `pending`, `no_access`, `error`) and the clicks/impressions of the last 28 days together with the comparison value of the preceding 28 days. Paginated with `limit`/`offset`, search `q`, sorting `sort` (domain, provider, status, clicks, impressions, sync) and `dir`.","parameters":[{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search in the domain","schema":{"type":"string"}},{"name":"provider","in":"query","required":false,"description":"google | bing","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"ok | pending | no_access | error","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinksResponse"},"example":{"success":true,"total":1,"links":[{"id":"uuid","provider":"google","domain":"kunde.de","property":"sc-domain:kunde.de","status":"ok","status_detail":null,"last_sync_at":"2026-10-12T04:10:00.000Z","clicks_28d":2864,"impressions_28d":72318,"clicks_prev_28d":3580,"alert_enabled":true,"alert_clicks_drop_pct":30,"alert_min_clicks":50,"alert_index_issues":true}]}}}},"402":{"description":"Not included in the plan (from Professional or Monitor Pro)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"post":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-link-create","summary":"Connect domain","description":"Connects a **verified** domain to Google Search Console or Bing Webmaster Tools and checks access immediately. Google: the service account address (see `config`) must be added in the domain's Search Console; a matching property (domain property `sc-domain:` preferred, otherwise URL prefix) is selected automatically. Bing: `api_key` is the Bing Webmaster Tools API key (stored encrypted, never returned). Afterwards the server fetches the data in the background (up to 16 months back) and refreshes it daily.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkCreateResponse"},"example":{"success":true,"link":{"id":"uuid","provider":"google","domain":"kunde.de","property":"sc-domain:kunde.de","status":"ok"}}}}},"400":{"description":"invalid_provider | invalid_domain | invalid_key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not included in the plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"domain_not_verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"already_linked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"not_configured (Google not set up on the server)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkCreateRequest"},"example":{"provider":"google","domain":"kunde.de"}}}}}},"/api/search-console/links/{id}":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-link-get","summary":"Connection with metrics","description":"Master data, alert settings, weekly comparison (`compare`, 7 days against the preceding 7) and 28-day comparison (`compare28`), number of checked pages per index status (`index`: PASS, FAIL, PARTIAL, NEUTRAL), sitemap errors, and for Bing the latest crawl statistics and the cached field measurement (`crux`).","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkGetResponse"},"example":{"success":true,"link":{"id":"uuid","provider":"google","domain":"kunde.de","status":"ok"},"compare":{"last_day":"2026-10-10","current":{"clicks":350,"impressions":18365,"days":7},"previous":{"clicks":800,"impressions":19200,"days":7},"clicks_change_pct":-56.3,"impressions_change_pct":-4.4,"complete":true},"index":{"PASS":5,"FAIL":2},"sitemaps":{"count":1,"errors":2,"warnings":0},"crawl":null,"crux":{"enabled":true}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"patch":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-link-update","summary":"Alert settings, channels, Bing key","description":"Thresholds for alerts (click drop in percent compared to the previous week, minimum clicks, index loss) and notification channels (same format as for monitors). For Bing, the API key can be replaced. The server also reports: click drop, pages dropping out of the Google index, sitemap errors, loss of access, malware notice (Bing), and poor Core Web Vitals.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkUpdateResponse"},"example":{"success":true,"link":{"id":"uuid","alert_clicks_drop_pct":40,"alert_min_clicks":200}}}}},"400":{"description":"Invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Channel not included in the plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkUpdateRequest"},"example":{"alert_clicks_drop_pct":40,"alert_min_clicks":200}}}}},"delete":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-link-delete","summary":"Remove connection","description":"Deletes the connection including all stored search data (and the encrypted Bing key). The customer's Search Console remains unchanged.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleLinkDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}}},"/api/search-console/links/{id}/daily":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-daily","summary":"Daily trend","description":"Clicks, impressions, and (Google) average position per day. Retention 16 months.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"30 | 90 | 180 | 365 | 480 (default 90)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleDailyResponse"},"example":{"success":true,"days":90,"daily":[{"day":"2026-10-10","clicks":48,"impressions":2510,"position":7.2}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/top":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-top","summary":"Search queries or pages","description":"Top list of the last 28 days with the values of the preceding 28 days (`prev_*`; `null` = new). `kind=query` or `kind=page`; paginated, search `q`, sorting `sort` (item, clicks, impressions, position, change).","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"query (default) | page","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Search","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleTopResponse"},"example":{"success":true,"total":40,"items":[{"item":"schuhe kaufen","clicks":200,"impressions":3000,"position":3.2,"prev_clicks":190,"prev_impressions":2900}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/keywords":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-keywords","summary":"Tracked keywords","description":"Tracked keywords of a Google connection with the values of the last 28 days (`position` = average weighted by impressions) and the change compared to the preceding 28 days (`position_change` = before − now, positive = better). Empty for Bing.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleKeywordsResponse"},"example":{"success":true,"limit":25,"keywords":[{"id":"6b0c…","keyword":"schuhe kaufen","clicks":120,"impressions":2000,"position":4.2,"prev_position":5.1,"position_change":0.9,"last_day":"2026-10-11"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}},"post":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-keyword-add","summary":"Track keyword","description":"Adds a keyword (Google only, at most 25 per domain; whitespace is collapsed, lowercase). The history is fetched retroactively in the background. Management requires the \"Manage domains\" permission.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleKeywordAddResponse"},"example":{"success":true,"keyword":{"id":"6b0c…","keyword":"schuhe kaufen"}}}}},"400":{"description":"keyword_invalid | keyword_limit | google_only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"keyword_exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleKeywordAddRequest"}}}}}},"/api/search-console/links/{id}/keywords/{keywordId}":{"delete":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-keyword-delete","summary":"Remove keyword","description":"Stops tracking and deletes the keyword's stored history.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}},{"name":"keywordId","in":"path","required":true,"description":"Keyword UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleKeywordDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}}},"/api/search-console/links/{id}/keywords/{keywordId}/daily":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-keyword-daily","summary":"Keyword history","description":"Daily values (clicks, impressions, average position) of a tracked keyword; `days` = 30, 90 (default), 180, 365, or 480.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}},{"name":"keywordId","in":"path","required":true,"description":"Keyword UUID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"30 | 90 | 180 | 365 | 480","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleKeywordDailyResponse"},"example":{"success":true,"keyword":"schuhe kaufen","days":90,"daily":[{"day":"2026-10-10","clicks":4,"impressions":52,"position":4.3}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/index":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-index","summary":"Index status of checked pages (Google)","description":"Result of the URL inspection: Google checks up to 25 pages per day (home page and top-click pages that have gone unchecked the longest). `verdict`: PASS (indexed), FAIL (problem), PARTIAL, NEUTRAL (excluded, e.g. noindex). Filter `verdict`, search `q`.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}},{"name":"verdict","in":"query","required":false,"description":"PASS | FAIL | PARTIAL | NEUTRAL","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleIndexResponse"},"example":{"success":true,"total":1,"pages":[{"url":"https://kunde.de/schuhe","verdict":"FAIL","coverage_state":"Gecrawlt – zurzeit nicht indexiert","indexing_state":"INDEXING_ALLOWED","last_crawl_at":"2026-10-01T08:00:00.000Z","google_canonical":"https://kunde.de/schuhe","user_canonical":"https://kunde.de/schuhe","checked_at":"2026-10-12T04:12:00.000Z"}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/sitemaps":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-sitemaps","summary":"Sitemaps","description":"Submitted sitemaps with errors, warnings, URLs, and number of indexed URLs (Google).","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleSitemapsResponse"},"example":{"success":true,"sitemaps":[{"path":"https://kunde.de/sitemap.xml","last_submitted":"2026-09-01T10:00:00.000Z","last_downloaded":"2026-10-11T02:00:00.000Z","errors":2,"warnings":0,"submitted":120,"indexed":100,"is_pending":false}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/crawl":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-crawl","summary":"Crawl statistics (Bing)","description":"Per day: crawled pages, crawl errors, pages blocked by robots.txt, 4xx/5xx, malware notices from Bing, and pages in the index (last 90 days).","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleCrawlResponse"},"example":{"success":true,"crawl":[{"day":"2026-10-11","crawled_pages":40,"crawl_errors":3,"blocked_robots":1,"in_index":400,"code_4xx":2,"code_5xx":0,"malware":0}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/search-console/links/{id}/sync":{"post":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-sync","summary":"Sync now","description":"Checks access and fetches the data immediately (otherwise daily in the background). At most 6 syncs per 10 minutes per connection.","parameters":[{"name":"id","in":"path","required":true,"description":"Connection UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleSyncResponse"},"example":{"success":true,"ok":true,"link":{"id":"uuid","status":"ok"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many refreshes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:write"]},{"oauth2":["monitor:write"]}],"x-required-scopes":{"scopes":["monitor:write"],"mode":"all"}}},"/api/search-console/crux":{"get":{"tags":["Search engines (Search Console, Bing, CrUX)"],"operationId":"search-console-crux","summary":"Core Web Vitals of real visitors (CrUX)","description":"Field measurement from the Chrome UX Report for an own, verified domain: LCP, INP, CLS, FCP, and TTFB for mobile and desktop (75th percentile of the last 28 days, rating `good | needs-improvement | poor`, share of visits per rating, weekly trend). No linking by the customer required; `no_data: true` if there are too few Chrome visits. Cache 20 hours.","parameters":[{"name":"domain","in":"query","required":true,"description":"Verified domain","schema":{"type":"string"}},{"name":"refresh","in":"query","required":false,"description":"1 = force fetch (at most every 20 hours)","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchConsoleCruxResponse"},"example":{"success":true,"domain":"kunde.de","crux":{"enabled":true,"phone":{"no_data":false,"metrics":{"lcp":{"p75":3100,"good":0.6,"ni":0.25,"poor":0.15,"rating":"needs-improvement"},"cls":{"p75":0.04,"good":0.9,"ni":0.05,"poor":0.05,"rating":"good"}},"period":{"from":"2026-09-01","to":"2026-09-28"}},"desktop":{"no_data":true,"metrics":null}}}}}},"400":{"description":"invalid_domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Neither search engine integration nor SEO & GEO module included in the plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"domain_not_verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["monitor:read"]},{"oauth2":["monitor:read"]}],"x-required-scopes":{"scopes":["monitor:read"],"mode":"all"}}},"/api/captcha/sites":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-list","summary":"EMPEDIAcaptcha domains","description":"Lists the organization's domains (a registrable domain with all its subdomains) with site key, hosts, mode, status and the key figures of the last 30 days. The secret is never returned.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesListResponse"},"example":{"success":true,"sites":[{"id":"uuid","name":"urbanstudio.de","sitekey":"ek_site_…","hosts":["urbanstudio.de","*.urbanstudio.de"],"mode":"balanced","status":"active","observe":false,"ok_30d":1234,"rejected_30d":56}]}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}},"post":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-create","summary":"Create a domain","description":"Creates a domain. All hosts must belong to the same registrable domain (`example.com`, `*.example.com`). The secret appears **only in this response**.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesCreateResponse"},"example":{"success":true,"site":{"id":"uuid","sitekey":"ek_site_…"},"secret":"ek_secret_…"}}}},"400":{"description":"invalid_host / multiple_domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"site_limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesCreateRequest"},"example":{"name":"urbanstudio.de","hosts":["urbanstudio.de","*.urbanstudio.de"],"mode":"balanced"}}}}}},"/api/captcha/sites/bulk":{"post":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-bulk","summary":"Create many domains at once","description":"Creates up to 100 domains in one call (e.g. for agencies). Each entry is validated individually; the response (207) reports success or error per entry. Secrets appear only here.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesBulkResponse"},"example":{"success":true,"created":2,"results":[{"index":0,"ok":true,"site":{"id":"uuid","sitekey":"ek_site_…"},"secret":"ek_secret_…"},{"index":1,"ok":false,"error":"site_limit"}]}}}},"400":{"description":"invalid_bulk","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesBulkRequest"},"example":{"sites":[{"name":"kunde-a.de","hosts":["kunde-a.de","*.kunde-a.de"]},{"name":"kunde-b.de","hosts":["kunde-b.de"]}]}}}}}},"/api/captcha/sites/{id}":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-get","summary":"Domain details","description":"Settings of a domain including page protection and observe mode.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesGetResponse"},"example":{"success":true,"site":{"id":"uuid","name":"urbanstudio.de","hosts":["urbanstudio.de"],"mode":"balanced","observe":false,"gate":{"enabled":false,"ttl_min":60,"skip":["/robots.txt"],"crawlers":true}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}},"patch":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-update","summary":"Update a domain","description":"Changes name, hosts, mode, token lifetime, pausing, **observe mode** (`observe`: assess and count but never block) and page protection (`gate`). Every change appears in the activity log.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesUpdateResponse"},"example":{"success":true,"site":{"id":"uuid","observe":true}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesUpdateRequest"},"example":{"observe":true}}}}},"delete":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-delete","summary":"Delete a domain","description":"Deletes the domain including keys, rules and statistics.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"}}},"/api/captcha/sites/{id}/rotate-secret":{"post":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-rotate","summary":"Renew secret","description":"Creates a new secret; the old one stays valid for one more hour.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesRotateResponse"},"example":{"success":true,"secret":"ek_secret_…"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"}}},"/api/captcha/sites/{id}/stats":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-stats","summary":"Domain statistics","description":"Counters per day and metric (challenge, solved, verify_ok, rejected, verify_fail, form_allow/review/block, gate_view/pass, observed_block, form_observed).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"1–90, default 30","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesStatsResponse"},"example":{"success":true,"days":30,"rows":[{"day":"2026-10-17","metric":"verify_ok","n":120}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}}},"/api/captcha/sites/{id}/export.csv":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-export","summary":"Statistics as CSV","description":"Daily values as CSV (semicolon separated, UTF-8 with BOM).","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"1–400, default 90","schema":{"type":"integer"}}],"responses":{"200":{"description":"day;rejected;verify_ok\r\n2026-10-17;3;120","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}}},"/api/captcha/sites/{id}/activity":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-sites-activity","summary":"Activity log","description":"Who changed what and when (create, settings, secret, rules). Without IP addresses and without values.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–100","schema":{"type":"integer"}},{"name":"offset","in":"query","required":false,"description":"Start offset","schema":{"type":"integer"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaSitesActivityResponse"},"example":{"success":true,"total":2,"activity":[{"action":"captcha.site_update","at":"2026-10-17T09:00:00Z","user":"Anna","via":"dashboard","fields":["observe"]}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}}},"/api/captcha/sites/{id}/rules":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-rules-list","summary":"Own rules","description":"Blocks and allows of the content check (IP, network, email, domain, username, text fragment) and learned entries.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaRulesListResponse"},"example":{"success":true,"rules":[{"id":"1","kind":"ip","action":"block","value":"203.0.113.9","source":"manual"}],"lists":[]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}},"post":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-rules-add","summary":"Add a rule","description":"Creates a block or allow. Allows take precedence.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaRulesAddResponse"},"example":{"success":true}}}},"400":{"description":"Invalid value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaRulesAddRequest"},"example":{"kind":"ip","action":"block","value":"203.0.113.9","note":"Spam-Welle"}}}}}},"/api/captcha/sites/{id}/rules/{rid}":{"delete":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-rules-delete","summary":"Delete a rule","description":"Removes an own rule.","parameters":[{"name":"id","in":"path","required":true,"description":"Domain ID","schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"description":"Rule ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaRulesDeleteResponse"},"example":{"success":true}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"oauth2ClientCredentials":["captcha:write"]},{"oauth2":["captcha:write"]}],"x-required-scopes":{"scopes":["captcha:write"],"mode":"all"}}},"/api/captcha/plan":{"get":{"tags":["EMPEDIAcaptcha (domains, rules, statistics)"],"operationId":"captcha-plan","summary":"Plan and usage","description":"Domain limit, included and used checks of the month and the resulting overage.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptchaPlanResponse"},"example":{"success":true,"plan":{"tier":"paid","name":"EMPEDIAcaptcha Pro","sites_limit":25,"sites_used":3,"checks_included":250000,"checks_used":1200}}}}}},"security":[{"oauth2ClientCredentials":["captcha:read"]},{"oauth2":["captcha:read"]}],"x-required-scopes":{"scopes":["captcha:read"],"mode":"all"}}}},"components":{"securitySchemes":{"sessionToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Dashboard session (login via the web interface)"},"partnerApiKey":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"Key of a quickcheck partner"},"oauth2ClientCredentials":{"type":"oauth2","description":"Server to server: short-lived access tokens for a service client (Settings → API access)","flows":{"clientCredentials":{"tokenUrl":"https://empedia.cloud/oauth/token","scopes":{"scan:read":"Read scans and reports","scan:write":"Start scans","report:read":"Read PDF reports and AI analyses","code:audit":"Run and read code audits","monitor:read":"Read monitoring (websites, servers, email reports (DMARC, TLS-RPT), status page)","monitor:write":"Manage monitoring (create/update/delete monitors, servers and email-security domains)","domain:read":"Read domains, zones, certificates, redirects and orders","domain:write":"Order and manage domains, edit zones, order certificates (paid actions are charged to the credit balance)","captcha:read":"Read EMPEDIAcaptcha (domains, rules, statistics, activity log)","captcha:write":"Manage EMPEDIAcaptcha (create/change/delete domains, renew secrets, rules, observe mode, page protection)","openid":"Identity (userinfo only)"}}}},"oauth2":{"type":"oauth2","description":"Authorization code with PKCE for apps with user sign-in","flows":{"authorizationCode":{"authorizationUrl":"https://empedia.cloud/oauth/authorize","tokenUrl":"https://empedia.cloud/oauth/token","refreshUrl":"https://empedia.cloud/oauth/token","scopes":{"scan:read":"Read scans and reports","scan:write":"Start scans","report:read":"Read PDF reports and AI analyses","code:audit":"Run and read code audits","monitor:read":"Read monitoring (websites, servers, email reports (DMARC, TLS-RPT), status page)","monitor:write":"Manage monitoring (create/update/delete monitors, servers and email-security domains)","domain:read":"Read domains, zones, certificates, redirects and orders","domain:write":"Order and manage domains, edit zones, order certificates (paid actions are charged to the credit balance)","captcha:read":"Read EMPEDIAcaptcha (domains, rules, statistics, activity log)","captcha:write":"Manage EMPEDIAcaptcha (create/change/delete domains, renew secrets, rules, observe mode, page protection)","openid":"Identity (userinfo only)"}}}}},"schemas":{"Error":{"type":"object","description":"Error response","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string","description":"Error message"}},"required":["success","error"],"examples":[{"success":false,"error":"Nicht gefunden"}]},"DomainsListResponseDomainsItem":{"type":"object","properties":{"domain":{"type":"string","examples":["example.com"],"description":"Domain without protocol"},"verified_at":{"type":"string","format":"date-time","examples":["2026-04-01T10:00:00Z"],"description":"Verification time (ISO 8601, UTC)"},"method":{"type":"string","examples":["dns"]},"token":{"type":"string","examples":["abc123..."]}},"required":["domain","verified_at","method","token"]},"DomainsListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainsListResponseDomainsItem"}}},"required":["success","domains"]},"DomainsRegisterRequest":{"type":"object","properties":{"domain":{"type":"string","description":"Domain name"}},"required":["domain"]},"DomainsRegisterResponseVerificationMethodsItem":{"type":"object","properties":{"method":{"type":"string","examples":["dns"]},"instruction":{"type":"string","examples":["Legen Sie einen DNS-TXT-Eintrag …"]},"values":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","examples":["Hostname"],"description":"Label"},"value":{"type":"string","examples":["_empedia"]}},"required":["label","value"]}}},"required":["method","instruction","values"]},"DomainsRegisterResponse":{"type":"object","properties":{"domain":{"type":"string","examples":["example.com"],"description":"Domain without protocol"},"token":{"type":"string","examples":["a1b2c3d4..."]},"verification_methods":{"type":"array","items":{"$ref":"#/components/schemas/DomainsRegisterResponseVerificationMethodsItem"}}},"required":["domain","token","verification_methods"]},"DomainsVerifyResponse":{"type":"object","properties":{"verified":{"type":"boolean"},"method":{"type":"string","examples":["dns"]}},"required":["verified","method"]},"ScanShortRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.maxPages":{"type":"integer","description":"Max. pages, 1–20 (default: 5)"},"options.screenshot":{"type":"boolean","description":"Create a screenshot of the start page"}},"required":["url"]},"FindingsSummary":{"type":"object","properties":{"total":{"type":"integer","examples":[12],"description":"Total count"},"high":{"type":"integer","examples":[1],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[4],"description":"Number of medium findings"},"low":{"type":"integer","examples":[7],"description":"Number of low findings"}},"required":["total","high","medium","low"],"description":"Number of findings by severity"},"ScanShortResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["short"]},"score":{"type":"integer","examples":[78],"description":"Overall score from 0 to 100"},"grade":{"type":"string","examples":["C"],"description":"Grade from A (very good) to F"},"findings_summary":{"$ref":"#/components/schemas/FindingsSummary"},"duration_ms":{"type":"integer","examples":[8420]}},"required":["success","mode","score","grade","findings_summary","duration_ms"]},"ScanFullRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.maxPages":{"type":"integer","description":"Max. pages — plan-dependent (20 / 50 / 100 / all)"},"options.maxDepth":{"type":"integer","description":"Crawler depth (default: 3)"},"options.concurrency":{"type":"integer","description":"Parallel browser tabs, 1–5 (default: 3)"},"options.screenshot":{"type":"boolean","description":"Create a screenshot of the start page"},"options.lighthouse":{"type":"boolean","description":"Enable Lighthouse performance analysis"},"options.simulateConsent":{"type":"boolean","description":"Consent rejection test for GDPR check"},"preset_sku":{"type":"string","description":"SKU of the scan preset (wp-emergency | gdpr-audit | bfsg-audit | seo-geo-audit | seo-geo-audit-consult | nis2-audit | dora-audit — only usable if the product has been purchased or is included in the plan). If set, steps, checks and unlocked_reports are derived automatically from the preset."}},"required":["url"]},"ScanFullResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["scan"]},"score":{"type":"integer","examples":[72],"description":"Overall score from 0 to 100"},"grade":{"type":"string","examples":["C"],"description":"Grade from A (very good) to F"},"tls":{"type":"object","properties":{"valid":{"type":"boolean"},"days_remaining":{"type":"integer","examples":[62]}},"required":["valid","days_remaining"]},"findings_summary":{"$ref":"#/components/schemas/FindingsSummary"},"coverage":{"type":"object","properties":{"discovered":{"type":"integer","examples":[148]},"crawled":{"type":"integer","examples":[120]},"skipped":{"type":"integer","examples":[3]},"unscanned":{"type":"integer","examples":[25]},"sitemap_urls":{"type":"integer","examples":[140]},"max_pages":{"type":"integer","examples":[200]},"limit_reason":{"type":"string","examples":["max_pages"]}},"required":["discovered","crawled","skipped","unscanned","sitemap_urls","max_pages","limit_reason"]},"infection":{"type":"object","properties":{"pages_checked":{"type":"integer","examples":[120]},"pages_with_indicators":{"type":"integer","examples":[0]},"indicators":{"type":"integer","examples":[0]},"items":{"type":"array","items":{}},"cloaking_checked":{"type":"boolean"},"cloaking_hits":{"type":"integer","examples":[0]}},"required":["pages_checked","pages_with_indicators","indicators","items","cloaking_checked","cloaking_hits"]},"duration_ms":{"type":"integer","examples":[62400]}},"required":["success","mode","score","grade","tls","findings_summary","coverage","infection","duration_ms"]},"ScanStreamRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.maxPages":{"type":"integer","description":"Max. pages — plan-dependent (20 / 50 / 100 / all)"},"options.maxDepth":{"type":"integer","description":"Crawler depth (default: 3)"},"options.concurrency":{"type":"integer","description":"Parallel browser tabs, 1–5 (default: 3)"},"options.screenshot":{"type":"boolean","description":"Create a screenshot of the start page"},"options.lighthouse":{"type":"boolean","description":"Enable Lighthouse performance analysis"},"options.simulateConsent":{"type":"boolean","description":"Consent rejection test for GDPR check"},"preset_sku":{"type":"string","description":"SKU of the scan preset (wp-emergency | gdpr-audit | bfsg-audit | seo-geo-audit | seo-geo-audit-consult | nis2-audit | dora-audit — only usable if the product has been purchased or is included in the plan). If set, steps, checks and unlocked_reports are derived automatically from the preset."}},"required":["url"]},"ScanDnsRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL or domain (https://example.com or example.com)"}},"required":["url"]},"ScanDnsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"string","examples":["example.com"],"description":"Domain without protocol"},"score":{"type":"integer","examples":[70],"description":"Overall score from 0 to 100"},"email_security":{"type":"object","properties":{"spf":{"type":"object","properties":{"exists":{"type":"boolean"},"has_all_fail":{"type":"boolean"}},"required":["exists","has_all_fail"]},"dkim":{"type":"object","properties":{"found":{"type":"boolean"}},"required":["found"]},"dmarc":{"type":"object","properties":{"exists":{"type":"boolean"},"policy":{"type":"string","examples":["reject"]}},"required":["exists","policy"]}},"required":["spf","dkim","dmarc"]},"reputation":{"type":"object","properties":{"ips":{"type":"object","properties":{"93.184.216.34":{"type":"object","properties":{"dnsbl":{"type":"array","items":{}},"abuseipdb":{"type":"object","properties":{"abuse_score":{"type":"integer","examples":[0]}},"required":["abuse_score"]}},"required":["dnsbl","abuseipdb"]}},"required":["93.184.216.34"]},"open_relay":{"type":"object","properties":{"open_relay":{"type":"boolean"}},"required":["open_relay"]}},"required":["ips","open_relay"]}},"required":["success","domain","score","email_security","reputation"]},"ScanGdprRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"}},"required":["url"]},"ScanGdprResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["gdpr"]},"gdpr_score":{"type":"integer","examples":[62]},"findings_summary":{"$ref":"#/components/schemas/FindingsSummary"}},"required":["success","mode","gdpr_score","findings_summary"]},"ScanGdprFullRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.maxPages":{"type":"integer","description":"Max. pages (plan-dependent)"}},"required":["url"]},"ScanGdprFullResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["gdpr-full"]},"gdpr_score":{"type":"integer","examples":[58]},"pages_scanned":{"type":"integer","examples":[12]}},"required":["success","mode","gdpr_score","pages_scanned"]},"ScanWpRequest":{"type":"object","properties":{"url":{"type":"string","description":"WordPress website URL (https://...)"}},"required":["url"]},"ScanWpResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"wordpress":{"type":"object","properties":{"version":{"type":"string","examples":["6.4.2"]},"is_latest":{"type":"boolean"}},"required":["version","is_latest"]},"findings_summary":{"type":"object","properties":{"total":{"type":"integer","examples":[5],"description":"Total count"},"high":{"type":"integer","examples":[2],"description":"Number of critical/high findings"}},"required":["total","high"],"description":"Number of findings by severity"},"ai_action_plan":{"type":"string","examples":["1. WordPress sofort auf 6.5 aktualisieren..."]}},"required":["success","wordpress","findings_summary","ai_action_plan"]},"CodeScanSarifResponse":{"type":"object","properties":{"$schema":{"type":"string","format":"uri","examples":["https://json.schemastore.org/sarif-2.1.0.json"]},"version":{"type":"string","examples":["2.1.0"]},"runs":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"object","properties":{"driver":{"type":"object","properties":{"name":{"type":"string","examples":["EMPEDIAcloud Code-Audit"],"description":"Name"},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["sast-xss"],"description":"Unique ID (UUID)"},"shortDescription":{"type":"object"},"defaultConfiguration":{"type":"object"}},"required":["id","shortDescription","defaultConfiguration"]}}},"required":["name","rules"]}},"required":["driver"]},"results":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string","examples":["sast-xss"]},"level":{"type":"string","examples":["error"]},"message":{"type":"object","properties":{"text":{"type":"string","examples":["Reflected XSS: src/a.php:12 — Empfehlung: Ausgabe escapen"]}},"required":["text"],"description":"Message"},"locations":{"type":"array","items":{"type":"object","properties":{"physicalLocation":{"type":"object"}},"required":["physicalLocation"]}}},"required":["ruleId","level","message","locations"]}}},"required":["tool","results"]}}},"required":["$schema","version","runs"]},"CodeUploadRequest":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"ZIP or TAR.GZ archive (max. size depends on plan, up to 1 GB)"},"ai":{"type":"boolean","description":"Enable AI analysis (true/false)"},"system":{"type":"string","description":"Framework: wordpress, laravel, shopware, magento, nextjs, django, symfony"}},"required":["file"]},"CodeUploadResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["upload"]},"files_scanned":{"type":"integer","examples":[142]},"findings_summary":{"$ref":"#/components/schemas/FindingsSummary"},"wordpress":{"type":"object","properties":{"version":{"type":"string","examples":["6.4.2"]},"plugins":{"type":"array","items":{"type":"string","examples":["woocommerce"]}}},"required":["version","plugins"]}},"required":["success","mode","files_scanned","findings_summary","wordpress"]},"CodeSshKeyResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"publicKey":{"type":"string","examples":["ssh-ed25519 AAAA... auditcollector-code-audit"]}},"required":["success","publicKey"]},"CodeConnectRequest":{"type":"object","properties":{"method":{"type":"string","description":"Connection type: sftp | ftp | git"},"host":{"type":"string","description":"Server hostname or IP address"},"port":{"type":"integer","description":"Port (default: 22 for SFTP, 21 for FTP)"},"username":{"type":"string","description":"SSH/FTP username"},"password":{"type":"string","description":"Password — leave empty for SSH key auth (the system key is used automatically)"},"privateKey":{"type":"string","description":"Own SSH private key as a string (optional, overrides the system key)"},"remotePath":{"type":"string","description":"Path on the server (default: /)"},"ai":{"type":"boolean","description":"Enable AI analysis"},"system":{"type":"string","description":"Framework: wordpress | laravel | shopware | magento | nextjs | django"}},"required":["method","host"]},"CodeConnectResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"mode":{"type":"string","examples":["sftp"]},"files_scanned":{"type":"integer","examples":[312]},"findings_summary":{"$ref":"#/components/schemas/FindingsSummary"}},"required":["success","mode","files_scanned","findings_summary"]},"CodeScanListResponseScansItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"target":{"type":"string","examples":["sftp://server.example.com/var/www"],"description":"Domain or URL that was checked"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"findings_summary":{"type":"object","properties":{"total":{"type":"integer","examples":[18],"description":"Total count"},"high":{"type":"integer","examples":[3],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[7],"description":"Number of medium findings"},"low":{"type":"integer","examples":[8],"description":"Number of low findings"}},"required":["total","high","medium","low"],"description":"Number of findings by severity"},"created_at":{"type":"string","format":"date-time","examples":["2026-04-22T03:00:01Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","target","status","findings_summary","created_at"]},"CodeScanListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"scans":{"type":"array","items":{"$ref":"#/components/schemas/CodeScanListResponseScansItem"}},"total":{"type":"integer","examples":[42],"description":"Total count"},"page":{"type":"integer","examples":[1],"description":"Page number"},"limit":{"type":"integer","examples":[20],"description":"Maximum number per page"}},"required":["success","scans","total","page","limit"]},"CodeScanDetailResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"scan":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"mode":{"type":"string","examples":["git"]},"target":{"type":"string","format":"uri","examples":["https://github.com/org/repo.git"],"description":"Domain or URL that was checked"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"findings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","examples":["sast-sqli-a3f2"],"description":"Unique ID (UUID)"},"severity":{"type":"string","examples":["high"],"description":"Severity (high, medium, low, info)"},"title":{"type":"string","examples":["SQL Injection"],"description":"Title"},"file":{"type":"string","examples":["db-helper.php"]},"line":{"type":"integer","examples":[42]}},"required":["id","severity","title","file","line"],"description":"List of findings"},"description":"List of findings"},"findings_summary":{"type":"object","properties":{"total":{"type":"integer","examples":[18],"description":"Total count"},"high":{"type":"integer","examples":[3],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[7],"description":"Number of medium findings"},"low":{"type":"integer","examples":[8],"description":"Number of low findings"}},"required":["total","high","medium","low"],"description":"Number of findings by severity"},"wordpress":{"type":["string","null"]},"ai":{"type":"object","properties":{"available":{"type":"boolean"},"findings_count":{"type":"integer","examples":[4]},"provider":{"type":"string","examples":["Claude (Anthropic)"]}},"required":["available","findings_count","provider"]},"duration_ms":{"type":"integer","examples":[12340]}},"required":["id","mode","target","status","findings","findings_summary","ai","duration_ms"]}},"required":["success","scan"]},"CodeScheduleListResponseSchedulesItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"label":{"type":"string","examples":["Nightly Git Audit"],"description":"Label"},"method":{"type":"string","examples":["git"]},"cron":{"type":"string","examples":["0 3 * * *"]},"enabled":{"type":"boolean","description":"Active or paused"},"last_run_at":{"type":"string","format":"date-time","examples":["2026-04-22T03:00:01Z"]},"next_run_at":{"type":"string","format":"date-time","examples":["2026-04-23T03:00:00Z"]},"has_credentials":{"type":"integer","examples":[1]}},"required":["id","label","method","cron","enabled","last_run_at","next_run_at","has_credentials"]},"CodeScheduleListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"schedules":{"type":"array","items":{"$ref":"#/components/schemas/CodeScheduleListResponseSchedulesItem"}}},"required":["success","schedules"]},"CodeRetryAiRequest":{"type":"object","properties":{"provider_id":{"type":"string","description":"AI provider UUID (empty = default model)"}}},"CodeRetryAiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"status":{"type":"string","examples":["running"],"description":"Current status"}},"required":["success","status"]},"CodeRetryAiStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"status":{"type":"string","examples":["done"],"description":"Current status"}},"required":["success","status"]},"CodeEstimateFullScanRequest":{"type":"object","properties":{"provider_id":{"type":"string","description":"AI provider UUID"},"file_count":{"type":"integer","description":"Number of code files"},"avg_file_size":{"type":"integer","description":"Average file size in bytes"}}},"CodeEstimateFullScanResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"estimated_files":{"type":"integer","examples":[347]},"estimated_tokens_in":{"type":"integer","examples":[297000]},"estimated_tokens_out":{"type":"integer","examples":[138800]},"estimated_cost_cents":{"type":"number","examples":[12.5]},"provider_name":{"type":"string","examples":["Claude Sonnet 4.6"]},"model":{"type":"string","examples":["claude-sonnet-4-6"]}},"required":["success","estimated_files","estimated_tokens_in","estimated_tokens_out","estimated_cost_cents","provider_name","model"]},"CodeListRemediationsResponseRemediationsItem":{"type":"object","properties":{"id":{"type":"string","examples":["rem-uuid"],"description":"Unique ID (UUID)"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"mode":{"type":"string","examples":["automatic"]},"method":{"type":"string","examples":["sftp"]},"findings_fixed":{"type":"integer","examples":[12]},"findings_skipped":{"type":"integer","examples":[3]},"findings_failed":{"type":"integer","examples":[0]},"created_at":{"type":"string","format":"date-time","examples":["2026-06-20T14:00:00Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","status","mode","method","findings_fixed","findings_skipped","findings_failed","created_at"]},"CodeListRemediationsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"remediations":{"type":"array","items":{"$ref":"#/components/schemas/CodeListRemediationsResponseRemediationsItem"}}},"required":["success","remediations"]},"CodeStartRemediationRequest":{"type":"object","properties":{"mode":{"type":"string","description":"automatic | interactive | review (default: automatic)"},"provider_id":{"type":"string","description":"AI provider UUID"},"token":{"type":"string","description":"Git token with push permissions (Git repos only, overrides the scan token)"}}},"CodeStartRemediationResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"job_id":{"type":"string","examples":["job-uuid"],"description":"ID of the background job"},"remediation_id":{"type":"string","examples":["rem-uuid"]},"mode":{"type":"string","examples":["interactive"]},"method":{"type":"string","examples":["sftp"]}},"required":["success","job_id","remediation_id","mode","method"]},"CodeRemediationStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"remediation":{"type":"object","properties":{"id":{"type":"string","examples":["rem-uuid"],"description":"Unique ID (UUID)"},"status":{"type":"string","examples":["running"],"description":"Current status"},"mode":{"type":"string","examples":["interactive"]},"findings_fixed":{"type":"integer","examples":[3]},"findings_skipped":{"type":"integer","examples":[1]},"ai_tokens_in":{"type":"integer","examples":[12438]},"ai_cost_cents":{"type":"number","examples":[8.9]}},"required":["id","status","mode","findings_fixed","findings_skipped","ai_tokens_in","ai_cost_cents"]}},"required":["success","remediation"]},"CodeRemediationMessagesResponseMessagesItem":{"type":"object","properties":{"role":{"type":"string","examples":["agent"]},"content":{"type":"string","examples":["Backup erstellt: 1247 Dateien"]},"message_type":{"type":"string","examples":["success"]},"options":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time","examples":["2026-06-20T14:00:00Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["role","content","message_type","created_at"]},"CodeRemediationMessagesResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/CodeRemediationMessagesResponseMessagesItem"}}},"required":["success","messages"]},"CodeRemediationRespondRequest":{"type":"object","properties":{"answer":{"type":"string","description":"Selected option (e.g. \"Apply\", \"Skip\")"}},"required":["answer"]},"CodeRemediationRespondResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"delivered":{"type":"boolean"}},"required":["success","delivered"]},"CodeRemediationActionsResponseActionsItem":{"type":"object","properties":{"id":{"type":"string","examples":["action-uuid"],"description":"Unique ID (UUID)"},"finding_id":{"type":"string","examples":["F001"]},"file_path":{"type":"string","examples":["wp-config.php"]},"action_type":{"type":"string","examples":["patch"]},"status":{"type":"string","examples":["applied"],"description":"Current status"},"ai_fix_approved":{"type":"integer","examples":[1]},"ai_verify_approved":{"type":"integer","examples":[1]},"ai_fix_reasoning":{"type":"string","examples":["SQL-Injection-Risiko behoben durch Prepared Statement"]},"ai_verify_reasoning":{"type":"string","examples":["Fix korrekt, keine Seiteneffekte"]},"user_approved":{"type":["string","null"]},"patch_diff":{"type":"string"},"applied_at":{"type":"string","format":"date-time","examples":["2026-06-20T14:05:00Z"]},"created_at":{"type":"string","format":"date-time","examples":["2026-06-20T14:04:00Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","finding_id","file_path","action_type","status","ai_fix_approved","ai_verify_approved","ai_fix_reasoning","ai_verify_reasoning","patch_diff","applied_at","created_at"]},"CodeRemediationActionsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"actions":{"type":"array","items":{"$ref":"#/components/schemas/CodeRemediationActionsResponseActionsItem"}}},"required":["success","actions"]},"CodeRemediationApproveRequest":{"type":"object","properties":{"action_ids":{"type":"array","items":{},"description":"UUIDs of the actions to approve"}},"required":["action_ids"]},"CodeRemediationApproveResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"applied":{"type":"integer","examples":[2]},"failed":{"type":"integer","examples":[0]}},"required":["success","applied","failed"]},"CodeRemediationRollbackResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"message":{"type":"string","examples":["Rollback erfolgreich — alle Dateien wiederhergestellt"],"description":"Message"}},"required":["success","message"]},"CodeConnectionsListResponseConnectionsItem":{"type":"object","properties":{"id":{"type":"string","examples":["conn-uuid"],"description":"Unique ID (UUID)"},"label":{"type":"string","examples":["Mein Server"],"description":"Label"},"method":{"type":"string","examples":["sftp"]},"host":{"type":"string","examples":["server.example.com"]},"port":{"type":"integer","examples":[22]},"username":{"type":"string","examples":["deploy"]},"remote_path":{"type":"string","examples":["/var/www"]},"system_hint":{"type":"string","examples":["wordpress"]},"has_credentials":{"type":"integer","examples":[1]},"last_used_at":{"type":"string","format":"date-time","examples":["2026-06-20T14:00:00Z"]},"created_at":{"type":"string","format":"date-time","examples":["2026-06-01T10:00:00Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","label","method","host","port","username","remote_path","system_hint","has_credentials","last_used_at","created_at"]},"CodeConnectionsListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"connections":{"type":"array","items":{"$ref":"#/components/schemas/CodeConnectionsListResponseConnectionsItem"}}},"required":["success","connections"]},"CodeConnectionsCreateRequest":{"type":"object","properties":{"label":{"type":"string","description":"Display name of the connection"},"method":{"type":"string","description":"Connection type: git | sftp | ftp | ssh"},"repo_url":{"type":"string","description":"Git repository URL (for method=git)"},"branch":{"type":"string","description":"Git branch (default: main)"},"host":{"type":"string","description":"Hostname/IP (for SFTP/FTP)"},"port":{"type":"integer","description":"Port (1-65535)"},"username":{"type":"string","description":"Username"},"password":{"type":"string","description":"Password (stored encrypted)"},"token":{"type":"string","description":"Git personal access token (stored encrypted)"},"private_key":{"type":"string","description":"SSH private key (stored encrypted)"},"remote_path":{"type":"string","description":"Path on the remote server"},"system_hint":{"type":"string","description":"Framework hint: wordpress | laravel | shopware | etc."}},"required":["label","method"]},"CodeConnectionsCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"id":{"type":"string","examples":["conn-uuid"],"description":"Unique ID (UUID)"}},"required":["success","id"]},"CodeConnectionsUpdateRequest":{"type":"object","properties":{"label":{"type":"string","description":"Display name"},"method":{"type":"string","description":"Connection type"},"host":{"type":"string","description":"Hostname"},"password":{"type":"string","description":"New password (stored encrypted)"},"token":{"type":"string","description":"New token (stored encrypted)"}}},"CodeConnectionsUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CodeConnectionsDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CodeScheduleCreateRequest":{"type":"object","properties":{"label":{"type":"string","description":"Display name of the schedule"},"method":{"type":"string","description":"Connection type: git | sftp | ftp | ssh"},"cron":{"type":"string","description":"Cron expression (5 fields): \"0 3 * * *\" = daily at 03:00"},"repo_url":{"type":"string","description":"Git repository URL (for method=git)"},"branch":{"type":"string","description":"Git branch (default: main)"},"token":{"type":"string","description":"Personal access token for private Git repos"},"host":{"type":"string","description":"Hostname/IP (for SFTP/FTP)"},"port":{"type":"integer","description":"Port (default: 22 for SFTP, 21 for FTP)"},"username":{"type":"string","description":"Username (for SFTP/FTP)"},"password":{"type":"string","description":"Password (for SFTP/FTP, stored encrypted)"},"remote_path":{"type":"string","description":"Path on the server (for SFTP/FTP)"},"use_ai":{"type":"boolean","description":"Enable AI analysis (default: true)"},"system_hint":{"type":"string","description":"Framework hint: wordpress | laravel | shopware …"},"provider_id":{"type":"string","description":"UUID of the AI provider (BYO-AI)"},"notify_on":{"type":"string","description":"Notification: always | new_high | new_any | never"}},"required":["method","cron"]},"CodeScheduleCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"schedule":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"label":{"type":"string","examples":["Nightly Git Audit"],"description":"Label"},"method":{"type":"string","examples":["git"]},"cron":{"type":"string","examples":["0 3 * * *"]},"enabled":{"type":"boolean","description":"Active or paused"},"next_run_at":{"type":"string","format":"date-time","examples":["2026-04-23T03:00:00Z"]}},"required":["id","label","method","cron","enabled","next_run_at"]}},"required":["success","schedule"]},"CodeScheduleUpdateRequest":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable/disable the schedule"},"cron":{"type":"string","description":"New cron expression"},"notify_on":{"type":"string","description":"Change the notification rule"}}},"CodeScheduleUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"schedule":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"enabled":{"type":"boolean","description":"Active or paused"},"cron":{"type":"string","examples":["0 4 * * 1"]}},"required":["id","enabled","cron"]}},"required":["success","schedule"]},"CodeScheduleDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CodeScheduleRunResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"message":{"type":"string","examples":["Audit gestartet."],"description":"Message"}},"required":["success","message"]},"MonServersListResponseServersItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["Webserver Produktion"],"description":"Name"},"hostname":{"type":"string","examples":["web01.example.com"]},"status":{"type":"string","examples":["active"],"description":"Current status"},"last_heartbeat":{"type":"string","format":"date-time","examples":["2026-04-20T08:00:00Z"]},"cpu_percent":{"type":"number","examples":[34.2]},"memory_percent":{"type":"number","examples":[61.8]},"disk_percent":{"type":"integer","examples":[48]},"load_1m":{"type":"number","examples":[0.82]}},"required":["id","name","hostname","status","last_heartbeat","cpu_percent","memory_percent","disk_percent","load_1m"]},"MonServersListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"servers":{"type":"array","items":{"$ref":"#/components/schemas/MonServersListResponseServersItem"}}},"required":["success","servers"]},"MonServersRegisterRequest":{"type":"object","properties":{"name":{"type":"string","description":"Display name of the server"},"alert_email":{"type":"string","description":"Email address for alerts (valid address, otherwise 400); added as a recipient in `alert_channels.email`"},"alert_channels":{"type":"object","description":"Notification channels: `{ email: { enabled, recipients: [\"user:<uuid>\", \"contact:<uuid>\", \"raw:<address>\"], notify_on }, sms: { … team members/contacts only }, slack|teams|discord: { enabled, webhook_url (https) }, webhook: { enabled, url (https) } }`. `notify_on`: `failure` | `recovery` | `always`. Recipients are validated (invalid email, free-form phone number for SMS, non-https URL → 400); channels not included in the plan → 402."}},"required":["name"]},"MonServersRegisterResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"agent_token":{"type":"string","examples":["a1b2c3d4e5f6..."]},"install_cmd":{"type":"string"},"server":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["Webserver Produktion"],"description":"Name"}},"required":["id","name"]}},"required":["success","agent_token","install_cmd","server"]},"MonServersDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"uninstall":{"type":"object","properties":{"pending":{"type":"boolean"}},"required":["pending"]}},"required":["success","uninstall"]},"MonServersMetricsResponseMetricsItem":{"type":"object","properties":{"ts":{"type":"string","format":"date-time","examples":["2026-04-20T07:00:00Z"]},"cpu_percent":{"type":"number","examples":[28.4]},"memory_percent":{"type":"number","examples":[59.1]},"disk_percent":{"type":"number","examples":[47.8]},"load_1m":{"type":"number","examples":[0.61]}},"required":["ts","cpu_percent","memory_percent","disk_percent","load_1m"]},"MonServersMetricsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"metrics":{"type":"array","items":{"$ref":"#/components/schemas/MonServersMetricsResponseMetricsItem"}}},"required":["success","metrics"]},"MonWebsitesListResponseWebsitesItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"url":{"type":"string","format":"uri","examples":["https://example.com"],"description":"Page address"},"name":{"type":"string","examples":["Produktiv-Website"],"description":"Name"},"status":{"type":"string","examples":["up"],"description":"Current status"},"last_check":{"type":"string","format":"date-time","examples":["2026-04-20T08:00:00Z"]},"response_time_ms":{"type":"integer","examples":[312]},"ssl_expires_in_days":{"type":"integer","examples":[62]},"check_interval_sec":{"type":"integer","examples":[60]},"check_types":{"type":"array","items":{"type":"string","examples":["uptime"]}}},"required":["id","url","name","status","last_check","response_time_ms","ssl_expires_in_days","check_interval_sec","check_types"]},"MonWebsitesListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"websites":{"type":"array","items":{"$ref":"#/components/schemas/MonWebsitesListResponseWebsitesItem"}}},"required":["success","websites"]},"MonWebsitesAddRequest":{"type":"object","properties":{"url":{"type":"string","description":"Full URL including protocol (https://...)"},"name":{"type":"string","description":"Display name (default: hostname)"},"check_interval_sec":{"type":"integer","description":"Check interval in seconds; minimum limited by plan"},"check_types":{"type":"array","items":{},"description":"Active checks: uptime | ssl | response-time | dns | domain-expiry (default: uptime, ssl, response-time, domain-expiry; domain expiry is included for HTTP monitors if the plan contains it)"},"alert_email":{"type":"string","description":"Alert email address (valid address, otherwise 400)"},"alert_channels":{"type":"object","description":"Notification channels: `{ email: { enabled, recipients: [\"user:<uuid>\", \"contact:<uuid>\", \"raw:<address>\"], notify_on }, sms: { … team members/contacts only }, slack|teams|discord: { enabled, webhook_url (https) }, webhook: { enabled, url (https) } }`. `notify_on`: `failure` | `recovery` | `always`. Recipients are validated (invalid email, free-form phone number for SMS, non-https URL → 400); channels not included in the plan → 402."},"keyword":{"type":"string","description":"Text that must appear on the page (or must not, see keyword_mode) — from Monitor Basic"},"keyword_mode":{"type":"string","description":"`present` (text must appear, default) or `absent` (text must not appear)"},"ports":{"type":"array","items":{},"description":"TCP ports of the host to check in addition, e.g. `[25, 443]` (at most 10; verified domains only; from Monitor Pro)"},"monitor_kind":{"type":"string","description":"`http` (default) or `heartbeat` (heartbeat monitor: then `name`, `heartbeat_interval_sec` and optionally `heartbeat_grace_sec` instead of `url`; the response contains `heartbeat_url`)"},"heartbeat_interval_sec":{"type":"integer","description":"Heartbeat monitor only: expected reporting interval, 60 s to 7 days"},"heartbeat_grace_sec":{"type":"integer","description":"Heartbeat monitor only: grace period after the interval expires, 0 s to 24 h (default 300 s)"},"blacklist":{"type":"boolean","description":"Enable spam list check (blacklist) — from Monitor Pro"},"subdomain_watch":{"type":"boolean","description":"Enable subdomain monitoring: search daily for subdomains of the domain (DNS, Certificate Transparency) and report new ones (alert, webhook `subdomain.discovered`). Website monitors with a verified domain only, from Monitor Business or Agency Pro (otherwise 402 `feature_not_available`). The first run only creates the baseline. Can be enabled/disabled later via PATCH; `GET /api/monitoring/websites/:id` returns `subdomains` (known subdomains with `ips`, `cname`, `ptr` (hostname of the target server), `resolves`, `first_seen`, `last_seen`, new ones flagged, `wildcard`)."},"server_id":{"type":"string","description":"UUID of a server (agent) of the organization on which the website runs (website monitors only). On an outage, alerts and the detail page show the likely cause based on the state of this server (offline, reboot, failed services, high load); server alerts name the affected websites. Can be changed later via PATCH; `null` removes the link. Foreign server → 404."},"mail_security":{"type":"boolean","description":"Check email security (SPF, DKIM, DMARC, MTA-STS, TLS-RPT, BIMI, DNSSEC) daily, with a score of 0–100 and suggested fixes — from Monitor Basic; website monitors only (monitor_kind http). Can be enabled/disabled later via PATCH /api/monitoring/websites/:id { mail_security }."}},"required":["url"]},"MonWebsitesAddResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"website":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"url":{"type":"string","format":"uri","examples":["https://example.com"],"description":"Page address"},"name":{"type":"string","examples":["Produktiv-Website"],"description":"Name"},"check_interval_sec":{"type":"integer","examples":[60]}},"required":["id","url","name","check_interval_sec"]}},"required":["success","website"]},"MonWebsitesUpdateRequest":{"type":"object","properties":{"name":{"type":"string","description":"New display name"},"server_id":{"type":"string","description":"UUID of the server on which the website runs; `null` removes the link (website monitors only)"},"subdomain_watch":{"type":"boolean","description":"Enable/disable subdomain monitoring (from Monitor Business, verified domain; when enabled, the baseline is recreated)"},"check_interval_sec":{"type":"integer","description":"New check interval (≥ plan minimum)"},"check_types":{"type":"array","items":{},"description":"New list of check types"},"alert_email":{"type":"string","description":"New alert email (valid address, otherwise 400)"},"alert_channels":{"type":"object","description":"Notification channels: `{ email: { enabled, recipients: [\"user:<uuid>\", \"contact:<uuid>\", \"raw:<address>\"], notify_on }, sms: { … team members/contacts only }, slack|teams|discord: { enabled, webhook_url (https) }, webhook: { enabled, url (https) } }`. `notify_on`: `failure` | `recovery` | `always`. Recipients are validated (invalid email, free-form phone number for SMS, non-https URL → 400); channels not included in the plan → 402."},"keyword":{"type":"string","description":"Text on the page (an empty string removes the check); together with `keyword_mode`"},"ports":{"type":"array","items":{},"description":"New port list (an empty array removes the port check); verified domains only, from Monitor Pro"},"heartbeat_interval_sec":{"type":"integer","description":"Heartbeat monitor: new expected interval"},"heartbeat_grace_sec":{"type":"integer","description":"Heartbeat monitor: new grace period"}}},"MonWebsitesUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"MonWebsitesDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"MonWebsitesGetResponseResultsItem":{"type":"object","properties":{"check_type":{"type":"string","examples":["uptime"]},"status":{"type":"string","examples":["up"],"description":"Current status"},"checked_at":{"type":"string","format":"date-time","examples":["2026-10-02T08:00:00Z"]},"detail":{"type":"object","properties":{"response_time_ms":{"type":"integer","examples":[312]}},"required":["response_time_ms"]}},"required":["check_type","status","checked_at","detail"]},"MonWebsitesGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"website":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"url":{"type":"string","format":"uri","examples":["https://example.com"],"description":"Page address"},"name":{"type":"string","examples":["Produktiv-Website"],"description":"Name"},"monitor_kind":{"type":"string","examples":["http"]},"status":{"type":"string","examples":["up"],"description":"Current status"},"check_interval_sec":{"type":"integer","examples":[60]},"check_types":{"type":"array","items":{"type":"string","examples":["uptime"]}}},"required":["id","url","name","monitor_kind","status","check_interval_sec","check_types"]},"results":{"type":"array","items":{"$ref":"#/components/schemas/MonWebsitesGetResponseResultsItem"}}},"required":["success","website","results"]},"MonHeartbeatStatsResponseBucketsItem":{"type":"object","properties":{"ts":{"type":"integer","examples":[1775944800]},"ok":{"type":"integer","examples":[3]},"fail":{"type":"integer","examples":[1]}},"required":["ts","ok","fail"]},"MonHeartbeatStatsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"range":{"type":"string","examples":["week"]},"from":{"type":"integer","examples":[1775512800]},"size":{"type":"integer","examples":[86400]},"count":{"type":"integer","examples":[7]},"buckets":{"type":"array","items":{"$ref":"#/components/schemas/MonHeartbeatStatsResponseBucketsItem"}}},"required":["success","range","from","size","count","buckets"]},"MonWebsitesLogResponseRowsItem":{"type":"object","properties":{"check_type":{"type":"string","examples":["uptime"]},"status":{"type":"string","examples":["up"],"description":"Current status"},"response_ms":{"type":"integer","examples":[182]},"status_code":{"type":"integer","examples":[200]},"detail":{"type":["string","null"]},"checked_at":{"type":"string","format":"date-time","examples":["2026-10-10T09:00:02.000Z"]}},"required":["check_type","status","response_ms","status_code","checked_at"]},"MonWebsitesLogResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/MonWebsitesLogResponseRowsItem"}},"total":{"type":"integer","examples":[1440],"description":"Total count"},"page":{"type":"integer","examples":[1],"description":"Page number"},"limit":{"type":"integer","examples":[100],"description":"Maximum number per page"}},"required":["success","rows","total","page","limit"]},"MonWebsitesHistoryResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"hours":{"type":"integer","examples":[24]},"history":{"type":"object","properties":{"uptime":{"type":"object","properties":{"timestamps":{"type":"array","items":{"type":"string","format":"date-time","examples":["2026-10-10T09:00:02.000Z"]}},"values":{"type":"array","items":{"type":"integer","examples":[182]}},"statuses":{"type":"array","items":{"type":"string","examples":["up"]}}},"required":["timestamps","values","statuses"]}},"required":["uptime"]}},"required":["success","hours","history"]},"MonWebsitesDnsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"dns":{"type":"object","properties":{"a":{"type":"array","items":{"type":"string","examples":["203.0.113.10"]}},"aaaa":{"type":"array","items":{}},"mx":{"type":"array","items":{"type":"object","properties":{"exchange":{"type":"string","examples":["mail.example.com"]},"priority":{"type":"integer","examples":[10]}},"required":["exchange","priority"]}},"ns":{"type":"array","items":{"type":"string","examples":["ns1.example.com"]}}},"required":["a","aaaa","mx","ns"]}},"required":["success","dns"]},"MonHeartbeatPingsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[2],"description":"Total count"},"pings":{"type":"array","items":{"type":"object","properties":{"ok":{"type":"integer","examples":[1]},"pinged_at":{"type":"string","format":"date-time","examples":["2026-04-20T03:00:02.000Z"]}},"required":["ok","pinged_at"]}}},"required":["success","total","pings"]},"MonServersGetResponseAlertsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["7b1e9c4a-0d52-4b0a-9a55-2f9c1d3e8a10"],"description":"Unique ID (UUID)"},"type":{"type":"string","examples":["service"],"description":"Type"},"severity":{"type":"string","examples":["critical"],"description":"Severity (high, medium, low, info)"},"message":{"type":"string","examples":["Dienst „nginx“ ausgefallen (gestoppt)"],"description":"Message"},"metric_value":{"type":["string","null"]},"threshold":{"type":["string","null"]},"snapshot":{"type":["string","null"]},"resolved_at":{"type":"string","format":"date-time","examples":["2026-04-20T09:42:11.000Z"]},"created_at":{"type":"string","format":"date-time","examples":["2026-04-20T09:31:02.000Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","type","severity","message","resolved_at","created_at"]},"MonServersGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"server":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["Webserver Produktion"],"description":"Name"},"hostname":{"type":"string","examples":["web01.example.com"]},"agent_version":{"type":"string","examples":["1.4.9"]},"scheduler":{"type":"string","examples":["systemd-timer"]},"extras":{"type":"object","properties":{"cpu_cores":{"type":"integer","examples":[8]},"filesystems":{"type":"array","items":{"type":"object","properties":{"mount":{"type":"string","examples":["/"]},"fs":{"type":"string","examples":["ext4"]},"total_gb":{"type":"integer","examples":[98]},"used_gb":{"type":"integer","examples":[47]},"pct":{"type":"integer","examples":[48]}},"required":["mount","fs","total_gb","used_gb","pct"]}},"top_processes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","examples":["php-fpm"],"description":"Name"},"cpu":{"type":"number","examples":[12.5]},"mem":{"type":"number","examples":[8.1]}},"required":["name","cpu","mem"]}},"updates":{"type":"object","properties":{"manager":{"type":"string","examples":["dnf"]},"method":{"type":"string","examples":["advisories"]},"security":{"type":"integer","examples":[0]},"total":{"type":"integer","examples":[0],"description":"Total count"},"reboot":{"type":"boolean"},"kernel":{"type":"object","properties":{"running":{"type":"string","examples":["4.18.0-553.139.1.el8_10.x86_64"]},"available":{"type":["string","null"]},"advisories":{"type":"integer","examples":[0]},"livepatch":{"type":"string","examples":["kernelcare"]}},"required":["running","advisories","livepatch"]},"items":{"type":"array","items":{}},"checked_at":{"type":"integer","examples":[1791600000]}},"required":["manager","method","security","total","reboot","kernel","items","checked_at"]}},"required":["cpu_cores","filesystems","top_processes","updates"]},"blacklist_detail":{"type":"object","properties":{"listed":{"type":"array","items":{}},"unknown":{"type":"array","items":{}},"results":{"type":"array","items":{"type":"object","properties":{"list":{"type":"string","examples":["Spamhaus ZEN"]},"target":{"type":"string","examples":["203.0.113.10"],"description":"Domain or URL that was checked"},"state":{"type":"string","examples":["clean"]}},"required":["list","target","state"]}}},"required":["listed","unknown","results"]}},"required":["id","name","hostname","agent_version","scheduler","extras","blacklist_detail"]},"metrics":{"type":"array","items":{}},"alerts":{"type":"array","items":{"$ref":"#/components/schemas/MonServersGetResponseAlertsItem"}},"kernel_cves":{"type":["string","null"]}},"required":["success","server","metrics","alerts"]},"MonServersUpdateRequest":{"type":"object","properties":{"name":{"type":"string","description":"Display name"},"offline_threshold_min":{"type":"integer","description":"Minutes without a report until \"offline\" (2–1440)"},"blacklist":{"type":"boolean","description":"Check the public IP against spam lists (from Monitor Pro)"},"report_interval_sec":{"type":"integer","description":"Custom reporting interval of the agent in seconds: `30`, `60`, `300` or `900`, never below the plan minimum (otherwise 402 `interval_not_in_plan`); `null` = plan default. Takes effect from the next report."},"watch_services":{"type":"array","items":{},"description":"Names of the services that must be running (at most 30; letters, digits, `. _ - @ :`), e.g. `[\"nginx\",\"mariadb\"]`. Replaces the existing list. Alert if a service is not running in 2 consecutive agent reports, recovery notice as soon as it runs again (from Monitor Basic, otherwise 402 `feature_not_available`)"}}},"MonServersUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"MonHeartbeatPingResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"JobsListResponseJobsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"type":{"type":"string","examples":["scan"],"description":"Type"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"progress":{"type":"integer","examples":[100],"description":"Progress in percent (0–100)"},"created_at":{"type":"string","format":"date-time","examples":["2026-04-18T10:00:00Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","type","status","progress","created_at"]},"JobsListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"jobs":{"type":"array","items":{"$ref":"#/components/schemas/JobsListResponseJobsItem"}}},"required":["success","jobs"]},"JobsStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"job":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"progress":{"type":"integer","examples":[100],"description":"Progress in percent (0–100)"},"scan_id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440001"],"description":"ID of the scan"},"error":{"type":["string","null"],"description":"Error message (errors only)"}},"required":["id","status","progress","scan_id"]}},"required":["success","job"]},"ScanSummaryResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"summary":{"type":"object","properties":{"domain":{"type":"string","examples":["example.com"],"description":"Domain without protocol"},"scan_id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440001"],"description":"ID of the scan"},"scanned_at":{"type":"string","format":"date-time","examples":["2026-10-02T10:00:00.000Z"]},"age_days":{"type":"integer","examples":[3]},"score":{"type":"integer","examples":[82],"description":"Overall score from 0 to 100"},"grade":{"type":"string","examples":["B"],"description":"Grade from A (very good) to F"},"trend":{"type":"object","properties":{"previous_score":{"type":"integer","examples":[76]},"previous_grade":{"type":"string","examples":["C"]},"delta":{"type":"integer","examples":[6]},"direction":{"type":"string","examples":["up"]}},"required":["previous_score","previous_grade","delta","direction"]},"findings":{"type":"object","properties":{"total":{"type":"integer","examples":[14],"description":"Total count"},"high":{"type":"integer","examples":[1],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[5],"description":"Number of medium findings"},"low":{"type":"integer","examples":[8],"description":"Number of low findings"}},"required":["total","high","medium","low"],"description":"List of findings"},"categories":{"type":"object","properties":{"gdpr":{"type":"object","properties":{"index":{"type":"integer","examples":[88]},"high":{"type":"integer","examples":[0],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[2],"description":"Number of medium findings"},"low":{"type":"integer","examples":[4],"description":"Number of low findings"}},"required":["index","high","medium","low"]},"a11y":{"type":"object","properties":{"index":{"type":"integer","examples":[71]},"high":{"type":"integer","examples":[1],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[2],"description":"Number of medium findings"},"low":{"type":"integer","examples":[3],"description":"Number of low findings"}},"required":["index","high","medium","low"]},"seo":{"type":"object","properties":{"index":{"type":"integer","examples":[93]},"high":{"type":"integer","examples":[0],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[1],"description":"Number of medium findings"},"low":{"type":"integer","examples":[0],"description":"Number of low findings"}},"required":["index","high","medium","low"]},"security":{"type":"object","properties":{"index":{"type":"integer","examples":[90]},"high":{"type":"integer","examples":[0],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[1],"description":"Number of medium findings"},"low":{"type":"integer","examples":[2],"description":"Number of low findings"}},"required":["index","high","medium","low"]}},"required":["gdpr","a11y","seo","security"]},"report_url":{"type":"string","format":"uri","examples":["https://empedia.cloud/scans-detail.html?id=550e8400-e29b-41d4-a716-446655440001"]},"pdf_url":{"type":"string","format":"uri","examples":["https://empedia.cloud/api/user/scans/550e8400-e29b-41d4-a716-446655440001/pdf"]}},"required":["domain","scan_id","scanned_at","age_days","score","grade","trend","findings","categories","report_url","pdf_url"]}},"required":["success","summary"]},"ReportPdfRequest":{"type":"object","properties":{"scanResult":{"type":"object","description":"Complete scan result JSON (from /api/audit/scan)"},"options.customerName":{"type":"string","description":"Customer name for the cover page"},"options.language":{"type":"string","description":"Language: de | en | es | fr | it | nl | pl | pt | tr (default: de)"},"options.reportType":{"type":"string","description":"full | security | gdpr | accessibility | nis2 | dora (default: full)"},"options.aiAnalysis":{"type":"string","description":"Embed an existing AI analysis as text"}},"required":["scanResult"]},"ReportHtmlRequest":{"type":"object","properties":{"scanResult":{"type":"object","description":"Complete scan result JSON"},"options.customerName":{"type":"string","description":"Customer name for the cover page"},"options.language":{"type":"string","description":"Language: de | en | es | fr | it | nl | pl | pt | tr"},"options.reportType":{"type":"string","description":"full | security | gdpr | accessibility | nis2 | dora"}},"required":["scanResult"]},"ScanAndReportRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.ai":{"type":"boolean","description":"Embed AI analysis in the report (+30–60 s)"},"options.customerName":{"type":"string","description":"Customer name for the cover page"},"options.language":{"type":"string","description":"Language: de | en | es | fr | it | nl | pl | pt | tr"},"options.screenshot":{"type":"boolean","description":"Screenshot of the home page"},"options.reportType":{"type":"string","description":"full | security | gdpr | accessibility | nis2 | dora"}},"required":["url"]},"ScanAndReportHtmlRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL including protocol (https://...)"},"options.ai":{"type":"boolean","description":"Embed AI analysis in the report"},"options.customerName":{"type":"string","description":"Customer name for the cover page"},"options.language":{"type":"string","description":"Language: de | en | es | fr | it | nl | pl | pt | tr"},"options.reportType":{"type":"string","description":"full | security | gdpr | accessibility | nis2 | dora"}},"required":["url"]},"AiAnalyzeResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"status":{"type":"string","examples":["generating"],"description":"Current status"}},"required":["success","status"]},"AiAnalyzeStatusResponse":{"type":"object","properties":{"status":{"type":"string","examples":["ready"],"description":"Current status"}},"required":["status"]},"AiConsentGetResponse":{"type":"object","properties":{"remembered":{"type":"boolean"},"consent_at":{"type":"string","format":"date-time","examples":["2026-04-19T10:00:00.000Z"]}},"required":["remembered","consent_at"]},"AiConsentSaveResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"AiConsentRevokeResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ComplianceOverviewResponseDomainsItem":{"type":"object","properties":{"domain":{"type":"string","examples":["example.org"],"description":"Domain without protocol"},"last_scan_at":{"type":"string","format":"date-time","examples":["2026-10-10T09:00:00.000Z"]},"statement_at":{"type":["string","null"]},"gdpr":{"type":"object","properties":{"score":{"type":"integer","examples":[89],"description":"Overall score from 0 to 100"},"level":{"type":"string","examples":["partial"]},"high":{"type":"integer","examples":[1],"description":"Number of critical/high findings"},"medium":{"type":"integer","examples":[0],"description":"Number of medium findings"},"scan_id":{"type":"string","format":"uuid","examples":["1fe76b67-c53e-11f1-89b4-02fc00000001"],"description":"ID of the scan"},"at":{"type":"string","format":"date-time","examples":["2026-10-10T09:00:00.000Z"]},"native":{"type":"boolean"}},"required":["score","level","high","medium","scan_id","at","native"]},"a11y":{"type":["string","null"]}},"required":["domain","last_scan_at","gdpr"]},"ComplianceOverviewResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/ComplianceOverviewResponseDomainsItem"}}},"required":["success","domains"]},"OidcDiscoveryResponse":{"type":"object","properties":{"issuer":{"type":"string","format":"uri","examples":["https://empedia.cloud"]},"authorization_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/authorize"]},"token_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/token"]},"userinfo_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/userinfo"]},"jwks_uri":{"type":"string","format":"uri","examples":["https://empedia.cloud/.well-known/jwks.json"]},"revocation_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/revoke"]},"introspection_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/introspect"]},"registration_endpoint":{"type":"string","format":"uri","examples":["https://empedia.cloud/oauth/register"]},"response_types_supported":{"type":"array","items":{"type":"string","examples":["code"]}},"grant_types_supported":{"type":"array","items":{"type":"string","examples":["authorization_code"]}},"id_token_signing_alg_values_supported":{"type":"array","items":{"type":"string","examples":["RS256"]}},"scopes_supported":{"type":"array","items":{"type":"string","examples":["openid"]}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string","examples":["S256"]}}},"required":["issuer","authorization_endpoint","token_endpoint","userinfo_endpoint","jwks_uri","revocation_endpoint","introspection_endpoint","registration_endpoint","response_types_supported","grant_types_supported","id_token_signing_alg_values_supported","scopes_supported","code_challenge_methods_supported"]},"OidcJwksResponseKeysItem":{"type":"object","properties":{"kty":{"type":"string","examples":["RSA"]},"n":{"type":"string","examples":["..."]},"e":{"type":"string","examples":["AQAB"]},"kid":{"type":"string","examples":["a1b2c3d4"]},"use":{"type":"string","examples":["sig"]},"alg":{"type":"string","examples":["RS256"]}},"required":["kty","n","e","kid","use","alg"]},"OidcJwksResponse":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/OidcJwksResponseKeysItem"}}},"required":["keys"]},"OidcTokenResponse":{"type":"object","properties":{"access_token":{"type":"string","examples":["a1b2c3..."],"description":"Access token for the Authorization header"},"token_type":{"type":"string","examples":["Bearer"],"description":"Always “Bearer”"},"expires_in":{"type":"integer","examples":[3600],"description":"Token lifetime in seconds"},"scope":{"type":"string","examples":["scan:read scan:write"],"description":"Granted scopes (space-separated)"}},"required":["access_token","token_type","expires_in","scope"]},"OidcUserinfoResponse":{"type":"object","properties":{"sub":{"type":"string","examples":["42"]},"email":{"type":"string","format":"email","examples":["jane@example.com"]},"email_verified":{"type":"boolean"},"name":{"type":"string","examples":["Jane Doe"],"description":"Name"},"given_name":{"type":"string","examples":["Jane"]},"family_name":{"type":"string","examples":["Doe"]}},"required":["sub","email","email_verified","name","given_name","family_name"]},"OidcRevokeResponse":{"type":"object","properties":{}},"OidcIntrospectResponse":{"type":"object","properties":{"active":{"type":"boolean"},"scope":{"type":"string","examples":["openid scan:read"],"description":"Granted scopes (space-separated)"},"client_id":{"type":"string","examples":["oidc_abc123"]},"sub":{"type":"string","examples":["42"]},"email":{"type":"string","format":"email","examples":["jane@example.com"]},"exp":{"type":"integer","examples":[1714000000]},"iat":{"type":"integer","examples":[1713996400]}},"required":["active","scope","client_id","sub","email","exp","iat"]},"OidcRegisterRequest":{"type":"object","properties":{"client_name":{"type":"string","description":"Display name on the consent screen (default: \"Unnamed MCP app\")"},"redirect_uris":{"type":"array","items":{"type":"string"},"description":"Must be https:// or loopback (localhost/127.0.0.1)"},"scope":{"type":"string","description":"Space-separated; trimmed to the allowlist: openid, profile, email, offline_access, scan:read, scan:write, report:read, monitor:read (excludes code:audit, monitor:write and domain:*)"},"token_endpoint_auth_method":{"type":"string","description":"\"none\" → public client (PKCE, no secret) — suitable for most MCP clients. Otherwise: confidential client with a generated client_secret (returned once in the response)."}},"required":["redirect_uris"]},"OidcRegisterResponse":{"type":"object","properties":{"client_id":{"type":"string","examples":["mcp_a1b2c3..."]},"client_id_issued_at":{"type":"integer","examples":[1714000000]},"client_name":{"type":"string","examples":["Claude"]},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri","examples":["https://claude.ai/api/mcp/auth_callback"]}},"scope":{"type":"string","examples":["openid profile scan:read scan:write report:read"],"description":"Granted scopes (space-separated)"},"token_endpoint_auth_method":{"type":"string","examples":["none"]},"grant_types":{"type":"array","items":{"type":"string","examples":["authorization_code"]}},"response_types":{"type":"array","items":{"type":"string","examples":["code"]}}},"required":["client_id","client_id_issued_at","client_name","redirect_uris","scope","token_endpoint_auth_method","grant_types","response_types"]},"OidcProtectedResourceResponse":{"type":"object","properties":{"resource":{"type":"string","format":"uri","examples":["https://empedia.cloud/mcp"]},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri","examples":["https://empedia.cloud"]}},"scopes_supported":{"type":"array","items":{"type":"string","examples":["scan:read"]}}},"required":["resource","authorization_servers","scopes_supported"]},"OidcClientsListResponseClientsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"client_id":{"type":"string","examples":["oidc_abc123"]},"name":{"type":"string","examples":["My App"],"description":"Name"},"is_public":{"type":"boolean"},"allowed_scopes":{"type":"array","items":{"type":"string","examples":["openid"]}},"enabled":{"type":"boolean","description":"Active or paused"},"created_at":{"type":"string","format":"date-time","examples":["2026-04-19T10:00:00.000Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","client_id","name","is_public","allowed_scopes","enabled","created_at"]},"OidcClientsListResponse":{"type":"object","properties":{"clients":{"type":"array","items":{"$ref":"#/components/schemas/OidcClientsListResponseClientsItem"}}},"required":["clients"]},"OidcClientsCreateRequest":{"type":"object","properties":{"name":{"type":"string","description":"Display name of the app"},"redirect_uris":{"type":"array","items":{},"description":"Allowed redirect URIs (at least one; not required for service_client)"},"service_client":{"type":"boolean","description":"Server-to-server client for client_credentials (always confidential; scopes scan:read, scan:write, report:read, code:audit, monitor:read, monitor:write, domain:read, domain:write)"},"is_public":{"type":"boolean","description":"Public client (SPA/mobile): no secret, PKCE required"},"allowed_scopes":{"type":"array","items":{},"description":"Scopes: openid, email, profile, scan:read, scan:write, report:read, code:audit, monitor:read, monitor:write, domain:read, domain:write"}},"required":["name"]},"OidcClientsCreateResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"Unique ID (UUID)"},"client_id":{"type":"string","examples":["oidc_a1b2c3d4e5f6a1b2c3d4e5f6"]},"client_secret":{"type":"string","examples":["secret-shown-once-store-securely"]}},"required":["id","client_id","client_secret"]},"OidcClientsRotateResponse":{"type":"object","properties":{"client_secret":{"type":"string","examples":["new-secret-shown-once"]}},"required":["client_secret"]},"OidcClientsDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ConnectedAppsListResponseAppsItem":{"type":"object","properties":{"client_id":{"type":"string","examples":["mcp_a1b2c3..."]},"name":{"type":"string","examples":["Claude"],"description":"Name"},"description":{"type":["string","null"],"description":"Description"},"logo_url":{"type":["string","null"]},"registration_type":{"type":"string","examples":["dynamic"]},"scope":{"type":"string","examples":["openid scan:read scan:write report:read"],"description":"Granted scopes (space-separated)"},"granted_at":{"type":"string","format":"date-time","examples":["2026-09-01T10:00:00.000Z"]}},"required":["client_id","name","registration_type","scope","granted_at"]},"ConnectedAppsListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"apps":{"type":"array","items":{"$ref":"#/components/schemas/ConnectedAppsListResponseAppsItem"}}},"required":["success","apps"]},"ConnectedAppsRevokeResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"AuditStartAsyncRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL (must belong to a verified domain)"},"preset_sku":{"type":"string","enum":["wp-emergency","gdpr-audit","gdpr-audit-consult","bfsg-audit","bfsg-audit-consult","seo-geo-audit","seo-geo-audit-consult","nis2-audit","dora-audit"],"examples":["bfsg-audit"],"description":"Scan preset (wp-emergency | gdpr-audit | bfsg-audit | seo-geo-audit | seo-geo-audit-consult | nis2-audit | dora-audit); defines steps, checks and unlocked reports. Without a preset, the module selection (`checks`) is required. A preset included in the plan costs nothing extra (counts as one scan of the monthly quota); a purchased single audit is valid for exactly one run and consumes only its own credit. Unknown preset → 400, neither in the plan nor purchased → 402."},"maxPages":{"type":"integer","examples":[20],"description":"Maximum number of pages; never higher than the plan's page limit (Free 20, Starter 50)"},"maxDepth":{"type":"integer","examples":[2],"description":"Crawler depth"},"steps":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","examples":["scan"]},"label":{"type":"string","examples":["Security-Scan"]}},"required":["type"]},"description":"Ignored: the server derives the steps from the module selection (`checks`) (GDPR as a separate step, the rest as a scan)."},"checks":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"examples":[{"accessibility":["contrast","alt_texts","pdf"]}],"description":"Required without a preset: modules and sub-checks, e.g. { \"accessibility\": [\"contrast\",\"alt_texts\",\"pdf\"] }. Modules: security, dns (all plans), gdpr (Starter and above), accessibility and performance = performance, SEO & GEO (Professional and above). Modules not included in the plan → 402 with a list (`modules`); missing/empty selection → 400 (`no_modules_selected`). The sub-check \"pdf\" in the accessibility module checks PDF documents linked on the page (tags, language, title, alt texts; up to 5 per page); included in the bfsg-audit preset."}},"required":["url"]},"AuditStartAsyncResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"job_id":{"type":"string","format":"uuid","examples":["550e8400-e29b-41d4-a716-446655440000"],"description":"ID of the background job"},"status":{"type":"string","examples":["pending"],"description":"Current status"}},"required":["success","job_id","status"]},"CodeAnalyzeAsyncRequest":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Source code archive"},"fullAiScan":{"type":"boolean","description":"Full AI analysis of all files (higher cost/duration)"}},"required":["file"]},"CodeAnalyzeAsyncResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"job_id":{"type":"string","examples":["uuid"],"description":"ID of the background job"}},"required":["success","job_id"]},"CodeConnectAsyncRequest":{"type":"object","properties":{"method":{"type":"string","description":"git | sftp | ssh | ftp"},"repoUrl":{"type":"string","description":"Git remote (with method=git)"},"host":{"type":"string","description":"Host (with sftp/ssh/ftp)"}},"required":["method"]},"CodeConnectAsyncResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"job_id":{"type":"string","examples":["uuid"],"description":"ID of the background job"}},"required":["success","job_id"]},"CodeTestConnectionRequest":{"type":"object","properties":{"method":{"type":"string","description":"git | sftp | ssh | ftp"}},"required":["method"]},"CodeTestConnectionResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"message":{"type":"string","examples":["SFTP-Verbindung erfolgreich"],"description":"Message"}},"required":["success","message"]},"WebhooksListResponseWebhooksItem":{"type":"object","properties":{"id":{"type":"string","examples":["…"],"description":"Unique ID (UUID)"},"url":{"type":"string","format":"uri","examples":["https://example.com/hooks/auditcollector"],"description":"Page address"},"enabled":{"type":"boolean","description":"Active or paused"},"events":{"type":"array","items":{"type":"string","examples":["scan.completed"],"description":"Subscribed events"},"description":"Subscribed events"},"failure_count":{"type":"integer","examples":[0]},"last_success_at":{"type":"string","format":"date-time","examples":["2026-10-02T10:00:00.000Z"]},"last_failure_at":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time","examples":["2026-10-01T09:00:00.000Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","url","enabled","events","failure_count","last_success_at","created_at"]},"WebhooksListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/WebhooksListResponseWebhooksItem"}},"events":{"type":"object","properties":{"scan.completed":{"type":"string","examples":["Ein Website-Audit wurde abgeschlossen"]},"monitor.down":{"type":"string","examples":["Ein Monitor meldet einen Ausfall bzw. eine Störung"]}},"required":["scan.completed","monitor.down"],"description":"Subscribed events"}},"required":["success","webhooks","events"]},"WebhooksCreateRequest":{"type":"object","properties":{"url":{"type":"string","description":"Target URL (https)"},"events":{"type":"array","items":{},"description":"Event types: scan.completed, scan.failed, score.degraded, monitor.down, monitor.up, ssl.expiring, blacklist.listed, heartbeat.missed, subdomain.discovered, domain.order.completed, domain.order.failed, certificate.issued, certificate.failed, certificate.expiring, handover.drift, captcha.attack_detected, captcha.quota_80, captcha.quota_100"}},"required":["url"]},"WebhooksCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"webhook":{"type":"object","properties":{"id":{"type":"string","examples":["…"],"description":"Unique ID (UUID)"},"url":{"type":"string","format":"uri","examples":["https://example.com/hooks/auditcollector"],"description":"Page address"},"enabled":{"type":"boolean","description":"Active or paused"},"events":{"type":"array","items":{"type":"string","examples":["scan.completed"],"description":"Subscribed events"},"description":"Subscribed events"}},"required":["id","url","enabled","events"]},"secret":{"type":"string","examples":["whsec_…nur-einmal-sichtbar"],"description":"Secret — shown only once"}},"required":["success","webhook","secret"]},"WebhooksUpdateRequest":{"type":"object","properties":{"url":{"type":"string","description":"New target URL (https)"},"events":{"type":"array","items":{},"description":"New event list"},"enabled":{"type":"boolean","description":"Active/inactive"}}},"WebhooksUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"WebhooksDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"WebhooksRotateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"secret":{"type":"string","examples":["whsec_…"],"description":"Secret — shown only once"}},"required":["success","secret"]},"WebhooksTestResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"result":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"integer","examples":[200],"description":"Current status"}},"required":["ok","status"]}},"required":["success","result"]},"WebhooksDeliveriesResponseDeliveriesItem":{"type":"object","properties":{"id":{"type":"string","examples":["…"],"description":"Unique ID (UUID)"},"event":{"type":"string","examples":["scan.completed"]},"status":{"type":"string","examples":["delivered"],"description":"Current status"},"attempts":{"type":"integer","examples":[1]},"response_code":{"type":"integer","examples":[200]},"error":{"type":["string","null"],"description":"Error message (errors only)"},"created_at":{"type":"string","format":"date-time","examples":["2026-10-02T10:00:00.000Z"],"description":"Creation time (ISO 8601, UTC)"}},"required":["id","event","status","attempts","response_code","created_at"]},"WebhooksDeliveriesResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhooksDeliveriesResponseDeliveriesItem"}}},"required":["success","deliveries"]},"BadgesCreateRequest":{"type":"object","properties":{"domain":{"type":"string","description":"Verified domain"}},"required":["domain"]},"BadgesCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"badge":{"type":"object","properties":{"id":{"type":"string","examples":["…"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["example.com"],"description":"Domain without protocol"},"embed":{"type":"object","properties":{"image_url":{"type":"string","format":"uri","examples":["https://empedia.cloud/api/public/badge/TOKEN.svg"]},"html":{"type":"string","examples":["<img …>"]}},"required":["image_url","html"]}},"required":["id","domain","embed"]}},"required":["success","badge"]},"BadgesDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"EmailSecurityListResponseDomainsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"rua":{"type":"string","format":"email","examples":["r-0123456789abcdef@rua.empedia.cloud"]},"last_report_at":{"type":"string","format":"date-time","examples":["2026-10-02T06:10:00Z"]},"total_30d":{"type":"integer","examples":[1480]},"pass_30d":{"type":"integer","examples":[1390]},"alert":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"min_mails":{"type":"integer","examples":[10]},"pass_below":{"type":"integer","examples":[90]}},"required":["enabled","min_mails","pass_below"]}},"required":["id","domain","rua","last_report_at","total_30d","pass_30d","alert"]},"EmailSecurityListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"enabled":{"type":"boolean","description":"Active or paused"},"rua_domain":{"type":"string","examples":["rua.empedia.cloud"]},"quota":{"type":"integer","examples":[5]},"used":{"type":"integer","examples":[1]},"domains":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityListResponseDomainsItem"}}},"required":["success","enabled","rua_domain","quota","used","domains"]},"EmailSecurityCreateRequest":{"type":"object","properties":{"domain":{"type":"string","description":"Domain without protocol"}},"required":["domain"]},"EmailSecurityCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"rua":{"type":"string","format":"email","examples":["r-0123456789abcdef@rua.empedia.cloud"]}},"required":["id","domain","rua"],"description":"Domain without protocol"}},"required":["success","domain"]},"EmailSecuritySummaryResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"summary":{"type":"object","properties":{"days":{"type":"integer","examples":[30]},"reports":{"type":"integer","examples":[42]},"totals":{"type":"object","properties":{"total":{"type":"integer","examples":[1480],"description":"Total count"},"pass":{"type":"integer","examples":[1390]},"quarantined":{"type":"integer","examples":[12]},"rejected":{"type":"integer","examples":[3]}},"required":["total","pass","quarantined","rejected"]},"daily":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-09-30"]},"total":{"type":"integer","examples":[52],"description":"Total count"},"pass":{"type":"integer","examples":[49]}},"required":["day","total","pass"]}},"sources":{"type":"array","items":{"type":"object","properties":{"ip":{"type":"string","examples":["209.85.220.41"]},"ptr":{"type":"string","examples":["mail-sor-f41.google.com"]},"total":{"type":"integer","examples":[900],"description":"Total count"},"pass":{"type":"integer","examples":[900]},"fail":{"type":"integer","examples":[0]},"is_new":{"type":"boolean"}},"required":["ip","ptr","total","pass","fail","is_new"]}}},"required":["days","reports","totals","daily","sources"]}},"required":["success","summary"]},"EmailSecurityGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"rua":{"type":"string","format":"email","examples":["r-0123456789abcdef@rua.empedia.cloud"]},"setup":{"type":"object","properties":{"status":{"type":"string","examples":["rua_missing"],"description":"Current status"},"checked_at":{"type":"string","format":"date-time","examples":["2026-10-03T08:00:00.000Z"]},"record":{"type":"string","examples":["v=DMARC1; p=reject; rua=mailto:dmarc@kunde.de"]},"existing_rua":{"type":"array","items":{"type":"string","format":"email","examples":["dmarc@kunde.de"]}},"authorized":{"type":"boolean"},"suggested_record":{"type":"string"}},"required":["status","checked_at","record","existing_rua","authorized","suggested_record"]},"alert":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"min_mails":{"type":"integer","examples":[10]},"pass_below":{"type":"integer","examples":[90]},"setup_lost":{"type":"boolean"},"no_report_days":{"type":"integer","examples":[7]}},"required":["enabled","min_mails","pass_below","setup_lost","no_report_days"]},"alert_channels":{"type":"object","properties":{"email":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"recipients":{"type":"array","items":{"type":"string","format":"email","examples":["raw:it@kunde.de"]}},"notify_on":{"type":"string","examples":["always"]}},"required":["enabled","recipients","notify_on"]}},"required":["email"]}},"required":["id","domain","rua","setup","alert","alert_channels"],"description":"Domain without protocol"}},"required":["success","domain"]},"EmailSecurityReportsResponseReportsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"org_name":{"type":"string","examples":["google.com"]},"report_id":{"type":"string","examples":["1234567890"]},"begin_at":{"type":"string","format":"date-time","examples":["2026-10-02T00:00:00.000Z"]},"end_at":{"type":"string","format":"date-time","examples":["2026-10-03T00:00:00.000Z"]},"policy_p":{"type":"string","examples":["none"]},"total_count":{"type":"integer","examples":[112]},"pass":{"type":"integer","examples":[112]}},"required":["id","org_name","report_id","begin_at","end_at","policy_p","total_count","pass"]},"EmailSecurityReportsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[42],"description":"Total count"},"page":{"type":"integer","examples":[1],"description":"Page number"},"per_page":{"type":"integer","examples":[20]},"reports":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityReportsResponseReportsItem"}}},"required":["success","total","page","per_page","reports"]},"EmailSecurityReportResponseRowsItem":{"type":"object","properties":{"ip":{"type":"string","examples":["209.85.220.41"]},"ptr":{"type":"string","examples":["mail-sor-f41.google.com"]},"count":{"type":"integer","examples":[112]},"disposition":{"type":"string","examples":["none"]},"dkim":{"type":"boolean"},"spf":{"type":"boolean"},"header_from":{"type":"string","examples":["kunde.de"]},"dkim_domain":{"type":"string","examples":["kunde.de"]},"dkim_selector":{"type":"string","examples":["s1"]},"spf_domain":{"type":"string","examples":["kunde.de"]}},"required":["ip","ptr","count","disposition","dkim","spf","header_from","dkim_domain","dkim_selector","spf_domain"]},"EmailSecurityReportResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"report":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"org_name":{"type":"string","examples":["google.com"]},"report_id":{"type":"string","examples":["1234567890"]},"policy_p":{"type":"string","examples":["none"]},"total":{"type":"integer","examples":[112],"description":"Total count"}},"required":["id","org_name","report_id","policy_p","total"]},"rows":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityReportResponseRowsItem"}}},"required":["success","report","rows"]},"EmailSecurityTlsrptSummaryResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"summary":{"type":"object","properties":{"days":{"type":"integer","examples":[30]},"totals":{"type":"object","properties":{"success":{"type":"integer","examples":[900],"description":"true on success"},"failure":{"type":"integer","examples":[100]}},"required":["success","failure"]},"daily":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-10-07"]},"success":{"type":"integer","examples":[180],"description":"true on success"},"failure":{"type":"integer","examples":[10]}},"required":["day","success","failure"]}},"by_type":{"type":"array","items":{"type":"object","properties":{"result_type":{"type":"string","examples":["certificate-expired"]},"count":{"type":"integer","examples":[60]},"mx_count":{"type":"integer","examples":[1]},"last_day":{"type":"string","format":"date","examples":["2026-10-06"]},"advice":{"type":"string","examples":["…"]}},"required":["result_type","count","mx_count","last_day","advice"]}},"by_mx":{"type":"array","items":{"type":"object","properties":{"mx":{"type":"string","examples":["mx1.kunde.de"]},"count":{"type":"integer","examples":[80]},"types":{"type":"array","items":{"type":"string","examples":["certificate-expired"]}}},"required":["mx","count","types"]}},"by_policy":{"type":"array","items":{"type":"object","properties":{"policy_type":{"type":"string","examples":["sts"]},"success":{"type":"integer","examples":[800],"description":"true on success"},"failure":{"type":"integer","examples":[90]}},"required":["policy_type","success","failure"]}},"reporters":{"type":"array","items":{"type":"object","properties":{"org_name":{"type":"string","examples":["Google Inc."]},"reports":{"type":"integer","examples":[5]},"success":{"type":"integer","examples":[600],"description":"true on success"},"failure":{"type":"integer","examples":[50]},"last_at":{"type":"string","format":"date-time","examples":["2026-10-08T01:00:00.000Z"]}},"required":["org_name","reports","success","failure","last_at"]}},"reports":{"type":"integer","examples":[10]},"last_report_at":{"type":"string","format":"date-time","examples":["2026-10-08T01:05:00.000Z"]}},"required":["days","totals","daily","by_type","by_mx","by_policy","reporters","reports","last_report_at"]}},"required":["success","summary"]},"EmailSecurityTlsrptReportsResponseReportsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"org_name":{"type":"string","examples":["Google Inc."]},"report_id":{"type":"string","examples":["2026-10-07T00:00:00Z_kunde.de"]},"begin_at":{"type":"string","format":"date-time","examples":["2026-10-07T00:00:00.000Z"]},"end_at":{"type":"string","format":"date-time","examples":["2026-10-07T23:59:59.000Z"]},"success_count":{"type":"integer","examples":[90]},"failure_count":{"type":"integer","examples":[10]}},"required":["id","org_name","report_id","begin_at","end_at","success_count","failure_count"]},"EmailSecurityTlsrptReportsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[10],"description":"Total count"},"limit":{"type":"integer","examples":[25],"description":"Maximum number per page"},"offset":{"type":"integer","examples":[0],"description":"Start position"},"reports":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityTlsrptReportsResponseReportsItem"}}},"required":["success","total","limit","offset","reports"]},"EmailSecurityTlsrptReportResponsePoliciesItem":{"type":"object","properties":{"type":{"type":"string","examples":["sts"],"description":"Type"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"success":{"type":"integer","examples":[90],"description":"true on success"},"failure":{"type":"integer","examples":[10]}},"required":["type","domain","success","failure"]},"EmailSecurityTlsrptReportResponseFailuresItem":{"type":"object","properties":{"policy_type":{"type":"string","examples":["sts"]},"result_type":{"type":"string","examples":["certificate-expired"]},"sending_ip":{"type":"string","examples":["209.85.220.41"]},"receiving_mx":{"type":"string","examples":["mx1.kunde.de"]},"receiving_ip":{"type":"string","examples":["203.0.113.5"]},"count":{"type":"integer","examples":[10]},"reason":{"type":["string","null"]}},"required":["policy_type","result_type","sending_ip","receiving_mx","receiving_ip","count"]},"EmailSecurityTlsrptReportResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"report":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"org_name":{"type":"string","examples":["Google Inc."]},"report_id":{"type":"string","examples":["…"]},"begin_at":{"type":"string","examples":["…"]},"end_at":{"type":"string","examples":["…"]},"contact":{"type":"string","format":"email","examples":["smtp-tls-reporting@google.com"]},"success":{"type":"integer","examples":[90],"description":"true on success"},"failure":{"type":"integer","examples":[10]}},"required":["id","org_name","report_id","begin_at","end_at","contact","success","failure"]},"policies":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityTlsrptReportResponsePoliciesItem"}},"failures":{"type":"array","items":{"$ref":"#/components/schemas/EmailSecurityTlsrptReportResponseFailuresItem"}}},"required":["success","report","policies","failures"]},"EmailSecurityUpdateRequest":{"type":"object","properties":{"alert_enabled":{"type":"boolean","description":"Alerting on/off"},"alert_min_mails":{"type":"integer","description":"Report a new source only from this many unauthenticated emails (1–100000)"},"alert_pass_below":{"type":"integer","description":"Daily pass rate threshold in percent (0 = off)"},"alert_no_report_days":{"type":"integer","description":"Alert if no report arrives for this many days (0 = off, 0–90, default 7)"},"alert_setup_lost":{"type":"boolean","description":"Alert if the setup is lost (DMARC record or report address missing)"},"tlsrpt_alert_enabled":{"type":"boolean","description":"TLS-RPT: alert on high failure rate or new failure type"},"tlsrpt_alert_min_sessions":{"type":"integer","description":"TLS-RPT: alert only from this number of sessions on the report day (1 to 1000000, default 20)"},"tlsrpt_alert_fail_pct":{"type":"integer","description":"TLS-RPT: alert from this percentage of failed sessions (0 = off, default 5)"},"alert_channels":{"type":"object","description":"Notification channels as for website/server monitors: `email` (recipients: `user:<uuid>`, `contact:<uuid>`, `raw:<address>`), `slack`/`teams`/`discord` (`webhook_url`, https), `sms` (team/contacts only), `webhook` (`url`, https); per channel `enabled` and `notify_on` = `failure` (problem) | `recovery` (all-clear) | `always`. `null` deletes the setting (alerts then go to the creator's alert rules)."}}},"EmailSecurityUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"alert":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"min_mails":{"type":"integer","examples":[10]},"pass_below":{"type":"integer","examples":[90]}},"required":["enabled","min_mails","pass_below"]}},"required":["id","domain","alert"],"description":"Domain without protocol"}},"required":["success","domain"]},"EmailSecurityCheckResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"status":{"type":"string","examples":["ok"],"description":"Current status"},"record":{"type":"string","examples":["v=DMARC1; p=none; rua=mailto:r-0123456789abcdef@rua.empedia.cloud"]},"authorized":{"type":"boolean"}},"required":["success","status","record","authorized"]},"EmailSecurityTokenResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"rua":{"type":"string","format":"email","examples":["r-fedcba9876543210@rua.empedia.cloud"]}},"required":["id","domain","rua"],"description":"Domain without protocol"}},"required":["success","domain"]},"EmailSecurityDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"DomainsList_ResponseDomainsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["kunde.de"],"description":"Name"},"ns_set":{"type":"string","examples":["urbandomains"]},"expire_at":{"type":"string","format":"date","examples":["2027-03-01"]},"cancelation":{"type":["string","null"]},"auto_renew":{"type":"string","examples":["TRUE"]},"has_zone":{"type":"boolean"},"zone_records":{"type":"integer","examples":[12]}},"required":["id","name","ns_set","expire_at","auto_renew","has_zone","zone_records"]},"DomainsList_Response":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[1],"description":"Total count"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainsList_ResponseDomainsItem"}}},"required":["success","total","domains"]},"DomainsGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["kunde.de"],"description":"Name"},"ns_set":{"type":"string","examples":["urbandomains"]},"nameservers":{"type":"array","items":{"type":"string","examples":["ns1.urbandomains.de"]}},"expire_at":{"type":"string","format":"date","examples":["2027-03-01"]},"auto_renew":{"type":"string","examples":["TRUE"]},"has_zone":{"type":"boolean"}},"required":["id","name","ns_set","nameservers","expire_at","auto_renew","has_zone"],"description":"Domain without protocol"}},"required":["success","domain"]},"DomainsQuoteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"quote":{"type":"object","properties":{"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"years":{"type":"integer","examples":[1]},"net_cents":{"type":"integer","examples":[1290]},"balance_cents":{"type":"integer","examples":[5000]}},"required":["domain","years","net_cents","balance_cents"]}},"required":["success","quote"]},"DomainsRegister_Request":{"type":"object","properties":{"domain":{"type":"string","description":"Domain name"},"years":{"type":"integer","description":"Term (at least that of the TLD)"},"expect_net_cents":{"type":"integer","description":"Expected net price from /orders/quote"}},"required":["domain","expect_net_cents"]},"DomainsRegister_Response":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"order":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"kind":{"type":"string","examples":["register"]},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"status":{"type":"string","examples":["processing"],"description":"Current status"}},"required":["id","kind","domain","status"]}},"required":["success","order"]},"DomainsOrdersResponseOrdersItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"kind":{"type":"string","examples":["register"]},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"status":{"type":"string","examples":["completed"],"description":"Current status"},"net_cents":{"type":"integer","examples":[1290]},"charged_cents":{"type":"integer","examples":[1535]},"refunded":{"type":"integer","examples":[0]}},"required":["id","kind","domain","status","net_cents","charged_cents","refunded"]},"DomainsOrdersResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[1],"description":"Total count"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/DomainsOrdersResponseOrdersItem"}}},"required":["success","total","orders"]},"DomainsRenewRequest":{"type":"object","properties":{"years":{"type":"integer","description":"1–10, at least the term of the TLD"}}},"DomainsRenewResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"DomainsRestoreResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"DomainsCancelRequest":{"type":"object","properties":{"confirm":{"type":"boolean","description":"Must be true"}},"required":["confirm"]},"DomainsCancelResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"DomainsUncancelResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"DomainsUpdateRequest":{"type":"object","properties":{"auto_renew":{"type":"string","description":"TRUE | FALSE | ONCE"},"ns_profile":{"type":"string","description":"urbandomains | microsoft | sedo | parkingcrew"},"nameservers":{"type":"array","items":{},"description":"Custom name servers (2–13)"}}},"DomainsUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ZonesRecordsResponseRecordsItem":{"type":"object","properties":{"name":{"type":"string","examples":["www"],"description":"Name"},"type":{"type":"string","examples":["CNAME"],"description":"Type"},"value":{"type":"string","examples":["kunde.de."]},"ttl":{"type":"integer","examples":[3600]}},"required":["name","type","value","ttl"]},"ZonesRecordsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[2],"description":"Total count"},"records":{"type":"array","items":{"$ref":"#/components/schemas/ZonesRecordsResponseRecordsItem"}}},"required":["success","total","records"]},"ZonesPatchRequest":{"type":"object","properties":{"add":{"type":"array","items":{},"description":"New records"},"remove":{"type":"array","items":{},"description":"Records to remove (change = remove + add)"},"main":{"type":"object","description":"Main IP address { address, ttl }"}}},"ZonesPatchResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ZonesChangesResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ZonesRollbackResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"ZonesExportResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertsCatalogResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertsPrepareRequest":{"type":"object","properties":{"product_id":{"type":"integer","description":"Product from the catalog"},"csr":{"type":"string","description":"CSR in PEM format"},"months":{"type":"integer","description":"Term in months"}},"required":["product_id","csr","months"]},"CertsPrepareResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertsOrderRequest":{"type":"object","properties":{"order_id":{"type":"string","examples":["uuid"]},"method":{"type":"string","examples":["DNS"]},"confirm":{"type":"boolean"},"contact":{"type":"object","properties":{"fname":{"type":"string","examples":["Max"]},"lname":{"type":"string","examples":["Muster"]},"email":{"type":"string","format":"email","examples":["max@kunde.de"]},"phone":{"type":"string","examples":["+49301234567"]},"address":{"type":"string","examples":["Musterstr. 1"]},"pcode":{"type":"string","examples":["10115"]},"city":{"type":"string","examples":["Berlin"]},"country":{"type":"string","examples":["DE"]}},"required":["fname","lname","email","phone","address","pcode","city","country"]},"expect_net_cents":{"type":"integer","examples":[1990]}},"required":["order_id","method","confirm","contact","expect_net_cents"]},"CertsOrderResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertsSmimeRequest":{"type":"object","properties":{"product_id":{"type":"integer","description":"S/MIME product from the catalog (`smime: true`)"},"months":{"type":"integer","description":"Term in months"},"email":{"type":"string","description":"Holder's email address"},"firstname":{"type":"string","description":"First name"},"lastname":{"type":"string","description":"Last name"},"password":{"type":"string","description":"Password for the download (8–32 characters: letters, digits, space, hyphen)"},"confirm":{"type":"boolean","description":"Confirm the binding order"}},"required":["product_id","months","email","firstname","lastname","password","confirm"]},"CertsSmimeResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"order":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"status":{"type":"string","examples":["validating"],"description":"Current status"},"email":{"type":"string","format":"email","examples":["max.muster@kunde.de"]},"charged_cents":{"type":"integer","examples":[2368]}},"required":["id","status","email","charged_cents"]}},"required":["success","order"]},"CertsOrdersListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertsDownloadResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"AftermarketQuoteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"quote":{"type":"object","properties":{"domain":{"type":"string","examples":["beispiel.de"],"description":"Domain without protocol"},"net_cents":{"type":"integer","examples":[6590]},"gross_cents":{"type":"integer","examples":[7842]},"requires_approval":{"type":"boolean"},"approval_limit_cents":{"type":"integer","examples":[200000]}},"required":["domain","net_cents","gross_cents","requires_approval","approval_limit_cents"]}},"required":["success","quote"]},"AftermarketStartRequest":{"type":"object","properties":{"domain":{"type":"string","description":"Domain name"},"expect_net_cents":{"type":"integer","description":"Expected net price from the price query"},"confirm":{"type":"boolean","description":"Confirm the binding order"},"owner":{"type":"object","description":"Owner: { handle } (existing contact) or { contact: {…} }"},"ns_profile":{"type":"string","description":"urbandomains | microsoft | sedo | parkingcrew | custom"}},"required":["domain","expect_net_cents","confirm","owner"]},"AftermarketStartResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"order":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["beispiel.de"],"description":"Domain without protocol"},"status":{"type":"string","examples":["awaiting_payment"],"description":"Current status"},"gross_cents":{"type":"integer","examples":[7842]},"checkout_url":{"type":"string","format":"uri","examples":["https://checkout.stripe.com/…"]}},"required":["id","domain","status","gross_cents","checkout_url"]}},"required":["success","order"]},"AftermarketListResponseOrdersItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"domain":{"type":"string","examples":["beispiel.de"],"description":"Domain without protocol"},"status":{"type":"string","examples":["awaiting_approval"],"description":"Current status"},"net_cents":{"type":"integer","examples":[250000]},"gross_cents":{"type":"integer","examples":[297500]},"requires_approval":{"type":"boolean"}},"required":["id","domain","status","net_cents","gross_cents","requires_approval"]},"AftermarketListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[1],"description":"Total count"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/AftermarketListResponseOrdersItem"}}},"required":["success","total","orders"]},"AftermarketPayResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"checkout_url":{"type":"string","format":"uri","examples":["https://checkout.stripe.com/…"]}},"required":["success","checkout_url"]},"AftermarketCancelResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertContactsListResponseContactsItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"fname":{"type":"string","examples":["Erika"]},"lname":{"type":"string","examples":["Muster"]},"organization":{"type":"string","examples":["Muster GmbH"]},"email":{"type":"string","format":"email","examples":["e@example.com"]},"phone":{"type":"string","examples":["+49 30 123456"]},"address":{"type":"string","examples":["Weg 1"]},"pcode":{"type":"string","examples":["10115"]},"city":{"type":"string","examples":["Berlin"]},"country":{"type":"string","examples":["DE"]}},"required":["id","fname","lname","organization","email","phone","address","pcode","city","country"]},"CertContactsListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/CertContactsListResponseContactsItem"}}},"required":["success","contacts"]},"CertContactsCreateRequest":{"type":"object","properties":{"fname":{"type":"string","description":"First name"},"lname":{"type":"string","description":"Last name"},"organization":{"type":"string","description":"Company (required for OV/EV)"},"email":{"type":"string","description":"Email"},"phone":{"type":"string","description":"Phone in international format"}},"required":["fname","lname","email","phone"]},"CertContactsCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertContactsUpdateRequest":{"type":"object","properties":{"fname":{"type":"string","examples":["Erika"]},"lname":{"type":"string","examples":["Muster"]},"address":{"type":"string","examples":["Weg 1"]},"pcode":{"type":"string","examples":["10115"]},"city":{"type":"string","examples":["Berlin"]},"country":{"type":"string","examples":["DE"]},"email":{"type":"string","format":"email","examples":["e@example.com"]},"phone":{"type":"string","examples":["+49 30 999999"]}},"required":["fname","lname","address","pcode","city","country","email","phone"]},"CertContactsUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CertContactsDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"RequestsCreateRequest":{"type":"object","properties":{"kind":{"type":"string","description":"domain | certificate"},"subject":{"type":"string","description":"Domain or certificate name"},"message":{"type":"string","description":"Note (up to 4000 characters)"}},"required":["kind","subject"]},"RequestsCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"SearchConsoleConfigResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"feature":{"type":"boolean"},"google":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"service_account_email":{"type":"string","format":"email","examples":["auditcollector@projekt.iam.gserviceaccount.com"]}},"required":["enabled","service_account_email"]},"bing":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"}},"required":["enabled"]},"crux":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"}},"required":["enabled"]}},"required":["success","feature","google","bing","crux"]},"SearchConsoleLinksResponseLinksItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"provider":{"type":"string","examples":["google"]},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"property":{"type":"string","examples":["sc-domain:kunde.de"]},"status":{"type":"string","examples":["ok"],"description":"Current status"},"status_detail":{"type":["string","null"]},"last_sync_at":{"type":"string","format":"date-time","examples":["2026-10-12T04:10:00.000Z"]},"clicks_28d":{"type":"integer","examples":[2864]},"impressions_28d":{"type":"integer","examples":[72318]},"clicks_prev_28d":{"type":"integer","examples":[3580]},"alert_enabled":{"type":"boolean"},"alert_clicks_drop_pct":{"type":"integer","examples":[30]},"alert_min_clicks":{"type":"integer","examples":[50]},"alert_index_issues":{"type":"boolean"}},"required":["id","provider","domain","property","status","last_sync_at","clicks_28d","impressions_28d","clicks_prev_28d","alert_enabled","alert_clicks_drop_pct","alert_min_clicks","alert_index_issues"]},"SearchConsoleLinksResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[1],"description":"Total count"},"links":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleLinksResponseLinksItem"}}},"required":["success","total","links"]},"SearchConsoleLinkCreateRequest":{"type":"object","properties":{"provider":{"type":"string","description":"google | bing"},"domain":{"type":"string","description":"Verified domain"},"api_key":{"type":"string","description":"Bing only: API key"}},"required":["provider","domain"]},"SearchConsoleLinkCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"link":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"provider":{"type":"string","examples":["google"]},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"property":{"type":"string","examples":["sc-domain:kunde.de"]},"status":{"type":"string","examples":["ok"],"description":"Current status"}},"required":["id","provider","domain","property","status"]}},"required":["success","link"]},"SearchConsoleLinkGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"link":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"provider":{"type":"string","examples":["google"]},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"status":{"type":"string","examples":["ok"],"description":"Current status"}},"required":["id","provider","domain","status"]},"compare":{"type":"object","properties":{"last_day":{"type":"string","format":"date","examples":["2026-10-10"]},"current":{"type":"object","properties":{"clicks":{"type":"integer","examples":[350]},"impressions":{"type":"integer","examples":[18365]},"days":{"type":"integer","examples":[7]}},"required":["clicks","impressions","days"]},"previous":{"type":"object","properties":{"clicks":{"type":"integer","examples":[800]},"impressions":{"type":"integer","examples":[19200]},"days":{"type":"integer","examples":[7]}},"required":["clicks","impressions","days"]},"clicks_change_pct":{"type":"number","examples":[-56.3]},"impressions_change_pct":{"type":"number","examples":[-4.4]},"complete":{"type":"boolean"}},"required":["last_day","current","previous","clicks_change_pct","impressions_change_pct","complete"]},"index":{"type":"object","properties":{"PASS":{"type":"integer","examples":[5]},"FAIL":{"type":"integer","examples":[2]}},"required":["PASS","FAIL"]},"sitemaps":{"type":"object","properties":{"count":{"type":"integer","examples":[1]},"errors":{"type":"integer","examples":[2]},"warnings":{"type":"integer","examples":[0]}},"required":["count","errors","warnings"]},"crawl":{"type":["string","null"]},"crux":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"}},"required":["enabled"]}},"required":["success","link","compare","index","sitemaps","crux"]},"SearchConsoleDailyResponseDailyItem":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-10-10"]},"clicks":{"type":"integer","examples":[48]},"impressions":{"type":"integer","examples":[2510]},"position":{"type":"number","examples":[7.2]}},"required":["day","clicks","impressions","position"]},"SearchConsoleDailyResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"days":{"type":"integer","examples":[90]},"daily":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleDailyResponseDailyItem"}}},"required":["success","days","daily"]},"SearchConsoleTopResponseItemsItem":{"type":"object","properties":{"item":{"type":"string","examples":["schuhe kaufen"]},"clicks":{"type":"integer","examples":[200]},"impressions":{"type":"integer","examples":[3000]},"position":{"type":"number","examples":[3.2]},"prev_clicks":{"type":"integer","examples":[190]},"prev_impressions":{"type":"integer","examples":[2900]}},"required":["item","clicks","impressions","position","prev_clicks","prev_impressions"]},"SearchConsoleTopResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[40],"description":"Total count"},"items":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleTopResponseItemsItem"}}},"required":["success","total","items"]},"SearchConsoleKeywordsResponseKeywordsItem":{"type":"object","properties":{"id":{"type":"string","examples":["6b0c…"],"description":"Unique ID (UUID)"},"keyword":{"type":"string","examples":["schuhe kaufen"]},"clicks":{"type":"integer","examples":[120]},"impressions":{"type":"integer","examples":[2000]},"position":{"type":"number","examples":[4.2]},"prev_position":{"type":"number","examples":[5.1]},"position_change":{"type":"number","examples":[0.9]},"last_day":{"type":"string","format":"date","examples":["2026-10-11"]}},"required":["id","keyword","clicks","impressions","position","prev_position","position_change","last_day"]},"SearchConsoleKeywordsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"limit":{"type":"integer","examples":[25],"description":"Maximum number per page"},"keywords":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleKeywordsResponseKeywordsItem"}}},"required":["success","limit","keywords"]},"SearchConsoleKeywordAddRequest":{"type":"object","properties":{"keyword":{"type":"string","description":"Search term (2–255 characters)"}},"required":["keyword"]},"SearchConsoleKeywordAddResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"keyword":{"type":"object","properties":{"id":{"type":"string","examples":["6b0c…"],"description":"Unique ID (UUID)"},"keyword":{"type":"string","examples":["schuhe kaufen"]}},"required":["id","keyword"]}},"required":["success","keyword"]},"SearchConsoleKeywordDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"SearchConsoleKeywordDailyResponseDailyItem":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-10-10"]},"clicks":{"type":"integer","examples":[4]},"impressions":{"type":"integer","examples":[52]},"position":{"type":"number","examples":[4.3]}},"required":["day","clicks","impressions","position"]},"SearchConsoleKeywordDailyResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"keyword":{"type":"string","examples":["schuhe kaufen"]},"days":{"type":"integer","examples":[90]},"daily":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleKeywordDailyResponseDailyItem"}}},"required":["success","keyword","days","daily"]},"SearchConsoleIndexResponsePagesItem":{"type":"object","properties":{"url":{"type":"string","format":"uri","examples":["https://kunde.de/schuhe"],"description":"Page address"},"verdict":{"type":"string","examples":["FAIL"]},"coverage_state":{"type":"string","examples":["Gecrawlt – zurzeit nicht indexiert"]},"indexing_state":{"type":"string","examples":["INDEXING_ALLOWED"]},"last_crawl_at":{"type":"string","format":"date-time","examples":["2026-10-01T08:00:00.000Z"]},"google_canonical":{"type":"string","format":"uri","examples":["https://kunde.de/schuhe"]},"user_canonical":{"type":"string","format":"uri","examples":["https://kunde.de/schuhe"]},"checked_at":{"type":"string","format":"date-time","examples":["2026-10-12T04:12:00.000Z"]}},"required":["url","verdict","coverage_state","indexing_state","last_crawl_at","google_canonical","user_canonical","checked_at"]},"SearchConsoleIndexResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[1],"description":"Total count"},"pages":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleIndexResponsePagesItem"}}},"required":["success","total","pages"]},"SearchConsoleSitemapsResponseSitemapsItem":{"type":"object","properties":{"path":{"type":"string","format":"uri","examples":["https://kunde.de/sitemap.xml"]},"last_submitted":{"type":"string","format":"date-time","examples":["2026-09-01T10:00:00.000Z"]},"last_downloaded":{"type":"string","format":"date-time","examples":["2026-10-11T02:00:00.000Z"]},"errors":{"type":"integer","examples":[2]},"warnings":{"type":"integer","examples":[0]},"submitted":{"type":"integer","examples":[120]},"indexed":{"type":"integer","examples":[100]},"is_pending":{"type":"boolean"}},"required":["path","last_submitted","last_downloaded","errors","warnings","submitted","indexed","is_pending"]},"SearchConsoleSitemapsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"sitemaps":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleSitemapsResponseSitemapsItem"}}},"required":["success","sitemaps"]},"SearchConsoleCrawlResponseCrawlItem":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-10-11"]},"crawled_pages":{"type":"integer","examples":[40]},"crawl_errors":{"type":"integer","examples":[3]},"blocked_robots":{"type":"integer","examples":[1]},"in_index":{"type":"integer","examples":[400]},"code_4xx":{"type":"integer","examples":[2]},"code_5xx":{"type":"integer","examples":[0]},"malware":{"type":"integer","examples":[0]}},"required":["day","crawled_pages","crawl_errors","blocked_robots","in_index","code_4xx","code_5xx","malware"]},"SearchConsoleCrawlResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"crawl":{"type":"array","items":{"$ref":"#/components/schemas/SearchConsoleCrawlResponseCrawlItem"}}},"required":["success","crawl"]},"SearchConsoleLinkUpdateRequest":{"type":"object","properties":{"alert_enabled":{"type":"boolean","description":"Alerts on/off"},"alert_clicks_drop_pct":{"type":"integer","description":"5–95"},"alert_min_clicks":{"type":"integer","description":"Clicks of the previous week from which a drop counts"},"alert_index_issues":{"type":"boolean","description":"Report index loss (Google)"},"alert_channels":{"type":"object","description":"Channels as for monitors"},"api_key":{"type":"string","description":"Bing only: new API key"}}},"SearchConsoleLinkUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"link":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"alert_clicks_drop_pct":{"type":"integer","examples":[40]},"alert_min_clicks":{"type":"integer","examples":[200]}},"required":["id","alert_clicks_drop_pct","alert_min_clicks"]}},"required":["success","link"]},"SearchConsoleSyncResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"ok":{"type":"boolean"},"link":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"status":{"type":"string","examples":["ok"],"description":"Current status"}},"required":["id","status"]}},"required":["success","ok","link"]},"SearchConsoleLinkDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"SearchConsoleCruxResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"domain":{"type":"string","examples":["kunde.de"],"description":"Domain without protocol"},"crux":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"phone":{"type":"object","properties":{"no_data":{"type":"boolean"},"metrics":{"type":"object","properties":{"lcp":{"type":"object","properties":{"p75":{"type":"integer","examples":[3100]},"good":{"type":"number","examples":[0.6]},"ni":{"type":"number","examples":[0.25]},"poor":{"type":"number","examples":[0.15]},"rating":{"type":"string","examples":["needs-improvement"]}},"required":["p75","good","ni","poor","rating"]},"cls":{"type":"object","properties":{"p75":{"type":"number","examples":[0.04]},"good":{"type":"number","examples":[0.9]},"ni":{"type":"number","examples":[0.05]},"poor":{"type":"number","examples":[0.05]},"rating":{"type":"string","examples":["good"]}},"required":["p75","good","ni","poor","rating"]}},"required":["lcp","cls"]},"period":{"type":"object","properties":{"from":{"type":"string","format":"date","examples":["2026-09-01"]},"to":{"type":"string","format":"date","examples":["2026-09-28"]}},"required":["from","to"]}},"required":["no_data","metrics","period"]},"desktop":{"type":"object","properties":{"no_data":{"type":"boolean"},"metrics":{"type":["string","null"]}},"required":["no_data"]}},"required":["enabled","phone","desktop"]}},"required":["success","domain","crux"]},"CaptchaSitesListResponseSitesItem":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["urbanstudio.de"],"description":"Name"},"sitekey":{"type":"string","examples":["ek_site_…"]},"hosts":{"type":"array","items":{"type":"string","examples":["urbanstudio.de"]}},"mode":{"type":"string","examples":["balanced"]},"status":{"type":"string","examples":["active"],"description":"Current status"},"observe":{"type":"boolean"},"ok_30d":{"type":"integer","examples":[1234]},"rejected_30d":{"type":"integer","examples":[56]}},"required":["id","name","sitekey","hosts","mode","status","observe","ok_30d","rejected_30d"]},"CaptchaSitesListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"sites":{"type":"array","items":{"$ref":"#/components/schemas/CaptchaSitesListResponseSitesItem"}}},"required":["success","sites"]},"CaptchaSitesCreateRequest":{"type":"object","properties":{"name":{"type":"string","description":"Name (up to 120 characters)"},"hosts":{"type":"array","items":{},"description":"Hosts of the domain"},"mode":{"type":"string","description":"lenient, balanced (default) or strict"}},"required":["name","hosts"]},"CaptchaSitesCreateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"site":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"sitekey":{"type":"string","examples":["ek_site_…"]}},"required":["id","sitekey"]},"secret":{"type":"string","examples":["ek_secret_…"],"description":"Secret — shown only once"}},"required":["success","site","secret"]},"CaptchaSitesBulkRequest":{"type":"object","properties":{"sites":{"type":"array","items":{},"description":"List of { name, hosts, mode? }, at most 100"}},"required":["sites"]},"CaptchaSitesBulkResponseResultsItem":{"type":"object","properties":{"index":{"type":"integer","examples":[0]},"ok":{"type":"boolean"},"site":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"sitekey":{"type":"string","examples":["ek_site_…"]}},"required":["id","sitekey"]},"secret":{"type":"string","examples":["ek_secret_…"],"description":"Secret — shown only once"}},"required":["index","ok","site","secret"]},"CaptchaSitesBulkResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"created":{"type":"integer","examples":[2]},"results":{"type":"array","items":{"$ref":"#/components/schemas/CaptchaSitesBulkResponseResultsItem"}}},"required":["success","created","results"]},"CaptchaSitesGetResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"site":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"name":{"type":"string","examples":["urbanstudio.de"],"description":"Name"},"hosts":{"type":"array","items":{"type":"string","examples":["urbanstudio.de"]}},"mode":{"type":"string","examples":["balanced"]},"observe":{"type":"boolean"},"gate":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Active or paused"},"ttl_min":{"type":"integer","examples":[60]},"skip":{"type":"array","items":{"type":"string","examples":["/robots.txt"]}},"crawlers":{"type":"boolean"}},"required":["enabled","ttl_min","skip","crawlers"]}},"required":["id","name","hosts","mode","observe","gate"]}},"required":["success","site"]},"CaptchaSitesUpdateRequest":{"type":"object","properties":{"name":{"type":"string","description":"Name"},"hosts":{"type":"array","items":{},"description":"Hosts"},"mode":{"type":"string","description":"lenient, balanced, strict"},"observe":{"type":"boolean","description":"Observe mode"},"status":{"type":"string","description":"active or paused"},"gate":{"type":"object","description":"{ enabled, ttl_min, skip, crawlers }"}}},"CaptchaSitesUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"site":{"type":"object","properties":{"id":{"type":"string","examples":["uuid"],"description":"Unique ID (UUID)"},"observe":{"type":"boolean"}},"required":["id","observe"]}},"required":["success","site"]},"CaptchaSitesRotateResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"secret":{"type":"string","examples":["ek_secret_…"],"description":"Secret — shown only once"}},"required":["success","secret"]},"CaptchaSitesDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CaptchaSitesStatsResponseRowsItem":{"type":"object","properties":{"day":{"type":"string","format":"date","examples":["2026-10-17"]},"metric":{"type":"string","examples":["verify_ok"]},"n":{"type":"integer","examples":[120]}},"required":["day","metric","n"]},"CaptchaSitesStatsResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"days":{"type":"integer","examples":[30]},"rows":{"type":"array","items":{"$ref":"#/components/schemas/CaptchaSitesStatsResponseRowsItem"}}},"required":["success","days","rows"]},"CaptchaSitesActivityResponseActivityItem":{"type":"object","properties":{"action":{"type":"string","examples":["captcha.site_update"]},"at":{"type":"string","format":"date-time","examples":["2026-10-17T09:00:00Z"]},"user":{"type":"string","examples":["Anna"]},"via":{"type":"string","examples":["dashboard"]},"fields":{"type":"array","items":{"type":"string","examples":["observe"]}}},"required":["action","at","user","via","fields"]},"CaptchaSitesActivityResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"total":{"type":"integer","examples":[2],"description":"Total count"},"activity":{"type":"array","items":{"$ref":"#/components/schemas/CaptchaSitesActivityResponseActivityItem"}}},"required":["success","total","activity"]},"CaptchaRulesListResponseRulesItem":{"type":"object","properties":{"id":{"type":"string","examples":["1"],"description":"Unique ID (UUID)"},"kind":{"type":"string","examples":["ip"]},"action":{"type":"string","examples":["block"]},"value":{"type":"string","examples":["203.0.113.9"]},"source":{"type":"string","examples":["manual"]}},"required":["id","kind","action","value","source"]},"CaptchaRulesListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"rules":{"type":"array","items":{"$ref":"#/components/schemas/CaptchaRulesListResponseRulesItem"}},"lists":{"type":"array","items":{}}},"required":["success","rules","lists"]},"CaptchaRulesAddRequest":{"type":"object","properties":{"kind":{"type":"string","description":"ip, cidr, email, domain, username or content"},"action":{"type":"string","description":"block or allow"},"value":{"type":"string","description":"Value"},"note":{"type":"string","description":"Note"}},"required":["kind","action","value"]},"CaptchaRulesAddResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CaptchaRulesDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"}},"required":["success"]},"CaptchaPlanResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"true on success"},"plan":{"type":"object","properties":{"tier":{"type":"string","examples":["paid"]},"name":{"type":"string","examples":["EMPEDIAcaptcha Pro"],"description":"Name"},"sites_limit":{"type":"integer","examples":[25]},"sites_used":{"type":"integer","examples":[3]},"checks_included":{"type":"integer","examples":[250000]},"checks_used":{"type":"integer","examples":[1200]}},"required":["tier","name","sites_limit","sites_used","checks_included","checks_used"]}},"required":["success","plan"]}}}}