{"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), or the request was made with a personal access 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":[]}]},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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 (admin only, like every field here: the route requires the write:organization scope)\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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist. Also returned for invalid input, when the helper plugin is not installed or the site cannot be reached, or when the site URL the plugin reports fails these checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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"}}}},"502":{"description":"Could not resolve the host to check it. Try again.","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 the websites in the organization that the caller can access. Collaborators limited to specific websites see only those.","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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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":"Could not resolve the host to check it. Try again.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist. Checked only when `url` changes or `type` converts the site to WordPress. Also returned for invalid input (including `type: non_wordpress`), or when the helper plugin is not installed or the site cannot be reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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"}}}},"502":{"description":"Could not resolve the host to check it. Try again.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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":"Counts of this website's tests since the run-all started (or since the `since` time you pass). Poll until pending and running are both 0 and passed + failed + awaiting reaches `expected`. The lock is cleared only by the website that holds it; a status for another website reports `lock_website_id` and leaves it alone.","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"since","required":false,"in":"query","description":"Only count this website's tests created at or after this time (ISO 8601, within the last 24 hours). Pass the triggered_at from the run-all response. Defaults to when this website's run-all started, or the last hour.","schema":{"example":"2026-02-18T15:30:00.000Z","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}}}},"400":{"description":"since is not an ISO 8601 time within the last 24 hours"},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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 an organization's monthly test limit. CheckView staff only: the limit otherwise comes from the plan.","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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 - CheckView staff only"},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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/disable-actions":{"get":{"operationId":"SettingsController_getDisableActions","summary":"Get disable-actions setting","description":"Get the organization default for \"Disable Form Integrations During Tests When Possible\", used by test flows set to inherit","parameters":[],"responses":{"200":{"description":"Disable-actions setting retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableActionsSettingsDto"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute 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_updateDisableActions","summary":"Update disable-actions setting","description":"Set the organization default for \"Disable Form Integrations During Tests When Possible\" (admin only)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key for safe retries, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableActionsSettingsDto"}}}},"responses":{"204":{"description":"Disable-actions 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}}}},"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/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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"403":{"description":"Subscription is not active or trialing (extensions.subscription_status)"},"429":{"description":"Invitation email limit reached (type https://api.checkview.io/errors/invite-email-limit, no Retry-After header; extensions.scope, and extensions.retry_after in seconds when known), or the per-minute API rate limit","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute 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}}}}},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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). The token from the invitation email's link may be sent along; when it is, it must belong to this 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new key.","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,255}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInvitationDto"}}}},"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}}}},"403":{"description":"Personal access tokens cannot accept invitations, or the organization's subscription is inactive or full"},"404":{"description":"No pending invitation for your email with this ID, or the token sent does not belong to it"},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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"}}}},"502":{"description":"Could not resolve the host to check it. Try again.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist. Checked on the pageUrl, startingUrl, productUrl, cartUrl and checkoutUrl parameters. Also returned for invalid input, or a form, page or product not found on the site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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"}}}},"502":{"description":"Could not resolve the host to check it. Try again. Also returned when the WordPress site could not be reached to validate the flow.","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.). Field names are snake_case (for example disable_actions); a camelCase spelling of a known field is rejected with 400.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist. Checked only on URL parameters that change. Also returned for invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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"}}}},"502":{"description":"Could not resolve the host to check it. Try again.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"The flow is not in a state this mode accepts (reset, use_as_is or retry)"},"404":{"description":"Test flow not found"},"409":{"description":"A setup is already running for this flow"},"429":{"description":"Refused: the flow's setup has been started 5 times in the last 24 hours","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per minute","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 1-minute 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}}}}},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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}}}},"400":{"description":"A URL failed the safety checks: invalid URL, protocol other than http or https, embedded credentials, a private or internal address, or a domain that does not exist. Checked on goto step URLs that change. A goto URL that uses a variable must be only that variable, optionally followed by a ?query (for example {{TEST_FLOW_PAGE_URL}}?x=1). Also returned for invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetailsDto"}}}},"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":"Could not resolve the host to check it. Try again.","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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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"}}}},"502":{"description":"Storage delete failed; safe to retry"}},"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: requires `merge: true` and reuses the saved URL. Use `merge: true` for edit-and-rebuild workflows (omitted fields preserve saved values; `userContext` shallow-merges). Idempotency: dropped — the service uses an atomic status claim (409 on the second click) instead of an idempotency-key cache. PAT consumers retrying a timed-out POST will receive 409 (treat as 'first call probably succeeded').","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}}],"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, validation error, or login-type with clearCredentials"},"409":{"description":"Test flow not found, not in a re-generatable state, or another generation is 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"}}}},"502":{"description":"Pub/Sub publish or credential delete failed after atomic claim"}},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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"}}}},"502":{"description":"Storage delete failed; safe to retry"}},"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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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, scoped to your organization and user. A successful response is replayed for 60 minutes to any request with the same key (the body is not compared), with the header `X-Idempotency-Replay: true`. Errors are never replayed. A request rejected with a 4xx error by the endpoint, or with an error that is safe to retry (for example a 502 when a URL or the WordPress site could not be checked), releases its key, so a retry with the same key runs immediately. A 403 because the token lacks a required scope or role keeps the key in progress for up to 2 minutes, as do other failures such as a 500: a retry in that window gets 409 Request In Progress; after it the key is reclaimed. To retry at once after such a failure, use a new 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"}}}},"502":{"description":"Failed to start audit generation"}},"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\n## Request Bodies\n\nA JSON body nested more than 64 levels deep is rejected on any endpoint with **400 Bad Request** and the detail `Request body is nested too deeply`.\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":"Non-empty array of at most 8 integers. Either weekly days only (0-7, where 0 and 7 are Sunday, 1=Monday, 6=Saturday), or exactly one monthly day as a negative number (-28 to -1, e.g. -15 = the 15th of every month). Mixing weekly and monthly days, or passing more than one monthly day, is rejected with 400.","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},"allow_original_recipients":{"type":"boolean","description":"Default for allow_original_recipients on test flows in this org. When true, form-submission emails during tests are delivered to the original form recipients in addition to the CheckView test inbox.","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","allow_original_recipients","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":"Non-empty array of at most 8 integers. Either weekly days only (0-7, where 0 and 7 are Sunday, 1=Monday, 6=Saturday), or exactly one monthly day as a negative number (-28 to -1, e.g. -15 = the 15th of every month). Mixing weekly and monthly days, or passing more than one monthly day, is rejected with 400.","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"]},"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"]},"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"},"type":{"type":"string","description":"Set to `wordpress` to convert a non-WordPress site once the CheckView plugin is installed on it. The plugin is checked first, as on create. Converting a WordPress site to `non_wordpress` is not supported.","enum":["wordpress"],"example":"wordpress"}}},"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 the organization's run-all lock is set. Run-alls are one website at a time per organization."},"lock_website_id":{"type":"object","example":"f0a2b2d4-7e5a-4b7e-9d33-9a1f0f6e1c22","nullable":true,"description":"The website whose run-all holds the lock, or null when no lock is set or the batch was started from the CheckView dashboard for the whole organization."},"expected":{"type":"object","example":9,"nullable":true,"description":"How many tests this website's run-all started, while this website holds the lock (also on the response that clears it); null otherwise."},"pending":{"type":"number","example":0,"description":"Tests queued but not started"},"running":{"type":"number","example":0,"description":"Tests currently executing"},"awaiting":{"type":"number","example":0,"description":"Tests finished and waiting for an email to arrive"},"passed":{"type":"number","example":3,"description":"Tests completed successfully"},"failed":{"type":"number","example":0,"description":"Tests that failed"}},"required":["locked","lock_website_id","expected","pending","running","awaiting","passed","failed"]},"ScheduleSettingsDto":{"type":"object","properties":{"time":{"type":"string","description":"Default test schedule time (HH:mm:ss)","example":"09:00:00"},"days":{"description":"Non-empty array of at most 8 integers. Either weekly days only (0-7, where 0 and 7 are Sunday, 1=Monday, 6=Saturday), or exactly one monthly day as a negative number (-28 to -1, e.g. -15 = the 15th of every month). Mixing weekly and monthly days, or passing more than one monthly day, is rejected with 400.","example":[0,1,2,3,4,5,6],"type":"array","items":{"type":"number"}},"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"]},"DisableActionsSettingsDto":{"type":"object","properties":{"disableActions":{"type":"boolean","description":"Whether test flows that inherit this setting suppress supported form add-on and store integrations (webhooks, CRM, email marketing, shipping) during tests when possible","example":true}},"required":["disableActions"]},"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. When demoting to collaborator, pass websites to restrict access, or omit them to keep access to all websites","example":"collaborator","enum":["admin","collaborator"]},"allowAccessToAllWebsites":{"type":"boolean","description":"Whether the member can access all websites. Setting false requires websites","example":true},"websites":{"description":"Website IDs to grant access to","type":"array","items":{"type":"string"}},"active":{"type":"boolean","description":"Not supported: a member's active status follows the organization's plan and subscription. Sending it returns 400.","deprecated":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"}}}},"AcceptInvitationDto":{"type":"object","properties":{"token":{"type":"string","description":"The token from the invitation email's link (the part after #token=). Optional; when sent it must belong to this invitation.","example":"k3b1Z0mX8qQ2vJdR7tN5wLcY9pH4sF6aG1uE2iO0rT8"}}},"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","maxLength":4000},"name":{"type":"string","description":"Test flow name (defaults to URL hostname)","example":"Contact Form Test","maxLength":255},"testType":{"type":"string","description":"Test type","enum":["form","login","search","membership","ecommerce","lms","other"],"default":"form"},"userContext":{"type":"object","description":"User context for generation. At most 50 keys, each value at most 2000 characters.","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"},"allow_original_recipients":{"type":"string","description":"Allow form-submission emails to reach original recipients during tests (in addition to the test inbox)"},"prefers_reduced_motion":{"type":"boolean","description":"Emulate prefers-reduced-motion during tests","example":false},"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 the element that opens the modal containing the form. Step generation clicks it after the page loads. It does not close popups; use auto_click_selector for that","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","allow_original_recipients","prefers_reduced_motion","status_dismissed","generate_steps","bulk_generation_locked","created_at","updated_at"]},"ScheduleInputDto":{"type":"object","properties":{"days":{"description":"Non-empty array of at most 8 integers. Either weekly days only (0-7, where 0 and 7 are Sunday, 1=Monday, 6=Saturday), or exactly one monthly day as a negative number (-28 to -1, e.g. -15 = the 15th of every month). Mixing weekly and monthly days, or passing more than one monthly day, is rejected with 400.","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"},"allowOriginalRecipients":{"type":"string","description":"Allow form-submission emails to reach original recipients during tests (in addition to the test inbox)","enum":["yes","no","inherit"],"example":"inherit"},"prefersReducedMotion":{"type":"boolean","description":"Emulate prefers-reduced-motion so sites skip animations during tests (default false)","example":false},"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"},"allow_original_recipients":{"type":"string","description":"Allow form-submission emails to reach original recipients during tests (in addition to the test inbox)"},"prefers_reduced_motion":{"type":"boolean","description":"Emulate prefers-reduced-motion during tests","example":false},"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 the element that opens the modal containing the form. Step generation clicks it after the page loads. It does not close popups; use auto_click_selector for that","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},"hasStoredCredentials":{"type":"boolean","description":"True when an encrypted credentials row exists in `test_flow_credentials` for this flow. Used by the rebuild modal to decide whether to allow blank credential inputs (`leave blank to keep saved password` UX). Never exposes the credential values themselves.","default":false}},"required":["id","name","type","parameters","org_id","website_id","status","paused","device_type","honor_robot_rules","disable_actions","allow_original_recipients","prefers_reduced_motion","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"},"prefersReducedMotion":{"type":"boolean","description":"Emulate prefers-reduced-motion so sites skip animations during tests","example":true}}},"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"},"allow_original_recipients":{"type":"string","description":"Allow form-submission emails to reach original recipients during tests (in addition to the test inbox) (inherit, yes, no)","example":"inherit"},"prefers_reduced_motion":{"type":"boolean","description":"Emulate prefers-reduced-motion during tests. Takes precedence over browser_settings.prefersReducedMotion.","example":true},"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 the element that opens the modal containing the form. Step generation clicks it after the page loads. It does not close popups; use auto_click_selector for that","example":"#open-contact-form"}}},"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":"Non-empty array of at most 8 integers. Either weekly days only (0-7, where 0 and 7 are Sunday, 1=Monday, 6=Saturday), or exactly one monthly day as a negative number (-28 to -1, e.g. -15 = the 15th of every month). Mixing weekly and monthly days, or passing more than one monthly day, is rejected with 400.","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 when no saved `mcpCustomUrl` exists; with `merge: true` (or replace-mode without `url`), falls back to the saved URL.","example":"https://example.com/contact","maxLength":4000},"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). At most 50 keys, each value at most 2000 characters.","example":{"firstName":"John","email":"test@example.com"}},"merge":{"type":"boolean","description":"Merge mode (default `false` = replace, preserves existing PAT behavior). When `true`, omitted fields preserve their saved values, and `userContext` is shallow-merged with the saved context. Use `merge: true` for edit-and-rebuild workflows. In merge mode the `userContext` allowlist is enforced (`prompt`, `message`, `username`, `password` only); empty string for `prompt`/`message` clears the saved value, and empty string for `username`/`password` preserves the saved value (use a non-empty value to replace). Each value max 2000 chars; aggregate `userContext` max 8000 chars.","default":false},"clearCredentials":{"type":"boolean","description":"When `true` (and `merge: true`), explicitly delete the saved `test_flow_credentials` row before triggering generation. Used by the rebuild modal when the user toggles login OFF on a flow with saved credentials. Rejected with 400 when the effective `mcpTestType` resolves to `login` (a login-type flow without credentials cannot generate steps). Sequencing: status atomic claim runs first; only on claim success does the credential delete run; on delete failure the route returns 502 and does NOT publish to Pub/Sub.","default":false}}},"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"]},"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"]}}}}