Skip to main content

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 gets instantly_query and is structurally incapable of sending mail.
  • Instantly Query (instantly_query) — read-only. resource selects 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.
    • emails always carries a time window (since, defaulting to the last 24 hours). GET /emails is 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 a since matched 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. Defaults skip_if_in_workspace to true so a contact already in another campaign is not double-sent, and warns when a lead is missing the custom_variables CRM join key.
    • create_campaign — requires name and campaign_schedule. sequences is 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 + optional body) for the long tail: webhooks, blocklists, lead updates, campaign pause/activate.

Watching for replies

There is no inbound webhook. A scheduled agent polls instantly_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 /emails is capped at 20 requests/minute and pages 100 records at a time. instantly_query defaults 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_variables at 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_variables on add_leads, but they come BACK under payload — flattened alongside firstName/email — on instantly_query resource: "leads". Reading custom_variables off a fetched lead always returns nothing.

Known API behaviour

  • add_leads is asynchronous. It returns leads_uploaded and a lead id, but the lead is not readable for roughly 45 seconds — instantly_query will show nothing and GET /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_manage polls it to a terminal state so a reported “enabled” means enabled.
  • Merge fields are written as custom_variables and read back as payload. Verified live; there is no custom_variables key on a fetched lead.
  • GET /emails is rate limited to 20 requests/minute, unlike the rest of the API.