{"openapi":"3.1.0","info":{"title":"PricklyMails API","description":"Email verification API: submit single or bulk verification jobs, poll results, and manage API keys, webhooks, and billing.","contact":{"email":"support@pricklymails.com"},"license":{"name":"Proprietary"},"version":"0.9.0"},"paths":{"/.well-known/oauth-authorization-server":{"get":{"tags":["oauth"],"summary":"Returns the OAuth 2.1 authorization server metadata (RFC 8414).","operationId":"authorization_server_metadata","responses":{"200":{"description":"Authorization server metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadataResponse"}}}}}}},"/api/agents":{"get":{"tags":["agents"],"summary":"Lists the agents of the authenticated account, newest first, paginated.","operationId":"list_agents","parameters":[{"name":"limit","in":"query","description":"Number of agents to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of agents to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated agent list, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAgentsResponse"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]},"post":{"tags":["agents"],"summary":"Creates an agent for the authenticated account, with its own granted scopes.","operationId":"create_agent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentRequest"}}},"required":true},"responses":{"201":{"description":"Agent created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCreatedResponse"}}}},"400":{"description":"Invalid name or scopes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The plan's agent cap was reached, or a requested scope is not allowed for the caller's plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/agents/{uuid}":{"get":{"tags":["agents"],"summary":"Returns one agent of the authenticated account.","operationId":"get_agent","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the agent.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The requested agent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No agent with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]},"delete":{"tags":["agents"],"summary":"Revokes an agent so it can no longer authenticate.","operationId":"revoke_agent","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the agent.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The revoked agent (idempotent on repeat calls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No agent with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/auth/2fa/verify":{"post":{"tags":["auth"],"summary":"Completes a sign-in that requires two-factor authentication.","operationId":"verify_2fa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verify2FARequest"}}},"required":true},"responses":{"200":{"description":"2FA verified; authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Temp token invalid, or the TOTP/backup code is wrong.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Too many failed 2FA attempts; temporarily locked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/confirm":{"post":{"tags":["auth"],"summary":"Confirms an account with the six-digit code mailed at signup, and signs it in.","operationId":"confirm","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmAccountRequest"}}},"required":true},"responses":{"200":{"description":"Email address confirmed; authenticated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmAccountResponse"}}}},"401":{"description":"The code does not confirm an account (`confirm_account.invalid_code`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/forgot-password":{"post":{"tags":["auth"],"summary":"Requests a password reset email.","operationId":"forgot_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"204":{"description":"Reset email sent if the address is registered. Same response whether or not the account exists."},"400":{"description":"Malformed email address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/login":{"post":{"tags":["auth"],"operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Authenticated, or a 2FA challenge requiring a follow-up call to `/api/auth/2fa/verify`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"401":{"description":"Invalid credentials, banned account, or deleted account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Correct password, but the account's email is not confirmed yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Account temporarily locked after repeated failed attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/logout":{"post":{"tags":["auth"],"summary":"Signs out by revoking the refresh token in the `prickly_refresh` cookie.","operationId":"logout","responses":{"204":{"description":"Refresh token revoked (or none present); browser cookies cleared. Idempotent."}}}},"/api/auth/refresh":{"post":{"tags":["auth"],"summary":"Exchanges the refresh token for a new access token.","operationId":"refresh","responses":{"200":{"description":"Rotated access token, with fresh refresh and session cookies. A `null` body means no `prickly_refresh` cookie was present; nothing to restore.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Refresh token invalid, expired, or its user no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/register":{"post":{"tags":["auth"],"summary":"Starts account creation with an email and a password.","operationId":"register","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"204":{"description":"Registration accepted. Same response whether the email was new or already registered."},"400":{"description":"Invalid email, invalid password, an unsupported locale (`register_user.invalid_locale`), a disposable email (`register_user.disposable_email`), or an undeliverable email (`register_user.undeliverable_email`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/resend-confirmation":{"post":{"tags":["auth"],"summary":"Sends a fresh confirmation code for a signup whose code expired, was burned by wrong guesses, or never arrived.","operationId":"resend_confirmation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendConfirmationRequest"}}},"required":true},"responses":{"204":{"description":"A new code sent if the address is registered, not yet confirmed, its last code is older than the resend cooldown, and it has not reached its daily allowance of codes. Same response in every other case."},"400":{"description":"Malformed email address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/reset-password":{"post":{"tags":["auth"],"summary":"Sets a new password using the token from the password reset email.","operationId":"reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"204":{"description":"Password changed."},"400":{"description":"New password fails the password policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Reset token invalid, expired, or already used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No account matches the reset token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/signup-preview":{"post":{"tags":["auth"],"summary":"Checks the address a visitor is about to sign up with, through the pipeline registration runs.","operationId":"signup_preview","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Which checks passed, and whether the address may sign up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupPreviewResponse"}}}},"400":{"description":"Malformed email address (`signup_preview.invalid_email`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Too many previews and registrations from this address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/auth/verify-email-change":{"post":{"tags":["auth"],"summary":"Applies a pending email change with the token from the confirmation email sent to the new address.","operationId":"verify_email_change","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailChangeRequest"}}},"required":true},"responses":{"204":{"description":"Email address change applied."},"401":{"description":"Email-change token invalid or expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"The new email address was taken by another account in the meantime.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/api/batches":{"get":{"tags":["batches"],"summary":"Lists the caller's bulk-verification batches, newest first, paginated.","operationId":"list_batches","parameters":[{"name":"limit","in":"query","description":"Number of batches to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of batches to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated batch list, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBatchesResponse"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"post":{"tags":["batches"],"summary":"Submits a list of emails for bulk verification.","operationId":"submit_batch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitBatchRequest"}}},"required":true},"responses":{"202":{"description":"Batch accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitBatchResponse"}}}},"400":{"description":"Empty or oversized email list, or every address rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"402":{"description":"Wallet balance too low to reserve the batch's cost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"A requested check is not allowed for the plan, the unique-valid email count exceeds the plan's max_batch_size, or the key or agent token lacks the `email:verify:bulk` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/batches/{uuid}":{"get":{"tags":["batches"],"summary":"Returns one batch's status, progress, and aggregated results.","operationId":"get_batch","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the batch.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The requested batch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No batch with that uuid belongs to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/batches/{uuid}/emails":{"post":{"tags":["batches"],"summary":"Appends one chunk of emails to a batch whose intake is still open (submitted with `final: false`).","operationId":"append_batch_emails","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the batch.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendEmailsRequest"}}},"required":true},"responses":{"202":{"description":"Chunk accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendEmailsResponse"}}}},"400":{"description":"Chunk exceeds the per-request email cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"402":{"description":"Wallet balance too low to reserve this chunk's cost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"A requested check is not allowed for the plan, the batch's cumulative unique-valid count would exceed the plan's max_batch_size, or the key or agent token lacks the `email:verify:bulk` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No batch with that uuid belongs to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"The batch's intake is already closed, or it is terminal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/batches/{uuid}/results":{"get":{"tags":["batches"],"summary":"Returns the per-email results of a batch.","operationId":"get_batch_results","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the batch.","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of results to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated per-email results for the batch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBatchResultsResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No batch with that uuid belongs to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/billing/checkout":{"post":{"tags":["billing"],"summary":"Creates a checkout session for a plan or a token top-up.","operationId":"create_checkout_session","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Hosted checkout redirect URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"400":{"description":"Unrecognized plan code, billing cycle, top-up quantity, or locale.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Caller already has an active paid subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"503":{"description":"Billing is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/billing/portal":{"post":{"tags":["billing"],"summary":"Creates a billing portal session.","operationId":"create_billing_portal_session","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePortalRequest"}}},"required":true},"responses":{"200":{"description":"Hosted billing portal redirect URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalSessionResponse"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Caller has no billing account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"503":{"description":"Billing is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/config":{"get":{"tags":["config"],"summary":"Public, unauthenticated endpoint returning the plan grid, top-up pricing, and per-check token costs.","operationId":"get_config","responses":{"200":{"description":"Public pricing and plan configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}}}}}},"/api/jobs":{"get":{"tags":["jobs"],"summary":"Returns a paginated list of the caller's standalone verification jobs, newest first by default.","operationId":"list_jobs","parameters":[{"name":"limit","in":"query","description":"Number of jobs to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of jobs to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"status","in":"query","description":"Comma-separated list of lifecycle statuses to match, OR'd together (e.g. `completed,failed`).","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive lower bound on `created_at` (RFC 3339).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Inclusive upper bound on `created_at` (RFC 3339).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"search","in":"query","description":"Case-insensitive prefix match on the job's public uuid.","required":false,"schema":{"type":"string"}},{"name":"verdict","in":"query","description":"Comma-separated list of deliverability verdicts to match, OR'd together (e.g. `valid,risky`).","required":false,"schema":{"type":"string"}},{"name":"sort","in":"query","description":"Column to order by: `created_at` (default), `score`, `status`, `verdict`, or `uuid`.","required":false,"schema":{"type":"string"}},{"name":"order","in":"query","description":"Order direction: `desc` (default) or `asc`.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated standalone-job list, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListJobsResponse"}}}},"400":{"description":"Unknown `sort`, `order`, `status`, or `verdict` value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/jobs/{uuid}":{"get":{"tags":["jobs"],"summary":"Returns one of the caller's jobs together with its per-check verification detail.","operationId":"get_job","parameters":[{"name":"uuid","in":"path","description":"Public uuid of the job.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The job and its per-check verification detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVerificationResponse"}}}},"400":{"description":"Malformed `uuid`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No job with that uuid belongs to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/keys":{"get":{"tags":["api-keys"],"summary":"Lists every API key owned by the authenticated user, newest first.","operationId":"list_api_keys","responses":{"200":{"description":"The caller's API keys, newest first.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyResponse"}}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `api_keys:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"post":{"tags":["api-keys"],"summary":"Creates an API key for the authenticated account and returns the full key in the response body.","operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"201":{"description":"Key created; `raw_key` is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}},"400":{"description":"Invalid name, environment, scopes, or checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Plan key limit reached, a check is not allowed for the plan, or the key or agent token lacks the `api_keys:create` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/keys/me":{"get":{"tags":["api-keys"],"summary":"Returns metadata about the API key that authenticated the request.","operationId":"get_current_key","responses":{"200":{"description":"Metadata for the authenticating key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentKeyResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]}]}},"/api/keys/{uuid}":{"get":{"tags":["api-keys"],"summary":"Returns a single API key owned by the authenticated user.","operationId":"get_api_key","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the API key.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The requested API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `api_keys:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No key with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"delete":{"tags":["api-keys"],"summary":"Revokes an API key so it can no longer authenticate.","operationId":"revoke_api_key","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the API key.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The revoked API key (idempotent on repeat calls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `api_keys:revoke` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No key with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"patch":{"tags":["api-keys"],"summary":"Updates the display name and enabled checks of an API key.","operationId":"update_api_key","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the API key.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"The updated API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Invalid name or checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"A requested check is not allowed for the plan, or the agent token lacks the `api_keys:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No key with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/notifications":{"get":{"tags":["notifications"],"summary":"Lists the authenticated account's notifications, newest first.","operationId":"list_notifications","parameters":[{"name":"limit","in":"query","description":"Number of events to return. Values outside 1 to 96 are clamped into that range; defaults to 24.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cursor","in":"query","description":"Opaque token from a previous page's `next_cursor`. Absent starts at the newest event.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"A page of the account's notifications.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListNotificationsResponse"}}}},"400":{"description":"Malformed cursor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/notifications/seen":{"post":{"tags":["notifications"],"summary":"Advances the account's cursor, so everything up to `up_to` stops reading as new.","operationId":"mark_notifications_seen","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkNotificationsSeenRequest"}}},"required":true},"responses":{"200":{"description":"The cursor now in effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkNotificationsSeenResponse"}}}},"400":{"description":"Missing or malformed body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/stats/overview":{"get":{"tags":["stats"],"summary":"Returns the caller's usage overview: verdict breakdown, activity series, check usage, and totals.","operationId":"get_stats_overview","parameters":[{"name":"granularity","in":"query","description":"Bucket width for the activity time series: `hour`, `day`, `week`, or `month` (default `day`).","required":false,"schema":{"type":"string"}},{"name":"days","in":"query","description":"Number of whole buckets the activity window covers at the chosen granularity, ending with the current, still-open bucket (default 28, clamped to 1..=364): 8 at `day` gives 8 buckets, 1 at `hour` gives 24, 364 at `month` gives 12.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Verdict breakdown, activity series, check usage, and totals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsOverviewResponse"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `usage:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/stats/summary":{"get":{"tags":["stats"],"operationId":"get_public_stats","responses":{"200":{"description":"All-time public verification stats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicStatsResponse"}}}}}}},"/api/subscription":{"get":{"tags":["subscription"],"summary":"Returns the caller's active subscription.","operationId":"get_subscription","responses":{"200":{"description":"The caller's active subscription (a Free plan if never subscribed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionResponse"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `billing:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/users/me":{"get":{"tags":["account"],"summary":"Returns the authenticated user's profile.","operationId":"get_me","responses":{"200":{"description":"The authenticated user's profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/2fa":{"get":{"tags":["account"],"summary":"Returns whether two-factor authentication is enabled for the caller.","operationId":"get_2fa_status","responses":{"200":{"description":"Whether 2FA is enabled for the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorStatusResponse"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/2fa/disable":{"post":{"tags":["account"],"summary":"Disables two-factor authentication.","operationId":"disable_2fa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Disable2FARequest"}}},"required":true},"responses":{"204":{"description":"2FA disabled."},"400":{"description":"Wrong password, invalid code, or 2FA not enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No user found for the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Too many failed 2FA attempts; temporarily locked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/2fa/enable":{"post":{"tags":["account"],"summary":"Starts two-factor authentication setup.","operationId":"enable_2fa","responses":{"200":{"description":"TOTP secret, otpauth URI, and backup codes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Enable2FAResponse"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"2FA is already enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/2fa/verify-setup":{"post":{"tags":["account"],"summary":"Activates two-factor authentication with a TOTP code from the authenticator app.","operationId":"verify_2fa_setup","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Verify2FASetupRequest"}}},"required":true},"responses":{"204":{"description":"2FA activated."},"400":{"description":"No setup in progress, or the code is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"2FA is already enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/locale":{"patch":{"tags":["account"],"summary":"Sets the language of the caller's transactional emails.","operationId":"change_locale","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeLocaleRequest"}}},"required":true},"responses":{"204":{"description":"Language stored."},"400":{"description":"Unsupported language (`change_locale.invalid_locale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"The caller's account no longer exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/sessions":{"get":{"tags":["sessions"],"summary":"Lists the caller's active sessions.","operationId":"list_sessions","responses":{"200":{"description":"Active sessions for the caller, newest first.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SessionResponse"}}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/me/sessions/{uuid}":{"delete":{"tags":["sessions"],"summary":"Revokes one of the caller's sessions, which also invalidates its refresh token.","operationId":"revoke_session","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the session to revoke.","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Session revoked."},"400":{"description":"Malformed session UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Session does not belong to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No session with this UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/{uuid}":{"get":{"tags":["account"],"summary":"Returns a user's profile by public UUID.","operationId":"get_user","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the user to fetch.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The requested user's profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"400":{"description":"Malformed UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is not permitted to read this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No user with this UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]},"delete":{"tags":["account"],"summary":"Deletes a user account.","operationId":"delete_user","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the user to delete.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteUserRequest"}}},"required":true},"responses":{"204":{"description":"Account deleted."},"400":{"description":"Invalid or wrong password, or already deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is not permitted to delete this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No user with this UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/{uuid}/email":{"patch":{"tags":["account"],"summary":"Requests an email address change.","operationId":"change_email","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the user whose email is being changed.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeEmailRequest"}}},"required":true},"responses":{"204":{"description":"Change requested; a confirmation link was emailed to the new address."},"400":{"description":"Invalid email, invalid password, or wrong current password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is not permitted to change this user's email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No user with this UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"The new email is already taken.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/users/{uuid}/password":{"patch":{"tags":["account"],"summary":"Changes the user's password after verifying the current one.","operationId":"change_password","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the user whose password is being changed.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Password changed."},"400":{"description":"Invalid new password or wrong current password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is not permitted to change this user's password.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No user with this UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/api/verify":{"post":{"tags":["verification"],"summary":"Submits a single-email verification job.","operationId":"submit_verification","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitVerificationRequest"}}},"required":true},"responses":{"200":{"description":"Idempotent replay of a prior submission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitVerificationResponse"}}}},"202":{"description":"Job accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitVerificationResponse"}}}},"402":{"description":"Wallet balance too low to reserve the job's cost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is missing the `email:verify:single` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/verify/{uuid}":{"get":{"tags":["verification"],"summary":"Returns a verification job and its per-email results.","operationId":"get_verification","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the verification job.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The job and its per-email verification results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVerificationResponse"}}}},"400":{"description":"Malformed job `uuid`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Caller is missing the `results:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No job with that uuid belongs to the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/wallet":{"get":{"tags":["wallet"],"summary":"Returns the caller's current credit balance.","operationId":"get_wallet_balance","responses":{"200":{"description":"Current credit balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletBalanceResponse"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `billing:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/wallet/balance-history":{"get":{"tags":["wallet"],"summary":"Returns a zero-filled, oldest-first series of the caller's available token balance at the end of each bucket.","operationId":"get_balance_history","parameters":[{"name":"granularity","in":"query","description":"Bucket width: `hour`, `day`, `week`, or `month` (default `day`).","required":false,"schema":{"type":"string"}},{"name":"days","in":"query","description":"Number of whole buckets the window covers at the chosen granularity, ending with the current, still-open bucket (default 28, clamped to 1..=364): 8 at `day` gives 8 buckets, 1 at `hour` gives 24, 364 at `month` gives 12.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Zero-filled, oldest-first available-balance series.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceHistoryRangeResponse"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `billing:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/wallet/transactions":{"get":{"tags":["wallet"],"summary":"Returns a paginated list of the caller's wallet transactions, newest first by default.","operationId":"list_wallet_transactions","parameters":[{"name":"limit","in":"query","description":"Number of transactions to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of transactions to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"sort","in":"query","description":"Field to order by: `occurred_at` (default), `amount`, or `transaction_type`.","required":false,"schema":{"type":"string"}},{"name":"order","in":"query","description":"Order direction: `desc` (default) or `asc`.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated wallet transaction list, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletTransactionsResponse"}}}},"400":{"description":"Unknown `sort` or `order` value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `billing:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/wallet/transactions/grouped":{"get":{"tags":["wallet"],"summary":"Returns the caller's wallet transactions grouped by verification job, newest group first by default.","operationId":"list_wallet_transaction_groups","parameters":[{"name":"limit","in":"query","description":"Number of groups to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of groups to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"sort","in":"query","description":"Column to order groups by: `occurred_at` (default), `amount`, or `transaction_type`.","required":false,"schema":{"type":"string"}},{"name":"order","in":"query","description":"Order direction: `desc` (default) or `asc`.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated, job-grouped wallet transaction list, newest group first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletTransactionGroupsResponse"}}}},"400":{"description":"Unknown `sort` or `order` value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `billing:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/webhooks":{"get":{"tags":["webhooks"],"summary":"Lists every webhook endpoint of the authenticated account.","operationId":"list_webhooks","responses":{"200":{"description":"The caller's webhook endpoints.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponse"}}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"post":{"tags":["webhooks"],"summary":"Creates a webhook endpoint for the authenticated account and returns its signing secret in the response body.","operationId":"create_webhook","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Endpoint created; `secret` is shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookResponse"}}}},"400":{"description":"Invalid url, events, or empty events list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Plan webhook-endpoint limit reached, or the key or agent token lacks the `webhooks:create` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/webhooks/{uuid}":{"get":{"tags":["webhooks"],"summary":"Returns one webhook endpoint of the authenticated account.","operationId":"get_webhook","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the webhook endpoint.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The requested webhook endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No endpoint with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"delete":{"tags":["webhooks"],"summary":"Deletes a webhook endpoint.","operationId":"delete_webhook","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the webhook endpoint.","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Endpoint deleted (idempotent on repeat calls)."},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:delete` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]},"patch":{"tags":["webhooks"],"summary":"Updates the URL, subscribed events, description or status of a webhook endpoint.","operationId":"update_webhook","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the webhook endpoint.","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}},"required":true},"responses":{"200":{"description":"The updated webhook endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid url, events, empty events list, or status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:update` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No endpoint with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/webhooks/{uuid}/deliveries":{"get":{"tags":["webhooks"],"summary":"Returns the delivery attempts made to one endpoint, newest first, paginated.","operationId":"list_webhook_deliveries","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the webhook endpoint.","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of entries to return (default 20, cap 96).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","description":"Number of entries to skip (default 0).","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated delivery history, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookDeliveriesResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:read` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No endpoint with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/api/webhooks/{uuid}/test":{"post":{"tags":["webhooks"],"summary":"Sends a signed test delivery to a webhook endpoint.","operationId":"test_webhook","parameters":[{"name":"uuid","in":"path","description":"Public UUID of the webhook endpoint.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The test-fire outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookResponse"}}}},"400":{"description":"Malformed uuid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid API key, session token, or agent token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The key or agent token lacks the `webhooks:update` scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No endpoint with that uuid owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"bearer_api_key":[]},{"jwt":[]}]}},"/oauth/authorize":{"get":{"tags":["oauth"],"operationId":"authorize","parameters":[{"name":"response_type","in":"query","description":"Must be `code`.","required":true,"schema":{"type":"string"}},{"name":"client_id","in":"query","description":"The requesting client's public client_id.","required":true,"schema":{"type":"string"}},{"name":"redirect_uri","in":"query","description":"Must exactly match one of the client's registered URIs.","required":true,"schema":{"type":"string"}},{"name":"scope","in":"query","description":"Requested scopes, space-delimited. Informational only.","required":false,"schema":{"type":"string"}},{"name":"state","in":"query","description":"Opaque anti-CSRF value, echoed back unchanged.","required":false,"schema":{"type":"string"}},{"name":"code_challenge","in":"query","description":"PKCE code_challenge (RFC 7636).","required":true,"schema":{"type":"string"}},{"name":"code_challenge_method","in":"query","description":"Must be `S256`.","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to the consent page."},"400":{"description":"Any validation failure: an unknown client_id, an unregistered redirect_uri, or a malformed response_type or PKCE parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/oauth/authorize/consent":{"post":{"tags":["oauth"],"operationId":"authorize_consent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentRequest"}}},"required":true},"responses":{"200":{"description":"Redirect URL for the frontend to navigate the browser to.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentResponse"}}}},"400":{"description":"Unknown client, redirect_uri mismatch, or invalid PKCE parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing or invalid JWT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"The caller is an admin impersonation session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"No agent with that UUID owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"security":[{"jwt":[]}]}},"/oauth/register":{"post":{"tags":["oauth"],"summary":"Registers an OAuth client (RFC 7591 dynamic client registration).","operationId":"register_client","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterClientRequest"}}},"required":true},"responses":{"201":{"description":"Client registered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterClientResponse"}}}},"400":{"description":"Invalid client_name or redirect_uris.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/oauth/token":{"post":{"tags":["oauth"],"summary":"Issues agent access tokens (RFC 6749 sections 4.1.3 and 6).","operationId":"token","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}},"required":true},"responses":{"200":{"description":"Agent session token issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"RFC 6749 error response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenErrorResponse"}}}}}}}},"components":{"schemas":{"ActivityPointResponse":{"type":"object","description":"A single time-bucketed activity point in the response body.","required":["date","count"],"properties":{"count":{"type":"integer","format":"int32","description":"Number of verifications recorded in this bucket.","minimum":0},"date":{"type":"string","description":"Start of the bucket, as an RFC3339 timestamp."}}},"AgentCreatedResponse":{"type":"object","description":"`POST /api/agents` response body.","required":["agent"],"properties":{"agent":{"$ref":"#/components/schemas/AgentResponse","description":"The new agent, including the scopes just granted to it."}}},"AgentResponse":{"type":"object","description":"Metadata of an agent, returned when creating, listing, reading or revoking agents.","required":["uuid","name","status","is_active","scopes","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"RFC 3339 creation timestamp."},"description":{"type":["string","null"],"description":"Description of the agent, omitted when none was set."},"is_active":{"type":"boolean","description":"Whether the agent can currently authenticate."},"name":{"type":"string","description":"Display name of the agent."},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to the agent."},"status":{"type":"string","description":"Status of the agent: `\"active\"` or `\"revoked\"`."},"updated_at":{"type":"string","description":"RFC 3339 timestamp of the last change."},"uuid":{"type":"string","description":"Public UUID of the agent."}}},"ApiErrorBody":{"type":"object","description":"Error envelope returned with every non-success status: `{ \"error\": { \"code\", \"message\" } }`.","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/ApiErrorDetail","description":"Error detail."}}},"ApiErrorDetail":{"type":"object","description":"Detail of an error response.","required":["code"],"properties":{"code":{"type":"string","description":"Stable key identifying the error (for example `\"verify.invalid_uuid\"`). Clients localize by this key."},"message":{"type":["string","null"],"description":"Present on most error kinds and equal to `code`; the API returns no localized text."}}},"ApiKeyCreatedResponse":{"type":"object","required":["key","raw_key"],"properties":{"key":{"$ref":"#/components/schemas/ApiKeyResponse","description":"Metadata of the new key."},"raw_key":{"type":"string","description":"The full API key. It is returned only once, so store it securely."}}},"ApiKeyResponse":{"type":"object","description":"Metadata of an API key, returned when listing, reading, updating or revoking keys.","required":["uuid","prefix","name","environment","scopes","enabled_checks","rate_limit","is_active","request_count","created_at"],"properties":{"created_at":{"type":"string","description":"RFC 3339 creation timestamp."},"enabled_checks":{"type":"array","items":{"type":"string"},"description":"Verification checks enabled for the key."},"environment":{"type":"string","description":"Environment of the key: `\"live\"` or `\"test\"`."},"expires_at":{"type":["string","null"],"description":"RFC 3339 expiry timestamp, or `null` when the key does not expire."},"is_active":{"type":"boolean","description":"Whether the key can currently authenticate (not revoked and not expired)."},"last_used_at":{"type":["string","null"],"description":"RFC 3339 timestamp of the last request made with the key, or `null` when it was never used."},"name":{"type":"string","description":"Display name of the key."},"prefix":{"type":"string","description":"Visible prefix of the key (for example `pm_live_abc12345`)."},"rate_limit":{"$ref":"#/components/schemas/RateLimitDto","description":"Request budget of the key."},"request_count":{"type":"integer","format":"int64","description":"Total number of requests made with the key.","minimum":0},"revoked_at":{"type":["string","null"],"description":"RFC 3339 timestamp of the revocation, or `null` when the key is not revoked."},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to the key."},"uuid":{"type":"string","description":"Public UUID of the key."}}},"AppendEmailsRequest":{"type":"object","description":"`POST /api/batches/{uuid}/emails` request body.","required":["emails"],"properties":{"checks":{"type":["array","null"],"items":{"type":"string"},"description":"Optional explicit check names; defaults to every check the caller's plan allows."},"custom_ids":{"type":"array","items":{"type":["string","null"]},"description":"Optional per-email client references, index-aligned 1:1 with `emails`; empty means none."},"emails":{"type":"array","items":{"type":"string"},"description":"Email addresses to verify in this chunk. May be empty (a pure \"close intake now\" call)."},"final":{"type":"boolean","description":"Whether this is the batch's final chunk; closes intake and completes the batch when every job (old and new) is\nalready processed. Defaults to `true`."}}},"AppendEmailsResponse":{"type":"object","description":"`POST /api/batches/{uuid}/emails` response body.","required":["batch_uuid","status","total_jobs","syntax_errors","duplicates","estimated_cost"],"properties":{"batch_uuid":{"type":"string","description":"Public UUID of the batch."},"duplicates":{"type":"integer","format":"int64","description":"Number of addresses in this chunk that were duplicates within the same chunk.","minimum":0},"estimated_cost":{"type":"integer","format":"int32","description":"Tokens reserved for this chunk.","minimum":0},"status":{"type":"string","description":"Status of the batch right after this chunk."},"syntax_errors":{"type":"integer","format":"int64","description":"Number of addresses in this chunk that failed syntax validation.","minimum":0},"total_jobs":{"type":"integer","format":"int64","description":"Cumulative number of unique valid emails queued as jobs across every chunk so far.","minimum":0}}},"AuthResponse":{"type":"object","description":"Response body for authentication endpoints.","required":["access_token","expires_in","user"],"properties":{"access_token":{"type":"string","description":"Access token (JWT), sent as a Bearer credential."},"expires_in":{"type":"integer","format":"int64","description":"Access token lifetime in seconds.","minimum":0},"user":{"$ref":"#/components/schemas/UserResponse","description":"Authenticated user details."}}},"AuthorizationServerMetadataResponse":{"type":"object","description":"`GET /.well-known/oauth-authorization-server` response body (RFC 8414 subset).","required":["issuer","authorization_endpoint","token_endpoint","registration_endpoint","scopes_supported","response_types_supported","grant_types_supported","code_challenge_methods_supported","token_endpoint_auth_methods_supported","authorization_response_iss_parameter_supported"],"properties":{"authorization_endpoint":{"type":"string","description":"The authorization endpoint URL."},"authorization_response_iss_parameter_supported":{"type":"boolean","description":"`true`: every authorization response (success and `access_denied`) carries `iss` (RFC 9207), letting a client\nthat talks to more than one authorization server verify which one a given callback actually came from."},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"},"description":"Supported PKCE code challenge methods (RFC 7636)."},"grant_types_supported":{"type":"array","items":{"type":"string"},"description":"Supported OAuth `grant_type` values."},"issuer":{"type":"string","description":"The authorization server's issuer identifier: its own public base URL."},"registration_endpoint":{"type":"string","description":"The dynamic client registration endpoint URL (RFC 7591)."},"response_types_supported":{"type":"array","items":{"type":"string"},"description":"Supported OAuth `response_type` values."},"scopes_supported":{"type":"array","items":{"type":"string"},"description":"Scopes this server may grant to a client."},"token_endpoint":{"type":"string","description":"The token endpoint URL."},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"},"description":"Supported token endpoint authentication methods."}}},"BalanceHistoryRangePoint":{"type":"object","description":"A single point in the range-selectable balance-history response body.","required":["date","balance"],"properties":{"balance":{"type":"integer","format":"int32","description":"Available token balance at the end of the bucket.","minimum":0},"date":{"type":"string","description":"Start of the bucket, as an RFC 3339 timestamp, which keeps the hour for the `\"hour\"` granularity."}}},"BalanceHistoryRangeResponse":{"type":"object","description":"JSON response body for `GET /api/wallet/balance-history`.","required":["points"],"properties":{"points":{"type":"array","items":{"$ref":"#/components/schemas/BalanceHistoryRangePoint"},"description":"The available balance series, oldest first."}}},"BatchProgressDto":{"type":"object","description":"Progress counters of a batch.","required":["total","processed","succeeded","failed","skipped","percent_complete"],"properties":{"failed":{"type":"integer","format":"int64","minimum":0},"percent_complete":{"type":"integer","format":"int32","minimum":0},"processed":{"type":"integer","format":"int64","minimum":0},"skipped":{"type":"integer","format":"int64","minimum":0},"succeeded":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"BatchResponse":{"type":"object","description":"A batch with its status, progress, aggregated results, and recommendation counts.","required":["uuid","status","progress","results","recommendations","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"name":{"type":["string","null"]},"progress":{"$ref":"#/components/schemas/BatchProgressDto"},"recommendations":{"$ref":"#/components/schemas/RecommendationCountsDto"},"results":{"$ref":"#/components/schemas/BatchResultsDto"},"status":{"type":"string"},"updated_at":{"type":"string"},"uuid":{"type":"string"}}},"BatchResultItem":{"type":"object","description":"One per-email row in a batch's results listing.","required":["uuid","status"],"properties":{"custom_id":{"type":["string","null"],"description":"The client reference supplied at submit for this email, if any."},"reason":{"type":["string","null"],"description":"Stable verdict reason string (e.g. `\"accept_all_provider\"`), populated once available."},"recommendation":{"type":["string","null"],"description":"Deterministic list-cleaning action (`\"remove\"`, `\"send\"`, or `\"review\"`), derived from the verdict, reason, and\ntypo flag. Populated under the same condition as `verdict`."},"score":{"type":["integer","null"],"format":"int32","description":"Quality score (0-100), populated once the job's result is available.","minimum":0},"status":{"type":"string","description":"Current lifecycle status (e.g. `\"queued\"`, `\"completed\"`)."},"uuid":{"type":"string","description":"Public UUID of the job."},"verdict":{"type":["string","null"],"description":"Deliverability verdict (e.g. `\"valid\"`, `\"risky\"`), populated once available."}}},"BatchResultsDto":{"type":"object","description":"Aggregated verdict counts of a batch.","required":["valid","invalid","risky","unknown","duplicates","syntax_errors"],"properties":{"duplicates":{"type":"integer","format":"int64","minimum":0},"invalid":{"type":"integer","format":"int64","minimum":0},"risky":{"type":"integer","format":"int64","minimum":0},"syntax_errors":{"type":"integer","format":"int64","minimum":0},"unknown":{"type":"integer","format":"int64","minimum":0},"valid":{"type":"integer","format":"int64","minimum":0}}},"ChangeEmailRequest":{"type":"object","description":"Request body for `PATCH /api/users/:uuid/email`.","required":["new_email","current_password"],"properties":{"current_password":{"type":"string","description":"The current password for confirmation."},"new_email":{"type":"string","description":"The new email address."}}},"ChangeLocaleRequest":{"type":"object","description":"Request body for `PATCH /api/users/me/locale`.","required":["locale"],"properties":{"locale":{"type":"string","description":"The language of the caller's emails (`\"en\"` or `\"fr\"`)."}}},"ChangePasswordRequest":{"type":"object","description":"Request body for `PATCH /api/users/:uuid/password`.","required":["current_password","new_password"],"properties":{"current_password":{"type":"string","description":"The current password."},"new_password":{"type":"string","description":"The new password, subject to the same rules as at registration."}}},"CheckCostsResponse":{"type":"object","description":"Public per-check token cost. Field names are the check names.","required":["syntax","mx","smtp","disposable","role","free","catchall"],"properties":{"catchall":{"type":"integer","format":"int32","description":"Token cost of the `catchall` check.","minimum":0},"disposable":{"type":"integer","format":"int32","description":"Token cost of the `disposable` check.","minimum":0},"free":{"type":"integer","format":"int32","description":"Token cost of the `free` check.","minimum":0},"mx":{"type":"integer","format":"int32","description":"Token cost of the `mx` check.","minimum":0},"role":{"type":"integer","format":"int32","description":"Token cost of the `role` check.","minimum":0},"smtp":{"type":"integer","format":"int32","description":"Token cost of the `smtp` check.","minimum":0},"syntax":{"type":"integer","format":"int32","description":"Token cost of the `syntax` check.","minimum":0}}},"CheckDurationsDto":{"type":"object","description":"Per-check elapsed time in milliseconds.","properties":{"catchall":{"type":["integer","null"],"format":"int64","minimum":0},"disposable":{"type":["integer","null"],"format":"int64","minimum":0},"free":{"type":["integer","null"],"format":"int64","minimum":0},"mx":{"type":["integer","null"],"format":"int64","minimum":0},"role":{"type":["integer","null"],"format":"int64","minimum":0},"smtp":{"type":["integer","null"],"format":"int64","minimum":0},"syntax":{"type":["integer","null"],"format":"int64","minimum":0},"typo":{"type":["integer","null"],"format":"int64","minimum":0}}},"CheckUsageResponse":{"type":"object","description":"A single check-usage count in the response body.","required":["check","count"],"properties":{"check":{"type":"string","description":"Check name (e.g. `\"syntax\"`, `\"mx\"`, `\"smtp\"`)."},"count":{"type":"integer","format":"int32","description":"Number of verifications for which this check ran.","minimum":0}}},"CheckoutSessionResponse":{"type":"object","description":"JSON response body for `POST /api/billing/checkout`.","required":["url"],"properties":{"url":{"type":"string","description":"Hosted checkout URL to redirect the user to."}}},"CheckoutTargetRequest":{"oneOf":[{"type":"object","description":"Subscribe to a plan.","required":["plan","cycle","type"],"properties":{"cycle":{"type":"string","description":"Billing cycle (`\"monthly\"` or `\"yearly\"`)."},"plan":{"type":"string","description":"Plan code (e.g. `\"starter\"`, `\"pro\"`, `\"business\"`, `\"enterprise\"`)."},"type":{"type":"string","enum":["plan"]}}},{"type":"object","description":"One-time credit top-up.","required":["token_quantity","type"],"properties":{"token_quantity":{"type":"integer","format":"int32","description":"Number of tokens to purchase.","minimum":0},"type":{"type":"string","enum":["top_up"]}}}],"description":"Checkout target from the request body."},"ChecksDto":{"type":"object","description":"Individual check results for a verified email address.","required":["syntax","mx","disposable","role","free","typo","smtp","catchall"],"properties":{"catchall":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is a catch-all server (accepts any address)."},"disposable":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is from a known disposable provider."},"free":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is a known free webmail provider (gmail, yahoo, etc.). Free providers are informational and\ndo not change the quality score."},"mx":{"$ref":"#/components/schemas/MxCheckDto","description":"MX record check result."},"role":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the local-part is a known role-based address (info@, support@, etc.). Role addresses are a risk factor\nand reduce the quality score."},"smtp":{"$ref":"#/components/schemas/SmtpCheckDto","description":"SMTP deliverability probe result."},"syntax":{"type":"boolean","description":"Whether the email syntax is valid."},"typo":{"$ref":"#/components/schemas/TypoCheckDto","description":"Typo detection result."}}},"ConfigResponse":{"type":"object","description":"JSON response body for `GET /api/config`.","required":["plans","topup","checks"],"properties":{"checks":{"$ref":"#/components/schemas/CheckCostsResponse","description":"Per-check token cost, keyed by check name."},"plans":{"type":"array","items":{"$ref":"#/components/schemas/PlanConfigResponse"},"description":"One entry per real plan, in tier order (Free through Enterprise)."},"topup":{"$ref":"#/components/schemas/TopupConfigResponse","description":"Token top-up pricing."}}},"ConfirmAccountRequest":{"type":"object","description":"Request body for `POST /api/auth/confirm`.","required":["email","code"],"properties":{"code":{"type":"string","description":"The six-digit code from the confirmation email."},"email":{"type":"string","description":"The address the account was registered under."},"preview_token":{"type":["string","null"],"description":"The `preview_token` of the check the visitor ran on this address before signing up: that check becomes the\naccount's first job."}}},"ConfirmAccountResponse":{"allOf":[{"$ref":"#/components/schemas/AuthResponse","description":"The session, as every sign-in returns it."},{"type":"object","properties":{"first_job_uuid":{"type":["string","null"],"format":"uuid","description":"The job recording the check the visitor ran on their address before signing up, readable through\n`GET /api/jobs/{uuid}`. Present only when `preview_token` named one."}}}],"description":"Response body for `POST /api/auth/confirm`: the session of the confirmed account."},"ConsentRequest":{"type":"object","description":"`POST /oauth/authorize/consent` request body.","required":["client_id","redirect_uri","code_challenge","code_challenge_method","agent_uuid","approve"],"properties":{"agent_uuid":{"type":"string","description":"Public UUID of the caller's own agent to authorize."},"approve":{"type":"boolean","description":"Whether the user approved the request."},"client_id":{"type":"string","description":"The client's public `client_id`."},"code_challenge":{"type":"string","description":"PKCE `code_challenge` (RFC 7636)."},"code_challenge_method":{"type":"string","description":"PKCE `code_challenge_method`; only `\"S256\"` is supported."},"redirect_uri":{"type":"string","description":"The redirect target, which must exactly match one of the client's registered URIs."},"state":{"type":["string","null"],"description":"Opaque anti-CSRF value, echoed back unchanged."}}},"ConsentResponse":{"type":"object","description":"`POST /oauth/authorize/consent` response body.","required":["redirect_url"],"properties":{"redirect_url":{"type":"string","description":"Where to navigate the browser next: the client's own `redirect_uri` carrying either `code` and\n`state` (approved) or `error=access_denied` and `state` (denied)."}}},"CreateAgentRequest":{"type":"object","description":"`POST /api/agents` request body.","required":["name"],"properties":{"description":{"type":["string","null"],"description":"Free-text description of the agent."},"name":{"type":"string","description":"Display name of the agent (at most 128 characters)."},"scopes":{"type":["array","null"],"items":{"type":"string"},"description":"Scopes to grant, for example `\"email:verify:single\"`. Must be allowed by the account's plan."}}},"CreateApiKeyRequest":{"type":"object","description":"`POST /api/keys` request body.","required":["name"],"properties":{"enabled_checks":{"type":["array","null"],"items":{"type":"string"},"description":"Verification checks to enable: `\"syntax\"`, `\"mx\"`, `\"smtp\"`, `\"disposable\"`, `\"role\"`, `\"free\"` or `\"catchall\"`."},"environment":{"type":["string","null"],"description":"Environment of the key: `\"live\"` or `\"test\"`. Defaults to `\"live\"` when absent."},"name":{"type":"string","description":"Display name shown in the dashboard."},"scopes":{"type":["array","null"],"items":{"type":"string"},"description":"Scopes to grant, for example `\"email:verify:single\"`."}}},"CreateCheckoutRequest":{"type":"object","description":"Request body for `POST /api/billing/checkout`.","required":["target","success_url","cancel_url"],"properties":{"cancel_url":{"type":"string","description":"URL the buyer is redirected to when they cancel the checkout."},"locale":{"type":["string","null"],"description":"Language of the hosted checkout page and of the terms the buyer accepts there (`\"en\"` or `\"fr\"`)."},"success_url":{"type":"string","description":"URL the buyer is redirected to after a successful payment."},"target":{"$ref":"#/components/schemas/CheckoutTargetRequest","description":"What to check out: a plan subscription or a credit top-up."}}},"CreatePortalRequest":{"type":"object","description":"Request body for `POST /api/billing/portal`.","required":["return_url"],"properties":{"return_url":{"type":"string","description":"URL the user is redirected to when they leave the billing portal."}}},"CreateWebhookRequest":{"type":"object","description":"`POST /api/webhooks` request body.","required":["url","events"],"properties":{"description":{"type":["string","null"],"description":"Free-text description of the endpoint."},"events":{"type":"array","items":{"type":"string"},"description":"Events to subscribe to, for example `\"job.completed\"` or `\"job.failed\"`. At least one is required."},"url":{"type":"string","description":"HTTPS URL that receives event notifications (at most 2048 characters, no private or loopback address)."}}},"CreateWebhookResponse":{"allOf":[{"$ref":"#/components/schemas/WebhookResponse"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"The signing secret, hex-encoded. It is returned only once, so store it securely."}}}]},"CurrentKeyResponse":{"type":"object","description":"JSON response body for `GET /api/keys/me`.","required":["uuid","prefix","name","environment","is_active","scopes","enabled_checks"],"properties":{"enabled_checks":{"type":"array","items":{"type":"string"},"description":"Verification checks enabled for the key, for example `\"syntax\"`, `\"mx\"` or `\"smtp\"`."},"environment":{"type":"string","description":"Environment of the key, matching its prefix: `\"live\"` or `\"test\"`."},"is_active":{"type":"boolean","description":"Whether the key is currently active (not revoked, not expired)."},"name":{"type":"string","description":"Display name of the key."},"prefix":{"type":"string","description":"Visible prefix (for example `pm_live_abc12345`)."},"scopes":{"type":"array","items":{"type":"string"},"description":"Scopes granted to the key, for example `\"email:verify:single\"`."},"uuid":{"type":"string","description":"Public UUID of the API key."}}},"DeleteUserRequest":{"type":"object","description":"Request body for `DELETE /api/users/:uuid`.","required":["password"],"properties":{"password":{"type":"string","description":"The current password, required to confirm account deletion."}}},"Disable2FARequest":{"type":"object","description":"Request body for `POST /api/users/me/2fa/disable`.","required":["password","code"],"properties":{"code":{"type":"string","description":"A valid TOTP code or backup code, proving possession of the second factor."},"password":{"type":"string","description":"The user's password for confirmation."}}},"Enable2FAResponse":{"type":"object","description":"Response body for `POST /api/users/me/2fa/enable`.","required":["qr_uri","backup_codes","secret"],"properties":{"backup_codes":{"type":"array","items":{"type":"string"},"description":"Single-use backup codes, shown only once."},"qr_uri":{"type":"string","description":"The `otpauth://` URI for QR code generation."},"secret":{"type":"string","description":"The base32-encoded TOTP secret."}}},"ForgotPasswordRequest":{"type":"object","description":"Request body for `POST /api/auth/forgot-password`.","required":["email"],"properties":{"email":{"type":"string","description":"The email address of the account requesting a password reset."}}},"GetVerificationResponse":{"type":"object","description":"`GET /api/verify/{uuid}` response body.","required":["job_uuid","status","verifications"],"properties":{"job_uuid":{"type":"string","description":"Public UUID of the job."},"status":{"type":"string","description":"Current status of the job."},"verifications":{"type":"array","items":{"$ref":"#/components/schemas/VerificationResultDto"},"description":"Per-email verification rows."}}},"JobItem":{"type":"object","description":"A single job summary item in the response list.","required":["uuid","status","email_count","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","description":"ISO 8601 creation timestamp."},"email_count":{"type":"integer","format":"int32","description":"Number of email addresses associated with this job.","minimum":0},"error":{"type":["string","null"],"description":"The job's failure reason, populated only when the job's lifecycle status is `\"failed\"`."},"score":{"type":["integer","null"],"format":"int32","description":"Quality score (0-100) of the job's sole verification.","minimum":0},"status":{"type":"string","description":"Current lifecycle status (e.g. `\"pending\"`, `\"completed\"`)."},"uuid":{"type":"string","description":"Public UUID of the job."},"verdict":{"type":["string","null"],"description":"Deliverability verdict of the job's sole verification (e.g. `\"valid\"`, `\"risky\"`), the same stable strings\n`POST /api/verify` returns. `null` under the same condition as `score`."}}},"ListAgentsResponse":{"type":"object","description":"`GET /api/agents` response body: a paginated page of the caller's agents.","required":["agents","limit","offset"],"properties":{"agents":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"description":"The caller's agents, newest first."},"limit":{"type":"integer","format":"int64","description":"Page size applied after clamping."},"offset":{"type":"integer","format":"int64","description":"Offset applied."}}},"ListBatchResultsResponse":{"type":"object","description":"`GET /api/batches/{uuid}/results` response body.","required":["results","limit","offset"],"properties":{"limit":{"type":"integer","format":"int64","description":"Pagination limit used for this page (effective after clamping)."},"offset":{"type":"integer","format":"int64","description":"Pagination offset used for this page."},"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchResultItem"},"description":"Per-email results for the batch, submission order first."}}},"ListBatchesResponse":{"type":"object","description":"`GET /api/batches` response body.","required":["batches","limit","offset"],"properties":{"batches":{"type":"array","items":{"$ref":"#/components/schemas/BatchResponse"},"description":"The caller's batches, newest first."},"limit":{"type":"integer","format":"int64","description":"Pagination limit used for this page (effective after clamping)."},"offset":{"type":"integer","format":"int64","description":"Pagination offset used for this page."}}},"ListJobsResponse":{"type":"object","description":"JSON response body for `GET /api/jobs`.","required":["jobs","limit","offset"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/JobItem"},"description":"List of jobs, newest first."},"limit":{"type":"integer","format":"int64","description":"Pagination limit used for this page (effective after clamping)."},"offset":{"type":"integer","format":"int64","description":"Pagination offset used for this page."}}},"ListNotificationsResponse":{"type":"object","description":"`GET /api/notifications` response.","required":["notifications","has_more","unseen_count"],"properties":{"has_more":{"type":"boolean","description":"Whether older events follow this page."},"last_seen_at":{"type":["string","null"],"format":"date-time","description":"The caller's stored cursor, or `null` when it has never been advanced."},"next_cursor":{"type":["string","null"],"description":"The token to pass back as `cursor` to read the next page, present only when `has_more` is true."},"notifications":{"type":"array","items":{"$ref":"#/components/schemas/NotificationResponse"},"description":"The page, newest first."},"unseen_count":{"type":"integer","format":"int64","description":"How many events are newer than the caller's cursor."}}},"ListWebhookDeliveriesResponse":{"type":"object","description":"`GET /api/webhooks/{uuid}/deliveries` response body.","required":["deliveries","limit","offset"],"properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryItem"},"description":"Delivery attempts, newest first."},"limit":{"type":"integer","format":"int64","description":"Page size applied after clamping."},"offset":{"type":"integer","format":"int64","description":"Offset applied."}}},"LoginRequest":{"type":"object","description":"Request body for `POST /api/auth/login`.","required":["email","password"],"properties":{"email":{"type":"string","description":"The email address of the account."},"password":{"type":"string","description":"The account password."}}},"LoginResponse":{"oneOf":[{"$ref":"#/components/schemas/AuthResponse","description":"Standard authentication response (no 2FA required)."},{"type":"object","description":"2FA is required; the client must call `/api/auth/2fa/verify` with the temp token.","required":["requires_2fa","temp_token"],"properties":{"requires_2fa":{"type":"boolean","description":"Always `true` when this variant is returned."},"temp_token":{"type":"string","description":"A short-lived token to send to `POST /api/auth/2fa/verify` with the code."}}}],"description":"Response returned by the login endpoint."},"MarkNotificationsSeenRequest":{"type":"object","description":"`POST /api/notifications/seen` request.","required":["up_to"],"properties":{"up_to":{"type":"string","format":"date-time","description":"The `occurred_at` of the newest notification the client displayed, as an RFC 3339 timestamp."}}},"MarkNotificationsSeenResponse":{"type":"object","description":"`POST /api/notifications/seen` response.","required":["last_seen_at"],"properties":{"last_seen_at":{"type":"string","format":"date-time","description":"The cursor now in effect."}}},"MxCheckDto":{"oneOf":[{"type":"object","description":"The check ran.","required":["valid","records"],"properties":{"records":{"type":"array","items":{"type":"string"},"description":"MX record hostnames found for the domain."},"valid":{"type":"boolean","description":"Whether the domain publishes at least one usable mail exchanger."}}},{"type":"object","description":"The check was not run.","required":["status"],"properties":{"status":{"type":"string","description":"Always `\"skipped\"`."}}}],"description":"MX record check result."},"MxPreviewDto":{"oneOf":[{"type":"object","description":"The check ran.","required":["valid"],"properties":{"valid":{"type":"boolean","description":"Whether the domain publishes at least one usable mail exchanger."}}},{"type":"object","description":"The check was not run.","required":["status"],"properties":{"status":{"type":"string","description":"Always `\"skipped\"`."}}}],"description":"The MX check of a signup preview."},"NotificationResponse":{"type":"object","description":"One notification line.","required":["id","event_type","translation_key","family","severity","params","occurred_at"],"properties":{"event_type":{"type":"string","description":"The event's slug, which doubles as the page's filter value."},"family":{"type":"string","description":"The group the event is filed under, for the family filter."},"id":{"type":"string","format":"uuid","description":"The event's UUID, so a client can key a rendered line."},"occurred_at":{"type":"string","format":"date-time","description":"When the event was recorded."},"params":{"type":"object","description":"The values the event's text interpolates: a flat object of strings and whole numbers, empty when the text has\nnone."},"severity":{"type":"string","description":"How loudly the event presents itself, driving its accent."},"translation_key":{"type":"string","description":"The dashboard locale key carrying this event's text."}}},"PlanConfigResponse":{"type":"object","description":"Plan pricing and limits for one plan tier.","required":["code","monthly_tokens","monthly_price_cents","yearly_price_cents","rate_limit_per_minute","max_api_keys","batch_max","max_agents","max_webhooks","allowed_checks","allowed_agent_scopes"],"properties":{"allowed_agent_scopes":{"type":"array","items":{"type":"string"},"description":"The scopes an agent (a non-human principal) under this plan may be granted, as scope strings such as\n`\"results:read\"`."},"allowed_checks":{"type":"array","items":{"type":"string"},"description":"The verification checks an API key or agent credential under this plan may enable, as check names such as\n`\"smtp\"`."},"batch_max":{"type":"integer","format":"int32","description":"Maximum batch size for a single bulk-verification submission.","minimum":0},"code":{"type":"string","description":"Plan code (e.g. `\"free\"`, `\"starter\"`, `\"pro\"`, `\"business\"`, `\"enterprise\"`)."},"max_agents":{"type":"integer","format":"int32","description":"Maximum number of active agents (non-human principals authenticating through a scoped credential).","minimum":0},"max_api_keys":{"type":"integer","format":"int32","description":"Maximum number of active API keys.","minimum":0},"max_webhooks":{"type":"integer","format":"int32","description":"Maximum number of webhook endpoints, whatever their status (paused and disabled endpoints count too); 0 on Free.","minimum":0},"monthly_price_cents":{"type":"integer","format":"int64","description":"Monthly price in cents.","minimum":0},"monthly_tokens":{"type":"integer","format":"int32","description":"Monthly token grant credited to the account's token balance on each billing cycle.","minimum":0},"rate_limit_per_minute":{"type":"integer","format":"int32","description":"API rate limit in requests per minute.","minimum":0},"yearly_price_cents":{"type":"integer","format":"int64","description":"Yearly price in cents (11 months for 12).","minimum":0}}},"PortalSessionResponse":{"type":"object","description":"JSON response body for `POST /api/billing/portal`.","required":["url"],"properties":{"url":{"type":"string","description":"Hosted billing portal URL to redirect the user to."}}},"PreviewChecksDto":{"type":"object","description":"Which checks passed for an address a visitor previews before signing up: the shape of the per-check result object,\nwithout the mail exchanger hostnames.","required":["syntax","mx","disposable","role","free","typo","smtp","catchall"],"properties":{"catchall":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is a catch-all server."},"disposable":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is from a known disposable provider."},"free":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the domain is a known free webmail provider."},"mx":{"$ref":"#/components/schemas/MxPreviewDto","description":"Whether the domain publishes a usable mail exchanger."},"role":{"$ref":"#/components/schemas/ProviderFlagDto","description":"Whether the local-part is a known role-based address."},"smtp":{"$ref":"#/components/schemas/SmtpCheckDto","description":"SMTP deliverability probe result."},"syntax":{"type":"boolean","description":"Whether the email syntax is valid."},"typo":{"$ref":"#/components/schemas/TypoCheckDto","description":"Typo detection result, with the corrected address when one was found."}}},"ProviderFlagDto":{"oneOf":[{"type":"boolean","description":"The check ran; carries the real boolean result."},{"type":"object","description":"The check was not run.","required":["status"],"properties":{"status":{"type":"string","description":"Always `\"skipped\"`."}}}],"description":"A boolean provider or risk-flag check result (`disposable`, `role`, `free`, `catchall`)."},"PublicStatsResponse":{"type":"object","description":"JSON response body for `GET /api/stats/summary`.","required":["total_verifications"],"properties":{"avg_latency_ms":{"type":["integer","null"],"format":"int64","description":"Average recorded check duration in milliseconds, rounded to the nearest millisecond."},"p90_latency_ms":{"type":["integer","null"],"format":"int64","description":"90th-percentile recorded check duration in milliseconds: an actual observed duration at or under which at\nleast 90% of results land. `null` when no verification has recorded a duration yet."},"total_verifications":{"type":"integer","format":"int64","description":"All-time total number of verification results recorded, across every customer."}}},"RateLimitDto":{"type":"object","description":"Request budget of an API key.","required":["per_minute"],"properties":{"per_minute":{"type":"integer","format":"int32","description":"Maximum number of requests the key may make per minute.","minimum":0}}},"RecommendationBreakdownResponse":{"type":"object","description":"Per-recommendation-bucket counts in the response body: the 3-bucket \"what to do with this address\" grouping,\northogonal to the raw verdict breakdown above.","required":["remove","send","review"],"properties":{"remove":{"type":"integer","format":"int32","description":"Count of verifications recommended for removal from the list.","minimum":0},"review":{"type":"integer","format":"int32","description":"Count of verifications recommended for manual review.","minimum":0},"send":{"type":"integer","format":"int32","description":"Count of verifications recommended to send to.","minimum":0}}},"RecommendationCountsDto":{"type":"object","description":"Recommendation-bucket counts (`remove`, `review`, `send`) for a batch's completed jobs.","required":["remove","review","send"],"properties":{"remove":{"type":"integer","format":"int32","minimum":0},"review":{"type":"integer","format":"int32","minimum":0},"send":{"type":"integer","format":"int32","minimum":0}}},"RegisterClientRequest":{"type":"object","description":"`POST /oauth/register` request body (RFC 7591 subset).","required":["client_name","redirect_uris"],"properties":{"client_name":{"type":"string","description":"Human-readable client name (RFC 7591 `client_name`)."},"redirect_uris":{"type":"array","items":{"type":"string"},"description":"Redirect URIs the client may be sent back to after authorization; at least one is required."}}},"RegisterClientResponse":{"type":"object","description":"`POST /oauth/register` response body (RFC 7591 subset).","required":["client_id","client_name","redirect_uris"],"properties":{"client_id":{"type":"string","description":"The generated public `client_id`."},"client_name":{"type":"string","description":"The registered client name, echoed back."},"redirect_uris":{"type":"array","items":{"type":"string"},"description":"The registered redirect URIs, echoed back."}}},"RegisterRequest":{"type":"object","description":"Request body for `POST /api/auth/register`.","required":["email","password"],"properties":{"email":{"type":"string","description":"The email address for the new account."},"locale":{"type":["string","null"],"description":"The language of the page the user signs up on (`\"en\"` or `\"fr\"`), which every email to the account then uses."},"password":{"type":"string","description":"The password for the new account: 12 to 128 characters with an uppercase letter, a digit, and a special\ncharacter."},"preview_token":{"type":["string","null"],"description":"The `preview_token` that `POST /api/auth/signup-preview` returned for this same address: its result stands in\nfor the check registration would otherwise run again. Ignored when unknown, expired, or issued for another\naddress."}}},"ResendConfirmationRequest":{"type":"object","description":"Request body for `POST /api/auth/resend-confirmation`.","required":["email"],"properties":{"email":{"type":"string","description":"The email address of the account requesting a fresh confirmation code."}}},"ResetPasswordRequest":{"type":"object","description":"Request body for `POST /api/auth/reset-password`.","required":["token","new_password"],"properties":{"new_password":{"type":"string","description":"The new password, subject to the same rules as at registration."},"token":{"type":"string","description":"The reset token from the password reset email."}}},"SessionResponse":{"type":"object","description":"Public representation of a session.","required":["uuid","last_active_at","created_at","current"],"properties":{"created_at":{"type":"string","description":"When the session was created (ISO 8601)."},"current":{"type":"boolean","description":"Whether this is the session the request's access token belongs to."},"device_name":{"type":["string","null"],"description":"Device name, if set."},"ip_address":{"type":["string","null"],"description":"IP address of the session origin."},"last_active_at":{"type":"string","description":"When the session was last active (ISO 8601)."},"user_agent":{"type":["string","null"],"description":"User agent of the session origin."},"uuid":{"type":"string","description":"Public UUID."}}},"SignupEligibilityDto":{"type":"string","description":"Whether the previewed address may sign up.","enum":["allowed","undeliverable","disposable","unchecked"]},"SignupPreviewRequest":{"type":"object","description":"Request body for `POST /api/auth/signup-preview`.","required":["email"],"properties":{"email":{"type":"string","description":"The address the visitor is about to sign up with."}}},"SignupPreviewResponse":{"type":"object","description":"Response body for `POST /api/auth/signup-preview`.","required":["signup"],"properties":{"checks":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PreviewChecksDto","description":"Which checks passed, absent when no check ran."}]},"preview_token":{"type":["string","null"],"description":"The handle on the stored result, to send back with `POST /api/auth/register` and `POST /api/auth/confirm`."},"signup":{"$ref":"#/components/schemas/SignupEligibilityDto","description":"Whether the address may sign up."}}},"SmtpCheckDto":{"type":"object","description":"SMTP deliverability probe result.","required":["status"],"properties":{"status":{"$ref":"#/components/schemas/SmtpStatusDto","description":"SMTP probe outcome: `deliverable` (the server accepted the `RCPT TO` command), `undeliverable` (the server\npermanently rejected the recipient, 5xx), `unknown` (no definitive answer: a temporary refusal, a timeout, a\nconnection failure, or a server that refused the probe itself), or `skipped` (not requested, or not\nneeded because the answer was already known)."}}},"SmtpStatusDto":{"type":"string","description":"Outcome of the SMTP probe.","enum":["deliverable","undeliverable","unknown","skipped"]},"StatsOverviewResponse":{"type":"object","description":"JSON response body for `GET /api/stats/overview`.","required":["verdict_breakdown","recommendations","activity","activity_previous","check_usage","totals"],"properties":{"activity":{"type":"array","items":{"$ref":"#/components/schemas/ActivityPointResponse"},"description":"Zero-filled activity time series for the requested window."},"activity_previous":{"type":"array","items":{"$ref":"#/components/schemas/ActivityPointResponse"},"description":"Zero-filled activity time series for the immediately preceding, equal-length window."},"check_usage":{"type":"array","items":{"$ref":"#/components/schemas/CheckUsageResponse"},"description":"Per-check usage counts for the requested window."},"recommendations":{"$ref":"#/components/schemas/RecommendationBreakdownResponse","description":"Per-recommendation-bucket counts for the requested window."},"totals":{"$ref":"#/components/schemas/StatsTotalsResponse","description":"At-a-glance totals for the requested window."},"verdict_breakdown":{"$ref":"#/components/schemas/VerdictBreakdownResponse","description":"Per-status verdict counts for the requested window."}}},"StatsTotalsResponse":{"type":"object","description":"At-a-glance totals in the response body.","required":["verifications_in_range","avg_score","deliverable_pct"],"properties":{"avg_score":{"type":"number","format":"double","description":"Average quality score (0-100) across the window's verifications."},"deliverable_pct":{"type":"number","format":"double","description":"Percentage (0-100) of the window's verifications that resolved `valid`."},"verifications_in_range":{"type":"integer","format":"int32","description":"Number of verifications performed within the selected window.","minimum":0}}},"SubmitBatchRequest":{"type":"object","description":"`POST /api/batches` request body.","required":["emails"],"properties":{"checks":{"type":["array","null"],"items":{"type":"string"},"description":"Optional explicit check names; defaults to every check the caller's plan allows."},"custom_ids":{"type":"array","items":{"type":["string","null"]},"description":"Optional per-email client references, index-aligned 1:1 with `emails`; empty means none."},"emails":{"type":"array","items":{"type":"string"},"description":"Email addresses to verify."},"final":{"type":"boolean","description":"Whether this is the batch's only (or final) chunk. Defaults to `true`, the single-shot behavior."},"name":{"type":["string","null"],"description":"Optional display name for the batch."}}},"SubmitBatchResponse":{"type":"object","description":"`POST /api/batches` response body.","required":["batch_uuid","status","total_jobs","syntax_errors","duplicates","estimated_cost"],"properties":{"batch_uuid":{"type":"string","description":"Public UUID of the batch. Use it with `GET /api/batches/{uuid}` to poll status."},"duplicates":{"type":"integer","format":"int64","description":"Number of submitted addresses that were exact duplicates of an already-accepted one.","minimum":0},"estimated_cost":{"type":"integer","format":"int32","description":"Total tokens reserved for the batch.","minimum":0},"status":{"type":"string","description":"Status of the batch right after submit (always `\"processing\"`)."},"syntax_errors":{"type":"integer","format":"int64","description":"Number of submitted addresses that failed syntax validation.","minimum":0},"total_jobs":{"type":"integer","format":"int64","description":"Number of unique valid emails queued as jobs.","minimum":0}}},"SubmitVerificationRequest":{"type":"object","description":"`POST /api/verify` request body.","required":["email"],"properties":{"email":{"type":"string","description":"Email address to verify."}}},"SubmitVerificationResponse":{"type":"object","description":"`POST /api/verify` response body.","required":["job_uuid","status","estimated_cost","idempotency_key","replayed","email"],"properties":{"email":{"type":"string","description":"Echo of the submitted email address."},"estimated_cost":{"type":"integer","format":"int32","description":"Total tokens reserved for the job.","minimum":0},"idempotency_key":{"type":"string","description":"Resolved idempotency key."},"job_uuid":{"type":"string","description":"Public UUID of the persisted job. Use it with `GET /api/verify/{uuid}` to poll the result."},"replayed":{"type":"boolean","description":"`true` when the response replays a prior submission made with the same idempotency key and the same email."},"status":{"type":"string","description":"Current status of the job (`pending`, `queued`, `processing`, `completed`, `failed`, `canceled`)."},"suggestion":{"type":["string","null"],"description":"Typo-corrected suggestion for the submitted email (e.g. `user@gmial.com` -> `user@gmail.com`), computed\nsynchronously at submit time."}}},"SubscriptionResponse":{"type":"object","description":"JSON response body for `GET /api/subscription`.","required":["plan","status","billing_cycle","period_start","period_end","monthly_credits","has_access"],"properties":{"billing_cycle":{"type":"string","description":"Billing cycle (`\"monthly\"` or `\"yearly\"`)."},"external_id":{"type":["string","null"],"description":"Identifier of the subscription at the payment provider, `null` when there is none."},"has_access":{"type":"boolean","description":"Whether the subscription provides access to the service."},"monthly_credits":{"type":"integer","format":"int32","description":"Tokens granted each month by the plan.","minimum":0},"period_end":{"type":"string","format":"date-time","description":"End of the current billing period."},"period_start":{"type":"string","format":"date-time","description":"Start of the current billing period."},"plan":{"type":"string","description":"Plan code: `\"free\"`, `\"starter\"`, `\"pro\"`, `\"business\"` or `\"enterprise\"`."},"status":{"type":"string","description":"Subscription status: `\"trial\"`, `\"active\"`, `\"past_due\"`, `\"canceled\"`, `\"expired\"` or `\"paused\"`."},"trial_days_remaining":{"type":["integer","null"],"format":"int64","description":"Days remaining in a trial period. `null` when not in trial."}}},"TestWebhookResponse":{"type":"object","description":"`POST /api/webhooks/{uuid}/test` response body: the outcome of the single test-fire attempt.","required":["delivered"],"properties":{"delivered":{"type":"boolean","description":"`true` when the endpoint answered with a 2xx status."},"error":{"type":["string","null"],"description":"A transport error message, or a description of the non-2xx status, `None` on success."},"status_code":{"type":["integer","null"],"format":"int32","description":"The HTTP status the endpoint returned, `None` on a transport-level failure.","minimum":0}}},"TokenErrorResponse":{"type":"object","description":"`POST /oauth/token` error response body (RFC 6749 section 5.2).","required":["error"],"properties":{"error":{"type":"string","description":"One of RFC 6749's defined error codes, such as `\"invalid_grant\"`, `\"invalid_request\"`, or\n`\"unsupported_grant_type\"`."}}},"TokenRequest":{"type":"object","description":"`POST /oauth/token` request body (RFC 6749 sections 4.1.3 and 6), submitted as `application/x-www-form-urlencoded`,\nthe content type every RFC-conformant OAuth client uses for the token endpoint.","required":["grant_type","client_id"],"properties":{"client_id":{"type":"string","description":"The client's public `client_id`."},"code":{"type":["string","null"],"description":"The single-use authorization code to redeem (`authorization_code` grant only)."},"code_verifier":{"type":["string","null"],"description":"The PKCE `code_verifier` (RFC 7636) proving possession of the `code_challenge` presented at `/oauth/authorize`\n(`authorization_code` grant only)."},"grant_type":{"type":"string","description":"Either `\"authorization_code\"` or `\"refresh_token\"`."},"redirect_uri":{"type":["string","null"],"description":"The redirect URI presented at `/oauth/authorize`, re-checked here per RFC 6749 section 4.1.3\n(`authorization_code` grant only)."},"refresh_token":{"type":["string","null"],"description":"The refresh token to redeem (`refresh_token` grant only, RFC 6749 section 6)."}}},"TokenResponse":{"type":"object","description":"`POST /oauth/token` success response body (RFC 6749 section 5.1).","required":["access_token","token_type","expires_in","scope","refresh_token"],"properties":{"access_token":{"type":"string","description":"The agent's short-lived access token (a JWT), sent as a Bearer credential."},"expires_in":{"type":"integer","format":"int64","description":"Seconds until `access_token` expires.","minimum":0},"refresh_token":{"type":"string","description":"A freshly minted refresh token (RFC 6749 section 5.1), issued on every successful grant (both\n`authorization_code` and `refresh_token`)."},"scope":{"type":"string","description":"The granted scopes, space-delimited (RFC 6749 section 5.1): the agent's own current scopes."},"token_type":{"type":"string","description":"Always `\"Bearer\"`."}}},"TopupConfigResponse":{"type":"object","description":"Token top-up pricing.","required":["tokens_per_euro","min_tokens","step_tokens","max_tokens"],"properties":{"max_tokens":{"type":"integer","format":"int32","description":"Maximum token quantity purchasable in a single top-up.","minimum":0},"min_tokens":{"type":"integer","format":"int32","description":"Minimum token quantity purchasable in a single top-up.","minimum":0},"step_tokens":{"type":"integer","format":"int32","description":"Required quantity increment; a top-up quantity must be a multiple of this value (identical to `tokens_per_euro`,\nso every charge is a whole number of cents).","minimum":0},"tokens_per_euro":{"type":"integer","format":"int32","description":"Number of tokens that map to one euro (e.g. `1000` = 0.001 EUR/token).","minimum":0}}},"TwoFactorStatusResponse":{"type":"object","description":"Response body for `GET /api/users/me/2fa`.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether 2FA is enabled for the caller."}}},"TypoCheckDto":{"type":"object","description":"Typo detection result.","required":["detected"],"properties":{"detected":{"type":"boolean","description":"Whether a domain typo was detected."},"suggested_domain":{"type":["string","null"],"description":"Corrected domain only (e.g. `\"gmail.com\"`), present on `GET /api/verify/{uuid}` when a typo was detected."},"suggestion":{"type":["string","null"],"description":"Full corrected address (e.g. `\"user@gmail.com\"`), only ever present on the synchronous submit response where the\nraw email is available in-request."}}},"UpdateApiKeyRequest":{"type":"object","description":"`PATCH /api/keys/{uuid}` request body.","properties":{"enabled_checks":{"type":["array","null"],"items":{"type":"string"},"description":"New set of enabled checks, with the same values as on creation. Left unchanged when absent."},"name":{"type":["string","null"],"description":"New display name. Left unchanged when absent."}}},"UpdateWebhookRequest":{"type":"object","description":"`PATCH /api/webhooks/{uuid}` request body.","properties":{"description":{"type":["string","null"],"description":"New description. Left unchanged when absent."},"events":{"type":["array","null"],"items":{"type":"string"},"description":"New list of subscribed events, with at least one entry. Left unchanged when absent."},"status":{"type":["string","null"],"description":"New status: `\"active\"` or `\"paused\"`. Left unchanged when absent."},"url":{"type":["string","null"],"description":"New HTTPS URL. Left unchanged when absent."}}},"UserResponse":{"type":"object","description":"Public representation of a user.","required":["uuid","email","role","email_verified","locale","created_at"],"properties":{"created_at":{"type":"string","description":"Account creation timestamp (ISO 8601)."},"email":{"type":"string","description":"Email address."},"email_verified":{"type":"boolean","description":"Whether the email has been verified."},"locale":{"type":"string","description":"Language of the account's emails (`\"en\"` or `\"fr\"`)."},"role":{"type":"string","description":"User role (`\"user\"` or `\"admin\"`)."},"uuid":{"type":"string","description":"Public UUID."}}},"VerdictBreakdownResponse":{"type":"object","description":"Per-status verdict counts in the response body.","required":["valid","risky","invalid","unknown"],"properties":{"invalid":{"type":"integer","format":"int32","description":"Count of `invalid` verifications.","minimum":0},"risky":{"type":"integer","format":"int32","description":"Count of `risky` verifications.","minimum":0},"unknown":{"type":"integer","format":"int32","description":"Count of `unknown` verifications.","minimum":0},"valid":{"type":"integer","format":"int32","description":"Count of `valid` verifications.","minimum":0}}},"VerificationResultDto":{"type":"object","description":"Per-email verification projection.","required":["email_hash","domain_hash","status","reason","score","recommendation","verified_at","checks","durations"],"properties":{"checks":{"$ref":"#/components/schemas/ChecksDto","description":"Per-check breakdown of the verification result."},"domain_hash":{"type":"string","description":"Keyed hash of the email domain."},"duration_ms":{"type":["integer","null"],"format":"int64","minimum":0},"durations":{"$ref":"#/components/schemas/CheckDurationsDto","description":"Per-check elapsed time in milliseconds."},"email_hash":{"type":"string","description":"Keyed hash of the normalized email address."},"reason":{"type":"string"},"recommendation":{"type":"string","description":"Deterministic list-cleaning action derived from `status`, `reason`, and the typo flag: one of `\"remove\"`,\n`\"send\"`, or `\"review\"`. A presentation layer on top of the honest verdict above, not a replacement for it."},"score":{"type":"integer","format":"int32","minimum":0},"status":{"type":"string"},"verified_at":{"type":"string"}}},"Verify2FARequest":{"type":"object","description":"Request body for `POST /api/auth/2fa/verify`.","required":["temp_token","code"],"properties":{"code":{"type":"string","description":"The TOTP code or backup code."},"temp_token":{"type":"string","description":"The `temp_token` returned by login when 2FA is required."}}},"Verify2FASetupRequest":{"type":"object","description":"Request body for `POST /api/users/me/2fa/verify-setup`.","required":["code"],"properties":{"code":{"type":"string","description":"A current TOTP code generated from the secret returned at enable time."}}},"VerifyEmailChangeRequest":{"type":"object","description":"Request body for `POST /api/auth/verify-email-change`.","required":["token"],"properties":{"token":{"type":"string","description":"The confirmation token from the link in the email-change email."}}},"WalletBalanceResponse":{"type":"object","description":"JSON response body for `GET /api/wallet`.","required":["available","reserved","total","updated_at","avg_daily_spend"],"properties":{"available":{"type":"integer","format":"int32","description":"Tokens available for immediate use.","minimum":0},"avg_daily_spend":{"type":"integer","format":"int32","description":"Mean daily spend (committed plus debited tokens) over the last 30 days, rounded down.","minimum":0},"reserved":{"type":"integer","format":"int32","description":"Tokens reserved by in-flight jobs.","minimum":0},"total":{"type":"integer","format":"int32","description":"Total tokens (available + reserved), capped at 4294967295.","minimum":0},"updated_at":{"type":"string","format":"date-time","description":"Timestamp of the last balance update."}}},"WalletTransactionGroupItem":{"type":"object","description":"A single entry of the job-grouped response: every transaction sharing the same `job_uuid` collapsed into one group.","required":["last_status","net_amount","occurred_at","entries"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/WalletTransactionItem"},"description":"Every transaction in the group, oldest first (for example a reservation followed by its commit or cancel)."},"job_uuid":{"type":["string","null"],"format":"uuid","description":"Public UUID of the linked verification job. `null` for a credit or top-up, which is its own single-entry group."},"last_status":{"type":"string","description":"The transaction type of the group's most recent entry (`\"Reservation\"`, `\"Commit\"`, `\"Cancel\"`, `\"Credit\"` or\n`\"Debit\"`), which is the job's current billing state."},"net_amount":{"type":"integer","format":"int64","description":"The signed net effect of the whole group on the wallet: positive for a net inflow (a credit, or a\ncanceled/refunded reservation), negative for a net outflow (a debit, a pending reservation, or a\ncommitted/billed job)."},"occurred_at":{"type":"string","format":"date-time","description":"Timestamp of the group's most recent entry."}}},"WalletTransactionGroupsResponse":{"type":"object","description":"JSON response body for `GET /api/wallet/transactions/grouped`.","required":["groups","limit","offset"],"properties":{"groups":{"type":"array","items":{"$ref":"#/components/schemas/WalletTransactionGroupItem"},"description":"Transaction groups of the page."},"limit":{"type":"integer","format":"int64","description":"Page size applied after clamping, counted in groups."},"offset":{"type":"integer","format":"int64","description":"Offset applied, counted in groups."}}},"WalletTransactionItem":{"type":"object","description":"A single transaction item in the response list.","required":["transaction_type","amount","context","occurred_at"],"properties":{"amount":{"type":"integer","format":"int32","description":"Token amount moved.","minimum":0},"context":{"type":"string","description":"Short label describing why the transaction happened."},"job_uuid":{"type":["string","null"],"format":"uuid","description":"Public UUID of the linked verification job, when the transaction is tied to one."},"occurred_at":{"type":"string","format":"date-time","description":"RFC 3339 timestamp of the transaction."},"transaction_type":{"type":"string","description":"Transaction type: `\"Credit\"`, `\"Debit\"`, `\"Reservation\"`, `\"Commit\"` or `\"Cancel\"`."}}},"WalletTransactionsResponse":{"type":"object","description":"JSON response body for `GET /api/wallet/transactions`.","required":["transactions","limit","offset"],"properties":{"limit":{"type":"integer","format":"int64","description":"Page size applied after clamping."},"offset":{"type":"integer","format":"int64","description":"Offset applied."},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/WalletTransactionItem"},"description":"Transactions of the page."}}},"WebhookDeliveryItem":{"type":"object","description":"One delivery attempt listed by `GET /api/webhooks/{uuid}/deliveries`.","required":["event","job_uuid","attempt_number","is_test","created_at"],"properties":{"attempt_number":{"type":"integer","format":"int32","description":"Attempt number, starting at 1.","minimum":0},"created_at":{"type":"string","description":"RFC 3339 timestamp of the attempt."},"event":{"type":"string","description":"Event that was delivered, for example `\"job.completed\"`."},"is_test":{"type":"boolean","description":"`true` for an attempt made by `POST /api/webhooks/{uuid}/test`."},"job_uuid":{"type":"string","description":"UUID of the job the event relates to (all zeros for a test attempt)."},"response_body":{"type":["string","null"],"description":"Response body returned by the endpoint, omitted when there was none."},"response_status":{"type":["integer","null"],"format":"int32","description":"HTTP status returned by the endpoint, omitted when the request failed before a response.","minimum":0}}},"WebhookResponse":{"type":"object","description":"Metadata of a webhook endpoint, returned when listing, reading or updating endpoints.","required":["uuid","url","events","status","total_deliveries","successful_deliveries","consecutive_failures","created_at"],"properties":{"consecutive_failures":{"type":"integer","format":"int32","description":"Number of failed deliveries in a row since the last success.","minimum":0},"created_at":{"type":"string","description":"RFC 3339 creation timestamp."},"description":{"type":["string","null"],"description":"Description of the endpoint, omitted when none was set."},"events":{"type":"array","items":{"type":"string"},"description":"Events the endpoint is subscribed to."},"last_delivery_at":{"type":["string","null"],"description":"RFC 3339 timestamp of the last delivery, omitted when there was none."},"status":{"type":"string","description":"Status of the endpoint: `\"active\"`, `\"paused\"` or `\"disabled\"`."},"successful_deliveries":{"type":"integer","format":"int64","description":"Number of deliveries the endpoint acknowledged with a 2xx status.","minimum":0},"total_deliveries":{"type":"integer","format":"int64","description":"Number of deliveries attempted.","minimum":0},"url":{"type":"string","description":"URL that receives the notifications."},"uuid":{"type":"string","description":"Public UUID of the endpoint."}}}},"securitySchemes":{"bearer_api_key":{"type":"http","scheme":"bearer","description":"A `pm_live_*` or `pm_test_*` API key."},"jwt":{"type":"http","scheme":"bearer","description":"A short-lived token from `/api/auth/login`, or `/oauth/token` for an agent."}}},"tags":[{"name":"config","description":"Public, unauthenticated pricing and plan configuration."},{"name":"verification","description":"Verify one address and read its result."},{"name":"batches","description":"Verify a list of addresses: submit, append, list, and read the results."},{"name":"agents","description":"The AI agents allowed to act on your account, each with its own scopes."},{"name":"auth","description":"Registration, login, token refresh, password reset, and 2FA."},{"name":"api-keys","description":"Create, list, update, and revoke API keys, and inspect the key in use."},{"name":"webhooks","description":"Webhook endpoints that receive your verification events."},{"name":"account","description":"The authenticated user's own profile, email, password, and 2FA."},{"name":"sessions","description":"The authenticated user's active sessions."},{"name":"notifications","description":"What happened on your account, as a read-only history."},{"name":"wallet","description":"Your token balance and its ledger."},{"name":"jobs","description":"Your verification jobs and their details."},{"name":"stats","description":"Your usage statistics, and the public service figures."},{"name":"subscription","description":"The caller's subscription plan and status."},{"name":"billing","description":"Checkout and billing portal sessions."},{"name":"oauth","description":"OAuth 2.1 authorization server: dynamic client registration (RFC 7591), discovery metadata (RFC 8414), and the authorization-code-with-PKCE flow (authorize, consent, token)."}]}