Campaigns API

    Create campaigns, start a send, pause and resume it, and download the open, click, bounce and unsubscribe logs for your own reporting.

    On this page

    This page covers the endpoints that create campaigns, control a send in progress, and get the results back out. When you finish you will be able to build a campaign from code, start it deliberately, and pull the engagement logs into your own reporting.

    Before you start

    You need an API token and the base URL from API authentication. Every request below also takes api_token as a query parameter. A campaign needs a list to send to and a sender address on an authenticated domain, both of which have to exist before the campaign will send anything.

    The endpoints#

    PurposeMethodPath
    List campaignsGET/campaigns
    Create a campaignPOST/campaigns/create
    Read one campaignGET/campaigns/{uid}
    Start sendingPOST/campaigns/{uid}/run
    Pause a sendPOST/campaigns/{uid}/pause
    Resume a paused sendPOST/campaigns/{uid}/resume
    Download the open logGET/campaigns/{uid}/open-log/download
    Download the click logGET/campaigns/{uid}/click-log/download
    Download the bounce logGET/campaigns/{uid}/bounce-log/download
    Download the unsubscribe logGET/campaigns/{uid}/unsubscribe-log/download

    The {uid} in these paths is the campaign's own identifier, which comes back when you create a campaign and appears on every campaign in the GET /campaigns response. Store it. Almost everything else on this page needs it.

    Creating a campaign#

    POST /campaigns/create
    

    A campaign creation request carries the same things you would fill in by hand: an internal name, the list or segment to send to, a sender name and address, a subject line, and the HTML content of the email. The exact field names are visible in the response from GET /campaigns/{uid} on a campaign you have already built in the interface, which is the reliable way to learn the shape.

    A useful approach for a first integration: build one campaign in the interface, read it back with GET /campaigns/{uid}, and model your create payload on what you see. That beats guessing, and it shows you which values the application filled in for you.

    Creating a campaign does not send it. It returns a campaign that exists and is waiting.

    Creating and sending are separate calls, on purpose#

    POST /campaigns/{uid}/run
    

    Nothing goes out until you call run. This is a safety property, not an inconvenience.

    Campaign creation is the step most likely to be wrong: a template variable that did not resolve, a segment that matched everyone instead of the 200 people you meant, a subject line still containing TEST. If create and send were one call, every one of those mistakes would be in somebody's inbox before you noticed. With two calls you can create the campaign, read it back, check the recipient count, look at the rendered content, and only then run it.

    For anything that goes to a real list, put a human between the two calls. Have your job create the campaign and stop, notify whoever owns the send, and let them press the button. Automating run is reasonable only when the content is fully generated and the audience is bounded, and even then, log the recipient count before the call so you can see what happened afterward.

    A send in progress is hard to take back

    Once run starts, messages begin leaving. You can pause, but every message already accepted for delivery is gone. There is no recall. Treat run as the irreversible step it is.

    Pausing and resuming#

    POST /campaigns/{uid}/pause
    POST /campaigns/{uid}/resume
    

    Pause stops the campaign sending further messages. Use it the moment you notice a problem with a live send: a broken link, the wrong offer, a personalization tag rendering as an empty gap. A campaign paused at 5% delivered is a small apology. The same campaign at 100% is a different conversation.

    Pause does not undo what has already been delivered, and it does not reverse the sending allowance those messages consumed.

    Resume continues from where the campaign stopped. Contacts who already received the message do not receive it again. If you fixed the content while the campaign was paused, be aware that the people reached before the pause got the old version, so the audience is now split across two variants. Sometimes the honest move is to leave the campaign paused and send a correction to the remainder as a new campaign.

    Pulling the reporting logs#

    GET /campaigns/{uid}/open-log/download
    GET /campaigns/{uid}/click-log/download
    GET /campaigns/{uid}/bounce-log/download
    GET /campaigns/{uid}/unsubscribe-log/download
    

    These four endpoints return the per-contact detail behind the summary numbers, as a downloadable file rather than a JSON body. Point them at a file rather than your terminal:

    curl "https://mail.igsendmail.com/api/v1/campaigns/CAMPAIGN_UID/click-log/download?api_token=YOUR_API_TOKEN" \
      -o click-log.csv
    

    What each one is good for:

    • Open log. Which contacts opened. Treat opens as a soft signal. Image blocking and privacy proxies both distort the number, in opposite directions, so opens are useful for comparing two of your own campaigns and poor for anything absolute.
    • Click log. Which contacts clicked, and what they clicked. This is the honest engagement metric. It is also the one worth pushing into your CRM, because a click on a pricing link is a sales signal.
    • Bounce log. Which addresses failed and why. Hard bounces are suppressed automatically, so the log is a diagnostic record rather than a to-do list. Read it when a bounce rate is unusually high: a cluster at one domain points at an authentication problem on your side rather than bad addresses. See Deliverability overview.
    • Unsubscribe log. Who left. Worth reconciling against your own database so a person who unsubscribed here does not get re-added by tomorrow's sync.

    Pull the logs after the send has finished. A log downloaded mid-send is a snapshot of an incomplete campaign, and if you store it as final your numbers will be permanently low.

    Triggering an automation for one contact#

    Two related endpoints sit alongside campaigns:

    PurposeMethodPath
    List automationsGET/automations
    Run an automation for a contactPOST/automations/{uid}/execute

    Use execute when the thing that should start a sequence happened in your system rather than in IGSendMail: an order shipped, a trial reached day 10, a document was signed. Your code calls the endpoint for that one contact and the sequence begins for them.

    This is a per-contact call, not a campaign. If you find yourself looping it over thousands of contacts, a campaign is almost certainly the right tool instead. See Automation overview for how sequences are built.

    If something goes wrong#

    The campaign was created but nothing sent. You did not call run, or the campaign is missing something it needs. Read it back with GET /campaigns/{uid} and look for empty fields.

    The recipient count is not what you expected. Unsubscribed, hard-bounced and blacklisted addresses are excluded, so a list of 5,000 never sends to 5,000. If the number is far off, check whether you targeted a segment rather than the whole list.

    A log download returns something that is not a file. Check the status code with -i. An authentication failure returns a response body that will happily save as a CSV and confuse you later.

    The send stops partway through. Check your remaining monthly allowance. Plan allowances reset each billing cycle and do not carry over, while add-on sending credit packs do carry over.

    Last updated September 10, 2026

    Was this page helpful?