Instantly
Sending and campaign operations
A cold email platform. It holds the mailboxes, the sequence copy and the sending schedule, and it decides which lead gets which email on which day.
Instantly is the last stop. Everything upstream exists to hand it a person who should be contacted, with the facts the copy needs. Once a lead is in a campaign, the decisions are already made, so most of my care goes into what crosses that line rather than what happens after.
How I use it
One campaign per segment, never one campaign with clever copy. If two groups need different arguments, they get different campaigns and different variables. Merging them means every variable has to be present on every lead, and the first missing one renders a blank sentence to a stranger.
Variables get gated before the push, not after. The push column only fires when the campaign’s variables are all present on that row. A campaign that references five variables cannot accept a lead that has four of them. That check belongs upstream, because by the time the lead is inside Instantly, the send is scheduled.
Infrastructure changes happen paused. Swapping which mailboxes a campaign sends from means: pause the campaign, change the sender tag, check every attached mailbox has a signature, fix the ones that do not, read the signatures back with a fresh request, then resume. I do it in that order because I once did it in a different order and mail went out unsigned.
I read the copy back byte for byte. Instantly stores subject and body exactly as sent, so after any write I fetch the campaign again and diff it against what I meant to write. On read-back, step content sits under the first variant of the step, not on the step itself, which is a small thing that costs an hour once.
What I have learned the hard way
The leads list ignores campaign_id. Filter by that key and you get the whole
workspace back, quietly, in the right shape, with no error. The honoured key is
campaign. Anything counted with the wrong key is a workspace total wearing a
campaign label, and it looks completely reasonable.
Custom variables pushed in from outside land under the lead’s payload, not
under the custom_variables field, which reads as empty. So a QA script that
checks the obvious field concludes every lead is missing every variable.
A move job locks the campaign. Moving leads caps at 500 per job, and a second move against the same campaign while the first is running returns a conflict. Chunk them, and run the chunks for one campaign one after another.
Lead limits are counted across the workspace, not per campaign. When the cap is hit, every push errors at once, and the error names the upload rather than the plan. Leads parked in a list instead of a campaign do not count against it, which is the cheap fix.
Small ones that cost real time: the API returns 403 to a default script user
agent, so send a browser one. A delete fails on an empty body unless you drop the
content type header. The schedule rejects America/New_York and accepts
America/Detroit for the same hours.
Resources
This is one part of a stack. The rest is on the tools page, and what I build with it is on work.