Integrations

Signed webhooks

Send HMAC-signed JSON events from Prosyo to any HTTPS endpoint when prospects are created, stages change or replies arrive. Code samples included.

On this page

Looking for the opposite direction, to start Prosyo outreach when something happens in another app? See Custom triggers.

Prosyo can POST a JSON event to any HTTPS URL when something happens. Use this to connect n8n, Zapier, Make, a data warehouse or your own backend.

Events#

EventFires when
prospect.createdA prospect is added by import, LinkedIn search, the Chrome extension or by hand
prospect.stage_changedA prospect moves stage in the table, board, side panel or Inbox
prospect.enrichedAI research or a first-touch line is saved
conversation.reply_receivedA LinkedIn or email reply stops the sequence
campaign.launchedA campaign starts sending
campaign.pausedA running campaign is paused
account.needs_reconnectA LinkedIn or email account needs reconnecting

Set up#

  1. Create an endpoint that accepts POST with a JSON body. It must be HTTPS and publicly reachable. HTTP, private and internal addresses are blocked.
  2. In Prosyo, go to Integrations → Custom webhook.
  3. Paste the URL into HTTPS endpoint.
  4. Click Connect.
  5. Copy the Signing secret. It's shown once. You can rotate it later.
  6. Choose the Events to send.
  7. Under Field mapping, choose which prospect fields appear in data.
  8. Click Test connection to send a sample.

Payload#

JSON
{
  "id": "evt_01HQEXAMPLE",
  "type": "conversation.reply_received",
  "created_at": "2026-08-17T12:00:00.000Z",
  "workspace_id": "ws_…",
  "data": {
    "prospect_id": "pr_…",
    "campaign_id": "cp_…",
    "event": "conversation.reply_received",
    "email": "alex@acme.com",
    "full_name": "Alex Rivera",
    "title": "Head of Sales",
    "company": "Acme",
    "linkedin_url": "https://www.linkedin.com/in/alexrivera",
    "stage": "replied",
    "personalized_message": "…"
  }
}

The fields inside data follow your field mapping. Integrations → Custom webhook always shows a sample payload that matches the live format.

Headers#

HeaderValue
Content-Typeapplication/json
X-Prosyo-SignatureHex HMAC-SHA256 of the raw body, using your signing secret
X-Prosyo-EventThe event type, for example conversation.reply_received
X-Prosyo-Delivery-IdUnique ID for this delivery. Use it to ignore duplicates.
User-AgentProsyo-Webhooks/1.0

Verify the signature#

Compute HMAC-SHA256 of the raw request body with your signing secret, as lowercase hex, and compare it to X-Prosyo-Signature. Reject the request if they don't match.

Node.js

JavaScript
import crypto from "node:crypto";

function isValidProsyoRequest(rawBody, signatureHeader, secret) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python

Python
import hmac, hashlib

def is_valid_prosyo_request(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

PHP

PHP
$expected = hash_hmac('sha256', file_get_contents('php://input'), $secret);
$valid = hash_equals($expected, $_SERVER['HTTP_X_PROSYO_SIGNATURE'] ?? '');

Always sign the raw body. Parsing the JSON and re-encoding it changes the bytes, and the signature won't match.

Responses and retries#

  • Return any 2xx status within about 10 seconds to mark the delivery successful.
  • Failed deliveries are retried with backoff.
  • Recent deliveries on the integration page shows each delivery and the last error.
  • Use X-Prosyo-Delivery-Id to skip duplicates, because a retry can deliver the same event twice.

Rotate the secret#

Rotate the signing secret from Integrations → Custom webhook. Update the secret in your workflow straight away. Deliveries signed with the new secret fail verification until you do.