Overview
The Instantly integration lets your agents drive a cold-email program: add leads to campaigns in bulk, create and configure campaigns, manage sending mailboxes and warmup, and pull replies and campaign analytics. Replies are picked up by polling on a schedule, so a scheduled agent can route them into your CRM without any inbound webhook setup. Your organization’s Instantly API key is injected automatically into every tool call — agents never see or handle the key.Prerequisites
- An Instantly account with API access
- An Instantly API v2 key (Instantly → Settings → Integrations → API Keys). v2 keys are scoped, so grant access to campaigns, leads, accounts, and webhooks
- An Aster admin to connect the integration (the connection is shared org-wide)
- A dedicated sending domain with warmed mailboxes. Sending cold mail from your primary business domain is what the dedicated-domain pattern exists to avoid
Setup Guide
1
Get your Instantly API key
In Instantly, open Settings → Integrations → API Keys and create a key with access to campaigns, leads, accounts, and webhooks.
2
Connect Instantly in Aster Agents
Navigate to Control Hub → Integrations, locate the Instantly card, click Connect, and paste your API key. Aster validates it against Instantly (
GET /campaigns) and stores it securely for your organization. The key is redacted on read-back, so it is never shown again after you save it.3
Add the Instantly tools to your agent
Edit your agent and enable the tools it needs. An agent that only reads — a reply watcher, a reporting agent — should get Instantly Query alone, which cannot send mail. Add Instantly Manage only for agents allowed to add leads or start campaigns, and Call Instantly API only when you need an endpoint the other two don’t cover.
Available Tools
Split on the permission boundary rather than per entity: reads in one tool, writes in another. An agent that only watches for replies getsinstantly_query and is structurally incapable of sending mail.
- Instantly Query (
instantly_query) — read-only.resourceselects what to read:campaigns,campaign,analytics,leads,emails(sent mail and replies),accounts(sending mailboxes and warmup state),background_job. Follows Instantly’s cursor automatically and spills large results to sandbox files.emailsalways carries a time window (since, defaulting to the last 24 hours).GET /emailsis capped at 20 requests/minute unlike the rest of the API and pages 100 records at a time, so an unscoped sweep re-walks the whole mailbox. Pass asincematched to your polling interval.
- Instantly Manage (
instantly_manage) — gated write companion. Only grant it to agents allowed to send on the org’s behalf.add_leads— bulk-add up to 1000 leads to a campaign. Defaultsskip_if_in_workspaceto true so a contact already in another campaign is not double-sent, and warns when a lead is missing thecustom_variablesCRM join key.create_campaign— requiresnameandcampaign_schedule.sequencesis an array but Instantly reads only the first element; the tool warns if you send more.enable_warmup/disable_warmup— Instantly returns a background job, not a result. The tool polls the job to a terminal state, so a reported “enabled” means enabled rather than “queued”.
- Call Instantly API (
instantly_api_call) — escape hatch to any v2 endpoint (method+endpoint+ optionalbody) for the long tail: webhooks, blocklists, lead updates, campaign pause/activate.
Watching for replies
There is no inbound webhook. A scheduled agent pollsinstantly_query with resource: "emails" and a since matched to its interval, then writes anything new into your CRM.
At a typical cold-email volume this is both simpler and more reliable than a push webhook: a run that fails just re-reads the same window next time, whereas a dropped webhook delivery is gone. It also needs no token, no registration step in Instantly, and no custom CRM properties.
Two things to get right:
- Always pass
since.GET /emailsis capped at 20 requests/minute and pages 100 records at a time.instantly_querydefaults to a 24-hour window so an unscoped sweep can’t happen, but set it to match your polling interval with a little overlap. - Carry your context in
custom_variablesat add time, then read it back off the lead when the reply arrives. Anything you put there survives the round trip, so a lead can carry the CRM record id, owner, region, or whatever your sync needs to write without re-deriving it. - Mind the naming asymmetry. You WRITE merge fields as
custom_variablesonadd_leads, but they come BACK underpayload— flattened alongsidefirstName/email— oninstantly_queryresource: "leads". Readingcustom_variablesoff a fetched lead always returns nothing.
Known API behaviour
add_leadsis asynchronous. It returnsleads_uploadedand a lead id, but the lead is not readable for roughly 45 seconds —instantly_querywill show nothing andGET /leads/{id}returns 404. Trust the add response; do not read back to verify and re-add, or you will create duplicates.- Warmup toggles return a background job, not a result.
instantly_managepolls it to a terminal state so a reported “enabled” means enabled. - Merge fields are written as
custom_variablesand read back aspayload. Verified live; there is nocustom_variableskey on a fetched lead. GET /emailsis rate limited to 20 requests/minute, unlike the rest of the API.