Argorant Help
EN|DEargorant.comOpen Argorant
Help/Account & security

Webhooks

Published by Argorant

Get a signed HTTPS call on your own server when a reply comes in, an export or list is ready, or a campaign pauses. Events, payloads, signature check, retries and limits.

A webhook is a message Argorant sends to an address on your own server when something happens in your account. Instead of asking the API again and again whether an export is done or a reply came in, your server is told. Use it to update your CRM, post to a team chat or start an automation in n8n, Zapier or Make. Webhooks come with the Pro plan and up.

Add a webhook

  1. Open Settings, then API keys and scroll to Webhooks.
  2. Under New webhook, enter your address in the URL field. It must start with https:// and be reachable from the internet.
  3. Click the events you want. A picked event shows a tick. You need at least one.
  4. Click Add webhook.
  5. A box Webhook created shows the signing secret, which starts with whsec_. Click Copy and store it with your server's other secrets. It is shown only once.
  6. Click Send test on the new row, then Deliveries to see whether it arrived.
The New webhook form with the address https://hooks.example.com/argorant, the events export.ready and reply.positive picked, and the Add webhook button
Enter the address (1), pick events (2), then click Add webhook (3).
A created webhook with its masked signing secret and Copy button, the webhook row with Pause, Send test, Hide deliveries and Delete, and three delivered events below
Copy the secret now (1). Send test (2) sends a signed sample, and Deliveries (3) shows what arrived.

If your plan does not include webhooks, clicking Add webhook opens the upgrade screen instead.

Events

EventWhen it is sentMain fields in data
reply.receivedA person replied to one of your campaigns. Out-of-office and other automatic replies are left out.classification, lead_email, campaign_id, subject, snippet
reply.positiveA reply was labelled interested, positive or as a meeting request.Same as reply.received
email.bouncedA campaign email bounced.lead_email, campaign_id, subject
email.unsubscribedSomeone asked not to be emailed, by reply or with the opt-out link.classification, lead_email, campaign_id
campaign.pausedA campaign stopped sending on its own, for example because the month's campaign emails are used up.campaign_id, campaign_name, reason
campaign.resumedSending started again, for example when the month resets or the plan grows.campaign_id, campaign_name, reason
export.readyAn export file is ready to download.job_id, total_rows, verified_rows, download_api_path
list.readyA saved list finished filling.list_id, list_name, total_items
verification.completedA check of one of your own addresses finished.email, status, deliverable
segment.new_matchesA saved filtered list has more matching people than when it was last counted. It is checked about every 30 minutes.list_id, previous_total, current_total, new_matches

Campaign events go to the webhooks of everyone in the workspace that owns the campaign.

What a delivery looks like

Each delivery is a POST with a JSON body and these headers:

Content-Type: application/json
User-Agent: Argorant-Webhooks/1.0
X-Argorant-Event: reply.positive
X-Argorant-Delivery: 903
X-Argorant-Signature: sha256=5d1c0e…

The body always has the same four fields. data changes with the event:

{
  "event": "reply.positive",
  "delivery_id": "903",
  "created_at": "2026-10-21T09:42:09.512340+00:00",
  "data": {
    "classification": "interested",
    "lead_email": "anna@northwind-supply.example",
    "campaign_id": "3f6c1a2e-8b1d-4c55-9a0e-2d7f4b1c9e10",
    "subject": "Re: Quick question, Anna",
    "snippet": "Sounds good. Can we talk on Thursday?"
  }
}
{
  "event": "export.ready",
  "delivery_id": "904",
  "created_at": "2026-10-21T09:35:01.104220+00:00",
  "data": {
    "job_id": 84213,
    "status": "done",
    "total_rows": 500,
    "verified_rows": 482,
    "status_api_path": "/api/mcp/exports/84213",
    "download_api_path": "/api/mcp/exports/84213/download"
  }
}

A Send test delivery uses the first event of the webhook and carries {"test": true, "event": "…", "message": "Argorant webhook test delivery"} as data, so your code can tell it apart from a real one.

Check that a delivery came from Argorant

X-Argorant-Signature is sha256= followed by the hex HMAC-SHA256 of the raw request body, made with your signing secret. Compute the same on your side and compare. Use the body exactly as it arrived, before any JSON parsing, or the signature will not match.

// Node.js (Express)
const crypto = require("crypto");
app.post("/argorant", express.raw({ type: "application/json" }), (req, res) => {
  const expected = "sha256=" + crypto.createHmac("sha256", process.env.ARGORANT_WEBHOOK_SECRET)
    .update(req.body).digest("hex");
  const got = req.get("X-Argorant-Signature") || "";
  if (got.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) return res.sendStatus(401);
  const event = JSON.parse(req.body);
  res.sendStatus(200);          // answer fast, do the work afterwards
});
# Python (Flask)
import hmac, hashlib, os
@app.post("/argorant")
def argorant():
    raw = request.get_data()
    expected = "sha256=" + hmac.new(os.environ["ARGORANT_WEBHOOK_SECRET"].encode(), raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, request.headers.get("X-Argorant-Signature", "")):
        return "", 401
    return "", 200

Answers, retries and switching off

  • Any 2xx answer counts as delivered. Answer within 10 seconds and do slow work after you answered.
  • Anything else, a timeout, or a redirect counts as failed. Redirects are never followed, so use the final address.
  • A failed delivery is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours. After 6 tries it stays failed.
  • After 50 failures in a row the webhook is switched off and shows as Paused. Fix your server, then click Resume; that also resets the failure count.
  • The same event can reach you twice, for example after a retry. Use delivery_id (also in X-Argorant-Delivery) to skip ones you already handled.

The row of each webhook shows its events, the time of the Last success and recent failures with the last error. Deliveries lists the latest 25 deliveries with their event, time and result, such as Delivered, Delivered, 2 attempts, pending or failed.

Manage a webhook

  • Pause stops deliveries without deleting anything. Resume starts them again. Send test only works while the webhook is active.
  • Delete removes the webhook and its delivery history after one confirmation.
  • Under Settings, then Workspace, the danger zone has Delete all webhooks.

From the API and the CLI

The same webhooks can be managed with an API key. Through the API the key needs permission to manage lists, which keys from Settings have.

curl -s https://app.argorant.com/api/v1/webhooks \
  -H "Authorization: Bearer $ARGORANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://hooks.example.com/argorant", "events": ["reply.positive", "export.ready"]}'

npx argorant webhooks add https://hooks.example.com/argorant --events reply.positive,export.ready
npx argorant webhooks                 # your webhooks and every event you can pick
npx argorant webhooks test 41
npx argorant webhooks deliveries 41
npx argorant webhooks set 41 --inactive
npx argorant webhooks rm 41 --yes

The create call answers with the secret once, exactly like the Settings page.

Limits

  • Up to 10 webhooks per account, paused ones included.
  • The address must start with https://, be at most 2,048 characters, and point to a public internet address. Private networks, local addresses and Argorant's own services are refused.
  • Webhooks are included from the Pro plan.

Common mistakes

  • The address is refused when you add it. You will see one of these messages.

    The webhook address must be a public internet address on your own server. Private networks, local addresses and our own services can't receive webhooks.

    We could not find a public internet address for this webhook. Check the address and try again.

    Use a public HTTPS address. For testing on your laptop, use a tunnel service that gives you a public HTTPS address.
  • The signature never matches. Your framework parsed the JSON before you computed the HMAC. Hash the raw bytes.
  • Deliveries fail with a redirect. The address answers with 301 or 302, for example from http to https or with a missing slash. Enter the final address.
  • The secret is lost. It cannot be shown again. Delete the webhook and add it again to get a new secret.
  • No events arrive. Check that the webhook is Active, that you picked the right events, and that something actually happened. Send test shows whether the path to your server works.

What happens next

Once deliveries show as Delivered, connect the events to your workflow. A common pattern is export.ready starting a download and an import into your CRM. Related reads are API keys and the REST API and n8n.

Related
API keys and the REST APISettings: every section explainedScheduled refreshes and event-triggered runsn8n: the Argorant node

Still stuck? support@argorant.com

Help homeargorant.comPricingRoadmap
support@argorant.com