{"openapi":"3.0.0","paths":{"/api/v1":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":"Welcome message","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"string"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Root endpoint","tags":["Health"]}},"/api/v1/health":{"get":{"operationId":"AppController_getHealth","parameters":[],"responses":{"200":{"description":"Health status including MongoDB, Redis, and memory usage","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/HealthResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Detailed health check with dependency status","tags":["Health"]}},"/api/v1/health/ready":{"get":{"operationId":"AppController_getReadiness","parameters":[],"responses":{"200":{"description":"Service is ready","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ReadinessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}},"503":{"description":"Service unavailable — MongoDB not connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"summary":"Readiness probe — returns 200 when critical dependencies are connected","tags":["Health"]}},"/api/v1/health/live":{"get":{"operationId":"AppController_getLiveness","parameters":[],"responses":{"200":{"description":"Process is alive","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/LivenessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Liveness probe — returns 200 if process is running","tags":["Health"]}},"/api/v1/log":{"post":{"operationId":"LoggerController_log","parameters":[],"requestBody":{"required":true,"description":"Client-side log entry","content":{"application/json":{"schema":{"type":"object","required":["level","message"],"properties":{"level":{"type":"string","enum":["debug","info","warn","error","fatal"],"description":"Log severity level"},"message":{"type":"string","description":"Log message (max 2000 chars)"},"scope":{"type":"string","description":"Optional context identifier"},"component":{"type":"string","description":"UI component name"},"action":{"type":"string","description":"User action"},"sessionId":{"type":"string","description":"Session ID"},"page":{"type":"string","description":"Current page path"},"duration":{"type":"number","description":"Duration in ms"}}}}}},"responses":{"204":{"description":"Log recorded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid log entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Forward structured log entry from the frontend","tags":["Logging"]}},"/api/v1/auth/extension-token-exchange":{"post":{"operationId":"AuthController_exchangeExtensionToken","parameters":[],"responses":{"200":{"description":"Extension tokens minted successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ExtensionTokenExchangeResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"No valid session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"API key callers are not permitted, or Origin is not on the allow-list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Too many token exchange attempts","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Mint a header-mode SuperTokens session for Chrome extension use","tags":["Auth"]}},"/api/v1/auth/extension-cookie-sync":{"post":{"operationId":"AuthController_syncExtensionCookieSession","parameters":[],"responses":{"200":{"description":"Website cookie session minted successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ExtensionCookieSyncResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"No valid session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"API key callers are not permitted or bearer token is missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Mint a cookie-mode SuperTokens sibling session for website auth","tags":["Auth"]}},"/api/v1/auth/session/refresh":{"post":{"operationId":"AuthController_refreshExtensionSession","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRefreshRequestDto"}}}},"responses":{"200":{"description":"Token pair rotated successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SessionRefreshResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Malformed request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Invalid or expired refresh token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Too many refresh attempts","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Rotate the extension SuperTokens token pair using a refresh token","tags":["Auth"]}},"/api/v1/auth/extension-google-callback":{"post":{"operationId":"AuthController_handleExtensionGoogleCallback","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtensionGoogleCallbackRequestDto"}}}},"responses":{"200":{"description":"Signed in. Session emitted via response headers.","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ExtensionGoogleCallbackResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing access_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Invalid Google access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Sign in to LLM Conveyors natively from the Chrome Extension","tags":["Auth"]}},"/api/v1/storage/serve":{"get":{"operationId":"StorageServeController_serve","parameters":[{"name":"token","required":true,"in":"query","description":"Signed HMAC storage token","schema":{}}],"responses":{"200":{"description":"File content streamed as attachment","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing token query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Invalid or tampered token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Token has expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Serve a file via signed token","tags":["Storage"]}},"/api/v1/privacy/consents":{"get":{"operationId":"PrivacyController_getConsents","parameters":[],"responses":{"200":{"description":"Consent records returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ConsentSummaryDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get current user consent records","tags":["Privacy"]}},"/api/v1/privacy/consents/{purpose}":{"post":{"operationId":"PrivacyController_grantConsent","parameters":[{"name":"purpose","required":true,"in":"path","description":"Consent purpose","schema":{"enum":["account","resume-processing","ai-generation","contact-enrichment","analytics","email-outreach"],"type":"string"}}],"responses":{"200":{"description":"Consent granted","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ConsentActionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid consent purpose","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Grant consent for a specific purpose","tags":["Privacy"]},"delete":{"operationId":"PrivacyController_withdrawConsent","parameters":[{"name":"purpose","required":true,"in":"path","description":"Consent purpose","schema":{"enum":["account","resume-processing","ai-generation","contact-enrichment","analytics","email-outreach"],"type":"string"}}],"responses":{"200":{"description":"Consent withdrawn","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ConsentActionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid consent purpose","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Withdraw consent for a specific purpose","tags":["Privacy"]}},"/api/v1/privacy/export":{"get":{"operationId":"PrivacyController_exportData","parameters":[],"responses":{"200":{"description":"User data export returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UserDataExportResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden — not available for API key authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Export user data (GDPR Art. 15)","tags":["Privacy"]}},"/api/v1/privacy/account":{"delete":{"operationId":"PrivacyController_deleteAccount","parameters":[{"name":"x-confirm-delete","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Confirm-Delete","in":"header","description":"Must be \"true\" to confirm deletion","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Account deletion completed","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/AccountDeletionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing X-Confirm-Delete header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden — not available for API key authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Delete user account (GDPR Art. 17)","tags":["Privacy"]}},"/metrics":{"get":{"operationId":"PrometheusController_index","parameters":[],"responses":{"200":{"description":"","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"tags":["Prometheus"]}},"/api/v1/agents/b2b-sales/generate":{"post":{"operationId":"B2BSalesController_generate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2BSalesGenerateRequestDto"}}}},"responses":{"202":{"description":"Generation queued successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/GenerateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error -- invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Session already has a generation in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Start a B2B Sales generation workflow","tags":["B2B Sales"]}},"/api/v1/agents/job-hunter/generate":{"post":{"operationId":"JobHunterController_generate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JHGenerateRequestDto"}}}},"responses":{"202":{"description":"Generation queued successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/GenerateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error -- invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Session already has a generation in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Start a Job Hunter generation workflow","tags":["Job Hunter"]}},"/api/v1/agents/job-hunter/generate-cv":{"post":{"operationId":"JobHunterController_generateCv","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateCvRequestDto"}}}},"responses":{"200":{"description":"CV generated successfully with resume JSON, usage, and model info","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/GenerateCvResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing or invalid prompt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Insufficient credits for CV generation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Standalone CV generation from a rendered prompt","tags":["Job Hunter"]}},"/api/v1/agents/portfolio/generate":{"post":{"operationId":"PortfolioController_generate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioGenerateRequestDto"}}}},"responses":{"202":{"description":"Optimization queued successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/GenerateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error -- invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Session already has a generation in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Start a portfolio optimization workflow","tags":["Portfolio"]}},"/api/v1/agents/portfolio/broker/zerodha/connect":{"get":{"operationId":"PortfolioBrokerController_connect","parameters":[{"name":"returnTo","required":false,"in":"query","description":"Relative frontend path to return to after connection","schema":{"type":"string"}}],"responses":{"200":{"description":"Zerodha login URL","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Initiate Zerodha Kite Connect flow","tags":["Portfolio"]}},"/api/v1/agents/portfolio/broker/zerodha/callback":{"get":{"operationId":"PortfolioBrokerController_callback","parameters":[{"name":"request_token","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"state","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects back to the frontend portfolio page"},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Handle Zerodha Kite callback redirect","tags":["Portfolio"]}},"/api/v1/agents/portfolio/broker/connections":{"get":{"operationId":"PortfolioBrokerController_listConnections","parameters":[],"responses":{"200":{"description":"Broker connection list","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List connected portfolio brokers","tags":["Portfolio"]}},"/api/v1/agents/portfolio/broker/connections/{connectionId}":{"delete":{"operationId":"PortfolioBrokerController_disconnect","parameters":[{"name":"connectionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Connection disconnected","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Disconnect a portfolio broker connection","tags":["Portfolio"]}},"/api/v1/sessions/init":{"get":{"operationId":"SessionsController_getInitData","parameters":[],"responses":{"200":{"description":"Init data including sessions, documents, strategies, and preferences","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SessionInitResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get session init data with cross-module context","tags":["Sessions"]}},"/api/v1/sessions/stats":{"get":{"operationId":"SessionsController_getStats","parameters":[{"name":"agentType","required":true,"in":"query","description":"Agent type to filter stats","schema":{"type":"string"}}],"responses":{"200":{"description":"Agent stats","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing agentType","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get aggregated stats for an agent type","tags":["Sessions"]}},"/api/v1/sessions":{"post":{"operationId":"SessionsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionDto"}}}},"responses":{"201":{"description":"Session created","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SessionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Create a new session","tags":["Sessions"]},"get":{"operationId":"SessionsController_findAll","parameters":[{"name":"limit","required":false,"in":"query","description":"Page size (1-50, default 20)","schema":{}},{"name":"cursor","required":false,"in":"query","description":"ISO-8601 createdAt cursor for next page","schema":{}}],"responses":{"200":{"description":"Session list (paginated envelope or bare array)","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List sessions with optional cursor-based pagination","tags":["Sessions"]}},"/api/v1/sessions/{id}":{"delete":{"operationId":"SessionsController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Session deleted","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/DeleteSessionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Delete a session","tags":["Sessions"]},"get":{"operationId":"SessionsController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Session details","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SessionResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get a session by ID","tags":["Sessions"]}},"/api/v1/sessions/{id}/hydrate":{"get":{"operationId":"SessionsController_hydrateSession","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Hydrated session data","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SessionHydrateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Hydrate a session with full artifact state","tags":["Sessions"]}},"/api/v1/sessions/{id}/download":{"get":{"operationId":"SessionsController_downloadArtifact","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}},{"name":"key","required":true,"in":"query","description":"Storage key of the artifact to download","schema":{"type":"string"}}],"responses":{"200":{"description":"Artifact file content","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing or invalid storage key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Session or artifact not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Download a session artifact by storage key","tags":["Sessions"]}},"/api/v1/sessions/{id}/log":{"post":{"operationId":"SessionsController_appendLog","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatLogEntryDto"}}}},"responses":{"200":{"description":"Log entry appended","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/AppendChatLogResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid log entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Append a chat log entry to a session","tags":["Sessions"]}},"/api/v1/sessions/{id}/generation-logs/{genId}/init":{"post":{"operationId":"SessionsController_initGenLog","parameters":[{"name":"id","required":true,"in":"path","description":"Session ID","schema":{"type":"string"}},{"name":"genId","required":true,"in":"path","description":"Generation ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Generation log initialized","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/GenerationLogInitResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Initialize a generation log entry","tags":["Sessions"]}},"/api/v1/stream/generation/{generationId}":{"get":{"operationId":"SseController_streamGeneration","parameters":[{"name":"generationId","required":true,"in":"path","description":"Generation ID to stream","schema":{"type":"string"}},{"name":"last-event-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"Last-Event-ID","in":"header","description":"Last received event ID for reconnection replay","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Server-Sent Events stream","content":{"text/event-stream":{"schema":{"type":"string"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid generation ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden — insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Stream generation output via Server-Sent Events","tags":["Streaming"]}},"/api/v1/stream/health":{"get":{"operationId":"SseController_sseHealth","parameters":[],"responses":{"200":{"description":"Server-Sent Events stream","content":{"text/event-stream":{"schema":{"type":"string"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"SSE health check","tags":["Streaming"]}},"/api/v1/agents/{agentType}/status/{jobId}":{"get":{"operationId":"UnifiedAgentController_getStatus","parameters":[{"name":"agentType","required":true,"in":"path","description":"Agent type","schema":{"enum":["job-hunter","b2b-sales","portfolio"],"type":"string"}},{"name":"jobId","required":true,"in":"path","description":"BullMQ job ID","schema":{"type":"string"}},{"name":"include","required":false,"in":"query","description":"Comma-separated fields to include (logs, artifacts)","schema":{"type":"string"}}],"responses":{"200":{"description":"Job status with optional logs and artifacts","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/JobStatusResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden -- access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get job status for a generation","tags":["Agents"]}},"/api/v1/agents/{agentType}/manifest":{"get":{"operationId":"UnifiedAgentController_getManifest","parameters":[{"name":"agentType","required":true,"in":"path","description":"Agent type","schema":{"enum":["job-hunter","b2b-sales","portfolio"],"type":"string"}}],"responses":{"200":{"description":"Agent manifest with input fields, billing, and capabilities","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/AgentManifestResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Unknown agent type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get agent manifest -- capabilities, billing, and input fields","tags":["Agents"]}},"/api/v1/agents/{agentType}/interact":{"post":{"operationId":"UnifiedAgentController_interact","parameters":[{"name":"agentType","required":true,"in":"path","description":"Agent type","schema":{"enum":["job-hunter","b2b-sales","portfolio"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InteractRequestDto"}}}},"responses":{"202":{"description":"Phase resumed successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/InteractResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error -- invalid interact request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Insufficient credits for Phase B","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden -- access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Generation not awaiting input or already resumed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Generation has expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Resume a phased generation with user input","tags":["Agents"]}},"/api/v1/ats/score":{"post":{"operationId":"AtsController_score","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AtsScoreRequestDto"}}}},"responses":{"200":{"description":"ATS score result with dimension breakdowns","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/AtsScoreResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error — invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Score a resume against a job description","tags":["ATS Scoring"]}},"/api/v1/ats/extract-skills":{"post":{"description":"Thin read-only wrapper around the private skill-taxonomy corpus. No LLM call, no credit deduction. Target response time <100ms for 10KB input.","operationId":"ExtractSkillsController_extractSkills","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractSkillsRequestDto"}}}},"responses":{"200":{"description":"Extracted skills ranked by relevance score","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ExtractSkillsResponseDataDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error -- invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized -- missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden -- API key missing ats:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited -- 60 requests per minute per IP","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Extract skills from a job description via deterministic Aho-Corasick matching","tags":["ATS Scoring"]}},"/api/v1/ats/extract-jd":{"post":{"description":"Takes raw scraped page text, returns structured JD (title, company, description, requirements, responsibilities, techStack) plus a validated skills array. LLM techStack is intersected with the deterministic Aho-Corasick matcher to produce clean, context-aware skill matches. Cached 24h by normalized content hash + taxonomy version.","operationId":"ExtractJdController_extractJd","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractJdRequestDto"}}}},"responses":{"200":{"description":"Extracted JD with validated skills","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ExtractJdResponseDataDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error or LLM failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized — missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Forbidden — API key missing ats:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited — 30 requests per minute per IP","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"LLM-assisted structured JD extraction with Aho-Corasick skill intersection","tags":["ATS Scoring"]}},"/api/v1/resume/parse":{"post":{"operationId":"ResumeController_parse","parameters":[{"name":"mode","required":false,"in":"query","description":"Parsing mode","schema":{"enum":["fast","thorough"],"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Resume parsed successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeParseResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid file or mode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Parse a resume file (PDF, DOCX, TXT)","tags":["Resume"]}},"/api/v1/resume/validate":{"post":{"operationId":"ResumeController_validate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeValidateDto"}}}},"responses":{"200":{"description":"Validation result returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeValidateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing resume in body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Validate a resume JSON object","tags":["Resume"]}},"/api/v1/resume/render":{"post":{"operationId":"ResumeController_render","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeRenderDto"}}}},"responses":{"200":{"description":"Rendered resume returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeRenderPdfResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing resume or theme","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Render a resume to PDF or HTML","tags":["Resume"]}},"/api/v1/resume/preview":{"post":{"operationId":"ResumeController_preview","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumePreviewDto"}}}},"responses":{"200":{"description":"HTML preview returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumePreviewResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing resume or theme","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Preview a resume with a specific theme","tags":["Resume"]}},"/api/v1/resume/themes":{"get":{"operationId":"ResumeController_getThemes","parameters":[],"responses":{"200":{"description":"List of themes returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ThemeListResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List available resume themes","tags":["Resume"]}},"/api/v1/resume/import/rx-resume":{"post":{"operationId":"ResumeController_importRxResume","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeImportDto"}}}},"responses":{"200":{"description":"Resume imported successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeImportResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid RX Resume data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Import a resume from RX Resume format","tags":["Resume"]}},"/api/v1/resume/export/rx-resume":{"post":{"operationId":"ResumeController_exportRxResume","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeExportDto"}}}},"responses":{"200":{"description":"Resume exported successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeExportResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Missing resume in body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Export a resume to RX Resume format","tags":["Resume"]}},"/api/v1/resume/master":{"get":{"operationId":"MasterResumeController_get","parameters":[],"responses":{"200":{"description":"Master resume returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MasterResumeResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"No master resume found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get the master resume for the authenticated user","tags":["Master Resume"]},"put":{"operationId":"MasterResumeController_upsert","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MasterResumeUpsertDto"}}}},"responses":{"200":{"description":"Master resume upserted","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MasterResumeResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Create or update the master resume (upsert)","tags":["Master Resume"]},"delete":{"operationId":"MasterResumeController_delete","parameters":[],"responses":{"200":{"description":"Master resume deleted","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SimpleSuccessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"No master resume found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Delete the master resume","tags":["Master Resume"]}},"/api/v1/upload/resume":{"post":{"operationId":"UploadController_uploadResume","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Resume parsed successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ResumeParseResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"File is required or invalid format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Upload a resume file for parsing","tags":["Upload"]}},"/api/v1/upload/job-text":{"post":{"operationId":"UploadController_processJobText","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessJobTextDto"}}}},"responses":{"200":{"description":"Job description processed successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/JdTextProcessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Process a job description from raw text","tags":["Upload"]}},"/api/v1/content/research-sender":{"post":{"operationId":"ContentController_researchSender","parameters":[],"requestBody":{"required":true,"description":"At least one of companyWebsite or companyName is required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchSenderRequestDto"}}}},"responses":{"200":{"description":"Research completed and saved","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid input or research failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Research sender company and save as company_context","tags":["Content"]}},"/api/v1/content/save":{"post":{"operationId":"ContentController_save","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveContentDto"}}}},"responses":{"200":{"description":"Document saved successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SaveContentResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid payload or docType","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Save a source document","tags":["Content"]}},"/api/v1/content/sources":{"get":{"operationId":"ContentController_getSources","parameters":[],"responses":{"200":{"description":"Source documents returned as camelCase key-value map","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List all source documents for the authenticated user","tags":["Content"]}},"/api/v1/content/sources/{docType}":{"get":{"operationId":"ContentController_getSource","parameters":[{"name":"docType","required":true,"in":"path","description":"Document type (e.g. original_cv, extensive_cv, company_context)","schema":{"type":"string"}}],"responses":{"200":{"description":"Source document content returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid document type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get a single source document by type","tags":["Content"]},"delete":{"operationId":"ContentController_deleteSource","parameters":[{"name":"docType","required":true,"in":"path","description":"Document type (e.g. original_cv, extensive_cv, company_context)","schema":{"type":"string"}}],"responses":{"200":{"description":"Source document deleted","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid document type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Delete a source document by type","tags":["Content"]}},"/api/v1/content/generations/{id}":{"delete":{"operationId":"ContentController_deleteGeneration","parameters":[{"name":"id","required":true,"in":"path","description":"Generation ID","schema":{"type":"string"}},{"name":"sessionId","required":true,"in":"query","description":"Session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Generation deleted successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/DeleteGenerationResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Delete a generation by ID","tags":["Content"]}},"/api/v1/settings/providers":{"get":{"operationId":"SettingsController_getProviderKeyStatuses","parameters":[],"responses":{"200":{"description":"Provider key statuses","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get status of all configured provider keys","tags":["Settings"]}},"/api/v1/settings/providers/supported":{"get":{"operationId":"SettingsController_getSupportedProviders","parameters":[],"responses":{"200":{"description":"Supported providers","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List supported AI providers and their capabilities","tags":["Settings"]}},"/api/v1/settings/providers/{provider}":{"post":{"operationId":"SettingsController_setProviderKey","parameters":[{"name":"provider","required":true,"in":"path","description":"Provider ID (e.g. google, fireworks)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["apiKey"],"properties":{"apiKey":{"type":"string","minLength":1,"maxLength":1024}}}}}},"responses":{"200":{"description":"Provider key saved","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SimpleSuccessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid provider or API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Set or update a provider API key","tags":["Settings"]},"delete":{"operationId":"SettingsController_removeProviderKey","parameters":[{"name":"provider","required":true,"in":"path","description":"Provider ID (e.g. google, fireworks)","schema":{"type":"string"}}],"responses":{"200":{"description":"Provider key removed","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SimpleSuccessResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Remove a provider API key","tags":["Settings"]}},"/api/v1/settings/usage-summary":{"get":{"operationId":"SettingsController_getUsageSummary","parameters":[],"responses":{"200":{"description":"Usage summary","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UsageSummaryResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get credit usage summary","tags":["Settings"]}},"/api/v1/settings/usage-logs":{"get":{"operationId":"SettingsController_getUsageLogs","parameters":[{"name":"limit","required":false,"in":"query","description":"Max items to return (default 50, max 200)","schema":{"type":"string"}},{"name":"offset","required":false,"in":"query","description":"Number of items to skip (default 0)","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated usage logs","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UsageLogsResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get paginated usage logs","tags":["Settings"]}},"/api/v1/settings/profile":{"get":{"operationId":"SettingsController_getProfile","parameters":[],"responses":{"200":{"description":"User profile data","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UserProfileResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get user profile","tags":["Settings"]}},"/api/v1/settings/preferences":{"get":{"operationId":"SettingsController_getPreferences","parameters":[{"name":"agentType","required":false,"in":"query","description":"Agent type to filter preferences for (e.g., \"b2b-sales\", \"job-hunter\"). Omit for all preferences.","schema":{"type":"string"}}],"responses":{"200":{"description":"User preferences","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UserPreferencesResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get user preferences (optionally filtered by agent type)","tags":["Settings"]},"post":{"operationId":"SettingsController_updatePreferences","parameters":[{"name":"agentType","required":true,"in":"query","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Partial preferences update — only provided fields are changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePreferencesDto"}}}},"responses":{"200":{"description":"Preferences updated","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UpdatePreferencesResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Update user preferences (agent-scoped config supported via agentType)","tags":["Settings"]}},"/api/v1/settings/platform-api-keys":{"post":{"operationId":"SettingsController_createPlatformApiKey","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlatformApiKeyDto"}}}},"responses":{"201":{"description":"Platform API key created","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/PlatformApiKeyCreateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Create a new platform API key","tags":["Settings"]},"get":{"operationId":"SettingsController_listPlatformApiKeys","parameters":[],"responses":{"200":{"description":"List of platform API keys with usage","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/PlatformApiKeyListEntryDto"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List all platform API keys","tags":["Settings"]}},"/api/v1/settings/platform-api-keys/{hash}/usage":{"get":{"operationId":"SettingsController_getPlatformApiKeyUsage","parameters":[{"name":"hash","required":true,"in":"path","description":"Key hash (hex string)","schema":{"type":"string"}}],"responses":{"200":{"description":"API key usage stats","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ApiKeyUsageStatsResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get usage stats for a platform API key","tags":["Settings"]}},"/api/v1/settings/platform-api-keys/{hash}/rotate":{"post":{"operationId":"SettingsController_rotatePlatformApiKey","parameters":[{"name":"hash","required":true,"in":"path","description":"Key hash (hex string)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotatePlatformApiKeyDto"}}}},"responses":{"200":{"description":"API key rotated","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ApiKeyRotateResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid grace period","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Rotate a platform API key","tags":["Settings"]}},"/api/v1/settings/platform-api-keys/{hash}":{"delete":{"operationId":"SettingsController_revokePlatformApiKey","parameters":[{"name":"hash","required":true,"in":"path","description":"Key hash (hex string)","schema":{"type":"string"}}],"responses":{"200":{"description":"API key revoked","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/RevokePlatformApiKeyResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Revoke a platform API key","tags":["Settings"]}},"/api/v1/settings/webhook-secret":{"get":{"operationId":"SettingsController_getWebhookSecret","parameters":[],"responses":{"200":{"description":"Webhook signing secret","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/WebhookSecretResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Missing webhook:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get or create the webhook signing secret","tags":["Settings"]}},"/api/v1/settings/webhook-secret/rotate":{"post":{"operationId":"SettingsController_rotateWebhookSecret","parameters":[],"responses":{"200":{"description":"New webhook signing secret","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/WebhookSecretResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Missing webhook:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded (5 per hour)","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Rotate the webhook signing secret","tags":["Settings"]}},"/api/v1/referral/stats":{"get":{"operationId":"ReferralController_getStats","parameters":[],"responses":{"200":{"description":"Referral stats returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ReferralStatsResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get referral stats for the current user","tags":["Referral"]}},"/api/v1/referral/code":{"get":{"operationId":"ReferralController_getCode","parameters":[],"responses":{"200":{"description":"Referral code returned","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ReferralCodeResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get or create the user referral code","tags":["Referral"]}},"/api/v1/referral/vanity-code":{"post":{"operationId":"ReferralController_setVanityCode","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetVanityCodeRequestDto"}}}},"responses":{"200":{"description":"Vanity code set successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SetVanityCodeResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Code already taken or not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Set a vanity referral code","tags":["Referral"]}},"/api/v1/shares":{"post":{"operationId":"SharesController_createShare","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShareDto"}}}},"responses":{"201":{"description":"Share link created","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/CreateShareResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"api-key":[]},{"bearer":[]}],"summary":"Create a share link for an ATS generation","tags":["Shares"]}},"/api/v1/shares/stats":{"get":{"operationId":"SharesController_getUserShares","parameters":[],"responses":{"200":{"description":"List of user share links","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/UserSharesListResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List all share links for the authenticated user","tags":["Shares"]}},"/api/v1/shares/{slug}/public":{"get":{"operationId":"SharesController_getSharePublic","parameters":[{"name":"slug","required":true,"in":"path","description":"Share slug","schema":{"type":"string"}}],"responses":{"200":{"description":"Public share data","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/SharePublicDataDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"404":{"description":"Share not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]}],"summary":"Get public share data (no auth required)","tags":["Shares"]}},"/api/v1/shares/{slug}/visit":{"post":{"operationId":"SharesController_recordVisit","parameters":[{"name":"slug","required":true,"in":"path","description":"Share slug","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordVisitDto"}}}},"responses":{"200":{"description":"Visit recorded","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/RecordVisitResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"security":[{"api-key":[]}],"summary":"Record a visitor interaction (no auth required)","tags":["Shares"]}},"/api/v1/shares/{slug}/stats":{"get":{"operationId":"SharesController_getShareStats","parameters":[{"name":"slug","required":true,"in":"path","description":"Share slug","schema":{"type":"string"}}],"responses":{"200":{"description":"Share statistics","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ShareStatsResponseDto"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Share not found or not owned by user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get share stats for the authenticated owner","tags":["Shares"]}},"/api/v1/outreach/sequences":{"post":{"operationId":"OutreachController_createSequence","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["generationId","sessionId"],"properties":{"generationId":{"type":"string","minLength":1},"sessionId":{"type":"string","minLength":1}}}}}},"responses":{"201":{"description":"Sequence created","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Missing outreach:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Create an outreach sequence from a generation","tags":["Outreach"]},"get":{"operationId":"OutreachController_listSequences","parameters":[],"responses":{"200":{"description":"Sequence list","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List outreach sequences for the current user","tags":["Outreach"]}},"/api/v1/outreach/sequences/{sequenceId}":{"get":{"operationId":"OutreachController_getSequence","parameters":[{"name":"sequenceId","required":true,"in":"path","description":"Sequence ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Sequence details with step statuses","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Sequence not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Get outreach sequence details","tags":["Outreach"]},"delete":{"operationId":"OutreachController_cancelSequence","parameters":[{"name":"sequenceId","required":true,"in":"path","description":"Sequence ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Sequence cancelled","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Sequence not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Cancel an outreach sequence","tags":["Outreach"]}},"/api/v1/outreach/connections":{"get":{"operationId":"OutreachController_listConnections","parameters":[{"name":"agentType","required":true,"in":"query","description":"Agent scope for isolated connections","schema":{"enum":["job-hunter","b2b-sales"],"type":"string"}}],"responses":{"200":{"description":"Connection list","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List email connections (Gmail, IMAP)","tags":["Outreach"]}},"/api/v1/outreach/connections/{connectionId}":{"delete":{"operationId":"OutreachController_disconnectEmail","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Connection ID","schema":{"type":"string"}},{"name":"agentType","required":true,"in":"query","description":"Agent scope for isolated connections","schema":{"enum":["job-hunter","b2b-sales"],"type":"string"}}],"responses":{"200":{"description":"Connection removed","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Disconnect an email account","tags":["Outreach"]}},"/api/v1/outreach/imap/connect":{"post":{"operationId":"OutreachController_connectImap","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentType","email","displayName","imapHost","imapPort","password"],"properties":{"agentType":{"type":"string","enum":["job-hunter","b2b-sales"]},"email":{"type":"string"},"displayName":{"type":"string"},"imapHost":{"type":"string"},"imapPort":{"type":"number","minimum":1,"maximum":65535},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"IMAP connection established","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid IMAP credentials or connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Missing outreach:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Connect an IMAP email account","tags":["Outreach"]}},"/api/v1/outreach/imap/test":{"post":{"operationId":"OutreachController_testImapConnection","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentType","email","imapHost","imapPort","password"],"properties":{"agentType":{"type":"string","enum":["job-hunter","b2b-sales"]},"email":{"type":"string"},"imapHost":{"type":"string"},"imapPort":{"type":"number","minimum":1,"maximum":65535},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"IMAP connection test result","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid credentials or connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Test IMAP credentials without saving","tags":["Outreach"]}},"/api/v1/outreach/suppression":{"get":{"operationId":"OutreachController_listSuppressed","parameters":[],"responses":{"200":{"description":"Suppression list (hashed emails only)","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"List suppressed email hashes for the current user","tags":["Outreach"]}},"/api/v1/outreach/gmail/connect":{"get":{"operationId":"OutreachOAuthController_connect","parameters":[{"name":"agentType","required":true,"in":"query","description":"Agent scope for isolated Gmail connection","schema":{"enum":["job-hunter","b2b-sales"],"type":"string"}},{"name":"returnTo","required":false,"in":"query","description":"Relative frontend path to return to after OAuth callback","schema":{"type":"string"}}],"responses":{"200":{"description":"Google OAuth redirect URL","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Initiate Gmail OAuth flow","tags":["Outreach"]}},"/api/v1/outreach/gmail/callback":{"get":{"operationId":"OutreachOAuthController_callback","parameters":[{"name":"code","required":true,"in":"query","schema":{"type":"string"}},{"name":"state","required":true,"in":"query","schema":{"type":"string"}},{"name":"error","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to frontend with success or error hash fragment","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Handle Gmail OAuth callback redirect","tags":["Outreach"]}},"/api/v1/outreach/gmail/disconnect":{"post":{"operationId":"OutreachOAuthController_disconnect","parameters":[{"name":"agentType","required":true,"in":"query","description":"Agent scope for isolated Gmail connection","schema":{"enum":["job-hunter","b2b-sales"],"type":"string"}}],"responses":{"200":{"description":"Disconnect completed","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"security":[{"api-key":[]},{"bearer":[]}],"summary":"Disconnect Gmail account and revoke tokens","tags":["Outreach"]}},"/api/v1/outreach/gmail/webhook":{"post":{"operationId":"OutreachPubsubController_handlePubSubPush","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message","subscription"],"properties":{"message":{"type":"object","required":["data","messageId","publishTime"],"properties":{"data":{"type":"string","description":"Base64-encoded Gmail notification payload"},"messageId":{"type":"string"},"publishTime":{"type":"string"}}},"subscription":{"type":"string"}}}}}},"responses":{"200":{"description":"Notification accepted or ignored","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid Pub/Sub payload or JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Receive Gmail Pub/Sub push notifications","tags":["Outreach"]}},"/api/v1/outreach/unsubscribe":{"post":{"operationId":"OutreachUnsubscribeController_handleOneClickUnsubscribe","parameters":[{"name":"token","required":true,"in":"query","description":"HMAC-signed unsubscribe token","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"properties":{"List-Unsubscribe":{"type":"string","example":"One-Click"}}}}}},"responses":{"200":{"description":"Unsubscribed successfully","content":{"application/json":{"schema":{"type":"object","required":["success","data","requestId","timestamp"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"},"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"RFC 8058 one-click unsubscribe (machine-initiated)","tags":["Outreach Compliance"]},"get":{"operationId":"OutreachUnsubscribeController_handleHumanUnsubscribe","parameters":[{"name":"token","required":true,"in":"query","description":"HMAC-signed unsubscribe token","schema":{"type":"string"}}],"responses":{"200":{"description":"HTML confirmation page","content":{"text/html":{"schema":{"type":"string"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current time window","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Number of requests remaining in the current time window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1711036800}},"Retry-After":{"description":"Seconds to wait before retrying (only present on 429 responses)","schema":{"type":"integer","example":60}}}}},"summary":"Human-initiated unsubscribe (renders confirmation page)","tags":["Outreach Compliance"]}}},"info":{"title":"LLM Conveyors API","description":"Agent delivery platform API — job hunting, B2B sales, resume optimization.\n\n## Response Envelope\n\nAll JSON responses are wrapped in a standard envelope.\n\n**Success (2xx):**\n```json\n{ \"success\": true, \"data\": \"<inner>\", \"requestId\": \"uuid\", \"timestamp\": \"ISO-8601\" }\n```\nThe `data` field contains the response payload documented in each endpoint's response schema.\n\n**Error (4xx/5xx):**\n```json\n{ \"success\": false, \"error\": { \"code\": \"ERROR_CODE\", \"message\": \"Human-readable message\", \"hint\": \"Developer guidance (optional)\", \"details\": {} }, \"requestId\": \"uuid\", \"timestamp\": \"ISO-8601\", \"path\": \"/api/v1/...\" }\n```\n\n**Excluded from envelope:** SSE streams (`text/event-stream`), binary file downloads, `/metrics` endpoint.","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"api-key":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Platform API key"},"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"SuperTokens session token"},"cookie":{"type":"apiKey","in":"cookie","name":"sAccessToken","description":"SuperTokens session cookie"},"internal-token":{"type":"apiKey","in":"header","name":"X-Debug-Token","description":"Internal debug access token"}},"schemas":{"HealthResponseDto":{"description":"Detailed health status including dependency checks and memory usage","type":"object","properties":{"status":{"description":"Overall system health","type":"string","enum":["healthy","degraded","unhealthy"]},"timestamp":{"description":"ISO 8601 timestamp of the check","type":"string","format":"date-time"},"uptime":{"description":"Uptime in seconds","type":"integer","minimum":0,"exclusiveMinimum":false},"version":{"description":"Application version","type":"string"},"checks":{"description":"Dependency health checks","type":"object","properties":{"mongo":{"description":"MongoDB connection status","type":"string","enum":["ok","error"]},"redis":{"description":"Redis connection status","type":"string","enum":["ok","error","disabled"]}},"required":["mongo","redis"]},"memory":{"description":"Process memory usage","type":"object","properties":{"rss":{"description":"Resident Set Size in MB","type":"number","minimum":0,"exclusiveMinimum":false},"heapUsed":{"description":"V8 heap used in MB","type":"number","minimum":0,"exclusiveMinimum":false},"heapTotal":{"description":"V8 heap total in MB","type":"number","minimum":0,"exclusiveMinimum":false}},"required":["rss","heapUsed","heapTotal"]}},"required":["status","timestamp","uptime","version","checks","memory"]},"ReadinessResponseDto":{"description":"Readiness probe response — 200 when service is ready to accept traffic","type":"object","properties":{"ready":{"description":"Whether critical dependencies (MongoDB) are connected","type":"boolean"}},"required":["ready"]},"LivenessResponseDto":{"description":"Liveness probe response — 200 if process is alive","type":"object","properties":{"alive":{"description":"Always true if the process is running","type":"boolean"}},"required":["alive"]},"ExtensionTokenExchangeResponseDto":{"type":"object","properties":{"accessToken":{"type":"string","minLength":1},"refreshToken":{"type":"string","minLength":1},"frontToken":{"type":"string","minLength":1},"accessTokenExpiry":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["accessToken","refreshToken","frontToken","accessTokenExpiry"]},"ExtensionCookieSyncResponseDto":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"SessionRefreshRequestDto":{"type":"object","properties":{"refreshToken":{"type":"string","minLength":1,"maxLength":4096}},"required":["refreshToken"]},"SessionRefreshResponseDto":{"type":"object","properties":{"accessToken":{"type":"string","minLength":1},"refreshToken":{"type":"string","minLength":1},"expiresAt":{"type":"integer","minimum":0,"exclusiveMinimum":true},"userId":{"type":"string","minLength":1}},"required":["accessToken","refreshToken","expiresAt","userId"]},"ExtensionGoogleCallbackRequestDto":{"type":"object","properties":{"access_token":{"type":"string","minLength":1,"maxLength":4096}},"required":["access_token"]},"ExtensionGoogleCallbackResponseDto":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"ConsentSummaryDto":{"type":"object","properties":{"userId":{"type":"string"},"consents":{"type":"object","additionalProperties":{"type":"object","properties":{"status":{"type":"string","enum":["granted","withdrawn"]},"legalBasis":{"type":"string","enum":["contract","legitimate-interest","consent"]},"grantedAt":{"type":"string","format":"date-time"},"withdrawnAt":{"type":"string","format":"date-time"},"version":{"type":"integer","minimum":1,"exclusiveMinimum":false}},"required":["status","legalBasis","version"]}},"generatedAt":{"type":"string","format":"date-time"}},"required":["userId","consents","generatedAt"]},"ConsentActionResponseDto":{"type":"object","properties":{"purpose":{"type":"string"},"granted":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["purpose","granted","updatedAt"]},"UserDataExportResponseDto":{"type":"object","properties":{"exportedAt":{"type":"string"},"data":{"type":"object","additionalProperties":{}},"collections":{"type":"array","items":{"type":"string"}}},"required":["exportedAt","data","collections"]},"AccountDeletionResponseDto":{"type":"object","properties":{"ok":{"description":"Whether the account deletion completed successfully","type":"boolean"},"deletedCollections":{"description":"Collections that were purged","type":"array","items":{"type":"string"}},"errors":{"description":"Per-collection deletion errors, if any","type":"array","items":{"type":"string"}}},"required":["ok","deletedCollections","errors"]},"B2BSalesGenerateRequestDto":{"type":"object","properties":{"sessionId":{"description":"Session ID (auto-generated if omitted)","type":"string","maxLength":512},"generationId":{"description":"Generation attempt ID (auto-generated if omitted)","type":"string","maxLength":512},"model":{"description":"User-selected AI model preference","type":"string","enum":["flash","pro"]},"autoApproveDraft":{"description":"Auto-approve initial email draft without review gate","type":"boolean"},"autoApproveFollowups":{"description":"Auto-approve follow-up emails without review gate","type":"boolean"},"followUpCount":{"description":"Number of follow-up emails per sequence (0-3)","type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":3,"exclusiveMaximum":false},"followUpDelayDays":{"description":"Business days between follow-up emails","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":14,"exclusiveMaximum":false},"companyName":{"description":"Target company name","type":"string","minLength":1,"maxLength":200},"companyWebsite":{"description":"Target company website — auto-prefixes https:// if missing","type":"string","format":"uri","maxLength":2048},"userCompanyContext":{"description":"Background about the user's company for personalization","type":"string","maxLength":20000,"default":""},"targetCompanyContext":{"description":"Pre-fetched target company context to override research","type":"string","maxLength":10000},"contactName":{"description":"Specific contact person to target","type":"string","maxLength":100},"contactTitle":{"description":"Job title of the target contact","type":"string","maxLength":100},"contactEmail":{"description":"Email of the target contact","oneOf":[{"type":"string","format":"email"},{"type":"string","enum":[""]}]},"salesStrategy":{"description":"User instructions for the sales approach","type":"string","maxLength":10000},"reconStrategy":{"description":"User instructions for research focus areas","type":"string","maxLength":10000},"companyResearch":{"description":"Pre-fetched research to bypass the research step","type":"string","maxLength":50000},"researchMode":{"description":"Research mode: \"parallel\" or \"sequential\"","type":"string","enum":["parallel","sequential"],"default":"sequential"},"skipResearchCache":{"description":"Bypass cached research and force fresh lookup","type":"boolean","default":false},"senderName":{"description":"Name used in cold email sign-off","type":"string","maxLength":100},"autoSelectContacts":{"description":"Auto-select contacts without user review","type":"boolean"}},"required":["followUpCount","followUpDelayDays","companyName","companyWebsite","skipResearchCache","autoSelectContacts"]},"GenerateResponseDto":{"type":"object","properties":{"jobId":{"description":"Job identifier (same value as generationId -- use generationId for all operations)","type":"string"},"generationId":{"description":"Generation ID for connecting to the SSE stream","type":"string"},"sessionId":{"description":"Session ID containing generation artifacts","type":"string"},"streamUrl":{"description":"SSE stream URL or relative path for real-time updates","type":"string","minLength":1}},"required":["jobId","generationId","sessionId","streamUrl"]},"JHGenerateRequestDto":{"type":"object","properties":{"sessionId":{"description":"Session ID (auto-generated if omitted)","type":"string","maxLength":512},"generationId":{"description":"Generation attempt ID (auto-generated if omitted)","type":"string","maxLength":512},"model":{"description":"User-selected AI model preference","type":"string","enum":["flash","pro"]},"autoApproveDraft":{"description":"Auto-approve initial email draft without review gate","type":"boolean"},"autoApproveFollowups":{"description":"Auto-approve follow-up emails without review gate","type":"boolean"},"followUpCount":{"description":"Number of follow-up emails per sequence (0-3)","type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":3,"exclusiveMaximum":false},"followUpDelayDays":{"description":"Business days between follow-up emails","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":14,"exclusiveMaximum":false},"jobDescription":{"description":"Full job description text to tailor the CV and cover letter against","type":"string","maxLength":51200,"default":""},"originalCV":{"description":"Raw text of the user's current CV/resume — auto-loaded if omitted","type":"string","maxLength":51200},"extensiveCV":{"description":"Comprehensive master CV — auto-loaded if omitted","type":"string","maxLength":51200},"cvStrategy":{"description":"User instructions for how to tailor the CV — auto-loaded if omitted","type":"string","maxLength":51200},"companyName":{"description":"Name of the target company","type":"string","minLength":1,"maxLength":512},"jobTitle":{"description":"Title of the target position","type":"string","minLength":1,"maxLength":512},"companyWebsite":{"description":"Target company website — auto-prefixes https:// if missing","type":"string","format":"uri","maxLength":2048},"contactName":{"description":"Name of the hiring manager or contact person","type":"string","maxLength":512},"contactTitle":{"description":"Job title of the contact person","type":"string","maxLength":512},"contactEmail":{"description":"Email address of the contact person","oneOf":[{"description":"Email address of the contact person","type":"string","format":"email"},{"type":"string","enum":[""]}]},"genericEmail":{"description":"Generic company email (e.g., hr@company.com) as fallback","oneOf":[{"description":"Generic company email (e.g., hr@company.com) as fallback","type":"string","format":"email"},{"type":"string","enum":[""]}]},"coverLetterStrategy":{"description":"User instructions for cover letter — auto-loaded if omitted","type":"string","maxLength":51200},"coldEmailStrategy":{"description":"User instructions for cold email — auto-loaded if omitted","type":"string","maxLength":51200},"reconStrategy":{"description":"User instructions for company research — auto-loaded if omitted","type":"string","maxLength":51200},"companyProfile":{"description":"Pre-fetched company research profile to skip research step","type":"string","maxLength":51200},"jobSourceUrl":{"description":"URL where the job posting was found","oneOf":[{"description":"URL where the job posting was found","type":"string","format":"uri","maxLength":2048},{"type":"string","enum":[""]}]},"emailAddresses":{"description":"Comma-separated email addresses for cold outreach","type":"string","maxLength":51200},"mode":{"description":"Generation mode: \"standard\" (CV + cover letter) or \"cold_outreach\" (CV + cold email)","type":"string","enum":["standard","cold_outreach"],"default":"standard"},"theme":{"description":"Resume template theme for PDF rendering","type":"string","enum":["even","stackoverflow","class","professional","elegant","macchiato","react","academic"]},"autoSelectContacts":{"description":"When true, auto-select AI-recommended contacts without user confirmation","type":"boolean"},"skipResearchCache":{"description":"When true, bypass cached company research and force a fresh lookup","type":"boolean"}},"required":["followUpCount","followUpDelayDays","companyName","jobTitle","companyWebsite","contactEmail","genericEmail","jobSourceUrl","autoSelectContacts","skipResearchCache"]},"GenerateCvRequestDto":{"type":"object","properties":{"prompt":{"description":"Free-text prompt or job description for CV generation","type":"string","minLength":1,"maxLength":50000}},"required":["prompt"]},"GenerateCvResponseDto":{"type":"object","properties":{"resume":{},"usage":{"type":"object","additionalProperties":{}},"model":{"type":"string"},"warning":{"type":"string"}},"required":["resume","model"]},"PortfolioGenerateRequestDto":{"type":"object","properties":{"targetReturnBps":{"description":"Target annual return in basis points (1200 = 12%)","type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":10000,"exclusiveMaximum":false},"riskTolerance":{"description":"Risk tolerance level","type":"string","enum":["conservative","balanced","aggressive"],"default":"balanced"},"universe":{"description":"Investable universe for optimization","type":"string","enum":["nifty50"],"default":"nifty50"},"constraints":{"description":"Portfolio optimization constraints","type":"object","properties":{"maxWeightBps":{"description":"Max weight per security in basis points (1000 = 10%)","type":"integer","minimum":100,"exclusiveMinimum":false,"maximum":10000,"exclusiveMaximum":false,"default":1000},"sectorCaps":{"description":"Per-sector weight caps in basis points","type":"object","additionalProperties":{"type":"integer","minimum":100,"exclusiveMinimum":false,"maximum":10000,"exclusiveMaximum":false}}}}}},"SessionInitResponseDto":{"description":"Session initialization payload with user context, sessions, documents, and preferences","type":"object","properties":{"user":{"description":"Authenticated user context for session initialization","type":"object","properties":{"uid":{"type":"string"},"email":{"type":"string"},"displayName":{"type":"string"},"photoURL":{"type":"string"},"tier":{"description":"User tier: free or byo","type":"string"},"credits":{"description":"Current credit balance","type":"number"},"isAdmin":{"type":"boolean"},"providerKeys":{"description":"Configured AI provider keys","type":"array","items":{"type":"object","properties":{"provider":{"type":"string"},"isEnabled":{"type":"boolean"},"hasKey":{"type":"boolean"}},"required":["provider","isEnabled","hasKey"]}}},"required":["uid","tier","credits","isAdmin","providerKeys"]},"sessions":{"type":"array","items":{"description":"Session document with metadata and chat history","type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"createdAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"updatedAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"status":{"description":"Session lifecycle status: active → processing → completed/failed, or processing → awaiting_input → processing","type":"string","enum":["active","processing","awaiting_input","completed","failed","archived","outreach_active"]},"metadata":{"description":"Agent-specific session metadata","type":"object","additionalProperties":{}},"chatHistory":{"description":"Chat messages exchanged during session","type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["id","userId","createdAt","updatedAt","status","metadata","chatHistory"]}},"documents":{"description":"User source documents by type","type":"object","additionalProperties":{"type":"string"}},"strategies":{"description":"User strategies by type","type":"object","additionalProperties":{"type":"string"}},"templates":{"description":"Available templates","type":"object","additionalProperties":{}},"preferences":{"description":"User preference settings","type":"object","additionalProperties":{}}},"required":["user","sessions","documents","strategies","templates","preferences"]},"CreateSessionDto":{"type":"object","properties":{"sessionId":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-zA-Z0-9_\\-:.]+$"},"metadata":{"type":"object","additionalProperties":{}}}},"SessionResponseDto":{"description":"Session document with metadata and chat history","type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"createdAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"updatedAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"status":{"description":"Session lifecycle status: active → processing → completed/failed, or processing → awaiting_input → processing","type":"string","enum":["active","processing","awaiting_input","completed","failed","archived","outreach_active"]},"metadata":{"description":"Agent-specific session metadata","type":"object","additionalProperties":{}},"chatHistory":{"description":"Chat messages exchanged during session","type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["id","userId","createdAt","updatedAt","status","metadata","chatHistory"]},"DeleteSessionResponseDto":{"description":"Session deletion confirmation","type":"object","properties":{"sessionId":{"type":"string"}},"required":["sessionId"]},"SessionHydrateResponseDto":{"description":"Full session hydration with artifacts, versions, and active generation state","type":"object","properties":{"session":{"description":"Session document with metadata and chat history","type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"createdAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"updatedAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"status":{"description":"Session lifecycle status: active → processing → completed/failed, or processing → awaiting_input → processing","type":"string","enum":["active","processing","awaiting_input","completed","failed","archived","outreach_active"]},"metadata":{"description":"Agent-specific session metadata","type":"object","additionalProperties":{}},"chatHistory":{"description":"Chat messages exchanged during session","type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["id","userId","createdAt","updatedAt","status","metadata","chatHistory"]},"artifacts":{"description":"Generated output artifacts","type":"array","items":{"type":"object","additionalProperties":{}}},"generationLogs":{"description":"Generation execution logs","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"index":{"type":"number"},"status":{"type":"string","enum":["pending","in_progress","completed","failed","awaiting_input","outreach_active"]},"startedAt":{"type":"string"},"lastUpdatedAt":{"type":"string"},"completedAt":{"type":"string"},"summary":{"type":"string"},"usage":{"type":"object","properties":{"promptTokens":{"description":"Prompt/input tokens consumed","type":"number"},"candidatesTokens":{"description":"Candidate/output tokens generated","type":"number"},"thoughtsTokens":{"description":"Thinking/reasoning tokens (when applicable)","type":"number"},"totalTokens":{"description":"Total tokens (prompt + candidates + thoughts)","type":"number"},"creditsUsed":{"description":"Credits charged for this operation","type":"number"},"resolvedModel":{"description":"Actual AI model ID used for generation","type":"string"},"cachedTokens":{"description":"Tokens served from Gemini cache (subset of promptTokens)","type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["promptTokens","candidatesTokens","totalTokens"]},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"content":{"type":"string"},"level":{"type":"string","enum":["debug","info","success","warn","error"]},"timestamp":{"type":"string"}},"required":["id","content","level","timestamp"]}}},"required":["generationId","index","status","startedAt","lastUpdatedAt","entries"]}},"activeGeneration":{"description":"Active generation state, or null","oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["processing"]},"generationId":{"type":"string"},"percent":{"type":"number"},"streamUrl":{"type":"string"},"completedPhase":{"type":"number"}},"required":["status","generationId","percent","streamUrl"]},{"type":"object","properties":{"status":{"type":"string","enum":["awaiting_input"]},"generationId":{"type":"string"},"interactionType":{"type":"string"},"interactionData":{"type":"object","additionalProperties":{}},"completedPhase":{"type":"number"}},"required":["status","generationId","interactionType","completedPhase"]}],"nullable":true},"cvVersions":{"description":"CV generation version index","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"theme":{"type":"string"},"pageCount":{"type":"number"},"changeSummary":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","failed","awaiting_input","outreach_active"]},"createdAt":{"type":"string"},"storageKey":{"type":"string"},"pdfStorageKey":{"type":"string"}},"required":["generationId","status","createdAt"]}},"coverLetterVersions":{"description":"Cover letter version index","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","failed","awaiting_input","outreach_active"]},"createdAt":{"type":"string"},"storageKey":{"type":"string"},"toAddress":{"type":"string"},"toName":{"type":"string"},"toTitle":{"type":"string"}},"required":["generationId","status","createdAt"]}},"coldEmailVersions":{"description":"Cold email version index","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","failed","awaiting_input","outreach_active"]},"createdAt":{"type":"string"},"storageKey":{"type":"string"},"subject":{"type":"string"},"body":{"type":"string"},"toAddress":{"type":"string"},"toName":{"type":"string"},"toTitle":{"type":"string"},"ccAddress":{"type":"string"},"ccName":{"type":"string"},"ccTitle":{"type":"string"},"content":{"type":"string"},"senderName":{"type":"string"}},"required":["generationId","status","createdAt"]}},"atsVersions":{"description":"ATS score comparison version index","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"before":{"type":"object","properties":{"overallScore":{"description":"Weighted overall ATS compatibility score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"grade":{"description":"Letter grade derived from overallScore (A: 85+, B: 70+, C: 55+, D: 40+, F: <40)","type":"string","enum":["A","B","C","D","F"]},"breakdown":{"description":"Per-dimension score breakdown before weighted aggregation","type":"object","properties":{"keywordMatch":{"description":"Keyword match dimension score (weight: 0.35)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevance":{"description":"Experience relevance dimension score (weight: 0.25)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"skillsCoverage":{"description":"Skills coverage dimension score (weight: 0.20)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"educationFit":{"description":"Education fit dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"formatQuality":{"description":"Format and structure quality dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false}},"required":["keywordMatch","experienceRelevance","skillsCoverage","educationFit","formatQuality"]},"matchedKeywords":{"description":"Keywords from the JD that were found in the resume","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The keyword or skill being matched against the resume","type":"string"},"found":{"description":"Whether this keyword was found in the resume text (derived from confidence >= 0.30)","type":"boolean"},"confidence":{"description":"Graded confidence score (0-1). Default 1 for backward compat with binary matches","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"matchChannel":{"description":"Best confidence channel that produced this match (e.g., deterministic, taxonomy-rel, embedding)","type":"string"},"context":{"description":"Resume snippet where the keyword was found","type":"string"},"synonymUsed":{"description":"Synonym or equivalent term that matched instead of the exact keyword","type":"string"}},"required":["keyword","found"]}},"missingKeywords":{"description":"Keywords from the JD that are missing from the resume","type":"array","items":{"type":"string"}},"suggestions":{"description":"Basic improvement suggestions (pre-enrichment)","type":"array","items":{"type":"string"}},"semanticInsights":{"description":"Legacy semantic analysis results from Gemini","type":"object","properties":{"equivalentExperience":{"description":"List of JD requirements matched to equivalent resume evidence","type":"array","items":{"type":"object","properties":{"requirement":{"description":"JD requirement or skill being evaluated","type":"string"},"evidenceInResume":{"description":"Resume text that demonstrates equivalent experience","type":"string"},"confidence":{"description":"Confidence score (0-1) that the resume evidence satisfies the requirement","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["requirement","evidenceInResume","confidence"]}},"overallFitNarrative":{"description":"AI-generated narrative explaining overall candidate-job fit","type":"string"},"experienceRelevanceScore":{"description":"Overall experience relevance score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevanceReasoning":{"description":"AI reasoning for the experience relevance score","type":"string"}},"required":["equivalentExperience","overallFitNarrative"],"nullable":true},"reasoning":{"description":"AI reasoning trace from the scoring pipeline","type":"string","nullable":true},"enrichedSuggestions":{"description":"Prioritized, section-targeted improvement suggestions","type":"array","items":{"type":"object","properties":{"text":{"description":"Actionable suggestion text for improving the resume","type":"string"},"priority":{"description":"Impact priority of implementing this suggestion","type":"string","enum":["high","medium","low"]},"targetSection":{"description":"Resume section where this suggestion should be applied (e.g., \"experience\", \"skills\")","type":"string"},"estimatedScoreImpact":{"description":"Estimated ATS score increase if this suggestion is implemented (0-20 points)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":20,"exclusiveMaximum":false}},"required":["text","priority","targetSection","estimatedScoreImpact"]},"nullable":true},"enrichedMissingKeywords":{"description":"Missing keywords with addition guidance","type":"array","items":{"type":"object","properties":{"keyword":{"description":"Missing keyword or skill not found in the resume","type":"string"},"priority":{"description":"Whether this is a must-have or nice-to-have keyword","type":"string","enum":["required","preferred"]},"suggestedSection":{"description":"Resume section where this keyword should be added","type":"string"},"additionGuidance":{"description":"Guidance on how to naturally incorporate this keyword","type":"string"},"semanticEquivalent":{"description":"Related term already in the resume that could be rephrased to match","type":"string"}},"required":["keyword","priority","suggestedSection","additionGuidance"]},"nullable":true},"keywordConfidences":{"description":"Per-keyword fused confidence scores with channel breakdown","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The JD keyword being scored","type":"string"},"canonical":{"description":"Canonical taxonomy name for this keyword","type":"string"},"confidence":{"description":"Fused confidence score via noisy-OR (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"matched":{"description":"Whether confidence >= 0.30 threshold","type":"boolean"},"roleRelevanceMultiplier":{"description":"Channel C role-relevance multiplier (0.5-1.0)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"finalConfidence":{"description":"confidence × roleRelevanceMultiplier","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"signals":{"description":"Per-channel confidence signals","type":"array","items":{"type":"object","properties":{"channel":{"description":"Confidence channel identifier (deterministic, taxonomy-rel, role-relevance, embedding, llm-semantic)","type":"string"},"confidence":{"description":"Channel-specific confidence score (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["channel","confidence"]}},"bestChannel":{"description":"Channel with the highest individual confidence","type":"string"},"priority":{"description":"JD priority tier for this keyword","type":"string","enum":["required","preferred"]},"llmExtractionConfidence":{"description":"Original LLM confidence from Pass 0 keyword extraction","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1}},"required":["keyword","canonical","confidence","matched","finalConfidence","signals","bestChannel","priority"]}},"domainIntelligence":{"description":"Domain intelligence summary for ATS score results","type":"object","properties":{"domainDistance":{"description":"Semantic distance between candidate and job domains","type":"string","enum":["same","adjacent","moderate","distant"]},"vocabularyMatchCount":{"description":"Number of domain-specific terms matched via skill taxonomy","type":"integer","minimum":0,"exclusiveMinimum":false},"transferableSkillCount":{"description":"Number of transferable skills identified across domains","type":"integer","minimum":0,"exclusiveMinimum":false},"skillGraphOverlapScore":{"description":"Skill graph overlap score from taxonomy (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true},"embeddingGapMagnitude":{"description":"Embedding vector distance between resume and JD domains (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true}},"required":["domainDistance","vocabularyMatchCount","transferableSkillCount"],"nullable":true}},"required":["overallScore","grade","breakdown","matchedKeywords","missingKeywords","suggestions"]},"after":{"type":"object","properties":{"overallScore":{"description":"Weighted overall ATS compatibility score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"grade":{"description":"Letter grade derived from overallScore (A: 85+, B: 70+, C: 55+, D: 40+, F: <40)","type":"string","enum":["A","B","C","D","F"]},"breakdown":{"description":"Per-dimension score breakdown before weighted aggregation","type":"object","properties":{"keywordMatch":{"description":"Keyword match dimension score (weight: 0.35)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevance":{"description":"Experience relevance dimension score (weight: 0.25)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"skillsCoverage":{"description":"Skills coverage dimension score (weight: 0.20)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"educationFit":{"description":"Education fit dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"formatQuality":{"description":"Format and structure quality dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false}},"required":["keywordMatch","experienceRelevance","skillsCoverage","educationFit","formatQuality"]},"matchedKeywords":{"description":"Keywords from the JD that were found in the resume","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The keyword or skill being matched against the resume","type":"string"},"found":{"description":"Whether this keyword was found in the resume text (derived from confidence >= 0.30)","type":"boolean"},"confidence":{"description":"Graded confidence score (0-1). Default 1 for backward compat with binary matches","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"matchChannel":{"description":"Best confidence channel that produced this match (e.g., deterministic, taxonomy-rel, embedding)","type":"string"},"context":{"description":"Resume snippet where the keyword was found","type":"string"},"synonymUsed":{"description":"Synonym or equivalent term that matched instead of the exact keyword","type":"string"}},"required":["keyword","found"]}},"missingKeywords":{"description":"Keywords from the JD that are missing from the resume","type":"array","items":{"type":"string"}},"suggestions":{"description":"Basic improvement suggestions (pre-enrichment)","type":"array","items":{"type":"string"}},"semanticInsights":{"description":"Legacy semantic analysis results from Gemini","type":"object","properties":{"equivalentExperience":{"description":"List of JD requirements matched to equivalent resume evidence","type":"array","items":{"type":"object","properties":{"requirement":{"description":"JD requirement or skill being evaluated","type":"string"},"evidenceInResume":{"description":"Resume text that demonstrates equivalent experience","type":"string"},"confidence":{"description":"Confidence score (0-1) that the resume evidence satisfies the requirement","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["requirement","evidenceInResume","confidence"]}},"overallFitNarrative":{"description":"AI-generated narrative explaining overall candidate-job fit","type":"string"},"experienceRelevanceScore":{"description":"Overall experience relevance score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevanceReasoning":{"description":"AI reasoning for the experience relevance score","type":"string"}},"required":["equivalentExperience","overallFitNarrative"],"nullable":true},"reasoning":{"description":"AI reasoning trace from the scoring pipeline","type":"string","nullable":true},"enrichedSuggestions":{"description":"Prioritized, section-targeted improvement suggestions","type":"array","items":{"type":"object","properties":{"text":{"description":"Actionable suggestion text for improving the resume","type":"string"},"priority":{"description":"Impact priority of implementing this suggestion","type":"string","enum":["high","medium","low"]},"targetSection":{"description":"Resume section where this suggestion should be applied (e.g., \"experience\", \"skills\")","type":"string"},"estimatedScoreImpact":{"description":"Estimated ATS score increase if this suggestion is implemented (0-20 points)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":20,"exclusiveMaximum":false}},"required":["text","priority","targetSection","estimatedScoreImpact"]},"nullable":true},"enrichedMissingKeywords":{"description":"Missing keywords with addition guidance","type":"array","items":{"type":"object","properties":{"keyword":{"description":"Missing keyword or skill not found in the resume","type":"string"},"priority":{"description":"Whether this is a must-have or nice-to-have keyword","type":"string","enum":["required","preferred"]},"suggestedSection":{"description":"Resume section where this keyword should be added","type":"string"},"additionGuidance":{"description":"Guidance on how to naturally incorporate this keyword","type":"string"},"semanticEquivalent":{"description":"Related term already in the resume that could be rephrased to match","type":"string"}},"required":["keyword","priority","suggestedSection","additionGuidance"]},"nullable":true},"keywordConfidences":{"description":"Per-keyword fused confidence scores with channel breakdown","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The JD keyword being scored","type":"string"},"canonical":{"description":"Canonical taxonomy name for this keyword","type":"string"},"confidence":{"description":"Fused confidence score via noisy-OR (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"matched":{"description":"Whether confidence >= 0.30 threshold","type":"boolean"},"roleRelevanceMultiplier":{"description":"Channel C role-relevance multiplier (0.5-1.0)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"finalConfidence":{"description":"confidence × roleRelevanceMultiplier","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"signals":{"description":"Per-channel confidence signals","type":"array","items":{"type":"object","properties":{"channel":{"description":"Confidence channel identifier (deterministic, taxonomy-rel, role-relevance, embedding, llm-semantic)","type":"string"},"confidence":{"description":"Channel-specific confidence score (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["channel","confidence"]}},"bestChannel":{"description":"Channel with the highest individual confidence","type":"string"},"priority":{"description":"JD priority tier for this keyword","type":"string","enum":["required","preferred"]},"llmExtractionConfidence":{"description":"Original LLM confidence from Pass 0 keyword extraction","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1}},"required":["keyword","canonical","confidence","matched","finalConfidence","signals","bestChannel","priority"]}},"domainIntelligence":{"description":"Domain intelligence summary for ATS score results","type":"object","properties":{"domainDistance":{"description":"Semantic distance between candidate and job domains","type":"string","enum":["same","adjacent","moderate","distant"]},"vocabularyMatchCount":{"description":"Number of domain-specific terms matched via skill taxonomy","type":"integer","minimum":0,"exclusiveMinimum":false},"transferableSkillCount":{"description":"Number of transferable skills identified across domains","type":"integer","minimum":0,"exclusiveMinimum":false},"skillGraphOverlapScore":{"description":"Skill graph overlap score from taxonomy (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true},"embeddingGapMagnitude":{"description":"Embedding vector distance between resume and JD domains (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true}},"required":["domainDistance","vocabularyMatchCount","transferableSkillCount"],"nullable":true}},"required":["overallScore","grade","breakdown","matchedKeywords","missingKeywords","suggestions"]},"improvement":{"type":"number"},"source":{"type":"string"},"createdAt":{"type":"string"},"shareSlug":{"type":"string"}},"required":["generationId","before","after","improvement","createdAt"]}},"outreachEmailVersions":{"description":"Outreach email version index","type":"array","items":{"type":"object","properties":{"generationId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","failed","awaiting_input","outreach_active"]},"createdAt":{"type":"string"},"storageKey":{"type":"string"},"subject":{"type":"string"},"toAddress":{"type":"string"},"toName":{"type":"string"},"toTitle":{"type":"string"},"sequenceId":{"type":"string"},"sequencePosition":{"type":"number"},"senderName":{"type":"string"}},"required":["generationId","status","createdAt"]}},"research":{"description":"Research data (company and/or person)","type":"object","properties":{"company":{"type":"string"},"person":{"type":"string"}}}},"required":["session","artifacts","generationLogs","activeGeneration","cvVersions","coverLetterVersions","coldEmailVersions","atsVersions"]},"ChatLogEntryDto":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system","tool","status"]},"content":{"type":"string","maxLength":100000},"payload":{"type":"object","additionalProperties":{}}},"required":["role"]},"AppendChatLogResponseDto":{"description":"Chat log append confirmation","type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"GenerationLogInitResponseDto":{"type":"object","properties":{"generationId":{"type":"string"},"createdAt":{"type":"string"}},"required":["generationId","createdAt"]},"JobStatusResponseDto":{"type":"object","properties":{"jobId":{"description":"Job identifier (same value as generationId)","type":"string"},"generationId":{"description":"Generation ID for SSE streaming","type":"string"},"sessionId":{"description":"Associated session ID","type":"string"},"agentType":{"description":"Agent type that created this job","type":"string"},"status":{"description":"Current job status","type":"string","enum":["queued","processing","completed","failed","awaiting_input"]},"progress":{"description":"Completion percentage (0–100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"currentStep":{"description":"Currently executing workflow step","type":"string"},"logs":{"description":"Generation log entries (when include=logs)","type":"array","items":{"type":"object","properties":{"content":{"description":"Log message content","type":"string"},"level":{"description":"Log level (info, warn, error)","type":"string"},"timestamp":{"description":"ISO 8601 timestamp","type":"string"}},"required":["content","level","timestamp"]}},"artifacts":{"description":"Generated artifacts (when include=artifacts)","type":"array","items":{"type":"object","additionalProperties":{}}},"failedReason":{"description":"Error description if status is \"failed\"","type":"string","maxLength":1000},"interactionData":{"description":"Data for user interaction (when status is \"awaiting_input\")","type":"object","additionalProperties":{}},"interactionType":{"description":"Type of user interaction needed (e.g., \"contact_selection\"). Present when status is \"awaiting_input\"","type":"string"},"completedPhase":{"description":"Zero-based index of the last completed phase (present when status is \"awaiting_input\")","type":"number"},"result":{"description":"Final generation result data","type":"object","additionalProperties":{}},"createdAt":{"description":"ISO 8601 job creation timestamp","type":"string"},"completedAt":{"description":"ISO 8601 job completion timestamp","type":"string"},"usage":{"description":"Token and credit usage for this generation (present when completed)","type":"object","properties":{"promptTokens":{"description":"Prompt/input tokens consumed","type":"number"},"candidatesTokens":{"description":"Candidate/output tokens generated","type":"number"},"thoughtsTokens":{"description":"Thinking/reasoning tokens (when applicable)","type":"number"},"totalTokens":{"description":"Total tokens (prompt + candidates + thoughts)","type":"number"},"creditsUsed":{"description":"Credits charged for this operation","type":"number"},"resolvedModel":{"description":"Actual AI model ID used for generation","type":"string"},"cachedTokens":{"description":"Tokens served from Gemini cache (subset of promptTokens)","type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["promptTokens","candidatesTokens","totalTokens"]}},"required":["jobId","status","createdAt"]},"AgentManifestResponseDto":{"type":"object","properties":{"agentType":{"description":"Agent type identifier","type":"string"},"label":{"description":"Human-readable agent name","type":"string"},"description":{"description":"Brief description of what the agent does","type":"string"},"skills":{"description":"Skill IDs used by this agent","type":"array","items":{"type":"string"}},"preferenceFields":{"description":"Agent preference keys used for dynamic settings rendering","type":"array","items":{"type":"string"}},"preferenceDescriptors":{"description":"Render-ready preference descriptors for fully dynamic settings UI","type":"array","items":{"type":"object","properties":{"key":{"description":"Preference key (matches persisted settings key)","type":"string"},"type":{"description":"Preference data type","type":"string","enum":["string","boolean","number","enum"]},"control":{"description":"Preferred UI control","type":"string","enum":["toggle","text","textarea","number","range","select"]},"label":{"description":"Display label for settings UI","type":"string"},"description":{"description":"Helper text for settings UI","type":"string"},"required":{"description":"Whether this preference is required","type":"boolean","default":false},"defaultValue":{"description":"Default value used when unset"},"min":{"description":"Minimum numeric value","type":"number"},"max":{"description":"Maximum numeric value","type":"number"},"step":{"description":"Step for numeric/range controls","type":"number"},"maxLength":{"description":"Maximum character length for text controls","type":"number"},"options":{"description":"Allowed options for enum/select controls","type":"array","items":{"type":"object","properties":{"value":{"description":"Stored option value","type":"string"},"label":{"description":"Human-readable option label","type":"string"}},"required":["value","label"]}},"section":{"description":"Optional UI section/group key","type":"string"},"order":{"description":"Optional relative display order","type":"integer"}},"required":["key","type","control","label","description"]}},"connectionCapabilities":{"description":"Connection providers supported by this agent with render-ready field metadata","type":"array","items":{"type":"object","properties":{"provider":{"description":"Email provider identifier","type":"string","enum":["gmail","imap","outlook","smtp"]},"required":{"description":"Whether this provider capability is required for this agent","type":"boolean","default":false},"enabled":{"description":"Whether this provider should be shown/enabled","type":"boolean","default":true},"description":{"description":"Human-readable provider capability description","type":"string"},"defaultPriority":{"description":"Lower number means higher selection priority","type":"integer"},"fields":{"description":"Provider-specific connection form fields","type":"array","items":{"type":"object","properties":{"name":{"description":"Connection field key","type":"string"},"label":{"description":"Display label for the field","type":"string"},"type":{"description":"Connection field data type","type":"string","enum":["string","number","boolean","enum"]},"required":{"description":"Whether this field is required","type":"boolean","default":false},"description":{"description":"Helper text for the field","type":"string"},"secret":{"description":"Whether this field is sensitive/secret input","type":"boolean","default":false},"defaultValue":{"description":"Default value for the field"},"min":{"description":"Minimum numeric value","type":"number"},"max":{"description":"Maximum numeric value","type":"number"},"maxLength":{"description":"Maximum string length","type":"number"},"options":{"description":"Allowed options when type is enum","type":"array","items":{"type":"object","properties":{"value":{"description":"Stored option value","type":"string"},"label":{"description":"Human-readable option label","type":"string"}},"required":["value","label"]}}},"required":["name","label","type","description"]},"default":[]}},"required":["provider","description"]}},"billing":{"type":"object","properties":{"minimumCredits":{"description":"Minimum credits required to start","type":"number"},"maximumCredits":{"description":"Maximum credits cap per generation","type":"number"}},"required":["minimumCredits"]},"capabilities":{"type":"object","properties":{"supportsPhasing":{"description":"Whether the agent supports phased execution with user interaction","type":"boolean"},"hasArtifactVersioning":{"description":"Whether the agent tracks artifact version history","type":"boolean"}},"required":["supportsPhasing","hasArtifactVersioning"]},"inputFields":{"description":"Accepted input fields with types and requirements","type":"array","items":{"type":"object","properties":{"name":{"description":"Field name (camelCase, matches request body key)","type":"string"},"type":{"description":"Field value type","type":"string","enum":["string","boolean","number","enum","array"]},"required":{"description":"Whether the field is required (after backend enrichment)","type":"boolean"},"autoLoaded":{"description":"Whether the backend can auto-load this from user context","type":"boolean","default":false},"maxLength":{"description":"Max string length (if applicable)","type":"number"},"enumValues":{"description":"Allowed values (if type is \"enum\")","type":"array","items":{"type":"string"}},"description":{"description":"Human-readable field description","type":"string"}},"required":["name","type","required","description"]}},"interactionTypes":{"description":"Supported interaction types (if supportsPhasing)","type":"array","items":{"type":"object","properties":{"type":{"description":"Interaction type identifier (e.g., \"contact_selection\")","type":"string"},"description":{"description":"Human-readable description of the interaction","type":"string"},"requiredFields":{"description":"Fields the client must include in interactionData","type":"array","items":{"type":"string"}}},"required":["type","description","requiredFields"]}}},"required":["agentType","label","description","skills","billing","capabilities","inputFields"]},"InteractRequestDto":{"type":"object","properties":{"generationId":{"description":"Generation ID from Phase A","type":"string","minLength":1},"sessionId":{"description":"Session ID from the original generation","type":"string","minLength":1},"interactionType":{"description":"Discriminator identifying the interaction type","type":"string","minLength":1},"interactionData":{"description":"Agent-specific interaction data keyed by field name","type":"object","additionalProperties":{}}},"required":["generationId","sessionId","interactionType","interactionData"]},"InteractResponseDto":{"type":"object","properties":{"success":{"description":"Whether the interaction was accepted","type":"boolean"},"jobId":{"description":"Job identifier for the resumed phase (new UUID -- doubles as the BullMQ job ID)","type":"string"},"streamUrl":{"description":"SSE stream URL or relative path for the next phase","type":"string","minLength":1},"generationId":{"description":"Generation identifier (present on completion responses)","type":"string"},"sessionId":{"description":"Session identifier (present on completion responses)","type":"string"},"status":{"description":"Terminal status when generation completes without starting a new phase (e.g. \"completed\")","type":"string"},"phase":{"description":"Final phase index (present when status is \"completed\")","type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["success"]},"AtsScoreRequestDto":{"type":"object","properties":{"resumeText":{"description":"Full text content of the resume to score","type":"string","minLength":1,"maxLength":100000},"jobDescription":{"description":"Full text of the job description to score against","type":"string","minLength":1,"maxLength":100000},"jobTitle":{"description":"Job title for context (extracted from JD if not provided)","type":"string","maxLength":512}},"required":["resumeText","jobDescription"]},"AtsScoreResponseDto":{"type":"object","properties":{"overallScore":{"description":"Weighted overall ATS compatibility score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"grade":{"description":"Letter grade derived from overallScore (A: 85+, B: 70+, C: 55+, D: 40+, F: <40)","type":"string","enum":["A","B","C","D","F"]},"breakdown":{"description":"Per-dimension score breakdown before weighted aggregation","type":"object","properties":{"keywordMatch":{"description":"Keyword match dimension score (weight: 0.35)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevance":{"description":"Experience relevance dimension score (weight: 0.25)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"skillsCoverage":{"description":"Skills coverage dimension score (weight: 0.20)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"educationFit":{"description":"Education fit dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"formatQuality":{"description":"Format and structure quality dimension score (weight: 0.10)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false}},"required":["keywordMatch","experienceRelevance","skillsCoverage","educationFit","formatQuality"]},"matchedKeywords":{"description":"Keywords from the JD that were found in the resume","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The keyword or skill being matched against the resume","type":"string"},"found":{"description":"Whether this keyword was found in the resume text (derived from confidence >= 0.30)","type":"boolean"},"confidence":{"description":"Graded confidence score (0-1). Default 1 for backward compat with binary matches","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"matchChannel":{"description":"Best confidence channel that produced this match (e.g., deterministic, taxonomy-rel, embedding)","type":"string"},"context":{"description":"Resume snippet where the keyword was found","type":"string"},"synonymUsed":{"description":"Synonym or equivalent term that matched instead of the exact keyword","type":"string"}},"required":["keyword","found"]}},"missingKeywords":{"description":"Keywords from the JD that are missing from the resume","type":"array","items":{"type":"string"}},"suggestions":{"description":"Basic improvement suggestions (pre-enrichment)","type":"array","items":{"type":"string"}},"semanticInsights":{"description":"Legacy semantic analysis results from Gemini","type":"object","properties":{"equivalentExperience":{"description":"List of JD requirements matched to equivalent resume evidence","type":"array","items":{"type":"object","properties":{"requirement":{"description":"JD requirement or skill being evaluated","type":"string"},"evidenceInResume":{"description":"Resume text that demonstrates equivalent experience","type":"string"},"confidence":{"description":"Confidence score (0-1) that the resume evidence satisfies the requirement","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["requirement","evidenceInResume","confidence"]}},"overallFitNarrative":{"description":"AI-generated narrative explaining overall candidate-job fit","type":"string"},"experienceRelevanceScore":{"description":"Overall experience relevance score (0-100)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"experienceRelevanceReasoning":{"description":"AI reasoning for the experience relevance score","type":"string"}},"required":["equivalentExperience","overallFitNarrative"],"nullable":true},"reasoning":{"description":"AI reasoning trace from the scoring pipeline","type":"string","nullable":true},"enrichedSuggestions":{"description":"Prioritized, section-targeted improvement suggestions","type":"array","items":{"type":"object","properties":{"text":{"description":"Actionable suggestion text for improving the resume","type":"string"},"priority":{"description":"Impact priority of implementing this suggestion","type":"string","enum":["high","medium","low"]},"targetSection":{"description":"Resume section where this suggestion should be applied (e.g., \"experience\", \"skills\")","type":"string"},"estimatedScoreImpact":{"description":"Estimated ATS score increase if this suggestion is implemented (0-20 points)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":20,"exclusiveMaximum":false}},"required":["text","priority","targetSection","estimatedScoreImpact"]},"nullable":true},"enrichedMissingKeywords":{"description":"Missing keywords with addition guidance","type":"array","items":{"type":"object","properties":{"keyword":{"description":"Missing keyword or skill not found in the resume","type":"string"},"priority":{"description":"Whether this is a must-have or nice-to-have keyword","type":"string","enum":["required","preferred"]},"suggestedSection":{"description":"Resume section where this keyword should be added","type":"string"},"additionGuidance":{"description":"Guidance on how to naturally incorporate this keyword","type":"string"},"semanticEquivalent":{"description":"Related term already in the resume that could be rephrased to match","type":"string"}},"required":["keyword","priority","suggestedSection","additionGuidance"]},"nullable":true},"keywordConfidences":{"description":"Per-keyword fused confidence scores with channel breakdown","type":"array","items":{"type":"object","properties":{"keyword":{"description":"The JD keyword being scored","type":"string"},"canonical":{"description":"Canonical taxonomy name for this keyword","type":"string"},"confidence":{"description":"Fused confidence score via noisy-OR (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"matched":{"description":"Whether confidence >= 0.30 threshold","type":"boolean"},"roleRelevanceMultiplier":{"description":"Channel C role-relevance multiplier (0.5-1.0)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1},"finalConfidence":{"description":"confidence × roleRelevanceMultiplier","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"signals":{"description":"Per-channel confidence signals","type":"array","items":{"type":"object","properties":{"channel":{"description":"Confidence channel identifier (deterministic, taxonomy-rel, role-relevance, embedding, llm-semantic)","type":"string"},"confidence":{"description":"Channel-specific confidence score (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false}},"required":["channel","confidence"]}},"bestChannel":{"description":"Channel with the highest individual confidence","type":"string"},"priority":{"description":"JD priority tier for this keyword","type":"string","enum":["required","preferred"]},"llmExtractionConfidence":{"description":"Original LLM confidence from Pass 0 keyword extraction","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"default":1}},"required":["keyword","canonical","confidence","matched","finalConfidence","signals","bestChannel","priority"]}},"domainIntelligence":{"description":"Domain intelligence summary for ATS score results","type":"object","properties":{"domainDistance":{"description":"Semantic distance between candidate and job domains","type":"string","enum":["same","adjacent","moderate","distant"]},"vocabularyMatchCount":{"description":"Number of domain-specific terms matched via skill taxonomy","type":"integer","minimum":0,"exclusiveMinimum":false},"transferableSkillCount":{"description":"Number of transferable skills identified across domains","type":"integer","minimum":0,"exclusiveMinimum":false},"skillGraphOverlapScore":{"description":"Skill graph overlap score from taxonomy (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true},"embeddingGapMagnitude":{"description":"Embedding vector distance between resume and JD domains (0-1)","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false,"nullable":true}},"required":["domainDistance","vocabularyMatchCount","transferableSkillCount"],"nullable":true}},"required":["overallScore","grade","breakdown","matchedKeywords","missingKeywords","suggestions"]},"ExtractSkillsRequestDto":{"type":"object","properties":{"text":{"description":"Job description free text to extract skills from","type":"string","minLength":1,"maxLength":50000},"options":{"type":"object","properties":{"topK":{"description":"Maximum number of skills to return, ranked by score","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false,"default":40},"categories":{"description":"If set, only return skills whose mapped category is in this list","type":"array","items":{"description":"Coarse skill bucket. 'hard' = technical (languages, databases), 'tool' = tools/frameworks/IDEs, 'domain' = industry/methodology (clinical, finance), 'soft' = interpersonal","type":"string","enum":["hard","soft","tool","domain"]}},"includeMissing":{"description":"If true, also return skills extracted from text but NOT present in resumeText. Requires resumeText to be set.","type":"boolean","default":false},"resumeText":{"description":"Candidate resume text, used only when includeMissing=true","type":"string","minLength":1,"maxLength":50000}},"default":{}}},"required":["text"]},"ExtractSkillsResponseDataDto":{"type":"object","properties":{"keywords":{"description":"Extracted skills ranked by score descending","type":"array","items":{"type":"object","properties":{"term":{"description":"Original surface form as it appeared in the input text (preserves user casing)","type":"string"},"category":{"description":"Coarse skill bucket. 'hard' = technical (languages, databases), 'tool' = tools/frameworks/IDEs, 'domain' = industry/methodology (clinical, finance), 'soft' = interpersonal","type":"string","enum":["hard","soft","tool","domain"]},"score":{"description":"Composite relevance score: 0.55*frequency + 0.25*position + 0.20*categoryWeight","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"occurrences":{"description":"Exact occurrence count of this canonical in the input text","type":"integer","minimum":0,"exclusiveMinimum":false},"canonicalForm":{"description":"Lowercased canonical skill name from the private skill-taxonomy corpus","type":"string"}},"required":["term","category","score","occurrences","canonicalForm"]}},"missing":{"description":"Skills present in text but absent from resumeText (only when includeMissing=true)","type":"array","items":{"type":"object","properties":{"term":{"description":"Original surface form as it appeared in the input text (preserves user casing)","type":"string"},"category":{"description":"Coarse skill bucket. 'hard' = technical (languages, databases), 'tool' = tools/frameworks/IDEs, 'domain' = industry/methodology (clinical, finance), 'soft' = interpersonal","type":"string","enum":["hard","soft","tool","domain"]},"score":{"description":"Composite relevance score: 0.55*frequency + 0.25*position + 0.20*categoryWeight","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"occurrences":{"description":"Exact occurrence count of this canonical in the input text","type":"integer","minimum":0,"exclusiveMinimum":false},"canonicalForm":{"description":"Lowercased canonical skill name from the private skill-taxonomy corpus","type":"string"}},"required":["term","category","score","occurrences","canonicalForm"]}},"tookMs":{"description":"Server-measured wall-clock time spent inside the extractor, in milliseconds","type":"number","minimum":0,"exclusiveMinimum":false},"taxonomyVersion":{"description":"Opaque identifier for the taxonomy corpus version used to compute this response. Enables version-pinned caching on the client.","type":"string","minLength":1}},"required":["keywords","tookMs","taxonomyVersion"]},"ExtractJdRequestDto":{"type":"object","properties":{"pageText":{"description":"Raw visible page text scraped from the JD page DOM","type":"string","minLength":200,"maxLength":200000},"url":{"description":"URL of the source page (optional, for telemetry only)","type":"string","format":"uri","maxLength":2048},"hostname":{"description":"Hostname hint for the LLM (e.g. \"boards.greenhouse.io\")","type":"string","maxLength":256}},"required":["pageText"]},"ExtractJdResponseDataDto":{"type":"object","properties":{"jd":{"type":"object","properties":{"title":{"type":"string","maxLength":500,"nullable":true},"company":{"type":"string","maxLength":500,"nullable":true},"location":{"type":"string","maxLength":500,"nullable":true},"employmentType":{"type":"string","enum":["full_time","part_time","contract","internship","unknown"]},"description":{"type":"string","maxLength":100000},"requirements":{"type":"string","maxLength":50000},"responsibilities":{"type":"string","maxLength":50000},"techStack":{"description":"Technologies, frameworks, languages, and tools mentioned in the JD. Canonical casing preferred. LLM is instructed to exclude generic English words and soft skills.","type":"array","maxItems":200,"items":{"type":"string","minLength":1,"maxLength":100}},"yearsExperience":{"type":"object","properties":{"min":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":50,"exclusiveMaximum":false,"nullable":true},"max":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":50,"exclusiveMaximum":false,"nullable":true}},"required":["min","max"],"nullable":true}},"required":["title","company","location","employmentType","description","requirements","responsibilities","techStack","yearsExperience"]},"skills":{"description":"Skills kept after LLM-techStack ∩ Aho-Corasick intersection. Also includes LLM-only skills that canonicalize via the taxonomy (flat score 0.5) and LLM-only unknowns (score 0.3, fed to DynamicSkillDoc enrichment queue).","type":"array","items":{"type":"object","properties":{"term":{"description":"Original surface form as it appeared in the input text (preserves user casing)","type":"string"},"category":{"description":"Coarse skill bucket. 'hard' = technical (languages, databases), 'tool' = tools/frameworks/IDEs, 'domain' = industry/methodology (clinical, finance), 'soft' = interpersonal","type":"string","enum":["hard","soft","tool","domain"]},"score":{"description":"Composite relevance score: 0.55*frequency + 0.25*position + 0.20*categoryWeight","type":"number","minimum":0,"exclusiveMinimum":false,"maximum":1,"exclusiveMaximum":false},"occurrences":{"description":"Exact occurrence count of this canonical in the input text","type":"integer","minimum":0,"exclusiveMinimum":false},"canonicalForm":{"description":"Lowercased canonical skill name from the private skill-taxonomy corpus","type":"string"}},"required":["term","category","score","occurrences","canonicalForm"]}},"tookMs":{"type":"integer","minimum":0,"exclusiveMinimum":false},"cacheHit":{"description":"True when the response came from Redis cache (keyed by normalized content hash + taxonomy version). False for fresh LLM calls.","type":"boolean"},"modelUsed":{"description":"Model that produced the LLM extraction (e.g. \"gemini-3-flash-preview\")","type":"string"},"contentHash":{"description":"SHA256 hex of normalized page text + taxonomy version — the cache key","type":"string"},"taxonomyVersion":{"description":"Monotonic taxonomy version counter; cache key includes this for natural invalidation","type":"integer"}},"required":["jd","skills","tookMs","cacheHit","modelUsed","contentHash","taxonomyVersion"]},"ResumeParseResponseDto":{"description":"Parsed resume from uploaded file","type":"object","properties":{"resume":{"description":"Parsed resume JSON","type":"object","additionalProperties":{}},"metadata":{"description":"Parser metadata (extraction mode, confidence, etc.)","type":"object","additionalProperties":{}}},"required":["resume","metadata"]},"ResumeValidateDto":{"type":"object","properties":{"resume":{"description":"Structured resume JSON object to validate","type":"object","additionalProperties":{}}},"required":["resume"]},"ResumeValidateResponseDto":{"description":"Resume validation result with optional coerced output","type":"object","properties":{"valid":{"type":"boolean"},"errors":{"description":"Validation errors found","type":"array","items":{"type":"object","properties":{"path":{"description":"JSON path to the invalid field","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"value":{"description":"The invalid value that triggered this error"}},"required":["path","message"]}},"warnings":{"description":"Non-fatal validation warnings","type":"array","items":{"type":"object","properties":{"path":{"description":"JSON path to the field with a warning","type":"string"},"message":{"description":"Human-readable warning message","type":"string"},"suggestion":{"description":"Suggested fix for the warning","type":"string"}},"required":["path","message"]}},"coerced":{"description":"Coerced resume if auto-fix was applied, null otherwise","type":"object","additionalProperties":{},"nullable":true}},"required":["valid","errors","warnings","coerced"]},"ResumeRenderDto":{"type":"object","properties":{"resume":{"description":"Structured resume JSON object to render","type":"object","additionalProperties":{}},"theme":{"description":"Theme name to apply (e.g., \"modern\", \"classic\")","type":"string","minLength":1,"maxLength":50},"format":{"description":"Output format: pdf or html","type":"string","enum":["pdf","html"],"default":"pdf"}},"required":["resume","theme"]},"ResumeRenderPdfResponseDto":{"description":"Rendered resume as base64 PDF","type":"object","properties":{"pdf":{"description":"Base64-encoded PDF bytes","type":"string"},"pageCount":{"type":"integer","minimum":0,"exclusiveMinimum":false},"theme":{"type":"string"},"mimeType":{"type":"string","enum":["application/pdf"]},"cacheHit":{"type":"boolean"}},"required":["pdf","theme","mimeType","cacheHit"]},"ResumePreviewDto":{"type":"object","properties":{"resume":{"description":"Structured resume JSON object to preview","type":"object","additionalProperties":{}},"theme":{"description":"Theme name for the preview","type":"string","minLength":1,"maxLength":50}},"required":["resume","theme"]},"ResumePreviewResponseDto":{"description":"Resume theme preview as HTML","type":"object","properties":{"html":{"type":"string"}},"required":["html"]},"ThemeListResponseDto":{"description":"Available resume themes","type":"array","items":{"type":"object","properties":{"name":{"description":"Theme identifier slug","type":"string"},"displayName":{"description":"Human-readable theme name","type":"string"},"description":{"description":"Brief description of the theme style","type":"string"},"supportsMarkdown":{"description":"Whether the theme supports markdown formatting in resume fields","type":"boolean"}},"required":["name","displayName","description","supportsMarkdown"]}},"ResumeImportDto":{"type":"object","properties":{"data":{"description":"RX Resume JSON data to import","type":"object","additionalProperties":{}}},"required":["data"]},"ResumeImportResponseDto":{"description":"Imported resume converted to internal format","type":"object","properties":{"resume":{"description":"Converted resume in internal format","type":"object","additionalProperties":{}},"designBlob":{"description":"Design/styling blob extracted from RX Resume data","type":"object","additionalProperties":{}}},"required":["resume","designBlob"]},"ResumeExportDto":{"type":"object","properties":{"resume":{"description":"Internal resume JSON to export","type":"object","additionalProperties":{}},"designBlob":{"description":"Design/styling blob to include in export","type":"object","additionalProperties":{}}},"required":["resume"]},"ResumeExportResponseDto":{"description":"Exported resume in RX Resume format","type":"object","properties":{"rxResume":{"description":"Resume in RX Resume format","type":"object","additionalProperties":{}}},"required":["rxResume"]},"MasterResumeResponseDto":{"type":"object","properties":{"userId":{"type":"string"},"label":{"type":"string"},"rawText":{"type":"string"},"structuredData":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["userId","label","rawText","createdAt","updatedAt"]},"MasterResumeUpsertDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"rawText":{"type":"string","minLength":1,"maxLength":100000},"structuredData":{}},"required":["label","rawText"]},"SimpleSuccessResponseDto":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"ProcessJobTextDto":{"type":"object","properties":{"text":{"description":"Raw job description text","type":"string","maxLength":50000},"url":{"description":"URL to fetch job description from","type":"string","format":"uri","maxLength":2048}}},"JdTextProcessResponseDto":{"type":"object","properties":{"companyName":{"type":"string"},"jobTitle":{"type":"string"},"jobDescription":{"type":"string"},"parsedFields":{"type":"object","additionalProperties":{}}}},"ResearchSenderRequestDto":{"type":"object","properties":{}},"SaveContentDto":{"type":"object","properties":{"docType":{"type":"string","enum":["original_cv","extensive_cv","cover_letter","cv_strategy","cover_letter_strategy","cold_email_strategy","recon_strategy","company_context"]},"content":{"type":"string","minLength":1,"maxLength":512000}},"required":["docType","content"]},"SaveContentResponseDto":{"description":"Source document save confirmation","type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"DeleteGenerationResponseDto":{"description":"Generation deletion result with cleanup counts","type":"object","additionalProperties":{}},"UsageSummaryResponseDto":{"description":"Aggregated credit usage statistics","type":"object","properties":{"totalCreditsUsed":{"description":"Total credits consumed across all generations","type":"number"},"totalGenerations":{"description":"Total number of generation runs","type":"integer","minimum":0,"exclusiveMinimum":false},"averageCreditsPerGeneration":{"description":"Mean credits per generation","type":"number"}},"required":["totalCreditsUsed","totalGenerations","averageCreditsPerGeneration"]},"UsageLogsResponseDto":{"description":"Paginated list of usage log entries","type":"object","properties":{"logs":{"type":"array","items":{"description":"Single AI generation usage log entry","type":"object","properties":{"id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"type":{"description":"AI task type","type":"string"},"model":{"description":"Model used for generation","type":"string"},"context":{"description":"Agent or module context","type":"string"},"sessionId":{"type":"string"},"jobId":{"type":"string"},"tokens":{"description":"Token usage breakdown","type":"object","properties":{"promptTokens":{"type":"integer","minimum":0,"exclusiveMinimum":false},"candidatesTokens":{"type":"integer","minimum":0,"exclusiveMinimum":false},"totalTokens":{"type":"integer","minimum":0,"exclusiveMinimum":false},"thoughtsTokens":{"type":"integer","minimum":0,"exclusiveMinimum":false},"cachedTokens":{"type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["promptTokens","candidatesTokens","totalTokens"]},"cost":{"description":"Cost breakdown","type":"object","properties":{"totalCredits":{"description":"Credits consumed","type":"number"},"providerCostUsd":{"description":"Estimated provider cost in USD","type":"number"}},"required":["totalCredits","providerCostUsd"]},"tier":{"type":"string"},"byoKey":{"description":"Whether BYO key was used","type":"boolean"}},"required":["id","timestamp","type","model","context","tokens","cost","tier","byoKey"]}},"total":{"description":"Total matching entries","type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["logs","total"]},"UserProfileResponseDto":{"description":"User profile with credit balance, tier, and identity fields","type":"object","properties":{"credits":{"description":"Current credit balance","type":"number"},"tier":{"description":"User tier: free or byo","type":"string"},"byoKeyEnabled":{"description":"Whether BYO API key is active","type":"boolean"},"email":{"description":"User email address, or null if not set","type":"string","nullable":true},"displayName":{"description":"User display name, or null if not set","type":"string","nullable":true},"photoURL":{"description":"User avatar URL, or null if not set","type":"string","nullable":true}},"required":["credits","tier","byoKeyEnabled","email","displayName","photoURL"]},"UserPreferencesResponseDto":{"description":"User preference key-value pairs","type":"object","additionalProperties":{}},"UpdatePreferencesDto":{"type":"object","properties":{"theme":{"type":"string","enum":["even","stackoverflow","class","professional","elegant","macchiato","react","academic"],"default":"academic"},"model":{"type":"string","enum":["flash","pro"],"default":"flash"},"autoSelectContacts":{"type":"boolean","default":true},"spellingVariant":{"type":"string","enum":["us","uk"],"default":"us"},"cta":{"type":"string","maxLength":500,"default":"Open to a 20 min call this week?"},"senderSignature":{"type":"string","maxLength":500,"default":""},"autoApproveDraft":{"type":"boolean","default":true},"autoApproveFollowups":{"type":"boolean","default":true},"followUpCount":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":3,"exclusiveMaximum":false,"default":2},"followUpDelayDays":{"type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":14,"exclusiveMaximum":false,"default":2}}},"UpdatePreferencesResponseDto":{"description":"Preferences update confirmation","type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"CreatePlatformApiKeyDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":100},"scopes":{"type":"array","maxItems":20,"items":{"type":"string","enum":["jobs:read","jobs:write","sales:read","sales:write","portfolio:read","portfolio:write","sessions:read","sessions:write","upload:write","resume:read","resume:write","ats:write","settings:read","settings:write","webhook:read","webhook:write","outreach:read","outreach:write","*"]}},"expiresAt":{"type":"string","format":"date-time"},"monthlyCreditsLimit":{"type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":1000000,"exclusiveMaximum":false}},"required":["label"]},"PlatformApiKeyCreateResponseDto":{"description":"Newly created platform API key with full key value","type":"object","properties":{"fullKey":{"description":"Full API key value (shown only once)","type":"string"},"keyPrefix":{"description":"Key prefix for identification","type":"string"},"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["jobs:read","jobs:write","sales:read","sales:write","portfolio:read","portfolio:write","sessions:read","sessions:write","upload:write","resume:read","resume:write","ats:write","settings:read","settings:write","webhook:read","webhook:write","outreach:read","outreach:write","*"]}},"expiresAt":{"oneOf":[{"type":"string","format":"date-time"},{}],"nullable":true},"monthlyCreditsLimit":{"type":"number","nullable":true},"createdAt":{"oneOf":[{"type":"string","format":"date-time"},{}]}},"required":["fullKey","keyPrefix","label","scopes","createdAt"]},"PlatformApiKeyListEntryDto":{"description":"Platform API key with current month usage statistics","type":"object","properties":{"keyHash":{"description":"SHA-256 hash used as identifier","type":"string"},"keyPrefix":{"description":"Key prefix for display","type":"string"},"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["jobs:read","jobs:write","sales:read","sales:write","portfolio:read","portfolio:write","sessions:read","sessions:write","upload:write","resume:read","resume:write","ats:write","settings:read","settings:write","webhook:read","webhook:write","outreach:read","outreach:write","*"]}},"expiresAt":{"oneOf":[{"type":"string","format":"date-time"},{}],"nullable":true},"monthlyCreditsLimit":{"type":"number","nullable":true},"createdAt":{"oneOf":[{"type":"string","format":"date-time"},{}]},"lastUsedAt":{"oneOf":[{"type":"string","format":"date-time"},{}],"nullable":true},"isActive":{"type":"boolean"},"currentMonthUsage":{"description":"Usage stats for the current billing month","type":"object","properties":{"creditsUsed":{"type":"number"},"requestCount":{"type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["creditsUsed","requestCount"]}},"required":["keyHash","keyPrefix","label","scopes","createdAt","isActive","currentMonthUsage"]},"ApiKeyUsageStatsResponseDto":{"type":"object","properties":{"totalRequests":{"type":"number"},"periodStart":{"type":"string"},"periodEnd":{"type":"string"},"breakdown":{"type":"object","additionalProperties":{}}},"required":["totalRequests","periodStart","periodEnd"]},"RotatePlatformApiKeyDto":{"type":"object","properties":{"gracePeriodHours":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":720,"exclusiveMaximum":false}}},"ApiKeyRotateResponseDto":{"type":"object","properties":{"newKeyPrefix":{"type":"string"},"rotatedAt":{"type":"string"},"gracePeriodEndsAt":{"type":"string"}},"required":["newKeyPrefix","rotatedAt"]},"RevokePlatformApiKeyResponseDto":{"description":"API key revocation confirmation","type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"WebhookSecretResponseDto":{"type":"object","properties":{"secret":{"description":"Webhook signing secret (hex string). Use this to verify X-Webhook-Signature headers.","type":"string"},"createdAt":{"description":"When the secret was created or last rotated","type":"string"}},"required":["secret","createdAt"]},"ReferralStatsResponseDto":{"type":"object","properties":{"referralCode":{"type":"string"},"isVanityCode":{"type":"boolean"},"totalReferrals":{"type":"integer","minimum":0,"exclusiveMinimum":false},"pendingReferrals":{"type":"integer","minimum":0,"exclusiveMinimum":false},"completedReferrals":{"type":"integer","minimum":0,"exclusiveMinimum":false},"totalCreditsEarned":{"type":"integer","minimum":0,"exclusiveMinimum":false},"remainingThisYear":{"type":"integer","minimum":0,"exclusiveMinimum":false},"referrals":{"type":"array","items":{"type":"object","properties":{"referredUserId":{"type":"string"},"referredEmail":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending","completed","expired","fraudulent"]},"createdAt":{"type":"string","format":"date-time"},"activatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["referredUserId","referredEmail","status","createdAt","activatedAt"]}}},"required":["referralCode","isVanityCode","totalReferrals","pendingReferrals","completedReferrals","totalCreditsEarned","remainingThisYear","referrals"]},"ReferralCodeResponseDto":{"description":"User referral code","type":"object","properties":{"code":{"type":"string"}},"required":["code"]},"SetVanityCodeRequestDto":{"type":"object","properties":{"code":{"type":"string","minLength":3,"maxLength":32,"pattern":"^[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?$"}},"required":["code"]},"SetVanityCodeResponseDto":{"type":"object","properties":{"code":{"description":"The vanity referral code that was set","type":"string"}},"required":["code"]},"CreateShareDto":{"type":"object","properties":{"sessionId":{"type":"string","minLength":1,"maxLength":128},"generationId":{"type":"string","minLength":1,"maxLength":128}},"required":["sessionId","generationId"]},"CreateShareResponseDto":{"type":"object","properties":{"shareSlug":{"type":"string"},"shareUrl":{"type":"string","format":"uri"}},"required":["shareSlug","shareUrl"]},"UserSharesListResponseDto":{"description":"List of share links created by the user","type":"array","items":{"type":"object","properties":{"shareSlug":{"type":"string"},"shareUrl":{"type":"string","format":"uri"},"companyName":{"type":"string"},"jobTitle":{"type":"string"},"uniqueVisitors":{"type":"integer","minimum":0,"exclusiveMinimum":false},"creditsEarned":{"type":"integer","minimum":0,"exclusiveMinimum":false},"status":{"type":"string","enum":["active","expired","invalidated"]},"createdAt":{"type":"string","format":"date-time"}},"required":["shareSlug","shareUrl","companyName","jobTitle","uniqueVisitors","creditsEarned","status","createdAt"]}},"SharePublicDataDto":{"type":"object","properties":{"companyName":{"type":"string"},"jobTitle":{"type":"string"},"improvementPercent":{"type":"number"},"beforeScore":{"type":"number"},"afterScore":{"type":"number"},"createdAt":{"type":"string","format":"date-time"}},"required":["companyName","jobTitle","improvementPercent","beforeScore","afterScore","createdAt"]},"RecordVisitDto":{"type":"object","properties":{"turnstileToken":{"type":"string","minLength":1,"maxLength":4096},"elapsedMs":{"type":"integer","minimum":0,"exclusiveMinimum":false,"maximum":300000,"exclusiveMaximum":false}},"required":["turnstileToken","elapsedMs"]},"RecordVisitResponseDto":{"description":"Visit recording result","type":"object","properties":{"counted":{"description":"Whether the visit was counted as unique","type":"boolean"}},"required":["counted"]},"ShareStatsResponseDto":{"type":"object","properties":{"shareSlug":{"type":"string"},"shareUrl":{"type":"string","format":"uri"},"uniqueVisitors":{"type":"integer","minimum":0,"exclusiveMinimum":false},"milestones":{"type":"array","items":{"type":"object","properties":{"visitors":{"type":"integer"},"credits":{"type":"integer"},"status":{"type":"string","enum":["pending_verification","credited","rejected"]},"awardedAt":{"type":"string","format":"date-time"},"totalCreditsAwarded":{"type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["visitors","credits","status"]}},"creditsEarned":{"type":"integer","minimum":0,"exclusiveMinimum":false},"status":{"type":"string","enum":["active","expired","invalidated"]},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"}},"required":["shareSlug","shareUrl","uniqueVisitors","milestones","creditsEarned","status","createdAt"]},"ErrorDetail":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"companyName is required"},"hint":{"type":"string","description":"Developer-friendly guidance"},"details":{"type":"object","description":"Additional error context (e.g., field validation errors)"}}},"ErrorEnvelope":{"type":"object","required":["success","error","requestId","timestamp","path"],"properties":{"success":{"type":"boolean","example":false},"error":{"$ref":"#/components/schemas/ErrorDetail"},"requestId":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"timestamp":{"type":"string","format":"date-time","example":"2026-03-21T12:00:00.000Z"},"path":{"type":"string","example":"/api/v1/agents/job-hunter/generate"}}}}}}