{"openapi":"3.0.0","paths":{"/api/v1/users/me":{"get":{"operationId":"UsersController_getCurrentUser","summary":"Get current user profile","description":"Get detailed profile information for the authenticated user from database","parameters":[],"responses":{"200":{"description":"User profile retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"user-uuid"},"email":{"type":"string","example":"user@example.com"},"first_name":{"type":"string","example":"John"},"last_name":{"type":"string","example":"Doe"},"full_name":{"type":"string","example":"John Doe"},"organizations":{"type":"array","items":{"type":"object"}},"roles":{"type":"array","items":{"type":"object"}},"is_admin":{"type":"boolean","example":false},"email_preferences":{"type":"object","nullable":true},"date_time_settings":{"type":"object","nullable":true}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized - Invalid or missing token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"User profile not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["users"],"security":[{"JWT-auth":[]}]}},"/api/v1/users/admin/stats":{"get":{"operationId":"UsersController_getAdminStats","summary":"Get admin statistics","description":"Get administrative statistics from database (admin only)","parameters":[],"responses":{"200":{"description":"Admin stats retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"totalUsers":{"type":"number","example":1250},"activeUsers":{"type":"number","example":890},"totalOrganizations":{"type":"number","example":45},"activeOrganizations":{"type":"number","example":42},"totalWebsites":{"type":"number","example":320},"totalTestFlows":{"type":"number","example":1500},"totalTestRuns":{"type":"number","example":50000},"timestamp":{"type":"string","example":"2024-01-01T00:00:00.000Z"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["users"],"security":[{"JWT-auth":[]}]}},"/api/v1/tokens":{"post":{"operationId":"PersonalAccessTokensController_createToken","summary":"Create personal access token","description":"Create a new personal access token for API access. **Requires authentication** - first login via POST /api/v1/auth/login to get an access token, then use it here with Bearer authentication. Note: Idempotency-Key is not honored on this endpoint; if a network error leaves you uncertain whether a token was created, list tokens and DELETE any duplicate.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePersonalAccessTokenDto"}}}},"responses":{"201":{"description":"Token created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalAccessTokenResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized - Invalid or missing authentication token"},"403":{"description":"Forbidden - Insufficient permissions (requires manage:tokens scope)"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["personal-access-tokens"],"security":[{"JWT-auth":[]}]},"get":{"operationId":"PersonalAccessTokensController_listTokens","summary":"List personal access tokens","description":"Get all active personal access tokens for the authenticated user. **Requires authentication** - use Bearer token in Authorization header.","parameters":[],"responses":{"200":{"description":"Tokens retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PersonalAccessTokenResponseDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized - Invalid or missing authentication token"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["personal-access-tokens"],"security":[{"JWT-auth":[]}]}},"/api/v1/tokens/{id}":{"get":{"operationId":"PersonalAccessTokensController_getToken","summary":"Get personal access token details","description":"Get details of a specific personal access token by ID. **Requires authentication** - use Bearer token in Authorization header.","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Token retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalAccessTokenResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized - Invalid or missing authentication token"},"404":{"description":"Token not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["personal-access-tokens"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"PersonalAccessTokensController_revokeToken","summary":"Revoke personal access token","description":"Revoke a personal access token by ID. This action cannot be undone. **Requires authentication** - use Bearer token in Authorization header.","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Token revoked successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"401":{"description":"Unauthorized - Invalid or missing authentication token"},"403":{"description":"Forbidden - Insufficient permissions (requires manage:tokens scope)"},"404":{"description":"Token not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["personal-access-tokens"],"security":[{"JWT-auth":[]}]}},"/api/v1/organizations/me":{"get":{"operationId":"OrganizationsController_getCurrentOrganization","summary":"Get current organization","description":"Get the organization details for the currently logged-in user (automatically from JWT token)","parameters":[],"responses":{"200":{"description":"Organization retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["organizations"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"OrganizationsController_updateMyOrganization","summary":"Update organization","description":"Update your organization details, settings, or record last visited.\n\nSupports partial updates - only send the fields you want to change:\n- name, email: Update organization details (admin only)\n- timezone, device_type, etc: Update settings (admin only)\n- record_last_visited: Update last visited timestamp (any member)\n\nExample requests:\n- Update name only: { \"name\": \"New Name\" }\n- Update settings: { \"timezone\": \"America/New_York\", \"device_type\": \"mobile\" }\n- Record visit: { \"record_last_visited\": true }","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrganizationDto"}}}},"responses":{"200":{"description":"Organization updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["organizations"],"security":[{"JWT-auth":[]}]}},"/api/v1/organizations/me/usage":{"get":{"operationId":"OrganizationsController_getMyUsage","summary":"Get organization usage","description":"Get your monthly test usage statistics","parameters":[],"responses":{"200":{"description":"Usage retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationUsageDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["organizations"],"security":[{"JWT-auth":[]}]}},"/api/v1/organizations/me/statistics":{"get":{"operationId":"OrganizationsController_getMyStatistics","summary":"Get organization statistics","description":"Get your organization statistics including websites, test flows, and tests","parameters":[],"responses":{"200":{"description":"Statistics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationStatisticsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["organizations"],"security":[{"JWT-auth":[]}]}},"/api/v1/organizations/me/trial":{"get":{"operationId":"OrganizationsController_checkMyTrialEligibility","summary":"Check trial eligibility","description":"Check if your organization is eligible for a trial.\n    \nNote: Trial eligibility is also included in the main GET /organizations/me response.\nUse this endpoint if you only need trial information without fetching the full organization.","parameters":[],"responses":{"200":{"description":"Trial eligibility checked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrialEligibilityDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["organizations"],"security":[{"JWT-auth":[]}]}},"/api/v1/admin/organizations":{"get":{"operationId":"AdminOrganizationsController_listOrganizations","summary":"List all organizations (admin only)","description":"Returns all organizations in the platform. Only available to CheckView super admins.","parameters":[{"name":"search","required":false,"in":"query","description":"Search query for organization name or email","schema":{"maxLength":255,"example":"Acme","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by organization status","schema":{"example":"active","enum":["active","inactive","pending","suspended"],"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of items to return (max 100)","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor for pagination (opaque string)","schema":{"type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Field to sort by","schema":{"default":"created_at","type":"string"}},{"name":"orderDirection","required":false,"in":"query","description":"Sort direction","schema":{"default":"DESC","enum":["ASC","DESC"],"type":"string"}}],"responses":{"200":{"description":"Organizations listed successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AdminOrganizationListItemDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["admin"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flow-types":{"get":{"operationId":"TestFlowTypesController_getTestFlowTypes","summary":"Get test flow types","description":"Get all available test flow types (form plugins) for your organization","parameters":[],"responses":{"200":{"description":"Test flow types retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestFlowTypeDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flow-types"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites":{"get":{"operationId":"WebsitesController_getWebsites","summary":"Get websites (paginated)","description":"Retrieve websites with cursor pagination and optional filters (state, search, type, etc.)","parameters":[{"name":"limit","required":false,"in":"query","description":"Number of items to return (max 100)","schema":{"minimum":1,"maximum":100,"default":20,"example":20,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor for pagination","schema":{"type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Field to sort by","schema":{"default":"created_at","example":"created_at","type":"string"}},{"name":"orderDirection","required":false,"in":"query","description":"Sort direction","schema":{"enum":["ASC","DESC"],"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search websites by name or URL","schema":{"example":"example.com","type":"string"}},{"name":"paused","required":false,"in":"query","description":"Filter by paused status","schema":{"example":false,"type":"boolean"}},{"name":"type","required":false,"in":"query","description":"Filter by website type","schema":{"example":"wordpress","enum":["wordpress","non_wordpress"],"type":"string"}},{"name":"passing","required":false,"in":"query","description":"Filter by websites with passing test flows","schema":{"example":true,"type":"boolean"}},{"name":"failing","required":false,"in":"query","description":"Filter by websites with failing test flows","schema":{"example":true,"type":"boolean"}},{"name":"pending","required":false,"in":"query","description":"Filter by websites with pending test flows","schema":{"example":false,"type":"boolean"}},{"name":"initializing","required":false,"in":"query","description":"Filter by websites with initializing test flows","schema":{"example":false,"type":"boolean"}},{"name":"initializationFailed","required":false,"in":"query","description":"Filter by websites with failed initialization test flows","schema":{"example":false,"type":"boolean"}},{"name":"aborted","required":false,"in":"query","description":"Filter by websites with aborted setup test flows","schema":{"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Websites retrieved successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"X-Next-Cursor":{"description":"Cursor for next page","schema":{"type":"string"}},"X-Has-More":{"description":"Whether more results exist","schema":{"type":"boolean"}},"X-Total-Count":{"description":"Total number of results","schema":{"type":"number"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebsiteDto"}}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"post":{"operationId":"WebsitesController_createWebsite","summary":"Create website","description":"Add a new website to your organization for monitoring","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebsiteDto"}}}},"responses":{"201":{"description":"Website created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"409":{"description":"Website already exists"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/analytics":{"get":{"operationId":"WebsitesController_getAnalytics","summary":"Get organization website analytics","description":"Get comprehensive analytics and status overview for all websites in the organization. Returns aggregated metrics across all monitored websites.","parameters":[],"responses":{"200":{"description":"Organization-wide website analytics retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebsiteStatusDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/availability":{"get":{"operationId":"WebsitesController_checkAvailability","summary":"Check website availability","description":"Check if a website URL is available for monitoring and not already being tracked by another organization","parameters":[{"name":"url","required":true,"in":"query","description":"Website URL to check (must use HTTPS)","schema":{"example":"https://example.com","type":"string"}}],"responses":{"200":{"description":"Availability check completed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","example":true},"exists":{"type":"boolean","example":false},"organizationId":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"message":{"type":"string","example":"Website is available for monitoring"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}":{"get":{"operationId":"WebsitesController_getWebsite","summary":"Get website","description":"Retrieve detailed information and configuration for a specific website","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Website details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"WebsitesController_updateWebsite","summary":"Update website","description":"Partially update website configuration, monitoring settings, and authentication details","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebsiteDto"}}}},"responses":{"200":{"description":"Website configuration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"WebsitesController_deleteWebsite","summary":"Delete website","description":"Permanently remove website from monitoring and delete all associated test flows and historical data","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Website removed from monitoring successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/health":{"get":{"operationId":"WebsitesController_checkHealth","summary":"Check website health","description":"Perform health check on website. Returns 502 with blocker detection info when a WAF/firewall is blocking the connection.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"WordPress: site health data from plugin API. Non-WordPress: basic HTTP reachability check.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"502":{"description":"Connection blocked — includes blocker name, docs URL, and response details"}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/screenshot":{"get":{"operationId":"WebsitesController_getScreenshot","summary":"Get website screenshot","description":"Get screenshot information and URL for a website","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteScreenshotDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/logs":{"get":{"operationId":"WebsitesController_getLogs","summary":"Get website logs","description":"Get activity and error logs for a website with optional filters","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"WordPress logs: { logs: { [name]: content } }. Non-WordPress: { logs: {} }","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/forms":{"get":{"operationId":"WebsitesController_getForms","summary":"Get installed forms","description":"Get list of available forms on the website (WordPress sites only)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InstalledFormDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/settings":{"get":{"operationId":"WebsitesController_getSettings","summary":"Get website settings","description":"Get platform-specific settings for a website (e.g., WordPress configuration)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WordPressSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/notifications":{"get":{"operationId":"WebsitesController_getNotifications","summary":"Get website notification settings","description":"Get notification preferences for a specific website","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteNotificationsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"WebsitesController_updateNotifications","summary":"Update website notification settings","description":"Update notification preferences for a specific website","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebsiteNotificationsDto"}}}},"responses":{"204":{"description":"Notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"WebsitesController_deleteNotifications","summary":"Delete website notification settings","description":"Remove website-specific notifications and revert to organization defaults","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Notification settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/pause":{"post":{"operationId":"WebsitesController_pauseWebsite","summary":"Pause website","description":"Pause all scheduled tests on a website. Tests will not run until resumed.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Website paused successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteOperationResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/resume":{"post":{"operationId":"WebsitesController_resumeWebsite","summary":"Resume website","description":"Resume all scheduled tests on a website that was previously paused.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Website resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteOperationResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/notifications/emails":{"get":{"operationId":"WebsitesController_getEmailReportSettings","summary":"Get website email report settings","description":"Retrieve per-website email report settings. Returns org-level defaults if no per-website override exists.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Email report settings retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailReportSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"WebsitesController_updateEmailReportSettings","summary":"Update website email report settings","description":"Create or update per-website email report settings (overrides org defaults). Includes Cloud Scheduler job creation.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailReportSettingsDto"}}}},"responses":{"204":{"description":"Email report settings updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"WebsitesController_deleteEmailReportSettings","summary":"Delete website email report settings","description":"Remove per-website email report overrides (reverts to organization defaults)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Email report settings deleted","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/run-all":{"post":{"operationId":"WebsitesController_runAllTests","summary":"Run all tests on a website","description":"Trigger execution of all eligible test flows for a website. Returns a triggered_at timestamp used to scope status queries. Returns 409 if a run-all is already in progress.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Tests triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunAllResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Website is paused"},"409":{"description":"Run-all already in progress"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{id}/run-all/status":{"get":{"operationId":"WebsitesController_getRunAllStatus","summary":"Get run-all status","description":"Get aggregate status of the latest bulk run. Poll until pending + running === 0, then check failed count.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Run-all status retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunAllStatusResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["websites"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/schedule":{"get":{"operationId":"SettingsController_getSchedule","summary":"Get schedule settings","description":"Get your organization default test schedule settings","parameters":[],"responses":{"200":{"description":"Schedule settings retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updateSchedule","summary":"Update schedule settings","description":"Update your organization default test schedule settings (admin only)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleSettingsDto"}}}},"responses":{"204":{"description":"Schedule settings updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/usage":{"get":{"operationId":"SettingsController_getUsage","summary":"Get usage settings","description":"Get your organization monthly test limit","parameters":[],"responses":{"200":{"description":"Usage settings retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updateUsage","summary":"Update usage settings","description":"Update your organization monthly test limit (admin only)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSettingsDto"}}}},"responses":{"204":{"description":"Usage settings updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/usage/reports":{"get":{"operationId":"SettingsController_getUsageReports","summary":"Get usage reports","description":"Get detailed usage reports for a date range","parameters":[{"name":"from","required":true,"in":"query","description":"Start date (ISO 8601)","schema":{"example":"2025-10-01T00:00:00Z","type":"string"}},{"name":"to","required":true,"in":"query","description":"End date (ISO 8601)","schema":{"example":"2025-10-31T23:59:59Z","type":"string"}}],"responses":{"200":{"description":"Usage reports retrieved","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsageReportDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/device":{"get":{"operationId":"SettingsController_getDevice","summary":"Get device settings","description":"Get your organization default device type","parameters":[],"responses":{"200":{"description":"Device settings retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updateDevice","summary":"Update device settings","description":"Update your organization default device type (admin only)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceSettingsDto"}}}},"responses":{"204":{"description":"Device settings updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/plugins":{"get":{"operationId":"SettingsController_getPlugins","summary":"Get plugin settings","description":"Get your organization helper plugin visibility settings","parameters":[],"responses":{"200":{"description":"Plugin settings retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PluginVisibilitySettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updatePlugins","summary":"Update plugin settings","description":"Update your organization helper plugin visibility settings (admin only). Returns list of sites where propagation failed.","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PluginVisibilitySettingsDto"}}}},"responses":{"200":{"description":"Plugin settings updated. Returns array of sites where WordPress API call failed (empty if all succeeded).","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PluginPropagationFailureDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/auto-retry":{"get":{"operationId":"SettingsController_getAutoRetry","summary":"Get auto-retry setting","description":"Get whether automatic test retry on failure is enabled","parameters":[],"responses":{"200":{"description":"Auto-retry setting retrieved","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updateAutoRetry","summary":"Update auto-retry setting","description":"Enable or disable automatic test retry on failure","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoRetrySettingsDto"}}}},"responses":{"204":{"description":"Auto-retry setting updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/settings/variables":{"get":{"operationId":"SettingsController_getVariables","summary":"Get organization variables","description":"Get your organization test variables (WooCommerce and form variables)","parameters":[],"responses":{"200":{"description":"Variables retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVariablesResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"SettingsController_updateVariables","summary":"Update organization variables","description":"Update your organization test variables (WooCommerce and form variables) (admin only). WARNING: This is a full replacement — you must send both woo_variables and form_variables, or omitted fields will be reset to empty objects. Variables are baked into test flow steps at initialization time, not runtime — you must re-initialize test flows for changes to take effect.","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariablesSettingsDto"}}}},"responses":{"204":{"description":"Variables updated","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"403":{"description":"Forbidden - Admin role required"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["settings"],"security":[{"JWT-auth":[]}]}},"/api/v1/team":{"get":{"operationId":"TeamController_getTeam","summary":"Get team","description":"Get all team members and pending invitations for your organization","parameters":[],"responses":{"200":{"description":"Team retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTeamResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/team/{userId}":{"put":{"operationId":"TeamController_updateTeamMember","summary":"Update team member","description":"Update team member role and website access","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamMemberDto"}}}},"responses":{"204":{"description":"Team member updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TeamController_removeTeamMember","summary":"Remove team member","description":"Remove a team member from your organization","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Team member removed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/team/invites":{"post":{"operationId":"TeamController_inviteTeamMember","summary":"Invite team member","description":"Send an invitation to join your organization","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteTeamMemberDto"}}}},"responses":{"201":{"description":"Invitation sent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"invitation_id":{"type":"string","format":"uuid"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/team/invites/{id}":{"get":{"operationId":"TeamController_getInvitation","summary":"Get invitation","description":"Get details of a pending invitation","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Invitation retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingInvitationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"TeamController_updateInvitation","summary":"Update invitation","description":"Update pending invitation details","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInvitationDto"}}}},"responses":{"204":{"description":"Invitation updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TeamController_deleteInvitation","summary":"Delete invitation","description":"Cancel a pending invitation","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Invitation deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/team/invites/{id}/accept":{"patch":{"operationId":"TeamController_acceptInvitation","summary":"Accept invitation","description":"Accept a pending invitation to join an organization (invitation must be for your email)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Invitation accepted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInvitationResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/team/members/me":{"delete":{"operationId":"TeamController_leaveOrganization","summary":"Leave organization","description":"Leave your current organization (cannot be the last admin)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"200":{"description":"Successfully left organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["team"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications":{"get":{"operationId":"NotificationsController_getAllSettings","summary":"Get all notification settings","description":"Retrieve all notification settings (email reports and test notifications) for the current organization","parameters":[],"responses":{"200":{"description":"Notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/emails":{"get":{"operationId":"NotificationsController_getEmailSettings","summary":"Get email notification settings","description":"Retrieve email notification settings for the current organization","parameters":[],"responses":{"200":{"description":"Email notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailReportSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"NotificationsController_updateEmailSettings","summary":"Update email notification settings","description":"Update email notification settings for the current organization","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailReportSettingsDto"}}}},"responses":{"204":{"description":"Email notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/tests":{"get":{"operationId":"NotificationsController_getTestSettings","summary":"Get test notification settings","description":"Retrieve test notification settings for the current organization","parameters":[],"responses":{"200":{"description":"Test notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"NotificationsController_updateTestSettings","summary":"Update test notification settings","description":"Update test notification settings for the current organization","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestNotificationSettingsDto"}}}},"responses":{"204":{"description":"Test notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/webhooks":{"get":{"operationId":"NotificationsController_getWebhookSettings","summary":"Get webhook notification settings","description":"Retrieve organization-level webhook notification settings","parameters":[],"responses":{"200":{"description":"Webhook notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"NotificationsController_updateWebhookSettings","summary":"Update webhook notification settings","description":"Create or update organization-level webhook notification settings","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookNotificationSettingsDto"}}}},"responses":{"204":{"description":"Webhook notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"NotificationsController_deleteWebhookSettings","summary":"Delete webhook notification settings","description":"Remove organization-level webhook notification settings (disables all webhooks)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Webhook notification settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/webhooks/test":{"post":{"operationId":"NotificationsController_testWebhook","summary":"Test webhook delivery","description":"Send a test ping with a sample payload to verify a webhook URL is reachable and responding","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookRequestDto"}}}},"responses":{"200":{"description":"Webhook test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/slack":{"get":{"operationId":"NotificationsController_getSlackSettings","summary":"Get Slack notification settings","description":"Retrieve organization-level Slack notification settings","parameters":[],"responses":{"200":{"description":"Slack notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"NotificationsController_updateSlackSettings","summary":"Update Slack notification settings","description":"Create or update organization-level Slack notification settings","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackNotificationSettingsDto"}}}},"responses":{"204":{"description":"Slack notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"NotificationsController_deleteSlackSettings","summary":"Delete Slack notification settings","description":"Remove organization-level Slack notification settings (disables Slack notifications)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Slack notification settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/notifications/types":{"get":{"operationId":"NotificationsController_getNotificationTypes","summary":"Get all notification types","description":"Retrieve available notification types for email reports and test flows","parameters":[],"responses":{"200":{"description":"Notification types retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationTypesDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["notifications"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/from-url":{"post":{"operationId":"TestFlowsController_createFromUrl","summary":"Create test flow from URL","description":"End-to-end creation: finds or creates the website, creates a test flow, and triggers AI-powered step generation","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestFlowFromUrlDto"}}}},"responses":{"201":{"description":"Test flow created and AI generation started","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid URL format"},"409":{"description":"Website URL exists in another organization"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows":{"get":{"operationId":"TestFlowsController_findAll","summary":"List test flows","description":"Retrieve all test flows with filtering, search, and pagination","parameters":[{"name":"limit","required":false,"in":"query","description":"Number of items to return (max 100)","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Cursor for pagination (opaque string)","schema":{"type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Field to sort by","schema":{"default":"created_at","type":"string"}},{"name":"orderDirection","required":false,"in":"query","description":"Sort direction","schema":{"default":"DESC","enum":["ASC","DESC"],"type":"string"}},{"name":"websiteId","required":false,"in":"query","description":"Website ID to filter by","schema":{"format":"uuid","type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query for test flow name","schema":{"example":"contact form","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by test flow type","schema":{"enum":["form","woo_checkout","custom"],"type":"string"}},{"name":"plugins","required":false,"in":"query","description":"Filter by plugin IDs","schema":{"type":"array","items":{"type":"string"}}},{"description":"Filter by passing status","required":false,"name":"passing","in":"query","schema":{"example":true,"type":"boolean"}},{"description":"Filter by failing status","required":false,"name":"failing","in":"query","schema":{"example":false,"type":"boolean"}},{"description":"Filter by paused status","required":false,"name":"paused","in":"query","schema":{"example":false,"type":"boolean"}},{"description":"Filter by pending status","required":false,"name":"pending","in":"query","schema":{"example":false,"type":"boolean"}},{"description":"Filter by initializing status","required":false,"name":"initializing","in":"query","schema":{"example":false,"type":"boolean"}},{"description":"Filter by initialization failed status","required":false,"name":"initializationFailed","in":"query","schema":{"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Test flows retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestFlowDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"post":{"operationId":"TestFlowsController_create","summary":"Create test flow","description":"Create a new test flow for a website","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestFlowDto"}}}},"responses":{"201":{"description":"Test flow created successfully. Returns ID and whether step generation was triggered.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}":{"get":{"operationId":"TestFlowsController_findById","summary":"Get test flow","description":"Retrieve a test flow by ID with full details including steps and schedule","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Test flow retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowWithDetailsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test flow not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestFlowsController_update","summary":"Update test flow","description":"Partially update a test flow (name, status, device, settings, etc.)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestFlowDto"}}}},"responses":{"200":{"description":"Test flow updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test flow not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TestFlowsController_delete","summary":"Delete test flow","description":"Delete a test flow (cannot delete if tests are running)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Test flow deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test flow not found"},"409":{"description":"Cannot delete test flow while tests are running"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/executions":{"post":{"operationId":"TestFlowsController_createExecution","summary":"Create test execution","description":"Trigger a new test execution for a test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestFlowExecutionDto"}}}},"responses":{"201":{"description":"Test execution created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowExecutionDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Test flow is paused or has no steps"},"403":{"description":"Monthly test limit reached"},"409":{"description":"Test already running"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"get":{"operationId":"TestFlowsController_listExecutions","summary":"List test executions","description":"Retrieve test execution history for a test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"pageIndex","required":false,"in":"query","description":"Page index (0-based)","schema":{"minimum":0,"example":0,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Page size","schema":{"minimum":1,"maximum":100,"example":20,"type":"number"}},{"name":"passing","required":false,"in":"query","description":"Filter by status (passing)","schema":{"example":false,"type":"boolean"}},{"name":"failing","required":false,"in":"query","description":"Filter by status (failing)","schema":{"example":false,"type":"boolean"}},{"name":"pending","required":false,"in":"query","description":"Filter by status (pending)","schema":{"example":false,"type":"boolean"}},{"name":"trigger","required":false,"in":"query","description":"Filter by trigger type","schema":{"example":"manual","type":"string"}},{"name":"from","required":false,"in":"query","description":"Filter from date (ISO 8601)","schema":{"example":"2026-01-01T00:00:00Z","type":"string"}},{"name":"to","required":false,"in":"query","description":"Filter to date (ISO 8601)","schema":{"example":"2026-01-31T23:59:59Z","type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Order by field","schema":{"example":"created_at","enum":["created_at","status","trigger"],"type":"string"}},{"name":"asc","required":false,"in":"query","description":"Sort ascending","schema":{"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Test executions retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestFlowExecutionDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/executions/{executionId}":{"get":{"operationId":"TestFlowsController_getExecution","summary":"Get test execution","description":"Retrieve details of a specific test execution","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Test execution retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowExecutionDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test execution not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/initializations":{"post":{"operationId":"TestFlowsController_createInitialization","summary":"Create initialization","description":"Start test flow initialization process (supports reset, use-as-is, and retry options)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestFlowInitializationDto"}}}},"responses":{"201":{"description":"Initialization started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowInitializationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/initializations/current":{"get":{"operationId":"TestFlowsController_getCurrentInitialization","summary":"Get current initialization","description":"Retrieve the current or most recent initialization status","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Initialization retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowInitializationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestFlowsController_updateInitialization","summary":"Update initialization","description":"Update initialization status (e.g., abort ongoing initialization)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestFlowInitializationDto"}}}},"responses":{"200":{"description":"Initialization updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowInitializationDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/steps":{"get":{"operationId":"TestFlowsController_getSteps","summary":"Get test flow steps","description":"Retrieve all steps for a test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Steps retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestFlowStepDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestFlowsController_updateSteps","summary":"Update test flow steps","description":"Replace all test flow steps with new ones","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestFlowStepsDto"}}}},"responses":{"200":{"description":"Steps updated successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestFlowStepDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/schedule":{"get":{"operationId":"TestFlowsController_getSchedule","summary":"Get test flow schedule","description":"Retrieve schedule configuration for a test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Schedule retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowScheduleDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestFlowsController_updateSchedule","summary":"Update test flow schedule","description":"Update when and how often the test flow runs automatically","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestFlowScheduleDto"}}}},"responses":{"200":{"description":"Schedule updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestFlowScheduleDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TestFlowsController_deleteSchedule","summary":"Delete test flow schedule","description":"Remove automatic scheduling from test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Schedule deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/files":{"post":{"operationId":"TestFlowsController_uploadFile","summary":"Upload file","description":"Upload a file to be used during test execution or initialization","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"201":{"description":"File uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitFileUploadResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"get":{"operationId":"TestFlowsController_listFiles","summary":"List files","description":"List all files uploaded for this test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Files retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"file_url":{"type":"string"},"created_at":{"type":"string"}}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/files/{fileId}":{"delete":{"operationId":"TestFlowsController_deleteFile","summary":"Delete file","description":"Delete a file from test flow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fileId","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"File deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/ai-generate":{"post":{"operationId":"TestFlowsController_triggerAiGenerate","summary":"Trigger AI generation","description":"Trigger AI-powered step generation. With a URL: analyzes the page directly. Without: regenerates steps using AI for the existing form.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerAiGenerateDto"}}}},"responses":{"200":{"description":"AI generation started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiGenerateResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid URL or test flow not in valid state"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/ai-generate/status":{"get":{"operationId":"TestFlowsController_getAiGenerateStatus","summary":"Get AI generation status","description":"Poll the current AI generation progress. Returns generated steps when complete.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiGenerateStatusDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test flow not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/notifications/webhooks":{"get":{"operationId":"TestFlowsController_getWebhookSettings","summary":"Get test flow webhook settings","description":"Retrieve per-flow webhook notification overrides (falls back to org defaults if not set)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Webhook settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"TestFlowsController_updateWebhookSettings","summary":"Update test flow webhook settings","description":"Create or update per-flow webhook notification overrides","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookNotificationSettingsDto"}}}},"responses":{"204":{"description":"Webhook settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TestFlowsController_deleteWebhookSettings","summary":"Delete test flow webhook settings","description":"Remove per-flow webhook notification overrides (reverts to organization defaults)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Webhook settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/notifications/emails":{"get":{"operationId":"TestFlowsController_getEmailNotificationSettings","summary":"Get test flow email notification settings","description":"Retrieve per-flow email notification overrides (returns defaults if using org settings)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Email notification settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"TestFlowsController_upsertEmailNotificationSettings","summary":"Update test flow email notification settings","description":"Set per-flow email notification overrides (overrides org defaults). Use testNotificationTypeId \"use-global-settings\" to inherit from org.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestNotificationSettingsDto"}}}},"responses":{"204":{"description":"Email notification settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TestFlowsController_deleteEmailNotificationSettings","summary":"Delete test flow email notification settings","description":"Remove per-flow email notification overrides (reverts to organization defaults)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Email notification settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/notifications/slack":{"get":{"operationId":"TestFlowsController_getSlackSettings","summary":"Get test flow Slack settings","description":"Retrieve per-flow Slack notification overrides (returns null if using org defaults)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Slack settings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackNotificationSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"put":{"operationId":"TestFlowsController_updateSlackSettings","summary":"Update test flow Slack settings","description":"Create or update per-flow Slack notification overrides","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackNotificationSettingsDto"}}}},"responses":{"204":{"description":"Slack settings updated successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"delete":{"operationId":"TestFlowsController_deleteSlackSettings","summary":"Delete test flow Slack settings","description":"Remove per-flow Slack notification overrides (reverts to organization defaults)","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Slack settings deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/screenshots":{"post":{"operationId":"TestFlowsController_uploadScreenshot","summary":"Upload screenshot","description":"Upload a reference screenshot for test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"201":{"description":"Screenshot uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitScreenshotUploadResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]},"get":{"operationId":"TestFlowsController_listScreenshots","summary":"List screenshots","description":"List all screenshots uploaded for this test flow","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Screenshots retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"screenshot_url":{"type":"string"},"created_at":{"type":"string"}}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/screenshots/{screenshotId}":{"delete":{"operationId":"TestFlowsController_deleteScreenshot","summary":"Delete screenshot","description":"Delete a screenshot from test flow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"screenshotId","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Screenshot deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-flows/{id}/ai-summary":{"get":{"operationId":"TestFlowsController_getAiSummary","summary":"Get AI analysis of test flow","description":"Returns the AI summary for a failed test flow initialization. Returns cached summary if available, otherwise generates on-demand via Gemini. Use forceRefresh=true to bypass cache.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"forceRefresh","required":false,"in":"query","description":"Force re-generation of the AI summary (bypass cache)","schema":{"example":"true","type":"boolean"}}],"responses":{"200":{"description":"AI summary response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSummaryResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-flows"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs":{"get":{"operationId":"TestRunsController_getTestRuns","summary":"Get test run history","description":"Retrieve test run history with pagination, filtering by website, type, status, date range, and search","parameters":[{"name":"pageIndex","required":false,"in":"query","description":"Page index (0-based)","schema":{"minimum":0,"example":0,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Page size","schema":{"minimum":1,"maximum":100,"example":20,"type":"number"}},{"name":"from","required":false,"in":"query","description":"Start date filter (ISO 8601)","schema":{"example":"2025-01-01T00:00:00Z","type":"string"}},{"name":"to","required":false,"in":"query","description":"End date filter (ISO 8601)","schema":{"example":"2025-12-31T23:59:59Z","type":"string"}},{"name":"orderBy","required":false,"in":"query","description":"Sort column","schema":{"default":"created_at","enum":["created_at","trigger","status","test_flow_name","test_flow_type","website_name","id"],"type":"string"}},{"name":"asc","required":false,"in":"query","description":"Sort ascending","schema":{"default":false,"type":"boolean"}},{"name":"like","required":false,"in":"query","description":"Search term (searches in website url/name, test flow name, test ID)","schema":{"example":"example.com","type":"string"}},{"name":"websites","required":false,"in":"query","description":"Filter by website IDs","schema":{"example":[],"type":"array","items":{"type":"string"}}},{"name":"types","required":false,"in":"query","description":"Filter by test flow types","schema":{"example":["form","woo_checkout","custom"],"type":"array","items":{"type":"string"}}},{"name":"passing","required":false,"in":"query","description":"Show passing tests","schema":{"default":true,"type":"boolean"}},{"name":"failing","required":false,"in":"query","description":"Show failing tests","schema":{"default":true,"type":"boolean"}},{"name":"pending","required":false,"in":"query","description":"Show pending tests","schema":{"default":true,"type":"boolean"}}],"responses":{"200":{"description":"Test runs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTestRunsResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestRunsController_bulkUpdateTestRuns","summary":"Bulk update test runs","description":"Update multiple test runs at once.\n\nCommon use case: Abort multiple running tests simultaneously\n\nExample request:\n{\n  \"ids\": [\"test-id-1\", \"test-id-2\", \"test-id-3\"],\n  \"status\": \"aborted\"\n}\n\nLimitations:\n- Maximum 50 test runs per request\n- Only test runs in 'created' or 'started' state can be aborted\n\nReturns detailed results showing which tests were successfully updated and which failed with reasons.","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateTestRunDto"}}}},"responses":{"200":{"description":"Bulk update completed (includes successes and failures)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkAbortResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid request - exceeds maximum limit or invalid parameters"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/metrics":{"get":{"operationId":"TestRunsController_getTestRunMetrics","summary":"Get test run metrics and analytics","description":"Retrieve aggregated metrics, statistics, and analytics for your test runs.\n\nMetrics included:\n- Overall statistics: Total runs, success rate, average duration\n- Time series data: Trends over time (daily, weekly, or monthly)\n- Breakdown by website: Performance per monitored site\n- Breakdown by test type: Form tests, checkout tests, custom flows, etc.\n\nUse cases:\n- Monitor testing health and success rates\n- Identify problematic websites or test types\n- Track testing trends over time\n- Generate reports for stakeholders\n\nQuery parameters allow filtering by:\n- Date range (from/to)\n- Specific websites\n- Test types\n- Time grouping (day/week/month)","parameters":[{"name":"from","required":false,"in":"query","description":"Start date (ISO 8601)","schema":{"example":"2025-01-01T00:00:00Z","type":"string"}},{"name":"to","required":false,"in":"query","description":"End date (ISO 8601)","schema":{"example":"2025-12-31T23:59:59Z","type":"string"}},{"name":"group_by","required":false,"in":"query","description":"Group by (day, week, month)","schema":{"default":"day","enum":["day","week","month"],"type":"string"}},{"name":"websites","required":false,"in":"query","description":"Filter by website IDs","schema":{"type":"array","items":{"type":"string"}}},{"name":"types","required":false,"in":"query","description":"Filter by test types","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"Metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRunMetricsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}":{"get":{"operationId":"TestRunsController_getTestRunById","summary":"Get test run details","description":"Retrieve detailed information about a test run including all steps, status, and metrics","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Test run details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRunDetailDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]},"patch":{"operationId":"TestRunsController_updateTestRun","summary":"Update test run (abort/modify)","description":"Update a test run's properties. \n    \nCommon use cases:\n- Abort a running test: Send { \"status\": \"aborted\" } to stop test execution\n- Update metadata: Modify other test run properties as needed\n\nThe test run must be in 'created' or 'started' state to be aborted.","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestRunDto"}}}},"responses":{"200":{"description":"Test run updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbortTestRunResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid request - Test run is not in a running state or invalid status value"},"404":{"description":"Test run not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/video":{"get":{"operationId":"TestRunsController_getTestRunVideo","summary":"Get test run video","description":"Get signed URL for test run video recording","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Video URL retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUrlResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or video not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/har/content":{"get":{"operationId":"TestRunsController_getTestRunHarContent","summary":"Get test run HAR file content inline","description":"Returns the HAR file content as inline JSON. Returns 413 if file exceeds 50MB.","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"HAR content retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HarContentResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or HAR file not found"},"413":{"description":"HAR file too large for inline content"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/har":{"get":{"operationId":"TestRunsController_getTestRunHar","summary":"Get test run HAR file","description":"Get signed URL for test run HAR (HTTP Archive) file for debugging","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"HAR file URL retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUrlResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or HAR file not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/screenshot/content":{"get":{"operationId":"TestRunsController_getStepScreenshotContent","summary":"Get test step screenshot content inline","description":"Returns the screenshot as base64-encoded PNG in a JSON envelope.","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Screenshot content retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenshotContentResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run, step, or screenshot not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/screenshot":{"get":{"operationId":"TestRunsController_getStepScreenshot","summary":"Get test step screenshot","description":"Get signed URL for test step screenshot","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Screenshot URL retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUrlResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run, step, or screenshot not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/console-logs":{"get":{"operationId":"TestRunsController_getStepConsoleLogs","summary":"Get test step console logs","description":"Retrieve all console logs (log, error, warn, info) for a test step","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Console logs retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConsoleLogDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or step not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/network-logs":{"get":{"operationId":"TestRunsController_getStepNetworkLogs","summary":"Get test step network logs","description":"Retrieve all network requests made during a test step (without request/response bodies)","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Network logs retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NetworkLogDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or step not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/network-logs/{logId}/request":{"get":{"operationId":"TestRunsController_getNetworkLogRequest","summary":"Get network log request","description":"Get HTTP request body for a specific network log entry","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}},{"name":"logId","required":true,"in":"path","description":"Network log ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Request body signed URL retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Signed download URL for the request body"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run, step, or network log not found (or request body is empty)"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/steps/{stepId}/network-logs/{logId}/response":{"get":{"operationId":"TestRunsController_getNetworkLogResponse","summary":"Get network log response","description":"Get signed URL for the HTTP response body of a specific network log entry","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"stepId","required":true,"in":"path","description":"Test step ID","schema":{"format":"uuid","type":"string"}},{"name":"logId","required":true,"in":"path","description":"Network log ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Response body signed URL retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Signed download URL for the response body"}}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run, step, or network log not found (or response body is empty)"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/comments":{"get":{"operationId":"TestRunsController_getTestRunComments","summary":"Get test run comments","description":"Retrieve all comments for a test run","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"responses":{"200":{"description":"Comments retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TestCommentDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]},"post":{"operationId":"TestRunsController_createTestRunComment","summary":"Create test run comment","description":"Add a comment to a test run for team collaboration","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestCommentDto"}}}},"responses":{"201":{"description":"Comment created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestCommentDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/comments/{commentId}":{"delete":{"operationId":"TestRunsController_deleteTestRunComment","summary":"Delete test run comment","description":"Delete a comment from a test run (only by comment author)","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","type":"string"}},{"name":"commentId","required":true,"in":"path","description":"Comment ID","schema":{"format":"uuid","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"responses":{"204":{"description":"Comment deleted successfully","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Test run or comment not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/comparisons":{"post":{"operationId":"TestRunsController_compareTestRuns","summary":"Compare multiple test runs","description":"Generate a side-by-side comparison of 2-5 test runs.\n\nUse cases:\n- Compare test results before and after code changes\n- Identify performance differences between test runs\n- Analyze test stability across multiple executions\n\nComparison includes:\n- Status differences\n- Step count changes\n- Duration comparisons\n- Individual step differences\n\nRequirements:\n- Minimum 2 test runs\n- Maximum 5 test runs\n- All test runs must belong to your organization","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareTestRunsDto"}}}},"responses":{"200":{"description":"Comparison generated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRunComparisonDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid request - must provide 2-5 test run IDs"},"404":{"description":"One or more test runs not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/test-runs/{id}/ai-summary":{"get":{"operationId":"TestRunsController_getAiSummary","summary":"Get AI analysis of test run","description":"Returns the AI summary for a failed test run. Returns cached summary if available, otherwise generates on-demand via Gemini. Use forceRefresh=true to bypass cache.","parameters":[{"name":"id","required":true,"in":"path","description":"Test run ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"forceRefresh","required":false,"in":"query","description":"Force re-generation of the AI summary (bypass cache)","schema":{"example":"true","type":"boolean"}}],"responses":{"200":{"description":"AI summary response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSummaryResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["test-runs"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{websiteId}/ux-audits":{"get":{"operationId":"UxAuditsController_listAudits","summary":"List UX audits","description":"Retrieve all UX audits for a website with pagination and sorting","parameters":[{"name":"websiteId","required":true,"in":"path","description":"Website ID","schema":{"format":"uuid","type":"string"}},{"name":"pageIndex","required":false,"in":"query","description":"Page index (0-based)","schema":{"default":0,"example":0,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Page size","schema":{"minimum":1,"maximum":100,"default":10,"example":10,"type":"number"}},{"name":"orderBy","required":false,"in":"query","description":"Order by field","schema":{"default":"created_at","enum":["created_at","name","status"],"type":"string"}},{"name":"asc","required":false,"in":"query","description":"Ascending order","schema":{"default":false,"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Audits retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UxAuditListResponseDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["ux-audits"],"security":[{"JWT-auth":[]}]},"post":{"operationId":"UxAuditsController_createAudit","summary":"Create UX audit","description":"Create a new AI-powered UX audit. Validates test flows have successful tests with screenshots, then triggers the audit generation Cloud Run job.","parameters":[{"name":"websiteId","required":true,"in":"path","description":"Website ID","schema":{"format":"uuid","type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries. Successful responses are cached for replay. Errored responses are not cached — the row remains in-progress until either the original request finishes or the 2-minute staleness window elapses. Retries within that window return 409 Conflict; after 2 minutes, retries reclaim the key and re-execute. To re-execute immediately after a failed call, retry with a fresh idempotency key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUxAuditDto"}}}},"responses":{"201":{"description":"Audit created and generation started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UxAuditDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Invalid test flows or missing screenshots"},"403":{"description":"Monthly audit limit reached"},"404":{"description":"Website not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["ux-audits"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{websiteId}/ux-audits/{auditId}":{"get":{"operationId":"UxAuditsController_getAudit","summary":"Get UX audit","description":"Retrieve full details of a UX audit including website info and job metadata","parameters":[{"name":"websiteId","required":true,"in":"path","description":"Website ID","schema":{"format":"uuid","type":"string"}},{"name":"auditId","required":true,"in":"path","description":"Audit ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Audit retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UxAuditDetailDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Audit not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["ux-audits"],"security":[{"JWT-auth":[]}]}},"/api/v1/websites/{websiteId}/ux-audits/{auditId}/report":{"get":{"operationId":"UxAuditsController_getAuditReport","summary":"Get UX audit report","description":"Get the structured JSON report data. Returns 202 if still processing, error info if failed.","parameters":[{"name":"websiteId","required":true,"in":"path","description":"Website ID","schema":{"format":"uuid","type":"string"}},{"name":"auditId","required":true,"in":"path","description":"Audit ID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Report available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UxAuditReportDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"404":{"description":"Audit not found"},"429":{"description":"Too Many Requests - Rate limit exceeded","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["ux-audits"],"security":[{"JWT-auth":[]}]}},"/api/v1/plans":{"get":{"operationId":"ReferenceDataController_getPlans","summary":"List available plans","description":"Returns all active pricing plans with their features and limits","parameters":[],"responses":{"200":{"description":"Plans retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlanDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Bad Request - Invalid input data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"401":{"description":"Unauthorized - Invalid or missing authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"429":{"description":"Too Many Requests - Rate limit exceeded. The response includes rate limit headers and an RFC 7807 body with extensions: `{ limit, remaining, reset, retry_after }`.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["Reference Data"],"security":[{"JWT-auth":[]}]}},"/api/v1/roles":{"get":{"operationId":"ReferenceDataController_getRoles","summary":"List available roles","description":"Returns all enabled team member roles","parameters":[],"responses":{"200":{"description":"Roles retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RoleDto"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}}}},"400":{"description":"Bad Request - Invalid input data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"401":{"description":"Unauthorized - Invalid or missing authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"429":{"description":"Too Many Requests - Rate limit exceeded. The response includes rate limit headers and an RFC 7807 body with extensions: `{ limit, remaining, reset, retry_after }`.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute window","schema":{"type":"integer","example":57}},"X-RateLimit-Reset":{"description":"Unix epoch timestamp (seconds) when the current window resets","schema":{"type":"integer","example":1771524060}},"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}}},"tags":["Reference Data"],"security":[{"JWT-auth":[]}]}},"/api/v1/health":{"get":{"operationId":"HealthController_getHealth","summary":"Comprehensive health check endpoint","description":"Returns detailed health status including database connectivity, memory usage, and overall system health. Used by load balancers and monitoring systems.","parameters":[],"responses":{"200":{"description":"Health check completed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy","degraded"],"example":"healthy","description":"Overall system health status"},"timestamp":{"type":"string","example":"2025-10-17T07:58:29.668Z","description":"ISO timestamp of the health check"},"uptime":{"type":"number","example":123.456,"description":"Application uptime in seconds"},"environment":{"type":"string","example":"development","description":"Current environment (development, staging, production)"},"version":{"type":"string","example":"1.0.0","description":"Application version"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"database"},"status":{"type":"string","enum":["healthy","unhealthy"],"example":"healthy"},"message":{"type":"string","example":"Connected to PostgreSQL"},"responseTime":{"type":"number","example":45}}},"description":"Individual health checks for system components"}}}}}},"503":{"description":"Service unavailable - one or more health checks failed","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"unhealthy"},"timestamp":{"type":"string","example":"2025-10-17T07:58:29.668Z"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"database"},"status":{"type":"string","example":"unhealthy"},"message":{"type":"string","example":"Database connection failed: connection timeout"}}}}}}}}}},"tags":["health"]}},"/api/v1/health/ready":{"get":{"operationId":"HealthController_getReadiness","summary":"Readiness probe endpoint","description":"Simple readiness check for Kubernetes/container orchestration. Returns 200 if application is ready to serve traffic.","parameters":[],"responses":{"200":{"description":"Application is ready","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ready"},"timestamp":{"type":"string","example":"2025-10-17T07:58:29.668Z"}}}}}}},"tags":["health"]}},"/api/v1/health/live":{"get":{"operationId":"HealthController_getLiveness","summary":"Liveness probe endpoint","description":"Simple liveness check for Kubernetes/container orchestration. Returns 200 if application process is alive.","parameters":[],"responses":{"200":{"description":"Application is alive","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"alive"},"timestamp":{"type":"string","example":"2025-10-17T07:58:29.668Z"},"uptime":{"type":"number","example":123.456}}}}}}},"tags":["health"]}},"/api/v1":{"get":{"operationId":"AppController_getInfo","summary":"Get API information","parameters":[],"responses":{"200":{"description":"API information retrieved successfully"}},"tags":["app"]}},"/api/v1/hello":{"get":{"operationId":"AppController_getHello","summary":"Hello world endpoint","parameters":[],"responses":{"200":{"description":"Hello message"}},"tags":["app"]}}},"info":{"title":"CheckView API","description":"\n# CheckView Public API\n\n## Authentication & Tenant Headers\n\n### Authentication Endpoints (No X-Tenant Required)\nThe following endpoints do NOT require the X-Tenant header:\n- `POST /auth/login` - Login with email, password, and organizationId\n- `POST /auth/refresh` - Refresh access tokens  \n- `POST /auth/register` - User registration\n- `GET /health` - Health check\n\n### Protected Endpoints\nAll other endpoints require:\n- **Authorization**: `Bearer <JWT_TOKEN>`\n- **X-Tenant**: Automatically extracted from JWT token's `tid` field (no manual input needed)\n\n### Login Flow\n1. **Login**: `POST /auth/login` with `{ email, password, organizationId }`\n2. **Response**: JWT token containing `tid` (tenant/organization ID) claim\n3. **Subsequent Requests**: Use JWT → system automatically extracts `tid` → sets X-Tenant header\n\n## Rate Limiting\n\nAll authenticated endpoints are rate limited per organization:\n\n| Plan | Requests per minute |\n|------|---------------------|\n| Any paid plan | 60 |\n| No active subscription | 10 |\n\nLimits apply uniformly across paid plans today. We may adjust or tier limits in the future based on observed usage; changes will be announced in the changelog.\n\n### Response Headers\n\nEvery authenticated response includes rate limit headers:\n\n| Header | Description |\n|--------|-------------|\n| `X-RateLimit-Limit` | Maximum requests allowed per minute |\n| `X-RateLimit-Remaining` | Requests remaining in the current 1-minute window |\n| `X-RateLimit-Reset` | Unix epoch timestamp (seconds) when the window resets |\n\nWhen the rate limit is exceeded, the API returns **429 Too Many Requests** with an additional header:\n\n| Header | Description |\n|--------|-------------|\n| `Retry-After` | Seconds to wait before retrying |\n\nThe 429 response body follows [RFC 7807](https://tools.ietf.org/html/rfc7807) format with rate limit details in `extensions`:\n```json\n{\n  \"type\": \"https://api.checkview.io/errors/too-many-requests\",\n  \"title\": \"Too Many Requests\",\n  \"status\": 429,\n  \"detail\": \"Rate limit exceeded. Limit: 60 requests per minute. Try again in 42 seconds.\",\n  \"instance\": \"/api/v1/websites\",\n  \"extensions\": { \"limit\": 60, \"remaining\": 0, \"reset\": 1771524060, \"retry_after\": 42 }\n}\n```\n\n**Notes:** Public endpoints (health, auth) are not rate limited. Rate limit windows are fixed 1-minute intervals.\n    ","version":"1.0","contact":{"name":"CheckView Support","url":"https://checkview.io/support","email":"support@checkview.io"},"license":{"name":"MIT","url":"https://opensource.org/licenses/MIT"}},"tags":[],"servers":[],"components":{"securitySchemes":{"JWT-auth":{"scheme":"bearer","bearerFormat":"JWT","type":"http","name":"JWT","description":"Enter JWT token","in":"header"}},"schemas":{"CreatePersonalAccessTokenDto":{"type":"object","properties":{"name":{"type":"string","example":"My API Token","description":"Name for the personal access token","minLength":1,"maxLength":255},"scopes":{"example":["read:profile","write:profile"],"description":"Scopes to grant to this token","type":"array","items":{"type":"string"}},"organizationId":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Organization ID to scope the token to"}},"required":["name","scopes","organizationId"]},"PersonalAccessTokenResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"pat-uuid","description":"Personal access token ID"},"name":{"type":"string","example":"My API Token","description":"Token name"},"token":{"type":"string","example":"cvpat_1234567890abcdef...","description":"The actual token (only shown once upon creation)"},"scopes":{"example":["read:profile","write:profile"],"description":"Token scopes","type":"array","items":{"type":"string"}},"organizationId":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Organization ID"},"lastUsedAt":{"type":"string","example":"2024-01-01T00:00:00Z","description":"Last used timestamp"},"createdAt":{"type":"string","example":"2024-01-01T00:00:00Z","description":"Created timestamp"},"isActive":{"type":"boolean","example":true,"description":"Whether the token is active"}},"required":["id","name","scopes","createdAt","isActive"]},"OrganizationDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier","example":"123e4567-e89b-12d3-a456-426614174000","format":"uuid"},"created_at":{"type":"string","description":"Creation timestamp","example":"2023-12-01T10:00:00Z","format":"date-time"},"updated_at":{"type":"string","description":"Last update timestamp","example":"2023-12-01T10:00:00Z","format":"date-time"},"org_id":{"type":"string","description":"Organization/Tenant identifier","example":"123e4567-e89b-12d3-a456-426614174000","format":"uuid"},"name":{"type":"string","description":"Organization name","example":"Acme Corporation","maxLength":255},"email":{"type":"string","description":"Organization email address","example":"admin@acme.com","format":"email"},"contact_email":{"type":"string","description":"Contact email address","example":"contact@acme.com","format":"email"},"status":{"type":"string","description":"Organization status","enum":["active","inactive","pending","suspended"],"example":"active"},"monthly_test_limit":{"type":"number","description":"Monthly test limit","example":500,"minimum":0},"timezone":{"type":"string","description":"Organization timezone","example":"America/New_York"},"default_test_schedule_time":{"type":"string","description":"Default test schedule time","example":"09:00"},"default_test_schedule_days":{"description":"Default test schedule days (0=Sunday, 6=Saturday)","example":[0,1,2,3,4,5,6],"type":"array","items":{"type":"number"}},"company_size_id":{"type":"string","description":"Company size identifier","example":"1_10"},"stripe_customer_id":{"type":"string","description":"Stripe customer ID","example":"cus_123456789"},"tax_id":{"type":"string","description":"Tax ID","example":"123-45-6789"},"tax_country_id":{"type":"string","description":"Tax country ID","example":"US"},"device_type":{"type":"string","description":"Device type preference","enum":["desktop","mobile"],"example":"desktop"},"honor_robot_rules":{"type":"boolean","description":"Honor robots.txt rules","example":false},"hide_helper_plugin":{"type":"boolean","description":"Hide helper plugin","example":false},"auto_retry_failed_tests":{"type":"boolean","description":"Auto-retry failed scheduled tests","example":false},"trial_eligible":{"type":"boolean","description":"Trial eligibility status","example":true},"subscriptions":{"type":"object","description":"Subscription details with plan"},"payment_methods":{"description":"Payment methods ordered by default first","type":"array","items":{"type":"object"}},"organization_test_variables":{"description":"Organization test variables","type":"array","items":{"type":"object"}},"organization_email_report_settings":{"type":"object","description":"Email report settings"},"organization_test_notification_settings":{"type":"object","description":"Test notification settings"}},"required":["id","created_at","updated_at","org_id","name","status","monthly_test_limit","timezone","default_test_schedule_time","default_test_schedule_days","device_type","honor_robot_rules","auto_retry_failed_tests"]},"UpdateOrganizationDto":{"type":"object","properties":{"name":{"type":"string","description":"Organization name","example":"Acme Corporation Updated","maxLength":255},"email":{"type":"string","description":"Organization email address","example":"admin@acme.com","format":"email"},"timezone":{"type":"string","description":"Organization timezone","example":"America/Los_Angeles"},"default_test_schedule_time":{"type":"string","description":"Default test schedule time","example":"10:00"},"default_test_schedule_days":{"description":"Default test schedule days","example":[1,2,3,4,5],"type":"array","items":{"type":"number"}},"device_type":{"type":"string","description":"Device type preference","enum":["desktop","mobile"]},"honor_robot_rules":{"type":"boolean","description":"Honor robots.txt rules","example":true},"hide_helper_plugin":{"type":"boolean","description":"Hide helper plugin","example":true},"auto_retry_failed_tests":{"type":"boolean","description":"Auto-retry failed scheduled tests","example":true},"record_last_visited":{"type":"boolean","description":"Record last visited timestamp (set to true to update)","example":true}}},"OrganizationUsageDto":{"type":"object","properties":{"org_id":{"type":"string","description":"Organization ID","example":"123e4567-e89b-12d3-a456-426614174000"},"usage":{"type":"number","description":"Current usage count","example":150},"monthly_limit":{"type":"number","description":"Monthly limit","example":500},"percentage_used":{"type":"number","description":"Percentage used","example":30},"remaining":{"type":"number","description":"Remaining tests","example":350},"period_start":{"type":"string","description":"Usage period start date","example":"2024-01-01T00:00:00Z"},"period_end":{"type":"string","description":"Usage period end date","example":"2024-01-31T23:59:59Z"},"audit_usage":{"type":"number","description":"Current monthly audit usage count","example":2},"monthly_audit_limit":{"type":"number","description":"Monthly audit limit from plan","example":10},"audit_remaining":{"type":"number","description":"Remaining audits this month","example":8}},"required":["org_id","usage","monthly_limit","percentage_used","remaining","period_start","period_end","audit_usage","monthly_audit_limit","audit_remaining"]},"OrganizationStatisticsDto":{"type":"object","properties":{"total_websites":{"type":"number","description":"Total websites","example":5},"total_test_flows":{"type":"number","description":"Total test flows","example":15},"tests_this_month":{"type":"number","description":"Total tests run this month","example":150},"passing_tests":{"type":"number","description":"Passing tests count","example":140},"failing_tests":{"type":"number","description":"Failing tests count","example":10},"team_members":{"type":"number","description":"Active team members","example":3}},"required":["total_websites","total_test_flows","tests_this_month","passing_tests","failing_tests","team_members"]},"TrialEligibilityDto":{"type":"object","properties":{"eligible":{"type":"boolean","description":"Trial eligibility status","example":true},"has_had_trial_before":{"type":"boolean","description":"Whether organization has had trial before","example":false},"reason":{"type":"string","description":"Reason if not eligible","example":"Organization has already used trial period"}},"required":["eligible","has_had_trial_before"]},"AdminOrganizationListItemDto":{"type":"object","properties":{"id":{"type":"string","description":"Organization ID"},"name":{"type":"string","description":"Organization name"},"email":{"type":"string","description":"Organization email"},"created_at":{"type":"string","description":"Creation timestamp (ISO 8601)"}},"required":["id","name"]},"TestFlowTypeDto":{"type":"object","properties":{"org_id":{"type":"string","description":"Organization ID","example":"550e8400-e29b-41d4-a716-446655440000"},"plugin_id":{"type":"string","description":"Plugin ID","example":"contact-form-7"},"name":{"type":"string","description":"Plugin/Form name","example":"Contact Form 7"}},"required":["org_id","plugin_id","name"]},"WebsiteDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier","example":"123e4567-e89b-12d3-a456-426614174000","format":"uuid"},"created_at":{"type":"string","description":"Creation timestamp","example":"2023-12-01T10:00:00Z","format":"date-time"},"updated_at":{"type":"string","description":"Last update timestamp","example":"2023-12-01T10:00:00Z","format":"date-time"},"org_id":{"type":"string","description":"Organization/Tenant identifier","example":"123e4567-e89b-12d3-a456-426614174000","format":"uuid"},"name":{"type":"string","description":"Website name","example":"My WordPress Site"},"url":{"type":"string","description":"Website URL","example":"https://example.com"},"paused":{"type":"boolean","description":"Whether the website is paused","example":false},"state":{"type":"string","description":"Website state","enum":["active","paused","archived","error"],"example":"active"},"reason_paused":{"type":"string","description":"Reason why the website is paused","enum":["user","subscription_canceled"],"example":"user"},"has_screenshot":{"type":"boolean","description":"Whether the website has a screenshot","example":true},"basic_auth":{"type":"boolean","description":"Whether basic auth is enabled","example":false},"basic_auth_username":{"type":"string","description":"Basic auth username","example":"admin"},"type":{"type":"string","description":"Website type","enum":["wordpress","non_wordpress"],"example":"wordpress"}},"required":["id","created_at","updated_at","org_id","name","url","paused","has_screenshot","type"]},"CreateWebsiteDto":{"type":"object","properties":{"url":{"type":"string","description":"Website URL (must use HTTPS)","example":"https://example.com"},"type":{"type":"string","description":"Website type","enum":["wordpress","non_wordpress"],"example":"wordpress","default":"wordpress"},"basic_auth_username":{"type":"string","description":"Basic auth username (if site requires authentication)","example":"admin"},"basic_auth_password":{"type":"string","description":"Basic auth password (if site requires authentication)","example":"password123"}},"required":["url","type"]},"WebsiteStatusDto":{"type":"object","properties":{"id":{"type":"string","description":"Website ID","example":"550e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","description":"Website name","example":"My WordPress Site"},"url":{"type":"string","description":"Website URL","example":"https://example.com"},"paused":{"type":"boolean","description":"Whether the website is paused","example":false},"total_count":{"type":"number","description":"Total test flows","example":10},"passing":{"type":"number","description":"Passing test flows","example":8},"failing":{"type":"number","description":"Failing test flows","example":2}},"required":["id","name","url","paused","total_count","passing","failing"]},"UpdateWebsiteDto":{"type":"object","properties":{"name":{"type":"string","description":"Website name","example":"My WordPress Site"},"url":{"type":"string","description":"Website URL","example":"https://example.com"},"paused":{"type":"boolean","description":"Whether the website is paused","example":false},"basic_auth":{"type":"boolean","description":"Whether basic auth is enabled","example":false},"basic_auth_username":{"type":"string","description":"Basic auth username","example":"admin"},"basic_auth_password":{"type":"string","description":"Basic auth password","example":"password123"}}},"DeleteResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Success status","example":true},"message":{"type":"string","description":"Success message","example":"Operation completed successfully"},"id":{"type":"string","description":"Deleted resource ID","example":"123e4567-e89b-12d3-a456-426614174000","format":"uuid"}},"required":["success","message","id"]},"WebsiteScreenshotDto":{"type":"object","properties":{"has_screenshot":{"type":"boolean","example":true},"screenshot_url":{"type":"string","example":"https://storage.googleapis.com/bucket/screenshot.png"},"updated_at":{"type":"string","example":"2025-11-04T12:00:00Z"},"width":{"type":"number","example":1920},"height":{"type":"number","example":1080}},"required":["has_screenshot"]},"FormUrlDto":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"name":{"type":"string"}},"required":["id","url","name"]},"FormDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"urls":{"type":"array","items":{"$ref":"#/components/schemas/FormUrlDto"}}},"required":["id","name","urls"]},"InstalledFormDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"forms":{"type":"array","items":{"$ref":"#/components/schemas/FormDto"}}},"required":["id","name","forms"]},"WordPressSettingsDto":{"type":"object","properties":{"plugin_version":{"type":"string","example":"1.2.3"},"hide_helper_plugin":{"type":"boolean","example":false},"hide_helper_plugin_updating":{"type":"boolean","example":false},"site_name":{"type":"string","example":"My Blog"},"wp_version":{"type":"string","example":"6.4.1"},"last_synced":{"type":"string","example":"2025-11-04T12:00:00Z"}},"required":["hide_helper_plugin","hide_helper_plugin_updating"]},"WebsiteNotificationsDto":{"type":"object","properties":{"email_addresses":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean","example":true},"report_type":{"type":"string","example":"daily"},"using_global":{"type":"boolean","example":false}},"required":["email_addresses","enabled","report_type","using_global"]},"UpdateWebsiteNotificationsDto":{"type":"object","properties":{"email_addresses":{"description":"Email addresses for reports","type":"array","items":{"type":"string"}},"enabled":{"type":"boolean","example":true},"report_type":{"type":"string","description":"Report frequency","enum":["daily","weekly","monthly"],"example":"daily"}}},"WebsiteOperationResponseDto":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Website paused successfully"}},"required":["success","message"]},"EmailReportSettingsDto":{"type":"object","properties":{"id":{"type":"string","description":"Settings ID","format":"uuid"},"email_addresses":{"description":"Email addresses to receive reports","example":["admin@example.com"],"type":"array","items":{"type":"string"}},"type_id":{"type":"string","description":"Report type","enum":["daily","weekly","monthly"],"example":"daily"},"enabled":{"type":"boolean","description":"Whether reports are enabled","example":true},"entity_type":{"type":"string","description":"Entity type","example":"organization"}},"required":["id","email_addresses","type_id","enabled"]},"UpdateEmailReportSettingsDto":{"type":"object","properties":{"emailAddresses":{"description":"Email addresses to receive reports","example":["admin@example.com"],"type":"array","items":{"type":"string"}},"typeId":{"type":"string","description":"Report type","enum":["daily","weekly","monthly"],"example":"daily"},"enabled":{"type":"boolean","description":"Whether reports are enabled","example":true}},"required":["emailAddresses","typeId","enabled"]},"RunAllResponseDto":{"type":"object","properties":{"triggered_count":{"type":"number","example":3,"description":"Number of test flows triggered"},"triggered_at":{"type":"string","example":"2026-02-18T15:30:00.000Z","description":"Timestamp used to scope status queries"}},"required":["triggered_count","triggered_at"]},"RunAllStatusResponseDto":{"type":"object","properties":{"locked":{"type":"boolean","example":false,"description":"Whether a run-all is currently in progress"},"pending":{"type":"number","example":0,"description":"Tests queued but not started"},"running":{"type":"number","example":0,"description":"Tests currently executing"},"passed":{"type":"number","example":3,"description":"Tests completed successfully"},"failed":{"type":"number","example":0,"description":"Tests that failed"}},"required":["locked","pending","running","passed","failed"]},"ScheduleSettingsDto":{"type":"object","properties":{"time":{"type":"string","description":"Default test schedule time (HH:mm:ss)","example":"09:00:00"},"days":{"description":"Default test schedule days: 0-7 for weekly (0/7=Sunday, 1=Monday, 6=Saturday), -28 to -1 for monthly (day of month)","example":[0,1,2,3,4,5,6],"type":"array","items":{"type":"string"}},"timezone":{"type":"string","description":"Timezone","example":"America/New_York"}},"required":["time","days","timezone"]},"UsageSettingsDto":{"type":"object","properties":{"monthly_test_limit":{"type":"number","description":"Monthly test limit","example":1000}},"required":["monthly_test_limit"]},"UsageReportDto":{"type":"object","properties":{"day_of_month":{"type":"string","description":"Day of month or date","example":"10/24"},"success_count":{"type":"number","description":"Number of successful tests","example":150},"error_count":{"type":"number","description":"Number of failed tests","example":5}},"required":["day_of_month","success_count","error_count"]},"DeviceSettingsDto":{"type":"object","properties":{"device_type":{"type":"string","description":"Device type","enum":["desktop","mobile"],"example":"desktop"},"honor_robot_rules":{"type":"boolean","description":"Whether to honor robots.txt rules when running tests","example":true}},"required":["device_type"]},"PluginVisibilitySettingsDto":{"type":"object","properties":{"hide_helper_plugin":{"type":"boolean","description":"Hide helper plugin","example":false},"hide_helper_plugin_updating":{"type":"boolean","description":"Hide helper plugin updating messages","example":false}},"required":["hide_helper_plugin"]},"PluginPropagationFailureDto":{"type":"object","properties":{"id":{"type":"string","description":"Website ID","example":"73c4b0d2-653c-481e-92ba-5d349931f471"},"name":{"type":"string","description":"Website name","example":"My WordPress Site"}},"required":["id","name"]},"AutoRetrySettingsDto":{"type":"object","properties":{"autoRetryFailedTests":{"type":"boolean","description":"Whether to automatically retry failed tests","example":true}},"required":["autoRetryFailedTests"]},"GetVariablesResponseDto":{"type":"object","properties":{"org_id":{"type":"string","description":"Organization ID","example":"550e8400-e29b-41d4-a716-446655440000"},"woo_variables":{"type":"object","description":"WooCommerce variables","example":{"shipping_address":"123 Main St"}},"form_variables":{"type":"object","description":"Form variables","example":{"email":"test@example.com"}}},"required":["org_id"]},"AddressDetailsDto":{"type":"object","properties":{"firstName":{"type":"string","description":"First name","example":"John"},"lastName":{"type":"string","description":"Last name","example":"Doe"},"companyName":{"type":"string","description":"Company name","example":"Acme Inc"},"country":{"type":"string","description":"Country","example":"United States"},"address1":{"type":"string","description":"Address line 1","example":"123 Main St"},"address2":{"type":"string","description":"Address line 2","example":"Suite 100"},"city":{"type":"string","description":"City","example":"New York"},"state":{"type":"string","description":"State","example":"NY"},"zipCode":{"type":"string","description":"Zip code","example":"10001"},"phoneNumber":{"type":"string","description":"Phone number","example":"+1-555-555-5555"}},"required":["firstName","lastName","country","address1","city","state","zipCode","phoneNumber"]},"WooVariablesDto":{"type":"object","properties":{"shippingDetails":{"description":"Shipping details (null if same as billing)","nullable":true,"allOf":[{"$ref":"#/components/schemas/AddressDetailsDto"}]},"billingDetails":{"description":"Billing details","allOf":[{"$ref":"#/components/schemas/AddressDetailsDto"}]},"additionalInformation":{"type":"string","description":"Additional order information","example":"Leave at door"}},"required":["billingDetails","additionalInformation"]},"FormVariablesDto":{"type":"object","properties":{"firstName":{"type":"string","description":"First name","example":"John"},"middleName":{"type":"string","description":"Middle name","example":"M"},"lastName":{"type":"string","description":"Last name","example":"Doe"},"phoneNumber":{"type":"string","description":"Phone number","example":"+1-555-555-5555"},"shortParagraph":{"type":"string","description":"Short paragraph for textarea fields","example":"This is a test submission."},"companyName":{"type":"string","description":"Company name","example":"Acme Inc"},"country":{"type":"string","description":"Country","example":"United States"},"address1":{"type":"string","description":"Address line 1","example":"123 Main St"},"address2":{"type":"string","description":"Address line 2","example":"Suite 100"},"city":{"type":"string","description":"City","example":"New York"},"state":{"type":"string","description":"State","example":"NY"},"zipCode":{"type":"string","description":"Zip code","example":"10001"},"website":{"type":"string","description":"Website URL","example":"https://example.com"}},"required":["firstName","lastName","phoneNumber","shortParagraph","country","address1","city","state","zipCode","website"]},"VariablesSettingsDto":{"type":"object","properties":{"woo_variables":{"description":"WooCommerce variables (billing/shipping details for checkout flows)","allOf":[{"$ref":"#/components/schemas/WooVariablesDto"}]},"form_variables":{"description":"Form variables (contact/personal info for form flows)","allOf":[{"$ref":"#/components/schemas/FormVariablesDto"}]}}},"TeamMemberDto":{"type":"object","properties":{"user_id":{"type":"string","description":"User ID","example":"550e8400-e29b-41d4-a716-446655440000"},"email":{"type":"string","description":"Email address","example":"user@example.com"},"first_name":{"type":"string","description":"First name","example":"John"},"last_name":{"type":"string","description":"Last name","example":"Doe"},"role_id":{"type":"string","description":"Role ID","example":"admin"},"role_name":{"type":"string","description":"Role name","example":"Administrator"},"active":{"type":"boolean","description":"Whether user is active","example":true},"allow_access_to_all_websites":{"type":"boolean","description":"Access to all websites","example":true},"website_ids":{"description":"Assigned website IDs","type":"array","items":{"type":"string"}},"websites":{"description":"Assigned websites with names","type":"array","items":{"type":"string"}},"added_at":{"type":"string","description":"Date added to organization"}},"required":["user_id","email","role_id","role_name","active","allow_access_to_all_websites","website_ids","websites","added_at"]},"PendingInvitationDto":{"type":"object","properties":{"id":{"type":"string","description":"Invitation ID","example":"550e8400-e29b-41d4-a716-446655440000"},"email_address":{"type":"string","description":"Email address","example":"newuser@example.com"},"role_id":{"type":"string","description":"Role ID","example":"user"},"allow_access_to_all_websites":{"type":"boolean","description":"Whether user has access to all websites","example":false},"status":{"type":"string","description":"Invitation status","enum":["pending","accepted","denied"],"example":"pending"},"sent_by":{"type":"string","description":"Sent by user ID","example":"550e8400-e29b-41d4-a716-446655440000"},"created_at":{"type":"string","description":"Created at","example":"2025-10-24T12:00:00Z"},"expires_at":{"type":"string","description":"Expires at","example":"2025-10-31T12:00:00Z"},"responded_at":{"type":"string","description":"Responded at","example":"2025-10-25T12:00:00Z"}},"required":["id","email_address","role_id","allow_access_to_all_websites","status","sent_by","created_at","expires_at"]},"GetTeamResponseDto":{"type":"object","properties":{"team_members":{"description":"Team members","type":"array","items":{"$ref":"#/components/schemas/TeamMemberDto"}},"pending_invites":{"description":"Pending invitations","type":"array","items":{"$ref":"#/components/schemas/PendingInvitationDto"}}},"required":["team_members","pending_invites"]},"UpdateTeamMemberDto":{"type":"object","properties":{"roleTypeId":{"type":"string","description":"Role type ID","example":"collaborator","enum":["admin","collaborator"]},"allowAccessToAllWebsites":{"type":"boolean","description":"Allow access to all websites","example":true},"websites":{"description":"Website IDs to grant access to","type":"array","items":{"type":"string"}},"active":{"type":"boolean","description":"Whether user is active","example":true}}},"InviteTeamMemberDto":{"type":"object","properties":{"email":{"type":"string","description":"Email address to invite","example":"newuser@example.com"},"roleTypeId":{"type":"string","description":"Role type ID","example":"collaborator","enum":["admin","collaborator"]},"allowAccessToAllWebsites":{"type":"boolean","description":"Allow access to all websites","example":false},"websites":{"description":"Website IDs to grant access to","type":"array","items":{"type":"string"}}},"required":["email","roleTypeId","allowAccessToAllWebsites","websites"]},"UpdateInvitationDto":{"type":"object","properties":{"roleTypeId":{"type":"string","description":"Role type ID","example":"collaborator","enum":["admin","collaborator"]},"allowAccessToAllWebsites":{"type":"boolean","description":"Allow access to all websites","example":false},"websites":{"description":"Website IDs","type":"array","items":{"type":"string"}}}},"AcceptInvitationResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Success status","example":true},"organizationId":{"type":"string","description":"Organization ID joined","example":"550e8400-e29b-41d4-a716-446655440000"},"organizationName":{"type":"string","description":"Organization name","example":"Acme Corporation"},"role":{"type":"string","description":"Role assigned","example":"collaborator"},"message":{"type":"string","description":"Message","example":"Successfully joined organization"}},"required":["success","organizationId","organizationName","role","message"]},"TestNotificationSettingsDto":{"type":"object","properties":{"id":{"type":"string","description":"Settings ID","format":"uuid"},"email_addresses":{"description":"Email addresses to receive notifications","example":["dev@example.com"],"type":"array","items":{"type":"string"}},"type_id":{"type":"object","description":"Notification type ID","format":"uuid","nullable":true},"enabled":{"type":"boolean","description":"Whether notifications are enabled","example":true},"entity_type":{"type":"string","description":"Entity type","example":"organization"}},"required":["id","email_addresses","enabled","entity_type"]},"OrganizationNotificationSettingsDto":{"type":"object","properties":{"email_reports":{"description":"Email report settings","allOf":[{"$ref":"#/components/schemas/EmailReportSettingsDto"}]},"test_notifications":{"description":"Test notification settings","allOf":[{"$ref":"#/components/schemas/TestNotificationSettingsDto"}]}},"required":["email_reports","test_notifications"]},"UpdateTestNotificationSettingsDto":{"type":"object","properties":{"emailAddresses":{"description":"Email addresses to receive notifications","example":["dev@example.com"],"type":"array","items":{"type":"string"}},"testNotificationTypeId":{"type":"string","description":"Notification type ID or \"use-global-settings\"","example":"use-global-settings","nullable":true},"enabled":{"type":"boolean","description":"Whether notifications are enabled","example":true}},"required":["emailAddresses","enabled"]},"WebhookConfigDto":{"type":"object","properties":{"url":{"type":"string","description":"Webhook endpoint URL","example":"https://example.com/webhooks/checkview"},"trigger":{"type":"string","description":"When to trigger the webhook","enum":["all","success_only","failure_only"],"example":"all"}},"required":["url","trigger"]},"WebhookNotificationSettingsDto":{"type":"object","properties":{"id":{"type":"string","description":"Settings ID (absent when no webhook settings exist)","format":"uuid"},"webhooks":{"description":"Webhook configurations","type":"array","items":{"$ref":"#/components/schemas/WebhookConfigDto"}},"enabled":{"type":"boolean","description":"Whether webhooks are enabled","example":true}},"required":["webhooks","enabled"]},"UpdateWebhookNotificationSettingsDto":{"type":"object","properties":{"webhooks":{"description":"Webhook configurations (required when enabled is true)","type":"array","items":{"$ref":"#/components/schemas/WebhookConfigDto"}},"enabled":{"type":"boolean","description":"Whether webhooks are enabled","example":true}},"required":["enabled"]},"TestWebhookRequestDto":{"type":"object","properties":{"url":{"type":"string","description":"Webhook URL to test","example":"https://example.com/webhooks/checkview"}},"required":["url"]},"TestWebhookResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the test ping was delivered successfully"},"status_code":{"type":"object","description":"HTTP status code returned by the webhook endpoint","example":200},"error":{"type":"string","description":"Error message if the test ping failed"}},"required":["success","status_code"]},"SlackNotificationSettingsDto":{"type":"object","properties":{"id":{"type":"string","description":"Settings ID","format":"uuid"},"enabled":{"type":"boolean","description":"Whether Slack notifications are enabled","example":true},"channels":{"description":"Slack channels to post to (must start with #)","example":["#testing","#alerts"],"type":"array","items":{"type":"string"}},"typeId":{"type":"object","description":"Slack notification type ID (from GET /notifications/types)","format":"uuid","nullable":true}},"required":["enabled","channels"]},"UpdateSlackNotificationSettingsDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether Slack notifications are enabled","example":true},"channels":{"description":"Slack channels (must start with #)","example":["#testing"],"type":"array","items":{"type":"string"}},"typeId":{"type":"object","description":"Slack notification type ID or \"use-global-settings\" for per-flow","nullable":true}},"required":["enabled"]},"EmailReportTypeDto":{"type":"object","properties":{"id":{"type":"string","description":"Type ID","example":"daily"},"name":{"type":"string","description":"Type name","example":"Daily"},"index":{"type":"number","description":"Display order","example":1}},"required":["id","name"]},"TestNotificationTypeDto":{"type":"object","properties":{"id":{"type":"string","description":"Type ID","format":"uuid"},"alias":{"type":"string","description":"Type alias","example":"all_tests"},"name":{"type":"string","description":"Type name","example":"All Tests"},"index":{"type":"number","description":"Display order","example":1}},"required":["id","alias","name"]},"NotificationTypesDto":{"type":"object","properties":{"email_report_types":{"description":"Available email report types","type":"array","items":{"$ref":"#/components/schemas/EmailReportTypeDto"}},"test_notification_types":{"description":"Available test notification types","type":"array","items":{"$ref":"#/components/schemas/TestNotificationTypeDto"}}},"required":["email_report_types","test_notification_types"]},"CreateTestFlowFromUrlDto":{"type":"object","properties":{"url":{"type":"string","description":"URL to create test flow from","example":"https://example.com/contact"},"name":{"type":"string","description":"Test flow name (defaults to URL hostname)","example":"Contact Form Test"},"testType":{"type":"string","description":"Test type","enum":["form","login","search","membership","ecommerce","lms","other"],"default":"form"},"userContext":{"type":"object","description":"User context for generation","example":{"firstName":"John","email":"test@example.com"}}},"required":["url"]},"TestFlowDto":{"type":"object","properties":{"id":{"type":"string","description":"Test flow ID","format":"uuid"},"name":{"type":"string","description":"Test flow name","example":"Contact Form Submission"},"type":{"type":"string","description":"Test flow type","enum":["form","woo_checkout","custom"],"example":"form"},"parameters":{"type":"object","description":"Test flow parameters"},"org_id":{"type":"string","description":"Organization ID","format":"uuid"},"website_id":{"type":"string","description":"Website ID","format":"uuid"},"status":{"type":"string","description":"Test flow status","enum":["created","passing","failing","pending","initializing","initialization_failed"],"example":"passing"},"paused":{"type":"boolean","description":"Is test flow paused","example":false},"reason_paused":{"type":"string","description":"Reason paused","enum":["user","subscription_canceled"],"nullable":true},"device_type":{"type":"string","description":"Device type","enum":["inherit","desktop","mobile"],"example":"inherit"},"honor_robot_rules":{"type":"string","description":"Honor robot rules","enum":["inherit","yes","no"],"example":"inherit"},"disable_actions":{"type":"string","description":"Disable form integrations during tests when possible"},"status_dismissed":{"type":"boolean","description":"Status dismissed","example":false},"preview_test_id":{"type":"string","description":"Preview test ID","format":"uuid","nullable":true},"init_failed_steps":{"type":"object","description":"Init failed steps","nullable":true},"gcp_job_uid":{"type":"string","description":"GCP job UID","format":"uuid","nullable":true},"gcp_job_name":{"type":"string","description":"GCP job name","nullable":true},"gcp_job_logs_uri":{"type":"string","description":"GCP job logs URI","nullable":true},"device":{"type":"object","description":"Device configuration","nullable":true},"auto_click_selector":{"type":"object","description":"CSS selector for an element to auto-click before test execution","nullable":true},"modal_selector":{"type":"object","description":"CSS selector for a modal to dismiss before test execution","nullable":true},"generate_steps":{"type":"boolean","description":"Whether step generation is enabled","example":true},"typing_method":{"type":"object","description":"Typing method for fill steps","nullable":true},"bulk_generation_locked":{"type":"boolean","description":"Bulk generation locked","example":false},"created_at":{"type":"string","description":"Created at timestamp"},"updated_at":{"type":"string","description":"Updated at timestamp"}},"required":["id","name","type","parameters","org_id","website_id","status","paused","device_type","honor_robot_rules","disable_actions","status_dismissed","generate_steps","bulk_generation_locked","created_at","updated_at"]},"ScheduleInputDto":{"type":"object","properties":{"days":{"description":"Days to run: 0-7 for weekly (0/7=Sunday), -28 to -1 for monthly (day of month)","example":[1,2,3,4,5],"type":"array","items":{"type":"number"}},"time":{"type":"string","description":"Time to run (HH:mm:ss)","example":"09:00:00"},"timezone":{"type":"string","description":"Timezone","example":"America/New_York"}},"required":["days","time","timezone"]},"CreateTestFlowDto":{"type":"object","properties":{"name":{"type":"string","description":"Test flow name","example":"Contact Form Submission"},"type":{"type":"string","description":"Test flow type","enum":["form","woo_checkout","custom"],"example":"form"},"parameters":{"type":"object","description":"Test flow parameters (validated against type-specific schema)"},"websiteId":{"type":"string","description":"Website ID","format":"uuid"},"deviceType":{"type":"string","description":"Device type","enum":["inherit","desktop","mobile"],"example":"inherit"},"honorRobotRules":{"type":"string","description":"Honor robot rules","enum":["inherit","yes","no"],"example":"inherit"},"disableActions":{"type":"string","description":"Disable form integrations during tests when possible","enum":["yes","no","inherit"],"example":"inherit"},"generateSteps":{"type":"boolean","description":"Whether to auto-generate test steps via AI after creation. Triggers the test-flow-steps-generator pipeline.","example":true,"default":true},"schedule":{"description":"Schedule for automatic test execution. If provided, a Cloud Scheduler job is created.","example":{"days":[1,2,3,4,5],"time":"09:00:00","timezone":"America/New_York"},"allOf":[{"$ref":"#/components/schemas/ScheduleInputDto"}]}},"required":["name","type","parameters","websiteId"]},"TestFlowStepDto":{"type":"object","properties":{"id":{"type":"string","description":"Step ID","format":"uuid"},"test_flow_id":{"type":"string","description":"Test flow ID","format":"uuid"},"org_id":{"type":"string","description":"Organization ID","format":"uuid"},"type":{"type":"string","description":"Step type","example":"click"},"metadata":{"type":"object","description":"Step metadata","example":{"selector":"#submit-button"}},"index":{"type":"number","description":"Step index/order","example":0},"optional":{"type":"boolean","description":"Is step optional","example":false},"notes":{"type":"object","description":"Step notes/comments","nullable":true}},"required":["id","test_flow_id","org_id","type","metadata","index","optional"]},"TestFlowScheduleDto":{"type":"object","properties":{"id":{"type":"string","description":"Schedule ID","format":"uuid"},"test_flow_id":{"type":"string","description":"Test flow ID","format":"uuid"},"days":{"description":"Days to run: 0-7 for weekly (0/7=Sunday, 1=Monday, 6=Saturday), -28 to -1 for monthly (day of month)","example":[1,2,3,4,5],"type":"array","items":{"type":"number"}},"time":{"type":"string","description":"Time to run (HH:mm:ss)","example":"09:00:00"},"timezone":{"type":"string","description":"Timezone","example":"America/New_York"},"cloud_scheduler_job_id":{"type":"string","description":"Cloud scheduler job ID","format":"uuid"},"created_at":{"type":"string","description":"Created at timestamp"},"updated_at":{"type":"string","description":"Updated at timestamp"}},"required":["id","test_flow_id","days","time","timezone","created_at","updated_at"]},"TestFlowWithDetailsDto":{"type":"object","properties":{"id":{"type":"string","description":"Test flow ID","format":"uuid"},"name":{"type":"string","description":"Test flow name","example":"Contact Form Submission"},"type":{"type":"string","description":"Test flow type","enum":["form","woo_checkout","custom"],"example":"form"},"parameters":{"type":"object","description":"Test flow parameters"},"org_id":{"type":"string","description":"Organization ID","format":"uuid"},"website_id":{"type":"string","description":"Website ID","format":"uuid"},"status":{"type":"string","description":"Test flow status","enum":["created","passing","failing","pending","initializing","initialization_failed"],"example":"passing"},"paused":{"type":"boolean","description":"Is test flow paused","example":false},"reason_paused":{"type":"string","description":"Reason paused","enum":["user","subscription_canceled"],"nullable":true},"device_type":{"type":"string","description":"Device type","enum":["inherit","desktop","mobile"],"example":"inherit"},"honor_robot_rules":{"type":"string","description":"Honor robot rules","enum":["inherit","yes","no"],"example":"inherit"},"disable_actions":{"type":"string","description":"Disable form integrations during tests when possible"},"status_dismissed":{"type":"boolean","description":"Status dismissed","example":false},"preview_test_id":{"type":"string","description":"Preview test ID","format":"uuid","nullable":true},"init_failed_steps":{"type":"object","description":"Init failed steps","nullable":true},"gcp_job_uid":{"type":"string","description":"GCP job UID","format":"uuid","nullable":true},"gcp_job_name":{"type":"string","description":"GCP job name","nullable":true},"gcp_job_logs_uri":{"type":"string","description":"GCP job logs URI","nullable":true},"device":{"type":"object","description":"Device configuration","nullable":true},"auto_click_selector":{"type":"object","description":"CSS selector for an element to auto-click before test execution","nullable":true},"modal_selector":{"type":"object","description":"CSS selector for a modal to dismiss before test execution","nullable":true},"generate_steps":{"type":"boolean","description":"Whether step generation is enabled","example":true},"typing_method":{"type":"object","description":"Typing method for fill steps","nullable":true},"bulk_generation_locked":{"type":"boolean","description":"Bulk generation locked","example":false},"created_at":{"type":"string","description":"Created at timestamp"},"updated_at":{"type":"string","description":"Updated at timestamp"},"steps":{"description":"Test flow steps","type":"array","items":{"$ref":"#/components/schemas/TestFlowStepDto"}},"schedule":{"description":"Test flow schedule","nullable":true,"allOf":[{"$ref":"#/components/schemas/TestFlowScheduleDto"}]},"most_recent_test":{"type":"object","description":"Most recent test (excludes initialization tests)","nullable":true},"website":{"type":"object","description":"Website this test flow belongs to","nullable":true},"notification_settings":{"type":"object","description":"Per-flow notification settings","nullable":true},"preview_test":{"type":"object","description":"Preview/initialization test","nullable":true},"plugin":{"type":"object","description":"Form plugin info (for form-type test flows). The id field is the plugin slug.","nullable":true},"video_screenshot_url":{"type":"object","description":"GCS signed URL for latest test screenshot","nullable":true}},"required":["id","name","type","parameters","org_id","website_id","status","paused","device_type","honor_robot_rules","disable_actions","status_dismissed","generate_steps","bulk_generation_locked","created_at","updated_at","steps"]},"NotificationSettingsInputDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable notifications","example":true},"email_addresses":{"description":"Email addresses for notifications","example":["user@example.com"],"type":"array","items":{"type":"string"}}}},"TimingSettingsInputDto":{"type":"object","properties":{"stepDelay":{"type":"number","description":"Delay between steps in seconds (0-10)","example":1},"elementTimeout":{"type":"number","description":"Element wait timeout in seconds (0-30)","example":20},"typingMethod":{"type":"string","description":"Typing method","enum":["fill","sequential"],"example":"fill"}}},"BrowserSettingsInputDto":{"type":"object","properties":{"customUserAgent":{"type":"string","description":"Custom user agent string","example":"Mozilla/5.0 Custom Agent"}}},"UpdateTestFlowDto":{"type":"object","properties":{"name":{"type":"string","description":"Test flow name","example":"Updated Form Submission"},"parameters":{"type":"object","description":"Test flow parameters"},"paused":{"type":"boolean","description":"Is test flow paused","example":true},"reason_paused":{"type":"string","description":"Reason paused","enum":["user","subscription_canceled"]},"device_type":{"type":"string","description":"Device type","enum":["inherit","desktop","mobile"],"example":"desktop"},"device":{"type":"object","description":"Device configuration"},"status_dismissed":{"type":"boolean","description":"Status dismissed","example":true},"notification_settings":{"description":"Notification settings","allOf":[{"$ref":"#/components/schemas/NotificationSettingsInputDto"}]},"timing_settings":{"description":"Timing settings. stepDelay and elementTimeout are stored in parameters JSON; typingMethod is stored as a separate column.","example":{"stepDelay":1,"elementTimeout":20,"typingMethod":"fill"},"allOf":[{"$ref":"#/components/schemas/TimingSettingsInputDto"}]},"browser_settings":{"description":"Browser settings. customUserAgent is stored at parameters.customUserAgent.","example":{"customUserAgent":"Mozilla/5.0 Custom Agent"},"allOf":[{"$ref":"#/components/schemas/BrowserSettingsInputDto"}]},"honor_robot_rules":{"type":"string","description":"Honor robot rules setting (inherit, always, never)","example":"inherit"},"disable_actions":{"type":"string","description":"Disable form integrations during tests when possible (inherit, yes, no)","example":"inherit"},"cookies":{"type":"array","description":"Custom cookies to set before test execution. Stored as customCookies in parameters.","items":{"type":"object","properties":{"name":{"type":"string","description":"Cookie name"},"value":{"type":"string","description":"Cookie value"}}},"example":[{"name":"session_id","value":"abc123"}]},"auto_click_selector":{"type":"string","description":"CSS selector for an element to auto-click before test execution (e.g., cookie consent button)","example":"#accept-cookies"},"modal_selector":{"type":"string","description":"CSS selector for a modal to dismiss before test execution","example":".popup-overlay .close-btn"}}},"OneTimeCredentialsDto":{"type":"object","properties":{"username":{"type":"string","description":"Username for one-time login","example":"testuser"},"password":{"type":"string","description":"Password for one-time login"}},"required":["username","password"]},"CreateTestFlowExecutionDto":{"type":"object","properties":{"trigger":{"type":"string","description":"Trigger type","example":"manual","enum":["manual","scheduled","api"]},"parameters":{"type":"object","description":"Additional execution parameters"},"credentials":{"description":"One-time credentials for this test run only. Encrypted at rest, auto-deleted after 5 minutes.","allOf":[{"$ref":"#/components/schemas/OneTimeCredentialsDto"}]}}},"TestFlowExecutionDto":{"type":"object","properties":{"id":{"type":"string","description":"Execution/Test ID","format":"uuid"},"test_flow_id":{"type":"string","description":"Test flow ID","format":"uuid"},"website_id":{"type":"object","description":"Website ID","format":"uuid","nullable":true},"status":{"type":"string","description":"Execution status","example":"created"},"trigger":{"type":"string","description":"Trigger type","example":"manual"},"created_at":{"type":"string","description":"Created at timestamp"},"started_at":{"type":"string","description":"Started at timestamp","nullable":true},"ended_at":{"type":"string","description":"Ended at timestamp","nullable":true},"video_url":{"type":"string","description":"Video URL","nullable":true},"har_url":{"type":"string","description":"HAR file URL","nullable":true}},"required":["id","test_flow_id","website_id","status","trigger","created_at"]},"CreateTestFlowInitializationDto":{"type":"object","properties":{"reset":{"type":"boolean","description":"Reset existing initialization","example":false},"use_as_is":{"type":"boolean","description":"Skip full initialization","example":false},"retry":{"type":"boolean","description":"Retry failed initialization","example":false}}},"TestFlowInitializationDto":{"type":"object","properties":{"id":{"type":"string","description":"Initialization ID","format":"uuid"},"test_flow_id":{"type":"string","description":"Test flow ID","format":"uuid"},"status":{"type":"string","description":"Initialization status"},"gcp_job_uid":{"type":"string","description":"GCP job UID","nullable":true},"gcp_job_name":{"type":"string","description":"GCP job name","nullable":true},"gcp_job_logs_uri":{"type":"string","description":"GCP job logs URI","nullable":true},"created_at":{"type":"string","description":"Created at timestamp"},"completed_at":{"type":"string","description":"Completed at timestamp","nullable":true}},"required":["id","test_flow_id","status","created_at"]},"UpdateTestFlowInitializationDto":{"type":"object","properties":{"status":{"type":"string","description":"Initialization status","enum":["initializing","completed","failed","aborted"]}}},"CreateTestFlowStepDto":{"type":"object","properties":{"type":{"type":"string","description":"Step type","example":"click"},"metadata":{"type":"object","description":"Step metadata","example":{"selector":"#submit-button"}},"index":{"type":"number","description":"Step index/order","example":0},"optional":{"type":"boolean","description":"Is step optional","example":false},"notes":{"type":"object","description":"Step notes/comments","nullable":true}},"required":["type","metadata","index","optional"]},"UpdateTestFlowStepsDto":{"type":"object","properties":{"steps":{"description":"Test flow steps","type":"array","items":{"$ref":"#/components/schemas/CreateTestFlowStepDto"}}},"required":["steps"]},"UpdateTestFlowScheduleDto":{"type":"object","properties":{"days":{"description":"Days to run: 0-7 for weekly (0/7=Sunday, 1=Monday, 6=Saturday), -28 to -1 for monthly (day of month)","example":[1,2,3,4,5],"type":"array","items":{"type":"number"}},"time":{"type":"string","description":"Time to run (HH:mm:ss)","example":"09:00:00"},"timezone":{"type":"string","description":"Timezone","example":"America/New_York"}},"required":["days","time","timezone"]},"InitFileUploadResponseDto":{"type":"object","properties":{"file_id":{"type":"string","description":"File ID","format":"uuid"},"file_url":{"type":"string","description":"File URL"},"message":{"type":"string","description":"Success message"}},"required":["file_id","file_url","message"]},"TriggerAiGenerateDto":{"type":"object","properties":{"url":{"type":"string","description":"URL to analyze for AI-powered test step generation. Required.","example":"https://example.com/contact"},"testType":{"type":"string","description":"Test type","enum":["form","login","search","membership","ecommerce","lms","other"],"default":"form"},"userContext":{"type":"object","description":"User context for generation (e.g., sample form data)","example":{"firstName":"John","email":"test@example.com"}}}},"AiGenerateResponseDto":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"AI generation started"},"gcpLogsUri":{"type":"string","description":"GCP logs URI for debugging"}},"required":["success","message"]},"AiGenerateStatusDto":{"type":"object","properties":{"status":{"type":"string","description":"Generation status","enum":["processing","complete","failed"],"example":"processing"},"message":{"type":"string","description":"Progress message","example":"Analyzing form structure..."},"currentStep":{"type":"string","description":"Current generation step (when processing)","example":"analyzing_ai"},"error":{"type":"string","description":"Error message (when failed)"},"steps":{"type":"array","description":"Generated steps (when complete)","items":{"type":"object","properties":{"type":{"type":"string"},"optional":{"type":"boolean"},"metadata":{"type":"object"}}}}},"required":["status","message"]},"InitScreenshotUploadResponseDto":{"type":"object","properties":{"screenshot_id":{"type":"string","description":"Screenshot ID","format":"uuid"},"screenshot_url":{"type":"string","description":"Screenshot URL"},"message":{"type":"string","description":"Success message"}},"required":["screenshot_id","screenshot_url","message"]},"AiSuggestedActionDto":{"type":"object","properties":{"text":{"type":"string","description":"Action text","example":"Try increasing Element Timeout in Test Flow Settings"},"helpUrl":{"type":"object","description":"Help URL","example":"https://checkview.io/docs/settings"}},"required":["text"]},"AiSummaryDto":{"type":"object","properties":{"summary":{"type":"string","description":"One-sentence summary of the test result"},"observedBehavior":{"description":"Factual observations about what happened","type":"array","items":{"type":"string"}},"possibleCause":{"type":"object","description":"Possible root cause explanation"},"suggestedActions":{"description":"Suggested actions to resolve the issue","type":"array","items":{"$ref":"#/components/schemas/AiSuggestedActionDto"}},"lowConfidence":{"type":"boolean","description":"Whether the AI had low confidence in the analysis"},"lowConfidenceReason":{"type":"object","description":"Reason for low confidence"}},"required":["summary","observedBehavior"]},"AiSummaryResponseDto":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether an AI summary is available"},"summary":{"description":"AI summary data (null if not yet generated)","allOf":[{"$ref":"#/components/schemas/AiSummaryDto"}]},"cached":{"type":"boolean","description":"Whether the summary was served from cache"},"message":{"type":"string","description":"Message when summary is not available"}},"required":["available"]},"TestRunDto":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"created_at":{"type":"string","description":"Creation timestamp"},"status":{"type":"string","description":"Test run status","enum":["created","started","success","error","awaiting_email","aborted","pending_abort"]},"kubernetes_job_id":{"type":"string","description":"Kubernetes job ID","nullable":true},"ended_at":{"type":"string","description":"Test end timestamp","nullable":true},"started_at":{"type":"string","description":"Test start timestamp","nullable":true},"video_url":{"type":"string","description":"Video URL","nullable":true},"website_id":{"type":"string","description":"Website ID"},"org_id":{"type":"string","description":"Organization ID"},"trigger":{"type":"string","description":"Test trigger","enum":["manual","automatic","api","scheduled","test_flow_init"]},"test_flow_id":{"type":"string","description":"Test flow ID"},"website":{"type":"object","description":"Website data"},"test_flow":{"type":"object","description":"Test flow data"},"comments":{"type":"number","description":"Number of comments","example":0}},"required":["id","created_at","status","kubernetes_job_id","ended_at","started_at","video_url","website_id","org_id","trigger","test_flow_id","website","test_flow","comments"]},"GetTestRunsResponseDto":{"type":"object","properties":{"page_count":{"type":"number","description":"Total number of pages"},"count":{"type":"number","description":"Number of results in current page"},"data":{"description":"Test runs","type":"array","items":{"$ref":"#/components/schemas/TestRunDto"}}},"required":["page_count","count","data"]},"TestRunMetricsDto":{"type":"object","properties":{"date_range":{"type":"object","description":"Date range covered"},"overall":{"type":"object","description":"Overall statistics"},"time_series":{"description":"Time series data","type":"array","items":{"type":"object"}},"by_website":{"description":"Breakdown by website","type":"array","items":{"type":"object"}},"by_type":{"description":"Breakdown by test type","type":"array","items":{"type":"object"}}},"required":["date_range","overall","time_series","by_website","by_type"]},"TestRunDetailDto":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"created_at":{"type":"string","description":"Creation timestamp"},"status":{"type":"string","description":"Test run status","enum":["created","started","success","error","awaiting_email","aborted","pending_abort"]},"kubernetes_job_id":{"type":"string","description":"Kubernetes job ID","nullable":true},"ended_at":{"type":"string","description":"Test end timestamp","nullable":true},"started_at":{"type":"string","description":"Test start timestamp","nullable":true},"video_url":{"type":"string","description":"Video URL","nullable":true},"website_id":{"type":"string","description":"Website ID"},"org_id":{"type":"string","description":"Organization ID"},"trigger":{"type":"string","description":"Test trigger","enum":["manual","automatic","api","scheduled","test_flow_init"]},"test_flow_id":{"type":"string","description":"Test flow ID"},"website":{"type":"object","description":"Website data"},"test_flow":{"type":"object","description":"Test flow data"},"comments":{"type":"number","description":"Number of comments","example":0},"har_url":{"type":"string","description":"HAR file URL","nullable":true},"gcp_job_uid":{"type":"string","description":"GCP job UID","nullable":true},"gcp_job_logs_uri":{"type":"string","description":"GCP job logs URI","nullable":true},"device":{"type":"object","description":"Device information","nullable":true},"gcp_job_name":{"type":"string","description":"GCP job name","nullable":true},"retry_count":{"type":"number","description":"Retry count","example":0},"blocker":{"type":"object","description":"Blocker plugin slug that prevented test execution","nullable":true},"blocker_message":{"type":"object","description":"Human-readable blocker description","nullable":true},"steps":{"description":"Test steps","type":"array","items":{"type":"object"}}},"required":["id","created_at","status","kubernetes_job_id","ended_at","started_at","video_url","website_id","org_id","trigger","test_flow_id","website","test_flow","comments","har_url","gcp_job_uid","gcp_job_logs_uri","device","gcp_job_name","retry_count","steps"]},"UpdateTestRunDto":{"type":"object","properties":{"status":{"type":"string","description":"Update test run status (e.g., \"aborted\" to stop execution)","enum":["aborted"],"example":"aborted"}}},"AbortTestRunResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Success status"},"message":{"type":"string","description":"Response message"}},"required":["success","message"]},"MediaUrlResponseDto":{"type":"object","properties":{"url":{"type":"string","description":"Signed URL for media access"},"expires_in":{"type":"number","description":"URL expiration time (in seconds)","example":3600}},"required":["url","expires_in"]},"HarContentResponseDto":{"type":"object","properties":{"data":{"type":"object","description":"HAR file content as JSON object"}},"required":["data"]},"ScreenshotContentResponseDto":{"type":"object","properties":{"data":{"type":"string","description":"Base64-encoded screenshot data"},"content_type":{"type":"string","description":"Content type of the screenshot","example":"image/png"}},"required":["data","content_type"]},"ConsoleLogDto":{"type":"object","properties":{"id":{"type":"string","description":"Log ID"},"message":{"type":"string","description":"Log message"},"type":{"type":"string","description":"Log type (log, error, warn, info)"},"created_at":{"type":"string","description":"Timestamp"}},"required":["id","message","type","created_at"]},"NetworkLogDto":{"type":"object","properties":{"id":{"type":"string","description":"Log ID"},"method":{"type":"string","description":"HTTP method"},"url":{"type":"string","description":"Request URL"},"status":{"type":"number","description":"HTTP status code","nullable":true},"content_type":{"type":"string","description":"Content type","nullable":true},"request_time":{"type":"string","description":"Request timestamp"},"response_time":{"type":"string","description":"Response timestamp"}},"required":["id","method","url","status","content_type","request_time","response_time"]},"TestCommentDto":{"type":"object","properties":{"id":{"type":"string","description":"Comment ID"},"comment":{"type":"string","description":"Comment text"},"user_id":{"type":"string","description":"User ID"},"user_profile":{"type":"object","description":"User profile"},"created_at":{"type":"string","description":"Creation timestamp"}},"required":["id","comment","user_id","user_profile","created_at"]},"CreateTestCommentDto":{"type":"object","properties":{"comment":{"type":"string","description":"Comment text","minLength":1,"maxLength":500}},"required":["comment"]},"BulkUpdateTestRunDto":{"type":"object","properties":{"ids":{"description":"Test run IDs to update","minItems":1,"maxItems":50,"example":["uuid-1","uuid-2","uuid-3"],"type":"array","items":{"type":"string"}},"status":{"type":"string","description":"Status to set for all test runs (currently only \"aborted\" supported)","enum":["aborted"],"example":"aborted"}},"required":["ids","status"]},"BulkAbortResponseDto":{"type":"object","properties":{"aborted_count":{"type":"number","description":"Number of tests successfully aborted","example":5},"failed_count":{"type":"number","description":"Number of tests that failed to abort","example":0},"aborted_ids":{"description":"Successfully aborted test run IDs","type":"array","items":{"type":"string"}},"failed_ids":{"type":"object","description":"Failed test run IDs with reasons"},"message":{"type":"string","description":"Success message"}},"required":["aborted_count","failed_count","aborted_ids","failed_ids","message"]},"CompareTestRunsDto":{"type":"object","properties":{"test_run_ids":{"description":"Test run IDs to compare (2-5 IDs)","minItems":2,"maxItems":5,"example":["uuid-1","uuid-2","uuid-3"],"type":"array","items":{"type":"string"}}},"required":["test_run_ids"]},"TestRunComparisonDto":{"type":"object","properties":{"test_run_ids":{"description":"Test run IDs being compared","type":"array","items":{"type":"string"}},"runs":{"description":"Comparison data","type":"array","items":{"type":"object"}},"differences":{"type":"object","description":"Differences highlighted"}},"required":["test_run_ids","runs","differences"]},"UxAuditDto":{"type":"object","properties":{"id":{"type":"string","description":"Audit ID","format":"uuid"},"name":{"type":"string","description":"Audit name"},"status":{"type":"string","description":"Audit status","enum":["pending","processing","ready","error"]},"created_at":{"type":"string","description":"Created at timestamp"},"completed_at":{"type":"object","description":"Completed at timestamp","nullable":true},"test_flow_ids":{"description":"Test flow IDs included in audit","type":"array","items":{"type":"string"}},"error_message":{"type":"object","description":"Error message (if failed)","nullable":true}},"required":["id","name","status","created_at","test_flow_ids"]},"UxAuditListResponseDto":{"type":"object","properties":{"data":{"description":"Audit list","type":"array","items":{"$ref":"#/components/schemas/UxAuditDto"}},"count":{"type":"number","description":"Total count","example":25},"page_count":{"type":"number","description":"Total pages","example":3}},"required":["data","count","page_count"]},"CreateUxAuditDto":{"type":"object","properties":{"name":{"type":"string","description":"Audit name","example":"Homepage UX Audit"},"testFlowIds":{"description":"Test flow IDs to include in the audit (1-20)","example":["uuid-1","uuid-2"],"type":"array","items":{"type":"string"}}},"required":["name","testFlowIds"]},"UxAuditDetailDto":{"type":"object","properties":{"id":{"type":"string","description":"Audit ID","format":"uuid"},"name":{"type":"string","description":"Audit name"},"status":{"type":"string","description":"Audit status","enum":["pending","processing","ready","error"]},"created_at":{"type":"string","description":"Created at timestamp"},"completed_at":{"type":"object","description":"Completed at timestamp","nullable":true},"test_flow_ids":{"description":"Test flow IDs included in audit","type":"array","items":{"type":"string"}},"error_message":{"type":"object","description":"Error message (if failed)","nullable":true},"org_id":{"type":"string","description":"Organization ID","format":"uuid"},"website_id":{"type":"string","description":"Website ID","format":"uuid"},"report_html_url":{"type":"object","description":"Report HTML URL","nullable":true},"gcp_job_uid":{"type":"object","description":"GCP job UID","nullable":true},"gcp_job_name":{"type":"object","description":"GCP job name","nullable":true},"gcp_job_logs_uri":{"type":"object","description":"GCP job logs URI","nullable":true},"started_at":{"type":"object","description":"Started at timestamp","nullable":true},"updated_at":{"type":"string","description":"Updated at timestamp"},"website":{"type":"object","description":"Website info","properties":{"name":{"type":"string"},"url":{"type":"string"}}}},"required":["id","name","status","created_at","test_flow_ids","org_id","website_id"]},"UxAuditReportDto":{"type":"object","properties":{"status":{"type":"string","description":"Audit status","enum":["pending","processing","ready","error"]},"message":{"type":"string","description":"Status message"},"report_data":{"type":"object","description":"Structured report data (JSON)"},"error":{"type":"object","description":"Error message (if failed)"}},"required":["status"]},"PlanDto":{"type":"object","properties":{"id":{"type":"string","description":"Plan ID","example":"uuid-string"},"name":{"type":"string","description":"Plan display name","example":"Professional"},"alias":{"type":"string","description":"Plan alias (identifier)","example":"professional"},"monthly_price":{"type":"string","description":"Monthly price in dollars","example":"29.00"},"yearly_price":{"type":"string","description":"Yearly price in dollars","example":"290.00"},"short_description":{"type":"string","description":"Short description of the plan"},"monthly_test_limit":{"type":"number","description":"Monthly test execution limit","example":500},"monthly_audit_limit":{"type":"number","description":"Monthly UX audit limit","example":10},"max_users":{"type":"number","description":"Maximum team members","example":5},"test_retention_days":{"type":"number","description":"Test data retention period in days","example":90},"index":{"type":"number","description":"Display order index","example":1},"tier":{"type":"number","description":"Plan tier level","example":2},"can_create_woo_test_flows":{"type":"boolean","description":"Can create WooCommerce test flows"},"can_edit_global_variables":{"type":"boolean","description":"Can edit global variables"},"can_use_reports":{"type":"object","description":"Can use email reports"},"plan_features":{"type":"object","description":"Comma-separated feature list"}},"required":["id","name","alias","monthly_price","yearly_price","monthly_test_limit","monthly_audit_limit","max_users","test_retention_days","index","tier","can_create_woo_test_flows","can_edit_global_variables"]},"ProblemDetailsDto":{"type":"object","properties":{"type":{"type":"string","description":"A URI reference that identifies the problem type","example":"https://api.checkview.io/errors/validation-failed"},"title":{"type":"string","description":"A short, human-readable summary of the problem type","example":"Validation Failed"},"status":{"type":"number","description":"The HTTP status code","example":400},"detail":{"type":"string","description":"A human-readable explanation specific to this occurrence","example":"The request body contains invalid data"},"instance":{"type":"string","description":"A URI reference that identifies the specific occurrence","example":"/organizations/123"},"extensions":{"type":"object","description":"Additional details about the error","example":{"validation_errors":[{"field":"name","message":"Name is required","code":"required"}]}}},"required":["type","title","status","detail","instance"]},"RoleDto":{"type":"object","properties":{"id":{"type":"string","description":"Role ID","example":"admin"},"name":{"type":"string","description":"Role display name","example":"Administrator"},"index":{"type":"number","description":"Display order index","example":1},"description":{"type":"object","description":"Role description"}},"required":["id","name","index"]}}}}