{"openapi":"3.1.0","info":{"title":"Aerosend Developer API","description":"# Introduction\n\nWelcome to the Aerosend Developer API! Aerosend is a comprehensive platform that enables you to manage your email domains, mailboxes, organizational tags, inbox placement analytics, and warmup scores programmatically. Whether you're building integrations, automating email workflows, or managing large-scale email operations, our API provides the tools you need.\n\n## What Aerosend Provides\n\nAerosend helps you manage your account efficiently:\n\n- **Domain Management**: Add, manage, and monitor your email domains\n- **Mailbox Management**: Create and manage email mailboxes across your domains, with support for SMTP and IMAP access credentials\n- **Tagging System**: Organize your domains and mailboxes using custom tags for better categorization and filtering\n- **Inbox Placement Analytics**: Retrieve inbox placement analytics, including overall delivery metrics, Google and Outlook totals, ESP breakdown, and per-domain performance\n- **Warmup Scores**: Retrieve warmup scores and warmup start dates for each mailbox\n- **Real-time Status**: Track the status of your domains and mailboxes (active, inactive, pending, in progress)\n- **Comprehensive Filtering**: Search and filter your resources by various criteria including status, tags, domain associations, and more\n\nThe API is designed to be RESTful, intuitive, and consistent, making it easy to integrate Aerosend into your applications and workflows.\n\n---\n\n# Getting Started\n\nBefore you can start making API requests, you'll need to generate an API key from your Aerosend account.\n\n## Generating Your API Key\n\n1. **Log in to your Aerosend account** at https://app.aerosend.io\n2. **Navigate to the Developer module** in your account dashboard\n3. **Click \"Generate API Key\"** and provide a name for your key\n4. **Copy your API key immediately** - it will be displayed only once for security reasons\n5. **Store it securely** in your application's environment variables or secure configuration\n\n⚠️ **Important Security Notes**:\n- You can only have **one API key** at a time\n- Your API key will **never be shown again** after the initial generation\n- If you lose your API key, you'll need to generate a new one\n- **Regenerating an API key will immediately revoke the old key** - any applications using the old key will stop working\n- Treat your API key like a password - never commit it to version control or share it publicly\n\nOnce you have your API key, you're ready to start making API requests!\n\n---\n\n# Authentication\n\nAll API requests must include your API key in the `X-API-Key` header:\n\n**Example Request**:\n```\nGET /api/v1/domains\nX-API-Key: your-api-key-here\n```\n\nIf your API key is invalid, expired, or missing, you'll receive a `401 Unauthorized` response. Make sure to:\n- Include the `X-API-Key` header in every request\n- Use the exact key value (no extra spaces or characters)\n- Ensure your API key hasn't been regenerated (which would revoke the old key)\n\n---\n\n# Rate Limiting\n\nTo ensure fair usage and maintain system stability, the Aerosend API enforces rate limits on all requests.\n\n## Rate Limit Details\n\n- **Limit**: 60 requests per minute per API key\n- **Window**: Rolling 60-second window\n\n## Rate Limit Headers\n\nEvery API response includes rate limit information in the response headers:\n\n- `X-RateLimit-Limit`: The maximum number of requests allowed (always `60`)\n- `X-RateLimit-Remaining`: The number of requests remaining in the current window\n- `X-RateLimit-Reset`: Unix timestamp (in seconds) when the rate limit window resets\n\n**Example Headers**:\n```\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 45\nX-RateLimit-Reset: 1702564800\n```\n\n## Handling Rate Limits\n\nIf you exceed the rate limit, you'll receive a `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds you should wait before retrying.\n\n**Best Practices**:\n- Monitor the `X-RateLimit-Remaining` header to track your usage\n- Implement exponential backoff when you receive a 429 response\n- Use the `Retry-After` header value to determine when to retry\n- Consider implementing request queuing or throttling in your application\n\n---\n\n# Request Tracking\n\nEvery API response includes an `X-Request-Id` header containing a unique identifier for that specific request.\n\n**Example**: `X-Request-Id: req_17ht01iv20aj02jm`\n\n## Why Request IDs Matter\n\nRequest IDs are essential for troubleshooting and support:\n\n- **Error Diagnosis**: If you encounter an error, include the request ID when contacting support\n- **Request Correlation**: Track a specific request through our systems for debugging\n- **Logging**: Include request IDs in your application logs to correlate client-side and server-side events\n- **Support Tickets**: When reporting issues, provide the request ID to help our team quickly locate and diagnose problems\n\nAlways log and store the `X-Request-Id` from responses, especially when handling errors. This information significantly speeds up issue resolution.\n\n---\n\n# Pagination\n\nList endpoints (domains, mailboxes, tags, warmup scores) support pagination to help you efficiently retrieve large datasets. Inbox placement analytics (`GET /api/v1/analytics/inbox-placement`) is **not paginated** — the full result set is returned in a single response.\n\n## Pagination Parameters\n\n- **offset**: Number of items to skip before starting to return results (default: `0`)\n- **limit**: Maximum number of items to return in a single request (default: `20`, maximum: `100`)\n\n**Example Request**:\n```\nGET /api/v1/domains?offset=20&limit=50\n```\n\nThis would skip the first 20 items and return up to 50 items.\n\n## Pagination Best Practices\n\n- Use smaller limits for faster response times\n- Use larger limits (up to 100) when you need to retrieve more data in fewer requests\n- Always check the total count and has_more flag in the response to determine if more pages are available\n- Implement proper error handling for pagination edge cases\n\n---\n\n# Error Handling\n\nThe Aerosend API uses consistent error responses to make error handling straightforward in your applications.\n\n## Error Response Format\n\nAll errors return a JSON object with the following structure:\n\n```json\n{\n    \"success\": false,\n    \"error\": \"ERROR_CODE\",\n    \"message\": \"Human-readable error message\",\n    \"timestamp\": \"2025-12-14T10:30:00Z\",\n    \"request_id\": \"req_17ht01iv20aj02jm\"\n}\n```\n\n## HTTP Status Codes\n\nThe API uses standard HTTP status codes:\n\n- **200 OK**: Request succeeded\n- **400 Bad Request**: Invalid request parameters or validation errors\n- **401 Unauthorized**: Invalid or missing API key\n- **403 Forbidden**: Valid API key but insufficient permissions\n- **404 Not Found**: Requested resource doesn't exist\n- **409 Conflict**: Resource conflict (e.g., duplicate email address)\n- **429 Too Many Requests**: Rate limit exceeded\n- **500 Internal Server Error**: Unexpected server error\n\n## Error Handling Best Practices\n\n- Always check the `success` field in responses\n- Read the `message` field for user-friendly error descriptions\n- Use the `error` code for programmatic error handling\n- Include the `request_id` when logging errors or contacting support\n- Implement retry logic for transient errors (429, 500)\n- Validate input before sending requests to avoid validation errors\n- Handle rate limit errors gracefully with exponential backoff\n\n---\n\n# Support and Resources\n\nIf you need help or have questions about the API, explore the endpoint documentation below for detailed information about each API operation.\n\nWhen contacting support, please include:\n- The `X-Request-Id` from the problematic request\n- A description of what you were trying to accomplish\n- Any relevant error messages or response bodies\n\n---\n\n# Use Aerosend from AI assistants (MCP)\n\nAerosend has a hosted MCP server, so Claude, ChatGPT, Cursor, VS Code and any other MCP client can manage your account directly.\n\n- Endpoint: `https://mcp.aerosend.io/mcp` (Streamable HTTP)\n- Auth: sign in with OAuth, or send `X-API-Key` with the same key you use for this API\n- Setup guide: https://www.aerosend.io/mcp/ (also `GET /mcp` on this host)\n- Docs for LLMs: https://api.aerosend.io/llms.txt\n","contact":{"name":"Aerosend Support","url":"https://aerosend.io","email":"support@aerosend.io"},"license":{"name":"Proprietary","url":"https://aerosend.io/terms-of-service"},"version":"1.5.0"},"servers":[{"url":"https://api.aerosend.io","description":"API Server"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Tags","description":"Tag management endpoints"},{"name":"Domains","description":"Domain management endpoints"},{"name":"Purchase","description":"Purchase domain and mailbox slots"},{"name":"Lead Scrapers","description":"Lead scraper catalog and input validation"},{"name":"Client","description":"Client profile and usage endpoints"},{"name":"Mailboxes","description":"Mailbox management endpoints"},{"name":"Health","description":"API health check endpoints"},{"name":"Domain Burn Alerts","description":"Sequencer connection, domain burn scans and burn reports"},{"name":"Analytics","description":"Inbox placement and warmup score analytics endpoints"}],"paths":{"/api/v1/tags/{tagId}":{"get":{"tags":["Tags"],"summary":"Get tag by ID","description":"Returns detailed information about a specific tag including domain and mailbox counts which is mapped to the tag.","operationId":"getTagById","parameters":[{"name":"tagId","in":"path","description":"Tag ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"include_counts","in":"query","description":"Include domain and mailbox counts","required":false,"schema":{"type":"boolean","default":true},"example":true}],"responses":{"200":{"description":"Successfully retrieved tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResponse"},"examples":{"TagGetSuccess":{"description":"TagGetSuccess","value":{"success":true,"data":{"id":1,"name":"client-marketing","display_name":"Client Marketing","color":"#000369","status":"active","domain_count":10,"mailbox_count":45,"created_at":"2025-12-01T10:30:00Z","updated_at":"2025-12-10T15:45:00Z"},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Tag not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"TagGetNotFound":{"description":"TagGetNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Tag not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"put":{"tags":["Tags"],"summary":"Update tag","description":"Updates a tag's display name and/or color. Only the specified fields are updated.\n\n## Behavior\n- You can update either `display_name`, `color`, or both\n- If `display_name` is updated, the normalized name is automatically recalculated\n- At least one field (`display_name` or `color`) must be provided\n- The tag's mappings to domains and mailboxes remain unchanged\n\n## Color Validation\n- **color**: Hex color code for the tag\n- Must start with `#` followed by hexadecimal characters (0-9, a-f, A-F)\n- Valid formats: `#000369`, `#abc123`, `#f00`\n- Maximum length: 8 characters (including `#`)\n- Invalid color formats will be rejected with a validation error\n\n## Validation\n- The tag ID must exist and belong to the authenticated client\n- `display_name` must be between 1 and 255 characters (if provided)\n- `color` must be a valid hex color code (max 8 characters)\n- If updating `display_name`, the normalized name must be unique (cannot match another tag's normalized name)\n- If the normalized name already exists for another tag, a conflict error will be returned\n","operationId":"updateTag","parameters":[{"name":"tagId","in":"path","description":"Tag ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTagRequest"}}},"required":true},"responses":{"200":{"description":"Tag updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResponse"},"examples":{"TagUpdateSuccess":{"description":"TagUpdateSuccess","value":{"success":true,"data":{"id":1,"name":"sales-team-abc","display_name":"Sales Team ABC","color":"#10B981","status":"active","created_at":"2025-12-01T10:30:00Z","updated_at":"2025-12-14T15:45:00Z"},"timestamp":"2025-12-14T15:45:00Z"}}}}}},"400":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"TagUpdateValidationError":{"description":"TagUpdateValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"At least one field (display_name or color) must be provided","timestamp":"2025-12-14T10:30:00Z"}},"TagUpdateColorValidationError":{"description":"TagUpdateColorValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"tags[0].color","message":"color must be a valid hex color code starting with # followed by hexadecimal characters (e.g., #000369, #abc123, #f00)"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"409":{"description":"Conflict - Tag name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TagUpdateNameConflict":{"description":"TagUpdateNameConflict","value":{"success":false,"error":"TAG_NAME_ALREADY_EXISTS","message":"A tag with the name 'Sales Team' already exists. Tag names must be unique.","timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Tag not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"TagUpdateNotFound":{"description":"TagUpdateNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Tag not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domains/redirect-urls":{"put":{"tags":["Domains"],"summary":"Update domain redirect URLs","description":"Updates redirect URLs for one or more domains. This endpoint allows you to efficiently update\nredirect URLs for multiple domains in a single request.\n\n## Redirect URL Validation\n- Redirect URLs are validated according to RFC standards (same validation as domain names)\n- Protocol (http://, https://) and trailing slashes are automatically removed\n- Redirect URLs are normalized to lowercase\n- Each redirect URL must be a valid domain format (e.g., `mysite.com`, `example.co.in`)\n\n## Behavior\n- You can update redirect URLs for one or multiple domains in a single request\n- All domain IDs must exist and belong to the authenticated client\n- Duplicate domain IDs in the request are rejected\n- All redirect URLs are validated before any updates are performed (atomic operation)\n\n## Use Cases\n- **Single domain**: Update redirect URL for one domain\n- **Multiple domains**: Efficiently update redirect URLs for multiple domains at once\n- **Bulk operations**: Update redirect URLs for up to 100 domains per request\n","operationId":"updateRedirectUrls","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDomainRedirectUrlsRequest"}}},"required":true},"responses":{"204":{"description":"Redirect URLs updated successfully"},"400":{"description":"Invalid request - validation error, invalid redirect URL format, or domain not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"Invalid redirect URL format":{"description":"Invalid redirect URL format","value":{"success":false,"error":"INVALID_REDIRECT_URL_FORMAT","message":"Invalid redirect URL format: Domain ID 123: Invalid domain syntax. Domain must follow RFC standards (e.g., example.com)","timestamp":"2025-12-14T10:30:00Z"}},"Domain not found":{"description":"Domain not found","value":{"success":false,"error":"DOMAIN_NOT_FOUND","message":"The following domain IDs do not exist","timestamp":"2025-12-14T10:30:00Z"}},"Duplicate domain IDs":{"description":"Duplicate domain IDs","value":{"success":false,"error":"DUPLICATE_DOMAIN_IDS","message":"Duplicate domain IDs in request: 123","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/tags":{"get":{"tags":["Tags"],"summary":"List Tags","description":"Returns a paginated list of tags for the authenticated client.\n\n## Tag Naming\nTags are stored with both a normalized name (lowercase, hyphenated) and a display name.\nWhen you search for a tag, we normalize your query to match against the stored name.\n\nFor example:\n- Display name: \"Client 123\"\n- Normalized name: \"client-123\"\n\n## Usage Counts\nSet `include_counts=true` to get the number of domains and mailboxes using each tag.\n","operationId":"listTags","parameters":[{"name":"offset","in":"query","description":"Number of items to skip","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0},"example":0},{"name":"limit","in":"query","description":"Maximum items to return (1-100)","required":false,"schema":{"type":"integer","format":"int32","default":20,"maximum":100,"minimum":1},"example":20},{"name":"sort","in":"query","description":"Sort order","required":false,"schema":{"type":"string","enum":["latest","oldest"],"pattern":"^(latest|oldest)$"},"example":"latest"},{"name":"search","in":"query","description":"Search by tag name","required":false,"schema":{"type":"string"},"example":"client-abc"},{"name":"status","in":"query","description":"Filter by status","required":false,"schema":{"type":"string"},"example":"active"},{"name":"include_counts","in":"query","description":"Include domain and mailbox counts","required":false,"schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Successfully retrieved tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"},"examples":{"TagListSuccess":{"description":"TagListSuccess","value":{"success":true,"data":[{"id":1,"name":"client-123","display_name":"Client 123","color":"#000369","status":"active","domain_count":10,"mailbox_count":45,"created_at":"2025-12-01T10:30:00Z","updated_at":"2025-12-10T15:45:00Z"},{"id":2,"name":"sales-team","display_name":"Sales Team","color":"#10B981","status":"active","domain_count":5,"mailbox_count":25}],"pagination":{"offset":0,"limit":20,"total":15,"has_more":false},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"LimitValidationError":{"description":"LimitValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"limit","message":"limit must be >= 1"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Tags"],"summary":"Create tags","description":"Creates one or more tags for the authenticated client.\n\n## Tag Naming\n- You provide a human-friendly `display_name` (e.g., \"Sales Team ABC\")\n- The API normalizes it into a fast, queryable `name` (e.g., `sales-team-abc`)\n- If a tag with the same normalized name already exists, the existing tag is returned (idempotent)\n\n## Color Validation\n- **color**: Optional hex color code for the tag\n- Must start with `#` followed by hexadecimal characters (0-9, a-f, A-F)\n- Valid formats: `#000369`, `#abc123`, `#f00`\n- Maximum length: 8 characters (including `#`)\n- Invalid color formats will be rejected with a validation error\n\n","operationId":"saveTags","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveTagsRequest"}}},"required":true},"responses":{"201":{"description":"Tags created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveTagsApiResponse"},"examples":{"TagCreateSuccess":{"description":"TagCreateSuccess","value":{"success":true,"data":[{"id":1,"name":"sales-team-abc","display_name":"Sales Team ABC","color":"#000369","status":"active"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"TagCreateValidationError":{"description":"TagCreateValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"tags[0].display_name","message":"display_name is required"}],"timestamp":"2025-12-14T10:30:00Z"}},"TagCreateColorValidationError":{"description":"TagCreateColorValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"tags[0].color","message":"color must be a valid hex color code starting with # followed by hexadecimal characters (e.g., #000369, #abc123, #f00)"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Tags"],"summary":"Delete tags","description":"Deletes one or more tags for the authenticated client.\n\n## Behavior\n- Deleting a tag also deletes its mappings to domains and mailboxes\n- If any of the requested tag IDs do not exist,\n  the request fails with a clear error message\n","operationId":"deleteTags","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteTagsRequest"}}},"required":true},"responses":{"204":{"description":"Tags deleted successfully"},"400":{"description":"One or more tags not found for the client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TagDeleteError":{"description":"TagDeleteError","value":{"success":false,"error":"TAG_NOT_FOUND","message":"Some tags do not exist","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/tags/mailboxes/mapping":{"post":{"tags":["Tags"],"summary":"Map tags to mailboxes","description":"Maps one or more tags directly to one or more mailboxes.\n\n## Behavior\n- If a tag-mailbox mapping already exists, it is ignored (no error)\n\n## Validation\n- All tag IDs must exist and belong to the authenticated client\n- All mailbox IDs must belong to the authenticated client\n","operationId":"mapTagsToMailboxes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxTagMappingRequest"}}},"required":true},"responses":{"204":{"description":"Tags mapped successfully"},"400":{"description":"Invalid tag or mailbox IDs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TagMailboxMappingError":{"description":"TagMailboxMappingError","value":{"success":false,"error":"TAG_NOT_FOUND","message":"Some tags do not exist","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/tags/domains/mapping":{"post":{"tags":["Tags"],"summary":"Map tags to domains","description":"Maps one or more tags to one or more domains.\n\n## Behavior\n- If a tag-domain mapping already exists, it is ignored (no error)\n- If `include_domain_mailboxes=true`, the same tags are also applied to all mailboxes\n  belonging to the specified domains\n\n## Validation\n- All tag IDs must exist and belong to the authenticated client\n- All domain IDs must belong to the authenticated client\n","operationId":"mapTagsToDomains","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainTagMappingRequest"}}},"required":true},"responses":{"204":{"description":"Tags mapped successfully"},"400":{"description":"Invalid tag or domain IDs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"TagDomainMappingError":{"description":"TagDomainMappingError","value":{"success":false,"error":"TAG_NOT_FOUND","message":"Some tags do not exist","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/mailboxes":{"get":{"tags":["Mailboxes"],"summary":"List mailboxes","description":"Returns a paginated list of mailboxes for the authenticated client.\n\n## Filtering\n- **search**: Filter by email address (partial match)\n- **status**: Filter by status. Valid values: `active`, `inactive`, `pending`, `in_progress`\n- **domain_id**: Filter by specific domain\n- **tag_ids**: Filter by tag IDs (comma-separated)\n\n## Sorting\n- **sort**: Order by creation date. Valid values: `latest` or `oldest` (default: `latest`)\n- Invalid sort values will be rejected with a validation error\n\n## Tags\n- **include_tags**: Include tags in response (default: `false`)\n- Tag filtering via `tag_ids` works regardless of the `include_tags` flag\n- When `include_tags=false`, tags are not included in the response but filtering still applies\n\n## Credentials\nSet `include_credentials=true` to include SMTP and IMAP connection details.\n**Note**: Credentials are not cached for security reasons.\n\n## SMTP/IMAP Configuration\nWhen credentials are requested:\n- **SMTP**: smtp.topdeliverabilityninja.com:587 (TLS)\n- **IMAP**: Retrieved from domain's mail server (SSL, port 993)\n","operationId":"listMailboxes","parameters":[{"name":"offset","in":"query","description":"Number of items to skip","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0},"example":0},{"name":"limit","in":"query","description":"Maximum items to return (1-100)","required":false,"schema":{"type":"integer","format":"int32","default":20,"maximum":100,"minimum":1},"example":20},{"name":"sort","in":"query","description":"Sort order","required":false,"schema":{"type":"string","enum":["latest","oldest"],"pattern":"^(latest|oldest)$"},"example":"latest"},{"name":"search","in":"query","description":"Search by email address","required":false,"schema":{"type":"string"},"example":"john@"},{"name":"status","in":"query","description":"Filter by status. Valid values: active, inactive, pending, in_progress","required":false,"schema":{"type":"string","enum":["active","inactive","pending","in_progress"]},"example":"active"},{"name":"domain_id","in":"query","description":"Filter by domain ID","required":false,"schema":{"type":"integer","format":"int64"},"example":123},{"name":"tag_ids","in":"query","description":"Filter by tag IDs (comma-separated)","required":false,"schema":{"type":"array","items":{"type":"integer","format":"int64"}},"example":"1,2,3"},{"name":"include_credentials","in":"query","description":"Include SMTP/IMAP credentials","required":false,"schema":{"type":"boolean","default":false},"example":false},{"name":"include_tags","in":"query","description":"Include tags in response. Tag filtering still works regardless of this flag.","required":false,"schema":{"type":"boolean","default":false},"example":false}],"responses":{"200":{"description":"Successfully retrieved mailboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxListResponse"},"examples":{"MailboxListSuccess":{"description":"MailboxListSuccess","value":{"success":true,"data":[{"id":456,"email":"john@example.com","first_name":"John","last_name":"Doe","status":"active","domain_id":123,"created_at":"2025-12-01T10:30:00Z","updated_at":"2025-12-10T15:45:00Z","tags":[{"id":1,"name":"sales-team","display_name":"Sales Team","color":"#10B981"}]}],"pagination":{"offset":0,"limit":20,"total":500,"has_more":true},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"MailboxListValidationError":{"description":"MailboxListValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"offset","message":"offset must be >= 0"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Mailboxes"],"summary":"Add mailboxes","description":"Adds one or more mailboxes for the authenticated client.\n\n## Email Validation\n- Email format is validated (must be valid RFC format)\n- Email is automatically normalized (lowercase)\n\n## Domain Validation\n- Domain must exist and belong to the client\n- Domain must be active (inactive domains cannot have mailboxes added)\n- If domain does not exist, all non-existent domains are returned in the error\n- If domain is inactive, all inactive domains are returned in the error\n\n## Mailbox Limits\n- Maximum mailboxes per domain: 3\n- If limit would be exceeded, error is returned with details\n\n## Duplicate Check\n- Email addresses must be unique within a domain\n- If duplicates exist, all duplicate emails are returned in the error\n\n## Default Settings\n- All new mailboxes have status set to `pending`\n","operationId":"addMailboxes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddMailboxesRequest"}}},"required":true},"responses":{"201":{"description":"Mailboxes added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddMailboxesApiResponse"},"examples":{"MailboxAddSuccess":{"description":"MailboxAddSuccess","value":{"success":true,"data":{"added_count":2,"mailboxes":[{"id":456,"email":"john.doe@example.com","domain_id":123,"status":"pending"},{"id":457,"email":"jane.smith@example.com","domain_id":123,"status":"pending"}]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request - validation error or invalid email format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"Invalid email format":{"description":"Invalid email format","value":{"success":false,"error":"INVALID_EMAIL_FORMAT","message":"Invalid email format: invalid-email: Invalid email format. Email must be in the format: user@domain.com","timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"MailboxAddDomainNotFound":{"description":"MailboxAddDomainNotFound","value":{"success":false,"error":"DOMAIN_NOT_FOUND","message":"The following domains do not exist for this client: example.com, test.com","timestamp":"2025-12-14T10:30:00Z"}}}}}},"409":{"description":"Conflict - Duplicate email, mailbox limit exceeded, or domain inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"Duplicate email":{"description":"Duplicate email","value":{"success":false,"error":"DUPLICATE_EMAIL","message":"The following emails already exist: john@example.com, jane@example.com","timestamp":"2025-12-14T10:30:00Z"}},"Mailbox limit exceeded":{"description":"Mailbox limit exceeded","value":{"success":false,"error":"MAILBOX_LIMIT_EXCEEDED","message":"Mailbox limit exceeded for domains: example.com (current: 3, requested: 1, max: 3)","timestamp":"2025-12-14T10:30:00Z"}},"Domain inactive":{"description":"Domain inactive","value":{"success":false,"error":"DOMAIN_INACTIVE","message":"Cannot add mailboxes to inactive domains: example.com, test.com","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Mailboxes"],"summary":"Delete mailboxes","description":"Deletes one or more mailboxes for the authenticated client.\n\n## Deletion Rules\n- Only mailboxes with `pending` status can be deleted\n- Mailboxes with other statuses are skipped and returned in the response\n\n## Identifiers\n- Can delete by mailbox IDs (`ids` array)\n- Can delete by email addresses (`emails` array)\n- Can use both IDs and emails in the same request\n- At least one identifier type must be provided\n\n## Response\n- Returns count of successfully deleted mailboxes\n- Returns list of skipped mailboxes with reasons\n","operationId":"deleteMailboxes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMailboxesRequest"}}},"required":true},"responses":{"200":{"description":"Mailboxes deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMailboxesApiResponse"},"examples":{"MailboxDeleteSuccess":{"description":"MailboxDeleteSuccess","value":{"success":true,"data":{"deleted_count":2,"skipped":[{"id":789,"email":"active@example.com","reason":"Mailbox is not in pending status. Current status: active"}]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request - missing identifiers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"MailboxDeleteValidationError":{"description":"MailboxDeleteValidationError","value":{"success":false,"error":"MISSING_IDENTIFIERS","message":"Either 'ids' or 'emails' must be provided","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/mailboxes/rename-request":{"post":{"tags":["Mailboxes"],"summary":"Request mailbox rename","description":"Submits a rename request for one or more mailboxes for the authenticated client. **Mailboxes are not renamed.**\n\n## Rename Rules\n- Changes the email address and/or first and last name\n- Mailboxes that are not `pending` (typically `active`) are included in the request\n- The Aerosend team handles the change\n- Mailboxes with `pending` status are skipped. Delete the pending mailbox and add a new one instead\n- Does **not** change the mailbox\n\n## Identifiers\n- Each item needs `id` or the current `email`\n- Each item also needs `new_email` and/or `new_first_name` / `new_last_name`\n\n## Response\n- Returns the current address and the requested email or name\n- Returns skipped mailboxes with reasons\n- Returns identifiers that were not found on the account\n","operationId":"requestMailboxRename","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxRenameRequest"}}},"required":true},"responses":{"200":{"description":"Rename request submitted, or pending mailboxes were skipped","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxRenameRequestApiResponse"},"examples":{"MailboxRenameRequestSuccess":{"description":"MailboxRenameRequestSuccess","value":{"success":true,"data":{"requested_count":1,"requested_mailboxes":[{"id":456,"email":"john@example.com","status":"active","new_email":"jane@example.com","first_name":"John","last_name":"Doe","new_first_name":"Jane","new_last_name":"Doe"}],"skipped":[],"not_found":[],"message":"Rename request submitted for 1 mailbox(es). Mailboxes have not been renamed. The Aerosend team has been notified."},"timestamp":"2026-04-07T10:30:00Z"}}}}}},"400":{"description":"No matching mailboxes, or the mailbox list is empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"NoMatchingMailboxes":{"description":"NoMatchingMailboxes","value":{"success":false,"error":"NO_MATCHING_MAILBOXES","message":"None of the requested mailboxes belong to this account","timestamp":"2026-04-07T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/lead-scrapers/submissions":{"post":{"tags":["Lead Scrapers"],"summary":"Submit lead scraper inputs","description":"Submits lead scraper inputs for the authenticated client. Validates them and returns the accepted params.\n\n## Behavior\n- Does not store a job\n- Does not charge and does not start a scrape\n- To price or pay, use `POST /api/v1/lead-scrapers/payment-preview` and `POST /api/v1/lead-scrapers/payment`\n\n## Validation\n- **scraper_id**: must be an id from `GET /api/v1/lead-scrapers`\n- **params**: object whose keys are that scraper's inputs. Any other key is rejected\n- Required inputs must be present. Omitted optional inputs are left out of the response\n- Blank select values are left out. Defaults from the form are not filled in\n- **number_of_companies** on `clutch`, when present, rounds up to the next 1,000\n- **file_name** keeps letters, numbers, spaces, underscores, and hyphens\n- `string_list` and `multi_select` values are JSON arrays of strings\n\n## Response\n- Returns `scraper_id` and the accepted `params`\n","operationId":"submit","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadScraperSubmissionRequest"},"examples":{"Clutch":{"description":"Clutch","value":{"scraper_id":"clutch","params":{"clutch_url":"https://clutch.co/agencies/digital-marketing","number_of_companies":1500,"file_name":"Digital Marketing Companies!"}}}}}},"required":true},"responses":{"200":{"description":"Inputs accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadScraperSubmissionApiResponse"},"examples":{"Clutch accepted":{"description":"Clutch accepted","value":{"success":true,"data":{"scraper_id":"clutch","params":{"clutch_url":"https://clutch.co/agencies/digital-marketing","number_of_companies":2000,"file_name":"Digital Marketing Companies"}},"timestamp":"2026-10-10T10:30:00Z"}}}}}},"400":{"description":"Unknown scraper or invalid inputs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"error":"BAD_REQUEST","message":"clutch_url is required","timestamp":"2026-10-10T10:30:00Z"}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/lead-scrapers/payment":{"post":{"tags":["Lead Scrapers"],"summary":"Pay for a lead scraper","description":"Charges for a lead scraper request for the authenticated client, or returns a checkout URL.\n\n## Behavior\n- Preview first with `POST /api/v1/lead-scrapers/payment-preview`\n- An active subscription with a card on file is charged once, at 50% off. `charged_immediately` is true\n- No active subscription pays the full price. Open `checkout_url` to pay\n- An active subscription that is not billed automatically still receives 50% off and a checkout URL\n- The lead scrape starts after payment is confirmed\n\n## Response\n- **checkout_url**: pay page when the saved card is not charged\n- **charged_immediately**: true when the saved card was charged\n","operationId":"pay","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadScraperSubmissionRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/lead-scrapers/payment-preview":{"post":{"tags":["Lead Scrapers"],"summary":"Preview a lead scraper payment","description":"Returns the amount due for a lead scraper request for the authenticated client. Does not charge.\n\n## Behavior\n- Validates `params` the same way as `POST /api/v1/lead-scrapers/submissions`\n- An active Aerosend subscription receives a 50% discount\n- An account with no active subscription pays the full price\n- A result count is required even when submit allows it to be omitted\n- When `requires_checkout` is false, confirming with `POST /api/v1/lead-scrapers/payment` charges the saved card\n- When `requires_checkout` is true, that pay call returns `checkout_url`\n\n## Response\n- **list_amount**: price before the subscription discount\n- **amount_due**: price after the discount\n- **discount_percent**: `50` or `0`\n","operationId":"previewPayment","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadScraperSubmissionRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/lead-scrapers/email-verification/file":{"post":{"tags":["Lead Scrapers"],"summary":"Upload an email verification CSV","description":"Uploads a CSV of contacts for email verification for the authenticated client.\n\n## Behavior\n- Returns `file_id`\n- Send that value as `params.file_id` when you submit the `email-verification` scraper\n- Does not verify the contacts and does not charge\n\n## Validation\n- **file**: multipart field. The file name must end with `.csv`\n- An empty file is rejected\n","operationId":"uploadEmailVerificationFile","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"CSV file. The file name must end with .csv."}},"required":["file"]}}}},"responses":{"200":{"description":"CSV stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerificationFileApiResponse"},"example":{"success":true,"data":{"file_id":"file_8f3a2c"},"timestamp":"2026-10-10T10:30:00Z"}}}},"400":{"description":"Missing file, empty file, or a file that is not a CSV","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"error":"BAD_REQUEST","message":"file must be a CSV","timestamp":"2026-10-10T10:30:00Z"}}}},"503":{"description":"File upload is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"success":false,"error":"SERVICE_UNAVAILABLE","message":"File upload is unavailable","timestamp":"2026-10-10T10:30:00Z"}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domains":{"get":{"tags":["Domains"],"summary":"List domains","description":"Returns a paginated list of domains for the authenticated client.\n\n## Filtering\n- **search**: Filter by domain name (partial match)\n- **status**: Filter by status. Valid values: `active`, `inactive`, `pending`, `in_progress`\n- **tag_ids**: Filter by tag IDs (comma-separated)\n- **is_warmup**: Filter by warmup status\n\n## Sorting\n- **sort**: Order by creation date. Valid values: `latest` or `oldest` (default: `latest`)\n- Invalid sort values will be rejected with a validation error\n\n## Pagination\n- **offset**: Number of items to skip (default: 0)\n- **limit**: Maximum items to return (default: 20, max: 100)\n\n## Response\nEach domain includes:\n- Basic domain information\n- Active nameservers\n- DNS provider details\n- Associated tags (if requested with `include_tags=true`)\n- Mailboxes (if requested with `include_mailboxes=true`)\n\n**Note**: Tag filtering via `tag_ids` works regardless of the `include_tags` flag.\nWhen `include_tags=false`, tags are not included in the response but filtering still applies.\n","operationId":"listDomains","parameters":[{"name":"offset","in":"query","description":"Number of items to skip","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0},"example":0},{"name":"limit","in":"query","description":"Maximum items to return (1-100)","required":false,"schema":{"type":"integer","format":"int32","default":20,"maximum":100,"minimum":1},"example":20},{"name":"sort","in":"query","description":"Sort order","required":false,"schema":{"type":"string","enum":["latest","oldest"],"pattern":"^(latest|oldest)$"},"example":"latest"},{"name":"search","in":"query","description":"Search by domain name","required":false,"schema":{"type":"string"},"example":"example.com"},{"name":"status","in":"query","description":"Filter by status. Valid values: active, inactive, pending, in_progress","required":false,"schema":{"type":"string","enum":["active","inactive","pending","in_progress"],"example":"active"},"example":"active"},{"name":"tag_ids","in":"query","description":"Filter by tag IDs (comma-separated)","required":false,"schema":{"type":"array","items":{"type":"integer","format":"int64"}},"example":"1,2,3"},{"name":"is_warmup","in":"query","description":"Filter by warmup status","required":false,"schema":{"type":"boolean"},"example":true},{"name":"include_mailboxes","in":"query","description":"Include mailboxes in response","required":false,"schema":{"type":"boolean","default":false},"example":false},{"name":"include_tags","in":"query","description":"Include tags in response. Tag filtering still works regardless of this flag.","required":false,"schema":{"type":"boolean","default":false},"example":false}],"responses":{"200":{"description":"Successfully retrieved domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainListResponse"},"examples":{"DomainListSuccess":{"description":"DomainListSuccess","value":{"success":true,"data":[{"id":123,"domain_tld":"example.com","mail_domain":"mail","status":"active","is_warmup":true,"warmup_start_date":"2025-12-01T00:00:00Z","warmup_end_date":"2025-12-22T00:00:00Z","mailbox_count":5,"redirect_url":"https://example.com","attached_at":"2025-11-01T10:30:00Z","nameservers":["ns1.cloudflare.com","ns2.cloudflare.com"],"dns_provider":{"id":1,"name":"Cloudflare"},"tags":[{"id":1,"name":"client-123","display_name":"Client 123","color":"#000369"}]}],"pagination":{"offset":0,"limit":20,"total":150,"has_more":true},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"DomainListValidationError":{"description":"DomainListValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"limit","message":"limit must be <= 100"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Domains"],"summary":"Add domains","description":"Adds one or more domains for the authenticated client.\n\n## Domain Validation\n- Domain format is validated according to RFC standards (e.g., `example.com`)\n- Domain names are normalized (http/https and trailing slashes removed)\n- Duplicate domains in the request are rejected\n\n## Redirect URL Validation\n- Redirect URLs are validated according to RFC standards (same validation as domain names)\n- Protocol (http://, https://) and trailing slashes are automatically removed\n- Redirect URLs are normalized to lowercase\n- Each redirect URL must be a valid domain format (e.g., `mysite.com`, `example.co.in`)\n\n## Slot Management\n- Client must have sufficient domain slots available\n- Domain slots are automatically updated after successful addition\n\n## Existing Domains\n- **Active domains**: Cannot be added (returns error)\n- **Inactive domains**: Reactivated and ownership transferred to the client\n\n## Default Settings\n- All new domains have warmup enabled by default\n- Initial status is set to `pending`\n","operationId":"addDomains","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDomainsRequest"}}},"required":true},"responses":{"201":{"description":"Domains added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDomainsApiResponse"},"examples":{"DomainAddSuccess":{"description":"DomainAddSuccess","value":{"success":true,"data":{"added_count":2,"reactivated_count":1,"domains":[{"id":123,"domain":"example.com","status":"pending","reactivated":false},{"id":124,"domain":"test.com","status":"pending","reactivated":false},{"id":125,"domain":"old.com","status":"pending","reactivated":true}]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request - validation error or invalid domain format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"Invalid domain format":{"description":"Invalid domain format","value":{"success":false,"error":"INVALID_DOMAIN_FORMAT","message":"Invalid domain format: domain a .com: Domain cannot contain spaces","timestamp":"2025-12-14T10:30:00Z"}},"Insufficient slots":{"description":"Insufficient slots","value":{"success":false,"error":"INSUFFICIENT_DOMAIN_SLOTS","message":"Insufficient domain slots. Available: 5, Required: 10","timestamp":"2025-12-14T10:30:00Z"}}}}}},"409":{"description":"Conflict - One or more domains already exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"DomainAddConflict":{"description":"DomainAddConflict","value":{"success":false,"error":"DOMAINS_ALREADY_EXIST","message":"The following domains already exist and are active: example.com, test.com","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Domains"],"summary":"Delete domains","description":"Deletes one or more domains for the authenticated client.\n\n## Deletion Rules\n- **Only pending domains can be deleted**\n- Domains in other statuses (active, in progress, inactive, etc.) are skipped\n- Skipped domains are returned in the response with a reason\n\n## Mailbox Handling\n- **All pending mailboxes** under the domain are automatically **inactivated** before domain deletion\n- **Domains with active mailboxes** (ACTIVE, IN_PROGRESS, etc.) **cannot be deleted** and are skipped\n- Only domains where all mailboxes are PENDING or INACTIVE can be deleted\n- When a domain is deleted, all its mailboxes are effectively removed (inactivated)\n\n## Identifiers\nYou can specify domains to delete using:\n- `ids`: Array of domain IDs\n- `domains`: Array of domain names\n- Or both (they will be combined)\n\n## Slot Management\n- **Domain slots** are automatically freed after successful deletion\n- **Mailbox slots** are automatically freed based on the number of mailboxes that were inactivated\n","operationId":"deleteDomains","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDomainsRequest"}}},"required":true},"responses":{"200":{"description":"Domains deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDomainsApiResponse"},"examples":{"DomainDeleteSuccess":{"description":"DomainDeleteSuccess","value":{"success":true,"data":{"deleted_count":2,"deleted_domains":["example.com","test.com"],"skipped_domains":[{"identifier":"example.com","reason":"Only pending domains can be deleted. Current status: active"},{"identifier":"test.com","reason":"Domain has active mailboxes. All mailboxes must be pending or inactive to delete the domain."}]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"400":{"description":"Invalid request - missing identifiers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"DomainDeleteValidationError":{"description":"DomainDeleteValidationError","value":{"success":false,"error":"MISSING_IDENTIFIERS","message":"Either 'ids' or 'domains' must be provided","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domains/deletion-request":{"post":{"tags":["Domains"],"summary":"Request domain deletion","description":"Submits a deletion request for one or more domains for the authenticated client. **Domains are not deleted.**\n\n## Deletion Rules\n- Domains that are not `pending` (typically `active`) are included in the request\n- The Aerosend team handles those domains\n- Does **not** change domain status or free slots\n- To delete **pending** domains with no active mailboxes, use `DELETE /api/v1/domains`\n\n## Behavior\n- Validates that each name belongs to the authenticated client\n- Returns which names were submitted and which were not found on the account\n","operationId":"requestDomainDeletion","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainDeletionRequest"}}},"required":true},"responses":{"200":{"description":"Deletion request submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainDeletionRequestApiResponse"},"examples":{"DomainDeletionRequestSuccess":{"description":"DomainDeletionRequestSuccess","value":{"success":true,"data":{"requested_count":2,"requested_domains":[{"domain":"example.com","status":"active"},{"domain":"test.com","status":"in_progress"}],"not_found_domains":["missing.com"],"message":"Deletion request submitted for 2 domain(s). Domains have not been deleted. The Aerosend team has been notified."},"timestamp":"2026-04-07T10:30:00Z"}}}}}},"400":{"description":"No matching domains on this account, or the domain list is empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"NoMatchingDomains":{"description":"NoMatchingDomains","value":{"success":false,"error":"NO_MATCHING_DOMAINS","message":"None of the requested domains belong to this account","timestamp":"2026-04-07T10:30:00Z"}},"EmptyDomains":{"description":"EmptyDomains","value":{"success":false,"error":"VALIDATION_ERROR","message":"At least one domain is required","timestamp":"2026-04-07T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/validate-api-key":{"post":{"tags":["Domain Burn Alerts"],"summary":"Validate a sequencer API key","description":"Checks the key with the sequencer without storing it. Returns `valid: false` for a rejected key.","operationId":"validateApiKey","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencerApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"Validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyValidationApiResponse"},"examples":{"ApiKeyValid":{"description":"ApiKeyValid","value":{"success":true,"data":{"sequencer":"smartlead","valid":true,"message":"API key is valid"},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/add-api-key":{"post":{"tags":["Domain Burn Alerts"],"summary":"Connect sequencers and generate report","description":"Accepts one or more Smartlead or Instantly keys. Every key is checked first.\nIf any key is invalid or already connected, nothing is stored and the report\nscan is not started. The response lists each key as VALID, INVALID, or DUPLICATE\nwith a clear message, and scan_started is false.\n","operationId":"addApiKey","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSequencerKeysRequest"}}},"required":true},"responses":{"200":{"description":"All keys are valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSequencerKeysApiResponse"},"examples":{"KeysAccepted":{"description":"KeysAccepted","value":{"success":true,"data":{"accepted":true,"scan_started":true,"message":"Connected 2 sequencers and started a scan to generate the report.","keys":[{"index":0,"sequencer":"smartlead","account_name":"Main workspace","key":"••••a1b2","status":"VALID","message":"This Smartlead API key is valid."},{"index":1,"sequencer":"instantly","account_name":"Outreach","key":"••••9xyz","status":"VALID","message":"This Instantly API key is valid."}],"scan":{"status":"IN_PROGRESS","report_exists":false,"next_step":"WAIT","message":"Generating your report. Syncing your sequencer accounts."}},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"400":{"description":"One or more keys are invalid. Nothing was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencerKeysError"},"examples":{"KeysRejected":{"description":"KeysRejected","value":{"success":false,"error":"KEYS_REJECTED","message":"1 of 2 keys is invalid and 1 is already connected. Keys were not saved and the report scan was not started. Fix the keys listed below and submit again.","accepted":false,"scan_started":false,"keys":[{"index":0,"sequencer":"smartlead","account_name":"Main workspace","key":"••••a1b2","status":"INVALID","message":"This Smartlead key was rejected: the API key is invalid. Check the key and try again."},{"index":1,"sequencer":"instantly","account_name":"Outreach","key":"••••9xyz","status":"DUPLICATE","message":"This Instantly key was rejected: it is already connected. Use a different key."}],"timestamp":"2026-10-05T06:30:00Z"}}}}}},"409":{"description":"One or more keys are already connected. Nothing was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencerKeysError"},"examples":{"KeysDuplicate":{"description":"KeysDuplicate","value":{"success":false,"error":"KEYS_REJECTED","message":"This sequencer key is already connected. Keys were not saved and the report scan was not started. Remove the duplicate keys and submit again.","accepted":false,"scan_started":false,"keys":[{"index":0,"sequencer":"smartlead","account_name":"Main workspace","key":"••••a1b2","status":"DUPLICATE","message":"This Smartlead key was rejected: it is already connected. Use a different key."}],"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/billing/domain-slots":{"post":{"tags":["Purchase"],"summary":"Purchase domain slots","description":"Buys domain slots for the authenticated client.\n\nSend `domain_slots` and/or `mailbox_slots` (3 mailboxes per domain slot). Preview first with\nPOST /api/v1/billing/domain-slots/preview.\n\nExisting subscription (`flow=update`): charges the saved card immediately. Slot counts on\nGET /api/v1/me update after payment is confirmed.\n\nNo subscription (`flow=create`): returns `checkout_url` at https://app.aerosend.io/payment?ptxn=...\nOpen that URL to pay. Slots appear after payment.\n","operationId":"purchase","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSlotPurchaseRequest"}}}},"responses":{"200":{"description":"Charged (flow=update) or checkout created (flow=create)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSlotPurchaseApiResponse"},"examples":{"Existing subscription":{"description":"Existing subscription","value":{"success":true,"data":{"flow":"update","charged_immediately":true,"domain_slots":10,"mailbox_slots":30,"unit_price":2.0,"currency_code":"USD","proration_amount":12.34,"upcoming_invoice_amount":180.0,"checkout_url":null,"message":"Payment submitted. Slot counts on GET /api/v1/me update after payment is confirmed (usually a few seconds)."},"timestamp":"2026-10-09T18:30:00Z"}},"New subscription":{"description":"New subscription","value":{"success":true,"data":{"flow":"create","charged_immediately":false,"domain_slots":10,"mailbox_slots":30,"unit_price":4.0,"currency_code":"USD","proration_amount":120.0,"upcoming_invoice_amount":120.0,"checkout_url":"https://app.aerosend.io/payment?ptxn=txn_01example","message":"No saved subscription. Open checkout_url to pay. Slot counts on GET /api/v1/me update after payment."},"timestamp":"2026-10-09T18:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/billing/domain-slots/preview":{"post":{"tags":["Purchase"],"summary":"Preview a domain-slot purchase","description":"Returns the price and flow for adding domain slots for the authenticated client. Does not charge.\n\n## Behavior\n- Send `domain_slots` and/or `mailbox_slots`. 1 domain slot = 3 mailboxes\n- Both fields are accepted only when they match that ratio\n- Existing subscription (`flow=update`) returns proration for the saved card\n- No subscription (`flow=create`) returns a catalog estimate\n\n## Response\n- Returns `proration_amount` and `upcoming_invoice_amount`\n- To charge or open checkout, use `POST /api/v1/billing/domain-slots`\n","operationId":"preview","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSlotPurchaseRequest"}}}},"responses":{"200":{"description":"Preview ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSlotPurchaseApiResponse"},"examples":{"Existing subscription":{"description":"Existing subscription","value":{"success":true,"data":{"flow":"update","charged_immediately":false,"domain_slots":10,"mailbox_slots":30,"unit_price":2.0,"currency_code":"USD","proration_amount":12.34,"upcoming_invoice_amount":180.0,"checkout_url":null,"message":"Existing subscription. This amount is charged to the saved card if you confirm with POST /api/v1/billing/domain-slots."},"timestamp":"2026-10-09T18:30:00Z"}},"New subscription":{"description":"New subscription","value":{"success":true,"data":{"flow":"create","charged_immediately":false,"domain_slots":10,"mailbox_slots":30,"unit_price":4.0,"currency_code":"USD","proration_amount":120.0,"upcoming_invoice_amount":120.0,"checkout_url":null,"message":"No saved subscription. Confirm with POST /api/v1/billing/domain-slots to get a checkout URL."},"timestamp":"2026-10-09T18:30:00Z"}}}}}},"400":{"description":"Invalid quantity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"example":{"success":false,"error":"VALIDATION_ERROR","message":"domain_slots and mailbox_slots must match 3:1 (1 domain slot = 3 mailboxes). Example: domain_slots=10 and mailbox_slots=30. Send one field, or both only when they match.","timestamp":"2026-10-09T18:30:00Z"}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/me":{"get":{"tags":["Client"],"summary":"Get authenticated client profile","description":"Returns basic profile and usage information for the authenticated client.\n\n## Fields\n- **id**: Client identifier\n- **name**: Client display name\n- **email**: Client contact email\n- **domain_slots**: Total domain slots allocated\n- **domain_slots_used**: Domain slots currently in use\n- **mailbox_slots**: Total mailbox slots allocated\n- **mailbox_slots_used**: Mailbox slots currently in use\n- **status**: Client status (`deactivated`, `pending`, `in_progress`, `active`, `forgot_password`, `subscription_not_paid`, `subscription_cancelled`)\n","operationId":"getMe","responses":{"200":{"description":"Successfully retrieved client profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientMeApiResponse"},"examples":{"ClientMeSuccess":{"description":"ClientMeSuccess","value":{"success":true,"data":{"id":123,"name":"John Doe","email":"john.doe@example.com","domain_slots":50,"domain_slots_used":10,"mailbox_slots":200,"mailbox_slots_used":25,"status":"active"},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/mailboxes/{mailboxId}":{"get":{"tags":["Mailboxes"],"summary":"Get mailbox by ID","description":"Returns detailed information about a specific mailbox.\n\nSet `include_credentials=true` to get SMTP and IMAP connection details.\n","operationId":"getMailboxById","parameters":[{"name":"mailboxId","in":"path","description":"Mailbox ID","required":true,"schema":{"type":"integer","format":"int64"},"example":456},{"name":"include_credentials","in":"query","description":"Include SMTP/IMAP credentials","required":false,"schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Successfully retrieved mailbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxResponse"},"examples":{"MailboxGetSuccess":{"description":"MailboxGetSuccess","value":{"success":true,"data":{"id":456,"email":"john@example.com","first_name":"John","last_name":"Doe","status":"active","domain_id":123,"credentials":{"smtp":{"host":"smtp.topdeliverabilityninja.com","port":587,"username":"john@example.com","password":"your-password","security":"TLS"},"imap":{"host":"imap.example.com","port":993,"username":"john@example.com","password":"your-password","security":"SSL"}},"tags":[]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Mailbox not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"MailboxGetNotFound":{"description":"MailboxGetNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Mailbox not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/lead-scrapers":{"get":{"tags":["Lead Scrapers"],"summary":"List lead scrapers","description":"Returns the lead scraper catalog for the authenticated client.\n\n## Behavior\n- Returns the same 16 scrapers for every account\n- Each scraper includes `id`, `name`, and `inputs`\n- Send `id` as `scraper_id` and each input `key` inside `params`\n- Does not include prices\n- Does not charge and does not start a scrape\n\n## Input object\n- **key**: snake_case name to send in `params`\n- **label**: the name shown to the customer\n- **type**: `text`, `url`, `number`, `boolean`, `string_list`, `select`, or `multi_select`\n- **required**: the field must be present on submit\n- **options**: allowed values when type is `select` or `multi_select`. Each option has `value` and `label`. Send `value`\n- **minimum**, **maximum**, and **step**: limits when the form enforces them\n\n`string_list` and `multi_select` are JSON arrays of strings. `file_name` keeps letters, numbers, spaces, underscores, and hyphens. A result count is required before payment even when that field is optional on submit.\n\n## Scrapers and params\n\n**clutch** (Clutch)\n- **clutch_url** (text, required)\n- **number_of_companies** (number, optional). When present, rounds up to the next 1,000\n- **file_name** (text, required)\n\n**google-maps** (Google Maps)\n- **categories** (string_list, required)\n- **exact_match** (boolean, optional)\n- **locations** (string_list, required)\n- **max_results** (number, required). Integer >= 1000 and a multiple of 1000\n- **enrichments** (multi_select, optional): `companyInsight`, `similarWeb`, `contactsLeadEnrichment`, `emailContacts`, `phoneEnricher`, `chainInfo`, `builtWith`\n- **file_name** (text, required)\n\n**ad-libraries** (Ad Libraries)\n- **company_names** (string_list, required)\n- **platforms** (multi_select, optional): `meta`, `tiktok`, `google`, `linkedin`\n- **file_name** (text, required)\n\n**sales-navigator** (Professional Navigator)\n- **sales_navigator_url** (url, required)\n- **sales_navigator_number_of_results** (number, optional). 1000, 2000, or 2500\n- **file_name** (text, required)\n\n**yelp** (Yelp)\n- **yelp_search_term** (text, required)\n- **yelp_location** (text, optional)\n- **yelp_number_of_results** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**yellow-pages** (Yellow Pages)\n- **search_term** (text, required)\n- **location** (text, optional)\n- **yellow_pages_number_of_results** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**indeed** (Indeed)\n- **job_title** (text, required)\n- **indeed_location** (text, optional)\n- **indeed_country** (select, optional): `us`, `uk`, `ca`, `au`, `de`, `fr`, `in`, `nl`, `ie`, `sg`, `ae`, `jp`, `br`, `mx`, `es`, `it`, `pl`, `be`, `ch`, `at`, `nz`, `za`, `ph`, `id`, `my`, `kr`, `tw`, `hk`, `pt`, `se`, `no`, `dk`, `fi`\n- **number_of_results** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**linkedin-jobs** (Professional Jobs)\n- **titles** (string_list, required)\n- **locations** (string_list, optional)\n- **date_posted** (select, optional): `r86400` past 24 hours, `r604800` past week, `r2592000` past month. Omit for any time\n- **contract_type** (multi_select, optional): `F` full-time, `P` part-time, `C` contract, `T` temporary, `I` internship, `V` volunteer\n- **experience_level** (multi_select, optional): `1` internship, `2` entry level, `3` associate, `4` mid-senior, `5` director, `6` executive\n- **remote_type** (multi_select, optional): `2` remote, `1` hybrid, `3` on-site\n- **results_limit** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**post-search** (Professional Post Search)\n- **search_keywords** (string_list, required)\n- **post_date_posted** (select, optional): `any`, `past1h`, `past24h`, `pastWeek`, `pastMonth`, `past3months`, `past6months`, `pastYear`\n- **post_sort_by** (select, optional): `relevant`, `recent`\n- **number_of_posts** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**profile-search** (Professional Profile Search)\n- **profile_search_query** (text, required). At most 300 characters\n- **profile_locations** (string_list, optional)\n- **current_job_titles** (string_list, optional)\n- **seniority_level** (multi_select, optional): `in_training`, `entry_level`, `senior`, `strategic`, `entry_manager`, `experienced_manager`, `director`, `vp`, `cxo`, `owner`\n- **profile_detail_level** (select, optional): `short`, `full`, `fullEmail`\n- **profile_number_of_results** (number, optional). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**email-verification** (Email Verification)\n- **file_id** (text, required). Returned by `POST /api/v1/lead-scrapers/email-verification/file`\n- **number_of_contacts_to_verify** (number, required). Integer >= 1\n- **file_name** (text, required)\n\n**apollo** (Apollo)\n- **apollo_search_url** (url, required)\n- **apollo_number_of_leads** (number, required). Integer >= 1000 and a multiple of 1000\n- **apollo_verify_emails** (select, optional): `dont-verify`, `verify`\n- **file_name** (text, required)\n\n**crunchbase** (Crunchbase)\n- **crunchbase_search_url** (url, required)\n- **crunchbase_number_of_companies** (number, required). Integer >= 1000 and a multiple of 1000\n- **file_name** (text, required)\n\n**profile-enrichment** (Profile Enrichment)\n- **profile_enrichment_urls** (string_list, required). Each item is a URL\n- **file_name** (text, required)\n\n**post-comments** (Post Commenters)\n- **post_urls** (string_list, required)\n- **max_comments_per_post** (number, optional). Integer >= 1\n- **posted_limit** (select, optional): `past24h`, `pastWeek`, `pastMonth`\n- **scrape_replies** (boolean, optional)\n- **profile_scraper_mode** (select, optional): `short`, `full`\n- **file_name** (text, required)\n\n**google-ads** (Google Ads)\n- **advertiser_name** (text). At least one of **advertiser_name** or **transparency_center_url** is required\n- **transparency_center_url** (text)\n- **ad_format** (select, optional): `text`, `image`, `video`. Omit for all formats\n- **max_results** (number, optional). Integer from 1 to 50000. Required before payment\n","operationId":"list","responses":{"200":{"description":"Catalog retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadScraperListApiResponse"},"examples":{"Clutch in the catalog":{"description":"Clutch in the catalog","value":{"success":true,"data":[{"id":"clutch","name":"Clutch","inputs":[{"key":"clutch_url","label":"Clutch URL","type":"text","required":true},{"key":"number_of_companies","label":"Number of Companies","type":"number","required":false,"minimum":1000,"step":1000},{"key":"file_name","label":"File Name","type":"text","required":true}]}],"timestamp":"2026-10-10T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domains/{domainId}":{"get":{"tags":["Domains"],"summary":"Get domain by ID","description":"Returns detailed information about a specific domain.\n\nThe response includes:\n- Full domain details\n- Active nameservers\n- DNS provider information\n- All associated tags\n- All mailboxes belonging to this domain\n","operationId":"getDomainById","parameters":[{"name":"domainId","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int64"},"example":123}],"responses":{"200":{"description":"Successfully retrieved domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"},"examples":{"DomainGetSuccess":{"description":"DomainGetSuccess","value":{"success":true,"data":{"id":123,"domain_tld":"example.com","mail_domain":"mail","status":"active","is_warmup":true,"warmup_start_date":"2025-12-01T00:00:00Z","warmup_end_date":"2025-12-22T00:00:00Z","mailbox_count":5,"nameservers":["ns1.cloudflare.com","ns2.cloudflare.com"],"dns_provider":{"id":1,"name":"Cloudflare"},"mailboxes":[{"id":456,"email":"john@example.com","first_name":"John","last_name":"Doe","status":"active"}],"tags":[]},"timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"DomainGetNotFound":{"description":"DomainGetNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Domain not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn":{"get":{"tags":["Domain Burn Alerts"],"summary":"Get the domain burn report","description":"Returns summary counts (total, burnt, at-risk, good, excellent, low-volume), status groups,\nend clients derived from redirect URLs, and one row per domain.\n\nWithout `id`, this is the entire customer report. With `id` from GET /keys, the report\nis limited to domains on that Smartlead or Instantly key\n(`customer_integrations.mb_integration_id` → `client_integrations.id`).\n\n`data.scan` is the same status object as GET /scan-score (`NOT_STARTED`, `IN_PROGRESS`,\n`COMPLETED`, `FAILED` and `next_step`). When no report exists yet, `report_available` is\nfalse and `scan.next_step` tells the UI whether to connect a sequencer, generate the report, or wait.\n","operationId":"getReport","parameters":[{"name":"id","in":"query","description":"client_integrations.id from GET /keys; omit for the entire report","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":100,"maximum":100,"minimum":1}}],"responses":{"200":{"description":"Domain burn report with summary counts and per-domain rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBurnReportApiResponse"},"examples":{"DomainBurnReport":{"description":"DomainBurnReport","value":{"success":true,"data":{"report_available":true,"scan":{"status":"COMPLETED","report_exists":true,"next_step":"VIEW_REPORT","message":"Your domain burn report is ready.","started_at":"2026-09-14T06:00:00Z","completed_at":"2026-09-14T08:30:00Z","sequencers":[{"sequencer":"smartlead","connected":true,"account_count":1,"scan_supported":true}]},"summary":{"total_domains":4,"burnt":1,"at_risk":1,"good":1,"excellent":0,"low_volume":1,"client_count":2,"metrics_date":"2026-09-14","report_from_date":"2026-08-15","report_to_date":"2026-09-14"},"groups":[{"status":"burnt","label":"Burnt","description":"Deliverability is failing. Fix the cause or replace.","count":1,"action":"replace","action_label":"Replace all"},{"status":"at-risk","label":"At-risk","description":"Slipping. Slow these down before they burn.","count":1,"action":"slowdown","action_label":"Slow down all"},{"status":"good","label":"Good","description":"Landing in the inbox. Nothing to do.","count":1,"action":null,"action_label":null},{"status":"excellent","label":"Excellent","description":"Strong deliverability. Keep the current cadence.","count":0,"action":null,"action_label":null},{"status":"low-volume","label":"Low-volume","description":"Too few sends or insufficient data this period to score confidently.","count":1,"action":null,"action_label":null}],"clients":[{"id":"all","name":"All clients","color":"#6B7280","domain_count":4,"unassigned":false},{"id":"acme-com","name":"acme.com","color":"#7B61FF","domain_count":2,"unassigned":false},{"id":"other-io","name":"other.io","color":"#00B2FF","domain_count":1,"unassigned":false},{"id":"unassigned","name":"Unassigned","color":"#9CA3AF","domain_count":1,"unassigned":true}],"domains":[{"domain":"burnt.acme.com","status":"burnt","burn_score":31,"sent":900,"delta":-12,"flags":["High bounce"],"client_name":"acme.com","metrics_date":"2026-09-14"},{"domain":"risk.acme.com","status":"at-risk","burn_score":55,"sent":500,"delta":-4,"flags":[],"client_name":"acme.com","metrics_date":"2026-09-14"},{"domain":"fine.example.com","status":"good","burn_score":81,"sent":700,"delta":2,"flags":[],"client_name":"Unassigned","metrics_date":"2026-09-14"},{"domain":"quiet.other.io","status":"low-volume","burn_score":null,"sent":0,"delta":null,"flags":[],"client_name":"other.io","metrics_date":null}],"pagination":{"offset":0,"limit":100,"total":4,"has_more":false}},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/sequencer":{"get":{"tags":["Domain Burn Alerts"],"summary":"Detect connected sequencers","description":"Lists Smartlead and Instantly with whether an active API key is stored. Keys are never returned.","operationId":"getSequencerConnection","responses":{"200":{"description":"Connected sequencers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencerConnectionApiResponse"},"examples":{"SequencerConnection":{"description":"SequencerConnection","value":{"success":true,"data":{"has_api_key":true,"sequencers":[{"sequencer":"smartlead","connected":true,"account_count":1,"scan_supported":true},{"sequencer":"instantly","connected":false,"account_count":0,"scan_supported":true}]},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/scan-score":{"get":{"tags":["Domain Burn Alerts"],"summary":"Get report status","description":"Same status object as `data.scan` on GET /domain-burn.\nStatus is NOT_STARTED, IN_PROGRESS, COMPLETED or FAILED; `next_step` drives the UI flow.\nPass `id` from GET /keys for that key's status; omit it for the client-wide status.\n","operationId":"getScanScore","parameters":[{"name":"id","in":"query","description":"client_integrations.id from GET /keys; omit for the entire report","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Current report status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanScoreApiResponse"},"examples":{"ScanScore":{"description":"ScanScore","value":{"success":true,"data":{"status":"COMPLETED","report_exists":true,"next_step":"VIEW_REPORT","message":"Your domain burn report is ready.","started_at":"2026-09-14T06:00:00Z","completed_at":"2026-09-14T08:30:00Z","sequencers":[{"sequencer":"smartlead","connected":true,"account_count":1,"scan_supported":true}]},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/keys":{"get":{"tags":["Domain Burn Alerts"],"summary":"List sequencer keys","description":"Active Smartlead and Instantly keys only (PlusVibe and EmailBison are omitted).\nEach row is `id` (pass as GET /domain-burn?id=), `sequencer`,\n`report_status`, and `display_name` from client_integrations.name.\n","operationId":"listKeys","responses":{"200":{"description":"Connected Smartlead and Instantly keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequencerKeyListApiResponse"},"examples":{"SequencerKeys":{"description":"SequencerKeys","value":{"success":true,"data":{"keys":[{"id":42,"sequencer":"smartlead","display_name":"Main workspace","report_status":"COMPLETED","message":"Your domain burn report is ready."},{"id":57,"sequencer":"instantly","display_name":"Instantly","report_status":"NOT_STARTED","message":"Your sequencer is connected. The report is not ready yet."}]},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/domain-burn/domains/{domain}":{"get":{"tags":["Domain Burn Alerts"],"summary":"Get burn detail for one domain","description":"Metrics, issues, monthly score history and the recommended action for a domain.\nPass `id` from GET /keys to require that the domain belongs to that sequencer key.\n","operationId":"getDomainDetail","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"query","description":"client_integrations.id from GET /keys; omit for the entire report","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Domain burn detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBurnDetailApiResponse"},"examples":{"DomainBurnDetail":{"description":"DomainBurnDetail","value":{"success":true,"data":{"domain":{"domain":"burnt.acme.com","status":"burnt","burn_score":31,"sent":900,"delta":-12,"flags":["High bounce","Low reply"],"client_name":"acme.com","metrics_date":"2026-09-14"},"sequencer":"Smartlead","metrics":{"burn_score":31.4,"warmup_score":72.0,"reply_rate":0.4,"bounce_rate":6.25,"placement_score":null,"total_sent":900,"metrics_date":"2026-09-14"},"issues":[{"tag":"High Bounce","text":"6.25% bounce rate this period."},{"tag":"Low Reply","text":"Replies on this domain are well below your other domains for this client."}],"history":[{"month":"2026-08","label":"Aug","score":48},{"month":"2026-09","label":"Sep","score":31}],"action":{"type":"replace","title":"Replace this domain","description":"This domain's deliverability is failing. Replacing it with a warmed domain restores your sending capacity.","button_label":"Replace this domain"}},"timestamp":"2026-10-05T06:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/analytics/warmup-scores":{"get":{"tags":["Analytics"],"summary":"List mailbox warmup scores","description":"Returns the warmup score and warmup start date for each mailbox belonging to the authenticated client.","operationId":"getWarmupScores","parameters":[{"name":"offset","in":"query","description":"Number of items to skip","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0},"example":0},{"name":"limit","in":"query","description":"Maximum items to return (1-100)","required":false,"schema":{"type":"integer","format":"int32","default":20,"maximum":100,"minimum":1},"example":20}],"responses":{"200":{"description":"Successfully retrieved warmup scores","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarmupScoreListApiResponse"},"examples":{"WarmupScoresSuccess":{"description":"WarmupScoresSuccess","value":{"success":true,"data":[{"email":"john@example.com","score":90,"warmup_start_date":"2026-09-01"},{"email":"sam@example.com","score":95,"warmup_start_date":"2026-09-01"}],"pagination":{"offset":0,"limit":20,"total":42,"has_more":true},"timestamp":"2026-09-22T10:00:00Z"}}}}}},"400":{"description":"Invalid pagination parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"WarmupScoresValidationError":{"description":"WarmupScoresValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"limit","message":"limit must be <= 100"}],"timestamp":"2026-09-22T10:00:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/analytics/inbox-placement":{"get":{"tags":["Analytics"],"summary":"Get inbox placement analytics","description":"Returns inbox placement analytics for the authenticated client.\n\nThe payload includes overall send/inbox/spam metrics, Google and Outlook totals, overall\nESP breakdown, and **all** sender domains from that test (each with a nested ESP breakdown).\nThere is no pagination - the full domain list is returned in a single response.\n","operationId":"getLatestInboxPlacementAnalytics","responses":{"200":{"description":"Successfully retrieved inbox placement analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxPlacementAnalyticsApiResponse"},"examples":{"LatestInboxPlacementSuccess":{"description":"LatestInboxPlacementSuccess","value":{"success":true,"data":{"test_run_at":"2026-09-20T13:00:00Z","total_emails_sent":765,"inbox_count":304,"spam_count":461,"inbox_percentage":39.74,"spam_percentage":60.26,"google_total_sent":522,"outlook_total_sent":243,"overall_esp_breakdown":[{"esp_name":"Google Workspace","total_emails":522,"inbox_count":61,"spam_count":461,"inbox_percentage":11.69},{"esp_name":"Microsoft 365","total_emails":243,"inbox_count":243,"spam_count":0,"inbox_percentage":100.0}],"domain_breakdown":[{"sender_domain":"example.com","total_emails":85,"inbox_count":77,"spam_count":8,"inbox_percentage":90.59,"esp_breakdown":[{"esp_name":"Google Workspace","total_emails":58,"inbox_count":50,"spam_count":8,"inbox_percentage":86.21},{"esp_name":"Microsoft 365","total_emails":27,"inbox_count":27,"spam_count":0,"inbox_percentage":100.0}]},{"sender_domain":"another.example.com","total_emails":85,"inbox_count":32,"spam_count":53,"inbox_percentage":37.65,"esp_breakdown":[{"esp_name":"Google Workspace","total_emails":58,"inbox_count":5,"spam_count":53,"inbox_percentage":8.62},{"esp_name":"Microsoft 365","total_emails":27,"inbox_count":27,"spam_count":0,"inbox_percentage":100.0}]}]},"timestamp":"2026-09-21T12:30:00Z"}}}}}},"404":{"description":"No completed inbox placement test with analytics exists for this client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"LatestInboxPlacementNotFound":{"description":"LatestInboxPlacementNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"No completed inbox placement test with analytics was found for this client","timestamp":"2026-09-21T12:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/health/ping":{"get":{"tags":["Health"],"summary":"Health check","description":"Simple health check endpoint to verify API availability. No authentication required.","operationId":"ping","responses":{"200":{"description":"API is healthy","content":{"application/json":{"examples":{"HealthPingSuccess":{"description":"HealthPingSuccess","value":{"status":"ok","timestamp":"2025-12-14T10:30:00Z"}}}}}}},"security":[]}},"/api/v1/tags/{tagId}/mailboxes":{"delete":{"tags":["Tags"],"summary":"Remove tag mappings from mailboxes","description":"Removes a tag from one or more mailboxes. The tag itself is not deleted, only the mappings are removed.\n\n## Behavior\n- If a tag-mailbox mapping does not exist, it is ignored (no error)\n- The tag itself remains intact and can still be used for other domains/mailboxes\n\n## Validation\n- The tag ID must exist and belong to the authenticated client\n- All mailbox IDs must belong to the authenticated client\n- Non-existent mailbox IDs will result in an error\n","operationId":"removeTagFromMailboxes","parameters":[{"name":"tagId","in":"path","description":"Tag ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveMailboxTagMappingRequest"}}},"required":true},"responses":{"204":{"description":"Tag mappings removed successfully"},"400":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"TagMailboxRemoveValidationError":{"description":"TagMailboxRemoveValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"mailbox_ids","message":"mailbox_ids cannot be empty"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Tag not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"TagMailboxRemoveNotFound":{"description":"TagMailboxRemoveNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Tag not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/v1/tags/{tagId}/domains":{"delete":{"tags":["Tags"],"summary":"Remove tag mappings from domains","description":"Removes a tag from one or more domains. The tag itself is not deleted, only the mappings are removed.\n\n## Behavior\n- If a tag-domain mapping does not exist, it is ignored (no error)\n- If `include_domain_mailboxes=true`, the tag is also removed from all mailboxes\n  belonging to the specified domains\n- The tag itself remains intact and can still be used for other domains/mailboxes\n\n## Validation\n- The tag ID must exist and belong to the authenticated client\n- All domain IDs must belong to the authenticated client\n- Non-existent domain IDs will result in an error\n","operationId":"removeTagFromDomains","parameters":[{"name":"tagId","in":"path","description":"Tag ID","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveDomainTagMappingRequest"}}},"required":true},"responses":{"204":{"description":"Tag mappings removed successfully"},"400":{"description":"Invalid request payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"TagDomainRemoveValidationError":{"description":"TagDomainRemoveValidationError","value":{"success":false,"error":"VALIDATION_ERROR","message":"Request validation failed","errors":[{"field":"domain_ids","message":"domain_ids cannot be empty"}],"timestamp":"2025-12-14T10:30:00Z"}}}}}},"404":{"description":"Tag not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"},"examples":{"TagDomainRemoveNotFound":{"description":"TagDomainRemoveNotFound","value":{"success":false,"error":"RESOURCE_NOT_FOUND","message":"Tag not found","timestamp":"2025-12-14T10:30:00Z"}}}}}},"401":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}}},"components":{"schemas":{"ErrorResponse":{"properties":{"success":{"example":false},"error":{"example":"RESOURCE_NOT_FOUND"},"message":{"example":"The requested resource was not found"},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"UnauthorizedError":{"properties":{"success":{"example":false},"error":{"example":"UNAUTHORIZED"},"message":{"example":"Invalid or expired API key"},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"NotFoundError":{"properties":{"success":{"example":false},"error":{"example":"RESOURCE_NOT_FOUND"},"message":{"example":"The requested resource was not found"},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"InternalError":{"properties":{"success":{"example":false},"error":{"example":"INTERNAL_ERROR"},"message":{"example":"An unexpected error occurred. Please try again later."},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"RateLimitError":{"properties":{"success":{"example":false},"error":{"example":"RATE_LIMIT_EXCEEDED"},"message":{"example":"Rate limit exceeded. Please retry after 30 seconds."},"retry_after":{"example":30},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"ValidationError":{"properties":{"success":{"example":false},"error":{"example":"VALIDATION_ERROR"},"message":{"example":"Request validation failed"},"errors":{"items":{"properties":{"field":{"example":"limit"},"message":{"example":"must be between given range"}}}},"timestamp":{"format":"date-time","example":"2025-12-14T10:30:00Z"}}},"UpdateTagRequest":{"type":"object","description":"Request to update tag display name and/or color","properties":{"color":{"type":"string","description":"New color for the tag. Must be a valid hex color code starting with # followed by hexadecimal characters (0-9, a-f, A-F). Examples: #000369, #abc123, #f00","example":"#000369","maxLength":8,"minLength":0,"pattern":"^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$"},"display_name":{"type":"string","description":"New display name for the tag. If provided, the normalized name will be automatically recalculated.","example":"Sales Team ABC","maxLength":255,"minLength":1}}},"Tag":{"type":"object","description":"Tag details","properties":{"id":{"type":"integer","format":"int64","description":"Tag ID","example":789},"name":{"type":"string","description":"Normalized tag name","example":"client-abc"},"display_name":{"type":"string","description":"Display name","example":"Client ABC"},"color":{"type":"string","description":"Tag color in hex","example":"#000369"},"status":{"type":"string","description":"Tag status","example":"active"},"domain_count":{"type":"integer","format":"int64","description":"Number of domains with this tag","example":10},"mailbox_count":{"type":"integer","format":"int64","description":"Number of mailboxes with this tag","example":45},"created_at":{"type":"string","description":"Creation timestamp","example":"2025-12-01T10:30:00Z"},"updated_at":{"type":"string","description":"Last update timestamp","example":"2025-12-10T15:45:00Z"}}},"TagResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/Tag","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"UpdateDomainRedirectUrlItem":{"type":"object","description":"Domain redirect URL update item","properties":{"domain_id":{"type":"integer","format":"int64","description":"Domain ID","example":123},"redirect_url":{"type":"string","description":"Redirect URL for the domain. Must be a valid domain format (e.g., mysite.com). Protocol and trailing slashes are automatically removed.","example":"mysite.com","maxLength":255,"minLength":0}},"required":["domain_id","redirect_url"]},"UpdateDomainRedirectUrlsRequest":{"type":"object","description":"Request to update redirect URLs for multiple domains","properties":{"domains":{"type":"array","description":"List of domains with their redirect URLs to update","example":[{"domain_id":123,"redirect_url":"mysite.com"},{"domain_id":124,"redirect_url":"anothersite.com"}],"items":{"$ref":"#/components/schemas/UpdateDomainRedirectUrlItem"},"maxItems":100,"minItems":0}},"required":["domains"]},"SaveTagItem":{"type":"object","description":"Single tag to be created or updated","properties":{"display_name":{"type":"string","description":"Tag display name. This is what users see in the UI.","example":"Client 123","maxLength":100,"minLength":0},"color":{"type":"string","description":"Optional hex color for the tag in UI. Must be a valid hex color code starting with # followed by hexadecimal characters (0-9, a-f, A-F). Examples: #000369, #abc123, #f00","example":"#000369","maxLength":8,"minLength":0,"pattern":"^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$"}},"required":["display_name"]},"SaveTagsRequest":{"type":"object","description":"Request to create one or more tags","properties":{"tags":{"type":"array","description":"List of tags to create. You can send one or many items in a single request.","items":{"$ref":"#/components/schemas/SaveTagItem"},"maxItems":100,"minItems":0}},"required":["tags"]},"SaveTagsApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"Response data","items":{"$ref":"#/components/schemas/Tag"}},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"MailboxTagMappingRequest":{"type":"object","description":"Request to map tags directly to mailboxes","properties":{"tag_ids":{"type":"array","description":"IDs of tags to apply","example":[1,2,3],"items":{"type":"integer","format":"int64"},"maxItems":100,"minItems":0},"mailbox_ids":{"type":"array","description":"IDs of mailboxes to tag","example":[100,101,102],"items":{"type":"integer","format":"int64"},"maxItems":1000,"minItems":0}},"required":["mailbox_ids","tag_ids"]},"DomainTagMappingRequest":{"type":"object","description":"Request to map tags to domains","properties":{"tag_ids":{"type":"array","description":"IDs of tags to apply","example":[1,2,3],"items":{"type":"integer","format":"int64"},"maxItems":100,"minItems":0},"domain_ids":{"type":"array","description":"IDs of domains to tag","example":[10,11,12],"items":{"type":"integer","format":"int64"},"maxItems":500,"minItems":0},"include_domain_mailboxes":{"type":"boolean","description":"If true, also apply the same tags to all mailboxes under the specified domains","example":false}},"required":["domain_ids","tag_ids"]},"AddMailboxItem":{"type":"object","description":"Details for a single mailbox to be added","properties":{"email":{"type":"string","format":"email","description":"Email address for the mailbox. Domain will be extracted automatically from the email.","example":"john.doe@example.com","maxLength":200,"minLength":0},"first_name":{"type":"string","description":"First name of the mailbox owner","example":"John","maxLength":100,"minLength":0},"last_name":{"type":"string","description":"Last name of the mailbox owner","example":"Doe","maxLength":100,"minLength":0}},"required":["email","first_name","last_name"]},"AddMailboxesRequest":{"type":"object","description":"Request to add one or more mailboxes","properties":{"mailboxes":{"type":"array","description":"List of mailboxes to add. Maximum 60 mailboxes per request.","items":{"$ref":"#/components/schemas/AddMailboxItem"},"maxItems":60,"minItems":0}},"required":["mailboxes"]},"AddMailboxesApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/AddMailboxesResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"AddMailboxesResponse":{"type":"object","description":"Response after adding mailboxes","properties":{"added_count":{"type":"integer","format":"int32","description":"Number of mailboxes successfully added","example":5},"mailboxes":{"type":"array","description":"List of added mailbox details","items":{"$ref":"#/components/schemas/MailboxSummary"}}}},"MailboxSummary":{"type":"object","description":"Summary of an added mailbox","properties":{"id":{"type":"integer","format":"int64","description":"Mailbox ID","example":456},"email":{"type":"string","description":"Email address","example":"john.doe@example.com"},"domain_id":{"type":"integer","format":"int64","description":"Domain ID","example":123},"status":{"type":"string","description":"Mailbox status","example":"pending"}}},"MailboxRenameItem":{"type":"object","description":"One mailbox to rename. Provide id or the current email, plus the new email and/or name.","properties":{"id":{"type":"integer","format":"int64","description":"Mailbox ID. Used when email is omitted.","example":456},"email":{"type":"string","description":"Current email address","example":"john@example.com","maxLength":200,"minLength":0},"new_email":{"type":"string","description":"Email address the mailbox should be renamed to","example":"jane@example.com","maxLength":200,"minLength":0},"new_first_name":{"type":"string","description":"New first name","example":"Jane","maxLength":100,"minLength":0},"new_last_name":{"type":"string","description":"New last name","example":"Doe","maxLength":100,"minLength":0}}},"MailboxRenameRequest":{"type":"object","description":"Rename request for one or more mailboxes. Does not rename them.","properties":{"mailboxes":{"type":"array","description":"Mailboxes to rename","items":{"$ref":"#/components/schemas/MailboxRenameItem"},"maxItems":100,"minItems":0}},"required":["mailboxes"]},"MailboxRenameRequestApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/MailboxRenameRequestResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"MailboxRenameRequestResponse":{"type":"object","description":"Result of submitting a mailbox rename request. Mailboxes are not renamed.","properties":{"requested_count":{"type":"integer","format":"int32","description":"Number of mailboxes included in the request","example":1},"requested_mailboxes":{"type":"array","description":"Mailboxes included in the request","items":{"$ref":"#/components/schemas/MailboxRenameRequestedMailbox"}},"skipped":{"type":"array","description":"Mailboxes that were not sent to the team","items":{"$ref":"#/components/schemas/MailboxRenameRequestSkipped"}},"not_found":{"type":"array","description":"IDs or emails that were not found on this account","items":{"type":"string"}},"message":{"type":"string","description":"Confirmation of what was submitted"}}},"MailboxRenameRequestSkipped":{"type":"object","description":"A mailbox omitted from the rename request","properties":{"id":{"type":"integer","format":"int64"},"email":{"type":"string"},"reason":{"type":"string"}}},"MailboxRenameRequestedMailbox":{"type":"object","description":"A mailbox included in the rename request","properties":{"id":{"type":"integer","format":"int64"},"email":{"type":"string"},"status":{"type":"string"},"new_email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"new_first_name":{"type":"string"},"new_last_name":{"type":"string"}}},"JsonNode":{"type":"object","properties":{"empty":{"type":"boolean"},"array":{"type":"boolean"},"null":{"type":"boolean"},"object":{"type":"boolean"},"float":{"type":"boolean"},"container":{"type":"boolean"},"string":{"type":"boolean"},"missingNode":{"type":"boolean"},"valueNode":{"type":"boolean"},"nodeType":{"type":"string","enum":["ARRAY","BINARY","BOOLEAN","MISSING","NULL","NUMBER","OBJECT","POJO","STRING"]},"pojo":{"type":"boolean"},"number":{"type":"boolean"},"integralNumber":{"type":"boolean"},"floatingPointNumber":{"type":"boolean"},"short":{"type":"boolean"},"int":{"type":"boolean"},"long":{"type":"boolean"},"double":{"type":"boolean"},"bigDecimal":{"type":"boolean"},"bigInteger":{"type":"boolean"},"textual":{"type":"boolean","deprecated":true},"boolean":{"type":"boolean"},"binary":{"type":"boolean"},"embeddedValue":{"type":"boolean"}}},"LeadScraperSubmissionRequest":{"type":"object","description":"Lead scraper id and the input values to validate","properties":{"scraperId":{"type":"string","description":"Scraper id from GET /api/v1/lead-scrapers","example":"clutch"},"params":{"$ref":"#/components/schemas/JsonNode","description":"Input values. Keys are the snake_case keys from that scraper's inputs."}}},"LeadScraperSubmission":{"type":"object","description":"Accepted lead scraper inputs. Nothing is stored or charged.","properties":{"scraperId":{"type":"string","description":"Scraper id that was validated","example":"clutch"},"params":{"type":"object","additionalProperties":{},"description":"Accepted params only. Omitted inputs are left out."}}},"LeadScraperSubmissionApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/LeadScraperSubmission","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"Error":{"type":"object","description":"Standard error response","properties":{"success":{"type":"boolean","description":"Success flag","example":false},"error":{"type":"string","description":"Error code","example":"RESOURCE_NOT_FOUND"},"message":{"type":"string","description":"Human readable error message","example":"The requested resource was not found"},"timestamp":{"type":"string","description":"Timestamp of the error","example":"2025-12-14T10:30:00Z"}}},"ApiResponse":{"type":"object","description":"Standard API response wrapper","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/LeadScraperPayment","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"LeadScraperPayment":{"type":"object","description":"Price and payment result for one lead scraper request","properties":{"scraperId":{"type":"string","description":"Scraper id","example":"google-ads"},"currencyCode":{"type":"string","description":"Currency code","example":"USD"},"discountPercent":{"type":"integer","format":"int32","description":"0 or 50. 50 when the account has an active Aerosend subscription","example":50},"listAmount":{"type":"number","format":"double","description":"Price before the subscription discount","example":1.0},"amountDue":{"type":"number","format":"double","description":"Amount due for this scrape","example":0.5},"quantity":{"type":"integer","format":"int32","description":"Billed blocks of 1,000 units","example":1},"unitCount":{"type":"integer","format":"int32","description":"Lead or result count used to price the request","example":1},"requiresCheckout":{"type":"boolean","description":"True when preview or pay needs a checkout page"},"chargedImmediately":{"type":"boolean","description":"True when the saved card was charged"},"checkoutUrl":{"type":"string","description":"Pay page. Set when pay does not charge the saved card","example":"https://app.aerosend.io/payment?ptxn=txn_01"},"message":{"type":"string","description":"What to do next"}}},"EmailVerificationFile":{"type":"object","description":"Stored CSV for an email-verification submission","properties":{"fileId":{"type":"string","description":"Pass this value as params.file_id when submitting email-verification","example":"file_8f3a2c"}}},"EmailVerificationFileApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/EmailVerificationFile","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"AddDomainItem":{"type":"object","description":"Domain to be added","properties":{"domain":{"type":"string","description":"Domain name (e.g., example.com)","example":"example.com","maxLength":255,"minLength":0},"redirect_url":{"type":"string","description":"Redirect URL for the domain","example":"mysite.com","maxLength":255,"minLength":0}},"required":["domain","redirect_url"]},"AddDomainsRequest":{"type":"object","description":"Request to add one or more domains","properties":{"domains":{"type":"array","description":"List of domains to add","items":{"$ref":"#/components/schemas/AddDomainItem"},"maxItems":100,"minItems":0}},"required":["domains"]},"AddDomainsApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/AddDomainsResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"AddDomainsResponse":{"type":"object","description":"Response after adding domains","properties":{"added_count":{"type":"integer","format":"int32","description":"Number of domains successfully added","example":3},"reactivated_count":{"type":"integer","format":"int32","description":"Number of inactive domains reactivated","example":1},"domains":{"type":"array","description":"List of added domain details","items":{"$ref":"#/components/schemas/DomainSummary"}}}},"DomainSummary":{"type":"object","description":"Summary of an added domain","properties":{"id":{"type":"integer","format":"int64","description":"Domain ID","example":123},"domain":{"type":"string","description":"Domain name","example":"example.com"},"status":{"type":"string","description":"Domain status","example":"pending"}}},"DomainDeletionRequest":{"type":"object","description":"Deletion request for one or more domains. Does not delete them.","properties":{"domains":{"type":"array","description":"Domain names to request deletion for","example":["example.com","test.com"],"items":{"type":"string"},"maxItems":100,"minItems":0}},"required":["domains"]},"DomainDeletionRequestApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DomainDeletionRequestResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainDeletionRequestResponse":{"type":"object","description":"Result of submitting a domain deletion request. Domains are not deleted.","properties":{"requested_count":{"type":"integer","format":"int32","description":"Number of account domains included in the request","example":2},"requested_domains":{"type":"array","description":"Account domains included in the request","items":{"$ref":"#/components/schemas/RequestedDomain"}},"not_found_domains":{"type":"array","description":"Names that were not found on this account or were invalid","items":{"type":"string"}},"message":{"type":"string","description":"Confirmation that the team was notified and domains were not deleted"}}},"RequestedDomain":{"type":"object","description":"A domain included in the deletion request","properties":{"domain":{"type":"string","description":"Domain name","example":"example.com"},"status":{"type":"string","description":"Current domain status","example":"active"}}},"SequencerApiKeyRequest":{"type":"object","description":"Sequencer API key to validate or connect","properties":{"sequencer":{"type":"string","description":"Sequencer: smartlead or instantly","example":"smartlead","minLength":1},"api_key":{"type":"string","description":"Sequencer API key","example":"sk_live_xxx","maxLength":512,"minLength":0},"account_name":{"type":"string","description":"Optional label for this sequencer account","example":"Main workspace","maxLength":255,"minLength":0}},"required":["api_key","sequencer"]},"ApiKeyValidation":{"type":"object","description":"Result of validating a sequencer API key","properties":{"sequencer":{"type":"string","example":"smartlead"},"valid":{"type":"boolean"},"message":{"type":"string","example":"API key is valid"}}},"ApiKeyValidationApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/ApiKeyValidation","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"AddSequencerKeysRequest":{"type":"object","description":"One or more Smartlead/Instantly keys. A single key object is also accepted.","properties":{"keys":{"type":"array","description":"Keys to connect (1–20)","items":{"$ref":"#/components/schemas/SequencerApiKeyRequest"},"maxItems":20,"minItems":0}},"required":["keys"]},"AddSequencerKeys":{"type":"object","description":"Result of connecting one or more sequencer API keys","properties":{"accepted":{"type":"boolean","description":"True only when every key was stored and a scan was started"},"scanStarted":{"type":"boolean","description":"True only when data-ingestion-master /sync/publish was called"},"message":{"type":"string","description":"Overall explanation of what happened"},"keys":{"type":"array","items":{"$ref":"#/components/schemas/SequencerKeyResult"}},"scan":{"$ref":"#/components/schemas/ScanScore","description":"Report status after a successful connect; omitted when keys were rejected"}}},"AddSequencerKeysApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/AddSequencerKeys","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"ScanScore":{"type":"object","description":"Domain Burn scan / report status for the authenticated client","properties":{"status":{"type":"string","description":"Scan / report status","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","FAILED"],"example":"COMPLETED"},"reportExists":{"type":"boolean","description":"True when a completed report is available (possibly from an earlier scan)"},"nextStep":{"type":"string","description":"What the UI should do next","enum":["CONNECT_SEQUENCER","WAIT","VIEW_REPORT","RETRY_SCAN"],"example":"VIEW_REPORT"},"message":{"type":"string","description":"Human readable explanation of the status"},"startedAt":{"type":"string","format":"date-time","description":"When the latest scan was started"},"completedAt":{"type":"string","format":"date-time","description":"When the latest report was produced"},"sequencers":{"type":"array","description":"Connected sequencers (keys are never returned)","items":{"$ref":"#/components/schemas/SequencerInfo"}}}},"SequencerInfo":{"type":"object","properties":{"sequencer":{"type":"string","example":"smartlead"},"connected":{"type":"boolean"},"accountCount":{"type":"integer","format":"int32","description":"Number of active API keys for this sequencer"},"scanSupported":{"type":"boolean","description":"False when DBA ingestion cannot scan this sequencer yet"}}},"SequencerKeyResult":{"type":"object","properties":{"index":{"type":"integer","format":"int32","description":"Position in the request keys array","example":0},"sequencer":{"type":"string","example":"smartlead"},"accountName":{"type":"string","description":"Account label from the request, if provided","example":"Main workspace"},"key":{"type":"string","description":"Masked key (last 4 characters)","example":"••••a1b2"},"status":{"type":"string","description":"valid, invalid, or duplicate","enum":["VALID","INVALID","DUPLICATE"],"example":"INVALID"},"message":{"type":"string","description":"Why this key was accepted or rejected"}}},"SequencerKeysError":{"type":"object","description":"Returned when any submitted key is invalid or already connected. Nothing is stored.","properties":{"success":{"type":"boolean"},"error":{"type":"string"},"message":{"type":"string"},"accepted":{"type":"boolean","description":"Always false when any key is invalid or duplicate"},"scanStarted":{"type":"boolean","description":"Always false — /sync/publish is not called when any key fails"},"keys":{"type":"array","items":{"$ref":"#/components/schemas/SequencerKeyResult"}},"timestamp":{"type":"string"}}},"DomainSlotPurchaseRequest":{"type":"object","description":"Buy domain slots. Send domain_slots and/or mailbox_slots (3 mailboxes per domain slot).","properties":{"domain_slots":{"type":"integer","format":"int32","description":"Domain slots to add. Min 10, step 10, max 100.","example":10},"mailbox_slots":{"type":"integer","format":"int32","description":"Mailbox slots to add. Must be domain_slots × 3 (30, 60, ... 300).","example":30}}},"DomainSlotPurchaseApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DomainSlotPurchaseResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainSlotPurchaseResponse":{"type":"object","description":"Preview or result of a domain-slot purchase","properties":{"flow":{"type":"string","description":"update charges the saved card. create returns a checkout URL.","example":"update"},"charged_immediately":{"type":"boolean","description":"True when the saved card was charged immediately"},"domain_slots":{"type":"integer","format":"int32","description":"Domain slots in this purchase","example":10},"mailbox_slots":{"type":"integer","format":"int32","description":"Mailbox slots in this purchase (domain_slots × 3)","example":30},"unit_price":{"type":"number","format":"double","description":"Per-mailbox unit price in currency_code","example":4.0},"currency_code":{"type":"string","description":"Currency code","example":"USD"},"proration_amount":{"type":"number","format":"double","description":"Amount due now (proration for update, estimate for create)"},"upcoming_invoice_amount":{"type":"number","format":"double","description":"Recurring amount after this change (update flow)"},"checkout_url":{"type":"string","description":"Pay page. Set on create purchase only."},"message":{"type":"string","description":"What the caller should do next"}}},"Pagination":{"type":"object","description":"Pagination metadata","properties":{"offset":{"type":"integer","format":"int32","description":"Current offset","example":0},"limit":{"type":"integer","format":"int32","description":"Items per page","example":20},"total":{"type":"integer","format":"int64","description":"Total number of items","example":150},"has_more":{"type":"boolean","description":"Whether there are more items","example":true}}},"TagListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"List of items","items":{"$ref":"#/components/schemas/Tag"}},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Pagination metadata"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"ClientMeApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/ClientMeResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"ClientMeResponse":{"type":"object","description":"Authenticated client profile and usage information","properties":{"id":{"type":"integer","format":"int64","description":"Client identifier","example":123},"name":{"type":"string","description":"Client name","example":"John Doe"},"email":{"type":"string","description":"Client email address","example":"john.doe@example.com"},"domain_slots":{"type":"integer","format":"int64","description":"Total domain slots allocated to the client","example":50},"domain_slots_used":{"type":"integer","format":"int64","description":"Number of domain slots currently used","example":10},"mailbox_slots":{"type":"integer","format":"int64","description":"Total mailbox slots allocated to the client","example":200},"mailbox_slots_used":{"type":"integer","format":"int64","description":"Number of mailbox slots currently used","example":25},"status":{"type":"string","description":"Status of the client","example":"active"}}},"Credentials":{"type":"object","description":"SMTP and IMAP credentials for mailbox","properties":{"smtp":{"$ref":"#/components/schemas/ServerConfig","description":"SMTP server configuration"},"imap":{"$ref":"#/components/schemas/ServerConfig","description":"IMAP server configuration"}}},"Mailbox":{"type":"object","description":"Mailbox details","properties":{"id":{"type":"integer","format":"int64","description":"Mailbox ID","example":456},"email":{"type":"string","description":"Email address","example":"john@example.com"},"first_name":{"type":"string","description":"First name","example":"John"},"last_name":{"type":"string","description":"Last name","example":"Doe"},"status":{"type":"string","description":"Mailbox status","example":"active"},"created_at":{"type":"string","description":"Creation timestamp","example":"2025-12-01T10:30:00Z"},"updated_at":{"type":"string","description":"Last modification timestamp","example":"2025-12-10T15:45:00Z"},"domain_id":{"type":"integer","format":"int64","description":"Domain ID this mailbox belongs to","example":123},"domain":{"type":"string","description":"Domain name","example":"example.com"},"credentials":{"$ref":"#/components/schemas/Credentials","description":"SMTP/IMAP credentials (if requested)"},"tags":{"type":"array","description":"Tags assigned to this mailbox","items":{"$ref":"#/components/schemas/Tag"}}}},"MailboxListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"List of items","items":{"$ref":"#/components/schemas/Mailbox"}},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Pagination metadata"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"ServerConfig":{"type":"object","description":"Mail server configuration","properties":{"host":{"type":"string","description":"Server hostname","example":"smtp.topdeliverabilityninja.com"},"port":{"type":"integer","format":"int32","description":"Server port","example":587},"username":{"type":"string","description":"Username (email address)","example":"john@example.com"},"password":{"type":"string","description":"Password for authentication"},"security":{"type":"string","description":"Security protocol","example":"TLS"}}},"MailboxResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/Mailbox","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"LeadScraper":{"type":"object","description":"One lead scraper and the inputs it accepts","properties":{"id":{"type":"string","description":"Scraper id to send as scraper_id","example":"clutch"},"name":{"type":"string","description":"Display name","example":"Clutch"},"inputs":{"type":"array","description":"Inputs this scraper accepts","items":{"$ref":"#/components/schemas/LeadScraperInput"}}}},"LeadScraperInput":{"type":"object","description":"One input a lead scraper accepts","properties":{"key":{"type":"string","description":"snake_case key to send in params","example":"clutch_url"},"label":{"type":"string","description":"Label from the form","example":"Clutch URL"},"type":{"type":"string","description":"text, url, number, boolean, string_list, select, or multi_select","example":"text"},"required":{"type":"boolean","description":"True when the field must be present"},"options":{"type":"array","description":"Allowed values when type is select or multi_select","items":{"$ref":"#/components/schemas/LeadScraperOption"}},"minimum":{"type":"integer","format":"int32","description":"Minimum when the form enforces one","example":1000},"maximum":{"type":"integer","format":"int32","description":"Maximum when the form enforces one","example":300},"step":{"type":"integer","format":"int32","description":"Step when the form enforces one","example":1000}}},"LeadScraperListApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"Response data","items":{"$ref":"#/components/schemas/LeadScraper"}},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"LeadScraperOption":{"type":"object","description":"One allowed value for a select or multi_select input","properties":{"value":{"type":"string","description":"Value to send in params","example":"text"},"label":{"type":"string","description":"Label shown on the form","example":"Text ads"}}},"DnsProvider":{"type":"object","description":"DNS provider information","properties":{"id":{"type":"integer","format":"int64","description":"Provider ID","example":1},"name":{"type":"string","description":"Provider name","example":"Cloudflare"}}},"Domain":{"type":"object","description":"Domain details","properties":{"id":{"type":"integer","format":"int64","description":"Domain ID","example":123},"domain_tld":{"type":"string","description":"Full domain name including TLD","example":"example.com"},"mail_domain":{"type":"string","description":"Mail domain prefix","example":"mail"},"status":{"type":"string","description":"Domain status","example":"active"},"is_warmup":{"type":"boolean","description":"Whether domain is in warmup","example":true},"warmup_start_date":{"type":"string","description":"Warmup start date","example":"2025-12-01T00:00:00Z"},"warmup_end_date":{"type":"string","description":"Warmup end date","example":"2025-12-22T00:00:00Z"},"mailbox_count":{"type":"integer","format":"int64","description":"Number of mailboxes used","example":5},"redirect_url":{"type":"string","description":"Domain redirect URL","example":"https://example.com"},"attached_at":{"type":"string","description":"Date domain was attached","example":"2025-11-01T10:30:00Z"},"nameservers":{"type":"array","description":"Active nameservers for the domain","items":{"type":"string"}},"dns_provider":{"$ref":"#/components/schemas/DnsProvider","description":"DNS provider information"},"mailboxes":{"type":"array","description":"Mailboxes belonging to this domain (if requested)","items":{"$ref":"#/components/schemas/Mailbox"}},"tags":{"type":"array","description":"Tags assigned to this domain","items":{"$ref":"#/components/schemas/Tag"}}}},"DomainListResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"List of items","items":{"$ref":"#/components/schemas/Domain"}},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Pagination metadata"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/Domain","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainBurnClient":{"type":"object","properties":{"id":{"type":"string","example":"acme-com"},"name":{"type":"string","example":"acme.com"},"color":{"type":"string","example":"#7B61FF"},"domainCount":{"type":"integer","format":"int32"},"unassigned":{"type":"boolean"}}},"DomainBurnDomain":{"type":"object","properties":{"domain":{"type":"string","example":"outreach-acme.com"},"status":{"type":"string","example":"burnt"},"burnScore":{"type":"integer","format":"int32","description":"Burn score (0-100); null when low-volume"},"sent":{"type":"integer","format":"int32","description":"Emails sent in the scored period"},"delta":{"type":"integer","format":"int32","description":"Score change vs previous period"},"flags":{"type":"array","items":{"type":"string"}},"clientName":{"type":"string"},"metricsDate":{"type":"string","format":"date"}}},"DomainBurnGroup":{"type":"object","properties":{"status":{"type":"string","example":"at-risk"},"label":{"type":"string","example":"At-risk"},"description":{"type":"string"},"count":{"type":"integer","format":"int32"},"action":{"type":"string","description":"Bulk action key: replace or slowdown; null when none","example":"slowdown"},"actionLabel":{"type":"string","example":"Slow down all"}}},"DomainBurnPagination":{"type":"object","description":"Offset pagination for domain rows","properties":{"offset":{"type":"integer","format":"int32","example":0},"limit":{"type":"integer","format":"int32","example":100},"total":{"type":"integer","format":"int64","example":250},"hasMore":{"type":"boolean","example":true}}},"DomainBurnReport":{"type":"object","description":"Domain Burn Alerts report for the authenticated client","properties":{"reportAvailable":{"type":"boolean","description":"False until a scan has produced a report; summary/domains are empty then"},"scan":{"$ref":"#/components/schemas/ScanScore","description":"Scan / report status — same payload as GET /scan-score"},"summary":{"$ref":"#/components/schemas/DomainBurnSummary"},"groups":{"type":"array","description":"Status groups in display order, with the bulk action for each","items":{"$ref":"#/components/schemas/DomainBurnGroup"}},"clients":{"type":"array","description":"End clients derived from domain redirect URLs, plus 'all' and 'unassigned'","items":{"$ref":"#/components/schemas/DomainBurnClient"}},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainBurnDomain"}},"pagination":{"$ref":"#/components/schemas/DomainBurnPagination","description":"Pagination for domains[] (offset / limit, max 100)"}}},"DomainBurnReportApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DomainBurnReport","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainBurnSummary":{"type":"object","properties":{"totalDomains":{"type":"integer","format":"int32"},"burnt":{"type":"integer","format":"int32"},"atRisk":{"type":"integer","format":"int32"},"good":{"type":"integer","format":"int32"},"excellent":{"type":"integer","format":"int32"},"lowVolume":{"type":"integer","format":"int32"},"clientCount":{"type":"integer","format":"int32","description":"Distinct end clients (redirect URLs)"},"metricsDate":{"type":"string","format":"date","description":"Latest scoring date"},"reportFromDate":{"type":"string","format":"date","description":"Start of the scored period"},"reportToDate":{"type":"string","format":"date","description":"End of the scored period"}}},"SequencerConnection":{"type":"object","description":"Sequencer API keys connected for Domain Burn Alerts","properties":{"hasApiKey":{"type":"boolean","description":"True when at least one supported sequencer key is connected"},"sequencers":{"type":"array","description":"Smartlead and Instantly connection state","items":{"$ref":"#/components/schemas/SequencerInfo"}}}},"SequencerConnectionApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/SequencerConnection","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"ScanScoreApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/ScanScore","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"SequencerKey":{"type":"object","properties":{"id":{"type":"integer","format":"int64","description":"Mailbridge client_integrations.id; pass as GET /domain-burn?id=","example":42},"sequencer":{"type":"string","description":"smartlead or instantly","example":"smartlead"},"displayName":{"type":"string","description":"Integration display name from client_integrations.name","example":"Main workspace"},"reportStatus":{"type":"string","description":"Report status for this key","enum":["NOT_STARTED","IN_PROGRESS","COMPLETED","FAILED"],"example":"COMPLETED"},"message":{"type":"string","description":"Human readable explanation of report_status"}}},"SequencerKeyList":{"type":"object","description":"Smartlead and Instantly keys connected for Domain Burn","properties":{"keys":{"type":"array","description":"Active Smartlead and Instantly keys. PlusVibe and EmailBison are omitted.","items":{"$ref":"#/components/schemas/SequencerKey"}}}},"SequencerKeyListApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/SequencerKeyList","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainBurnAction":{"type":"object","properties":{"type":{"type":"string","example":"replace"},"title":{"type":"string"},"description":{"type":"string"},"buttonLabel":{"type":"string"}}},"DomainBurnDetailApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DomainBurnDomainDetail","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainBurnDomainDetail":{"type":"object","description":"Health detail for a single domain","properties":{"domain":{"$ref":"#/components/schemas/DomainBurnDomain"},"sequencer":{"type":"string","description":"Display name of the sequencer(s) the domain is scored from","example":"Smartlead"},"metrics":{"$ref":"#/components/schemas/DomainBurnMetrics"},"issues":{"type":"array","description":"Why the domain is in its bucket; empty for good/excellent/low-volume","items":{"$ref":"#/components/schemas/DomainBurnIssue"}},"history":{"type":"array","description":"Monthly burn score history, oldest first","items":{"$ref":"#/components/schemas/DomainBurnHistoryPoint"}},"action":{"$ref":"#/components/schemas/DomainBurnAction","description":"Recommended action; null when nothing to do"},"notice":{"type":"string","description":"Shown instead of history for low-volume domains"}}},"DomainBurnHistoryPoint":{"type":"object","properties":{"month":{"type":"string","example":"2026-09"},"label":{"type":"string","example":"Sep"},"score":{"type":"integer","format":"int32"}}},"DomainBurnIssue":{"type":"object","properties":{"tag":{"type":"string","example":"High Bounce"},"text":{"type":"string"}}},"DomainBurnMetrics":{"type":"object","properties":{"burnScore":{"type":"number","format":"double"},"warmupScore":{"type":"number","format":"double"},"replyRate":{"type":"number","format":"double","description":"Reply rate (%)"},"bounceRate":{"type":"number","format":"double","description":"Bounce rate (%)"},"placementScore":{"type":"number","format":"double","description":"Inbox placement (%)"},"totalSent":{"type":"integer","format":"int32"},"metricsDate":{"type":"string","format":"date"}}},"WarmupScore":{"type":"object","description":"Warmup score for a mailbox","properties":{"email":{"type":"string","description":"Mailbox email address","example":"john@example.com"},"score":{"type":"integer","format":"int32","description":"Warmup score","example":90},"warmup_start_date":{"type":"string","description":"Domain warmup start date (YYYY-MM-DD)","example":"2026-09-01"}}},"WarmupScoreListApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"type":"array","description":"List of items","items":{"$ref":"#/components/schemas/WarmupScore"}},"pagination":{"$ref":"#/components/schemas/Pagination","description":"Pagination metadata"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DomainAnalytics":{"type":"object","description":"Inbox placement metrics for a sender domain, including per-ESP breakdown","properties":{"sender_domain":{"type":"string","description":"Sender domain","example":"example.com"},"total_emails":{"type":"integer","format":"int32","description":"Total emails sent from this domain","example":85},"inbox_count":{"type":"integer","format":"int32","description":"Emails delivered to inbox","example":32},"spam_count":{"type":"integer","format":"int32","description":"Emails delivered to spam","example":53},"inbox_percentage":{"type":"number","description":"Inbox rate as a percentage of total emails","example":37.65},"esp_breakdown":{"type":"array","description":"Per-ESP metrics for this domain","items":{"$ref":"#/components/schemas/EspBreakdown"}}}},"EspBreakdown":{"type":"object","description":"Inbox placement metrics for a single email service provider","properties":{"esp_name":{"type":"string","description":"Email service provider name","enum":["Gmail","Google Workspace","Outlook","Microsoft 365","Yahoo Mail","Zoho Mail","Other"],"example":"Google Workspace"},"total_emails":{"type":"integer","format":"int32","description":"Total emails sent to this ESP","example":522},"inbox_count":{"type":"integer","format":"int32","description":"Emails delivered to inbox","example":61},"spam_count":{"type":"integer","format":"int32","description":"Emails delivered to spam","example":461},"inbox_percentage":{"type":"number","description":"Inbox rate as a percentage of total emails","example":11.69}}},"InboxPlacementAnalytics":{"type":"object","description":"Inbox placement test analytics for the authenticated client","properties":{"test_run_at":{"type":"string","description":"When the test was run","example":"2026-09-20T13:00:00Z"},"total_emails_sent":{"type":"integer","format":"int32","description":"Total emails sent in the test","example":765},"inbox_count":{"type":"integer","format":"int32","description":"Emails delivered to inbox","example":304},"spam_count":{"type":"integer","format":"int32","description":"Emails delivered to spam","example":461},"inbox_percentage":{"type":"number","description":"Overall inbox rate as a percentage","example":39.74},"spam_percentage":{"type":"number","description":"Overall spam rate as a percentage","example":60.26},"google_total_sent":{"type":"integer","format":"int32","description":"Total emails sent to Google / Google Workspace seed inboxes","example":522},"outlook_total_sent":{"type":"integer","format":"int32","description":"Total emails sent to Outlook / Microsoft 365 seed inboxes","example":243},"overall_esp_breakdown":{"type":"array","description":"Overall metrics grouped by email service provider","items":{"$ref":"#/components/schemas/EspBreakdown"}},"domain_breakdown":{"type":"array","description":"Per-domain metrics, including nested ESP breakdown. All domains from the test are returned.","items":{"$ref":"#/components/schemas/DomainAnalytics"}}}},"InboxPlacementAnalyticsApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/InboxPlacementAnalytics","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DeleteTagsRequest":{"type":"object","description":"Request to delete one or more tags","properties":{"tag_ids":{"type":"array","description":"IDs of tags to delete","example":[1,2,3],"items":{"type":"integer","format":"int64"},"maxItems":100,"minItems":0}},"required":["tag_ids"]},"RemoveMailboxTagMappingRequest":{"type":"object","description":"Request to remove tag mappings from mailboxes","properties":{"mailbox_ids":{"type":"array","description":"IDs of mailboxes to remove the tag from","example":[100,101,102],"items":{"type":"integer","format":"int64"},"maxItems":500,"minItems":0}},"required":["mailbox_ids"]},"RemoveDomainTagMappingRequest":{"type":"object","description":"Request to remove tag mappings from domains","properties":{"domain_ids":{"type":"array","description":"IDs of domains to remove the tag from","example":[10,11,12],"items":{"type":"integer","format":"int64"},"maxItems":500,"minItems":0},"include_domain_mailboxes":{"type":"boolean","description":"If true, also remove the tag from all mailboxes under the specified domains","example":false}},"required":["domain_ids"]},"DeleteMailboxesRequest":{"type":"object","description":"Request to delete one or more mailboxes","properties":{"ids":{"type":"array","description":"List of mailbox IDs to delete","example":[456,789],"items":{"type":"integer","format":"int64"},"maxItems":100,"minItems":0},"emails":{"type":"array","description":"List of email addresses to delete","example":["john@example.com","jane@example.com"],"items":{"type":"string"},"maxItems":100,"minItems":0}}},"DeleteMailboxesApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DeleteMailboxesResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DeleteMailboxesResponse":{"type":"object","description":"Response after deleting mailboxes","properties":{"deleted_count":{"type":"integer","format":"int32","description":"Number of mailboxes successfully deleted","example":3},"skipped":{"type":"array","description":"List of mailboxes that were skipped (not in pending status)","example":[],"items":{"$ref":"#/components/schemas/SkippedMailbox"}}}},"SkippedMailbox":{"type":"object","description":"Mailbox that was skipped during deletion","properties":{"id":{"type":"integer","format":"int64","description":"Mailbox ID","example":789},"email":{"type":"string","description":"Email address","example":"jane@example.com"},"reason":{"type":"string","description":"Reason for skipping","example":"Mailbox is not in pending status"}}},"DeleteDomainsRequest":{"type":"object","description":"Request to delete one or more domains","properties":{"ids":{"type":"array","description":"List of domain IDs to delete","example":[123,456],"items":{"type":"integer","format":"int64"},"maxItems":100,"minItems":0},"domains":{"type":"array","description":"List of domain names to delete","example":["example.com","test.com"],"items":{"type":"string"},"maxItems":100,"minItems":0}}},"DeleteDomainsApiResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Success flag","example":true},"data":{"$ref":"#/components/schemas/DeleteDomainsResponse","description":"Response data"},"timestamp":{"type":"string","description":"Response timestamp","example":"2025-12-14T10:30:00Z"}}},"DeleteDomainsResponse":{"type":"object","description":"Response after deleting domains","properties":{"deleted_count":{"type":"integer","format":"int32","description":"Number of domains successfully deleted","example":2},"deleted_domains":{"type":"array","description":"List of deleted domain names","items":{"type":"string"}},"skipped_domains":{"type":"array","description":"List of domains that could not be deleted (not in pending status)","items":{"$ref":"#/components/schemas/SkippedDomain"}}}},"SkippedDomain":{"type":"object","description":"Domain that was skipped during deletion","properties":{"identifier":{"type":"string","description":"Domain name or ID","example":"example.com"},"reason":{"type":"string","description":"Reason for skipping","example":"Domain is not in pending status"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - Invalid or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"RateLimitError":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}},"NotFoundError":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"ValidationError":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","description":"Your Aerosend API key. Include this in the X-API-Key header of every request.","name":"X-API-Key","in":"header"}}}}