# Aerosend Developer API and MCP Server > Programmatic access to an Aerosend account: cold email sending domains, mailboxes (with SMTP/IMAP credentials), tags, mailbox warmup scores, inbox placement tests and domain burn reports. AI assistants should connect to the hosted MCP server at https://mcp.aerosend.io/mcp. Code and automations should call the REST API at https://api.aerosend.io. Aerosend is cold email infrastructure. It provisions the domains and mailboxes that sequencers such as Smartlead and Instantly send through. It is not a sequencer and does not send campaigns itself. ## Connect an AI assistant (MCP) - Endpoint: `https://mcp.aerosend.io/mcp` (Streamable HTTP transport) - Auth option 1, OAuth: clients that support MCP OAuth (Claude, ChatGPT, Cursor, VS Code) open an Aerosend sign-in page when you add the URL. Nothing else to configure. New users can sign up on that page (Google or email). - Auth option 2, API key: send the header `X-API-Key: aero_...`. Create the key in app.aerosend.io > Developer. Each account has one key, and regenerating it revokes the old one immediately. - [MCP setup guide](https://www.aerosend.io/mcp/): copy-paste setup for Claude, Claude Code, ChatGPT, Cursor and VS Code - [MCP connector notes](https://api.aerosend.io/mcp): the same setup steps on this API host - [MCP server card](https://mcp.aerosend.io/mcp/server-card): machine-readable connection details (MCP Server Card format) ## Rules agents need before acting - Call `get_me` before adding domains or mailboxes. Free domain slots = `domain_slots - domain_slots_used`, and mailboxes work the same way. `add_domains` fails entirely if there are not enough free slots. Nothing is partially created. - Brand-new account with no plan, or not enough slots: preview with `preview_domain_slot_purchase`, then `purchase_domain_slots` (or `POST /api/v1/billing/domain-slots`). Min 10 domain slots, step 10. 1 domain slot = 3 mailboxes. Existing subscriptions charge the saved card; new accounts return `checkout_url` at https://app.aerosend.io/payment?ptxn=... - Most tools take numeric ids. When the user gives a domain name, email or tag name, look it up with `list_domains`, `list_mailboxes` or `list_tags` first. - Status lifecycle: `pending` (just added) > `in_progress` (being provisioned) > `active`. `inactive` items stay listed but use no slots. - Mailboxes can only be added to `active` domains. Limits: 3 mailboxes per domain, 60 mailboxes per request. - `add_domains` needs a redirect URL for every domain, as a bare domain such as `mysite.com`. - `delete_domains` and `delete_mailboxes` only remove `pending` items. Other items are skipped, and the call still returns success, so compare the deleted count with what you asked for. Ask the user before deleting. Deletes cannot be undone. - To remove active domains, use `request_domain_deletion`. It notifies the Aerosend team and does not delete anything immediately. Tell the user that. - Never ask the user for Smartlead or Instantly API keys in chat. If sequencer keys are missing, send them to https://app.aerosend.io/connect-sequencer - Only request SMTP/IMAP credentials (`includeCredentials`) when the user needs them. - List endpoints page with `offset` and `limit`. The default limit is 20 and the maximum is 100. - Rate limit: 60 requests per minute per API key. Prefer the bulk inputs (comma-separated lists or JSON arrays) over one call per item. - Lead scrapers: call `GET /api/v1/lead-scrapers` (or `list_lead_scrapers`) and copy that scraper's `id` and input `key` values. Send them as `scraper_id` and `params`. The field list for every scraper is below. ## Lead scrapers `GET /api/v1/lead-scrapers` returns the same 16 scrapers for every account. Each item has `id`, `name`, and `inputs`. An input has `key`, `label`, `type`, `required`, and `options` when the value must be chosen from a list. Send `value` from `options`, not the label. Submit with `POST /api/v1/lead-scrapers/submissions`: ```json { "scraper_id": "linkedin-jobs", "params": { "titles": ["Marketing Manager"], "results_limit": 3000, "file_name": "linkedin jobs" } } ``` `string_list` and `multi_select` are arrays of strings. `file_name` keeps letters, numbers, spaces, underscores, and hyphens. A result count is required before `POST /api/v1/lead-scrapers/payment-preview` even when that field is optional on submit. Email verification needs `file_id` from `POST /api/v1/lead-scrapers/email-verification/file` first. **clutch** — Clutch. `clutch_url` text required. `number_of_companies` number optional, rounds up to the next 1,000. `file_name` text required. **google-maps** — Google Maps. `categories` string_list required. `exact_match` boolean optional. `locations` string_list required. `max_results` number required, integer >= 1000 and a multiple of 1000. `enrichments` multi_select optional: `companyInsight`, `similarWeb`, `contactsLeadEnrichment`, `emailContacts`, `phoneEnricher`, `chainInfo`, `builtWith`. `file_name` text required. **ad-libraries** — Ad Libraries. `company_names` string_list required. `platforms` multi_select optional: `meta`, `tiktok`, `google`, `linkedin`. `file_name` text required. **sales-navigator** — Professional Navigator. `sales_navigator_url` url required. `sales_navigator_number_of_results` number optional: 1000, 2000, or 2500. `file_name` text required. **yelp** — Yelp. `yelp_search_term` text required. `yelp_location` text optional. `yelp_number_of_results` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **yellow-pages** — Yellow Pages. `search_term` text required. `location` text optional. `yellow_pages_number_of_results` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **indeed** — Indeed. `job_title` text required. `indeed_location` text optional. `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`. `number_of_results` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **linkedin-jobs** — Professional Jobs. `titles` string_list required. `locations` string_list optional. `date_posted` select optional: `r86400` past 24 hours, `r604800` past week, `r2592000` past month. `contract_type` multi_select optional: `F` full-time, `P` part-time, `C` contract, `T` temporary, `I` internship, `V` volunteer. `experience_level` multi_select optional: `1` internship, `2` entry level, `3` associate, `4` mid-senior, `5` director, `6` executive. `remote_type` multi_select optional: `2` remote, `1` hybrid, `3` on-site. `results_limit` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **post-search** — Professional Post Search. `search_keywords` string_list required. `post_date_posted` select optional: `any`, `past1h`, `past24h`, `pastWeek`, `pastMonth`, `past3months`, `past6months`, `pastYear`. `post_sort_by` select optional: `relevant`, `recent`. `number_of_posts` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **profile-search** — Professional Profile Search. `profile_search_query` text required, at most 300 characters. `profile_locations` string_list optional. `current_job_titles` string_list optional. `seniority_level` multi_select optional: `in_training`, `entry_level`, `senior`, `strategic`, `entry_manager`, `experienced_manager`, `director`, `vp`, `cxo`, `owner`. `profile_detail_level` select optional: `short`, `full`, `fullEmail`. `profile_number_of_results` number optional, integer >= 1000 and a multiple of 1000. `file_name` text required. **email-verification** — Email Verification. `file_id` text required. `number_of_contacts_to_verify` number required, integer >= 1. `file_name` text required. **apollo** — Apollo. `apollo_search_url` url required. `apollo_number_of_leads` number required, integer >= 1000 and a multiple of 1000. `apollo_verify_emails` select optional: `dont-verify`, `verify`. `file_name` text required. **crunchbase** — Crunchbase. `crunchbase_search_url` url required. `crunchbase_number_of_companies` number required, integer >= 1000 and a multiple of 1000. `file_name` text required. **profile-enrichment** — Profile Enrichment. `profile_enrichment_urls` string_list required, each item a URL. `file_name` text required. **post-comments** — Post Commenters. `post_urls` string_list required. `max_comments_per_post` number optional, integer >= 1. `posted_limit` select optional: `past24h`, `pastWeek`, `pastMonth`. `scrape_replies` boolean optional. `profile_scraper_mode` select optional: `short`, `full`. `file_name` text required. **google-ads** — Google Ads. At least one of `advertiser_name` or `transparency_center_url` (both text). `ad_format` select optional: `text`, `image`, `video`. `max_results` number optional, integer from 1 to 50000, required before payment. ## MCP tools Read-only: - `get_me`: account name, status and slot usage (`GET /api/v1/me`) - `preview_domain_slot_purchase`: price and flow for adding domain slots; does not charge (`POST /api/v1/billing/domain-slots/preview`) - `list_domains` / `get_domain`: domains with status, warmup flag, mailbox count, redirect URL, nameservers, DNS provider and tags (`GET /api/v1/domains`, `GET /api/v1/domains/{id}`) - `list_mailboxes` / `get_mailbox`: mailboxes, optionally with SMTP and IMAP credentials (`GET /api/v1/mailboxes`, `GET /api/v1/mailboxes/{id}`) - `list_tags` / `get_tag`: tags with optional domain and mailbox counts (`GET /api/v1/tags`, `GET /api/v1/tags/{id}`) - `list_warmup_scores`: warmup score and start date per mailbox (`GET /api/v1/analytics/warmup-scores`) - `get_inbox_placement_analytics`: latest inbox placement test: inbox and spam percentages, Google and Outlook split, per-domain breakdown (`GET /api/v1/analytics/inbox-placement`) - `get_domain_burn_report`: per-domain burn status (burnt, at-risk, good, excellent, low-volume) with summary counts (`GET /api/v1/domain-burn`) - `get_domain_burn_detail`: one domain's burn metrics, issues, monthly history and recommended action (replace or slow down) (`GET /api/v1/domain-burn/domains/{domain}`) - `get_domain_burn_scan_status`: whether the burn report is ready, plus the next step (`GET /api/v1/domain-burn/scan-score`) - `get_domain_burn_sequencers` / `list_domain_burn_keys`: which Smartlead and Instantly accounts are connected. Key values are never returned (`GET /api/v1/domain-burn/sequencer`, `GET /api/v1/domain-burn/keys`) - `get_domain_burn_connect_url`: the page where the user connects sequencer keys - `list_lead_scrapers`: every lead scraper `id` and the input `key` values for that scraper (`GET /api/v1/lead-scrapers`) - `preview_lead_scraper_payment`: amount due for one scrape. Does not charge (`POST /api/v1/lead-scrapers/payment-preview`) Write: - `purchase_domain_slots`: buy domain slots. Charges the saved card on an existing subscription, or returns a checkout URL (`POST /api/v1/billing/domain-slots`) - `add_domains`: add domains (they start `pending` with warmup on) (`POST /api/v1/domains`) - `add_mailboxes`: add mailboxes to active domains (`POST /api/v1/mailboxes`) - `upload_email_verification_file`: upload a CSV and return `file_id` for the `email-verification` scraper (`POST /api/v1/lead-scrapers/email-verification/file`) - `submit_lead_scraper`: validate one scraper's `params`. Does not charge (`POST /api/v1/lead-scrapers/submissions`) - `pay_lead_scraper`: pay for a lead scrape. Charges the saved card, or returns `checkout_url` (`POST /api/v1/lead-scrapers/payment`) - `create_tags`: create tags. Safe to repeat: existing names are returned instead of duplicated (`POST /api/v1/tags`) - `map_tags_to_domains` / `map_tags_to_mailboxes`: attach tags. Existing mappings are ignored (`POST /api/v1/tags/domains/mapping`, `POST /api/v1/tags/mailboxes/mapping`) Write, changes or removes data: - `update_domain_redirect_urls`: change redirect URLs, up to 100 per call (`PUT /api/v1/domains/redirect-urls`) - `update_tag`: rename or recolor a tag (`PUT /api/v1/tags/{id}`) - `remove_tag_from_domains` / `remove_tag_from_mailboxes`: detach a tag. The tag itself is kept (`DELETE /api/v1/tags/{id}/domains`, `DELETE /api/v1/tags/{id}/mailboxes`) - `delete_tags`: delete tags and all their mappings (`DELETE /api/v1/tags`) - `delete_domains` / `delete_mailboxes`: delete `pending` items only (`DELETE /api/v1/domains`, `DELETE /api/v1/mailboxes`) - `request_domain_deletion`: ask the Aerosend team to delete domains, including active ones (`POST /api/v1/domains/deletion-request`) ## REST API - Base URL `https://api.aerosend.io`. Send `X-API-Key: aero_...` on every request. `GET /api/health/ping` needs no key. - Success responses look like `{"success": true, "data": ..., "pagination"?: {"offset", "limit", "total", "has_more"}, "timestamp"}`. Some writes return `204` with no body. - Error responses look like `{"success": false, "error": "CODE", "message": "...", "errors"?: [{"field", "message"}]}`. Common codes: `VALIDATION_ERROR`, `INSUFFICIENT_DOMAIN_SLOTS`, `DOMAIN_INACTIVE`, `MAILBOX_LIMIT_EXCEEDED`, `DOMAINS_ALREADY_EXIST`, `RATE_LIMIT_EXCEEDED` (with `Retry-After`). - Every response has an `X-Request-Id` header. Include it in support requests. - [OpenAPI 3.1 spec](https://api.aerosend.io/api-docs): every endpoint, parameter and schema, as JSON - [API reference](https://api.aerosend.io/): the same spec, rendered for people ## Optional - [What is Aerosend](https://www.aerosend.io/cold-email/what-is-aerosend/): product overview and how it fits with sequencers - [Pricing](https://www.aerosend.io/pricing/): plans and slot pricing - [Website llms.txt](https://www.aerosend.io/llms.txt): product, deliverability guides and comparisons - Support: support@aerosend.io