Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Instantly Campaign

ASecurity

Create a paused cold email campaign in Instantly with all leads loaded and all sending accounts attached. I read your locked sequence, sanitize bodies (Instantly drops bodies that contain a literal ampersand - documented bug), bulk-load up to 1000 leads per call, and configure the schedule with a timezone Instantly accepts (America/Vancouver for Pacific, handles DST automatically). Always paused for your review - never auto-launched.

113 stars
0 votes
0 copies
0 views
Added 9/19/2026
content-marketingrustgoreactapi

Works with

api

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add gethouston/houston --skill instantly-campaign --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Instantly Campaign?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Instantly Campaign
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gethouston-instantly-campaign/badge)](https://www.skillsdirectory.com/skills/gethouston-instantly-campaign)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: instantly-campaign
description: "Create a paused cold email campaign in Instantly with all leads loaded and all sending accounts attached. I read your locked sequence, sanitize bodies (Instantly drops bodies that contain a literal ampersand - documented bug), bulk-load up to 1000 leads per call, and configure the schedule with a timezone Instantly accepts (America/Vancouver for Pacific, handles DST automatically). Always paused for your review - never auto-launched."
version: 1
category: Outbound
featured: no
image: rocket
integrations: [instantly]
x_houston:
  created_by: houston
  skill_schema: 1
---


# Instantly Campaign

Create a fully-loaded, **paused** cold email campaign in Instantly. I take a locked sequence file plus a verified-contacts file, build the campaign through the Instantly REST API, work around two known bugs (timezone enum restrictions and the ampersand body-drop bug), bulk-load all the leads in one call, and attach every connected sending account. The campaign always ends in `paused` status. You hit Activate when you're ready.

## When to use

- "Load this sequence into Instantly: <sequence file>".
- "Create the Instantly campaign for this list".
- Phase 5 of either LinkedIn pipeline.
- You have a locked sequence and a verified contact list and want them sending.

## When NOT to use

- The sequence isn't locked yet  -  finish `cold-email-sequence` first.
- The contact list doesn't have verified emails yet  -  run `apollo-enrichment` first.
- You want to **edit** an existing campaign  -  Instantly's dashboard handles that. I create new campaigns; I don't mutate live ones.
- You want a **warm** email send (one-off to a specific person)  -  use Gmail / Outlook directly, not a cold email platform.

## Connections I need

- **Instantly** (sending platform) - Required. I create the campaign, load leads, attach accounts, configure schedule.

If Instantly isn't connected I stop and ask you to connect it.

## Information I need

- **The locked sequence file** - Required. Path to a `.md` file produced by `cold-email-sequence`. If missing I ask: "Where's the locked sequence file? It should be in your `sequences/` folder."
- **The verified-contacts file** - Required. Path to the `contacts.json` produced by `apollo-enrichment`. If missing I ask: "Where's the contacts file? It should be in `runs/{runId}/contacts.json`."
- **A campaign name** - Optional. Defaults to deriving from the sequence file name (e.g. `2026-05-05-jane-doe-revops-sequence.md` becomes `LinkedIn - Jane Doe RevOps`). Override per call.
- **Sending accounts to attach** - Optional. Defaults to "all connected sending accounts in your Instantly workspace". Override per call if you want only specific ones.
- **Schedule** - Optional. Defaults from `config/context-ledger.json` (default `America/Vancouver`, Mon-Fri, 8-5).

## Steps
<!-- houston-workflow:v1 -->

1. **Read inputs.** Parse the sequence file into `{subject, body}` per email. Read the contacts file into a list of `{firstName, fullName, email, company, title, linkedinUrl, personalizationFields}`. Sanity-check that every email is non-empty and every body is non-empty.

2. **Sanitize bodies.** **Strip every `&` character from each email body.** Instantly's body-store quietly drops bodies that contain a literal ampersand  -  the campaign creates fine, but the body uploads as empty and your campaign sends blank emails. Replace `&` with `and`. Document this in the Instantly campaign description so future-you remembers why.

3. **List sending accounts.** Call Instantly's `list_accounts` via Composio. If the user named specific accounts, filter to those. If "all" (the default), keep them all.

4. **Pick a schedule.** Use the schedule from `config/context-ledger.json` defaults. The timezone field is the easy one to get wrong  -  Instantly's timezone enum is restricted and doesn't accept all `IANA` zones. Safe choices:
   - **Pacific**: `America/Vancouver` (handles US Pacific DST automatically and is on Instantly's accepted list).
   - **Eastern**: `America/Toronto`.
   - **Central European**: `Europe/Berlin`.
   - If the context ledger has a timezone Instantly rejects, fall back to `America/Vancouver` and surface the substitution in the run notes.

5. **Create the campaign.** POST to Instantly's `create_campaign` endpoint with:
   - Name = derived (or user-provided).
   - Steps = 3, with day offsets 0 / 3 / 7 matching the sequence file.
   - Bodies = sanitized in step 2.
   - Schedule = picked in step 4.
   - Status = `paused` (always - never `active`, even if the API allows it).

6. **Verify all step bodies are non-empty after create.** Re-fetch the new campaign via `get_campaign` and assert that each step's body is non-empty. If any step is empty, raise loudly  -  the ampersand bug bit you despite the sanitization, or there's a different field that got dropped. Do not proceed to the load step.

7. **Bulk-load leads.** POST to Instantly's `add_leads_to_campaign` with the verified contacts. Instantly accepts up to 1000 leads per call - if you have more, page in chunks of 1000. Per-lead fields:
   - `email` (required).
   - `first_name` (required for the `{{firstName}}` merge field).
   - `last_name`.
   - `company`.
   - `title`.
   - `personalization` (optional, only populated for reaction-source contacts where `personalizationFields` is non-empty).
   - `linkedin_url` (helpful but not required).

8. **Attach sending accounts.** POST to Instantly's `attach_accounts_to_campaign` with the accounts from step 3. Attaching all connected accounts is the default; Instantly rotates sends across them, which improves deliverability vs. a single account.

9. **Confirm paused status.** Re-fetch the campaign one more time. Assert `status: "paused"`. If anything other than paused, log loudly to the run notes and surface to the user  -  Instantly should never auto-activate but if a default config slipped through, the user needs to know immediately.

10. **Append to `campaigns.json`.** One row: `{name, instantlyCampaignId, sequenceFile, leadCount, sendingAccounts, schedule, status: "paused", createdAt}`.

11. **Update `leads.json`.** For every loaded lead, set `loadedToCampaignId: instantlyCampaignId` on the matching `email` row. Read-merge-write atomically.

12. **Append to `outputs.json`.** One row: `{type: "campaign", title: "{Campaign name}", summary: "Campaign created in Instantly with {leadCount} leads, {accountCount} sending accounts. Status: PAUSED.", path: null, status: "paused", domain: "sending"}`. The `path: null` because the campaign lives in Instantly, not on disk.

13. **Final summary to user.**
    - Campaign name + status (paused).
    - Leads loaded.
    - Sending accounts attached.
    - Schedule (e.g. "Mon-Fri, 8-5 Pacific via America/Vancouver - handles DST automatically").
    - Direct link to the campaign in the Instantly dashboard.
    - "Review in Instantly. Activate when you're ready - I won't do it for you."

## Outputs

- New Instantly campaign (paused) with 3 email steps, all leads loaded, all sending accounts attached.
- `campaigns.json`  -  one row.
- `leads.json`  -  `loadedToCampaignId` set on every loaded lead.
- `outputs.json`  -  one row, `type: "campaign"`, `status: "paused"`, `domain: "sending"`.

## Common failure modes

| Failure | Why | Fix |
|---|---|---|
| Empty body on Instantly side after upload | A literal `&` was in the email body | The sanitize step strips them; if it slipped through (e.g. inside a URL), strip again and verify with `get_campaign` |
| Timezone rejected by `create_campaign` | Instantly's timezone enum is restricted | Use `America/Vancouver` (Pacific), `America/Toronto` (Eastern), `Europe/Berlin` (Central European); avoid `Etc/GMT*` |
| 401 on `add_leads_to_campaign` | Instantly token expired in Composio | User reconnects Instantly from the Integrations tab |
| Lead count loaded < expected | Instantly silently rejected duplicates (same email already in another campaign) | This is correct behavior; surface the diff in the run notes so the user sees which leads were skipped and why |
| Campaign created with `status: "active"` | I forgot to set `status: "paused"` on create | Always set explicitly; never trust the API default |

## What I never do

- **Activate the campaign.** Always paused. The user hits Activate in the Instantly dashboard. Even if the orchestrator passes a flag asking for active, I refuse - this is a hard rule, not a default.
- **Skip the sanitize step.** Bodies always pass through ampersand-stripping before upload, even if the body looks clean.
- **Skip the verify step.** I always re-fetch the campaign after create and after load to confirm bodies are non-empty and status is paused.
- **Mutate an existing live campaign.** I create new campaigns. Editing live ones is the user's job in the Instantly dashboard.
- **Hardcode the campaign create / load / verify endpoint names.** All discovered via Composio at runtime.

Attribution

gethoustongethouston
View sourceMore from gethouston →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Postiz

Postiz is a tool to schedule social media and chat posts to 28+ channels X, LinkedIn, LinkedIn Page, Reddit, Instagram, Facebook Page, Threads, YouTube, Google My Business, TikTok, Pinterest, Dribbble, Discord, Slack, Kick, Twitch, Mastodon, Bluesky, Lemmy, Farcaster, Telegram, Nostr, VK, Medium, Dev.to, Hashnode, WordPress, ListMonk

21281 votes

Serp Analysis

SERP analysis techniques for intent classification, feature identification, and competitive intelligence. Use when analyzing search results for content strategy.

2831 votes

On Page Seo Auditor

This skill performs detailed on-page SEO audits to identify issues and optimization opportunities. It analyzes all on-page elements that affect search rankings and provides actionable recommendations.

1821 votes

Brand

Brand voice, visual identity, messaging frameworks, asset management, brand consistency. Activate for branded content, tone of voice, marketing assets, brand compliance, style guides.

1240080 votes

Release Announcement

Write a release announcement — changelog, blog post, in-app note, or social post — that leads with user impact, names the audience, and includes upgrade/migration steps without filler.

798220 votes
View all in content-marketing →