Find Prospects Now Docs

Webhook payload reference

The JSON payload Find Prospects Now sends to custom webhooks after a scan, its headers, and how to verify the HMAC-SHA256 signature.

Custom (non-Slack, non-Discord) webhooks receive one POST request with a JSON body per scan that finds new matches.

Example

{
  "schema_version": 1,
  "event_id": "6f1c2a8e-1b0d-4b7a-9d3e-2f4c5a6b7c8d",
  "event": "scan_completed",
  "timestamp": "2026-10-17T14:05:12.000Z",
  "scan_id": "a3b4c5d6-…",
  "summary": {
    "total_matches": 2,
    "total_processed": 180,
    "groups_scanned": 9,
    "scan_type": "scheduled",
    "truncated_leads": 0
  },
  "leads": [
    {
      "post_id": "1234567890",
      "group_name": "Austin Homeowners",
      "author": "Jane Doe",
      "text": "Can anyone recommend a plumber? Our water heater is leaking.",
      "url": "https://www.facebook.com/groups/…/posts/…",
      "created_at": "2026-10-17T13:52:00.000Z",
      "matched_keywords": ["recommend a plumber", "leaking"],
      "match_type": "keyword",
      "ai_classified": true,
      "ai_match": true,
      "ai_label": "Plumbing request"
    }
  ]
}

Fields

FieldDescription
eventscan_completed for real scans. Test sends the same shape with scan_type: "test" and a sample lead.
event_idUnique ID of this event. Use it to ignore duplicates.
timestampWhen the scan finished (ISO 8601).
summary.total_matchesNumber of matching posts in the scan.
summary.total_processedPosts checked.
summary.groups_scannedGroups scanned.
summary.scan_typeHow the scan started, for example manual, scheduled or test.
summary.truncated_leadsLeads not included because a payload holds at most 100 leads.
leads[].post_idFacebook post ID.
leads[].group_nameGroup name.
leads[].authorAuthor's display name.
leads[].textPost text.
leads[].urlLink to the post on Facebook.
leads[].created_atWhen the post was published, or null if unknown.
leads[].matched_keywordsKeywords that matched (may be empty).
leads[].match_typekeyword or ai.
leads[].ai_classifiedWhether AI checked the post.
leads[].ai_matchWhether an AI criterion matched.
leads[].ai_labelLabel of the matching AI criterion, or null.

Headers

HeaderValue
Content-Typeapplication/json
User-AgentFindProspectsNow/1.0
X-Webhook-EventThe event name, e.g. scan_completed
X-Webhook-IdThe event ID
X-FPN-Delivery-IdUnique ID of this delivery attempt series
X-Webhook-Signaturesha256=<hex> — only when a signing secret is set

Verify the signature

When you set a signing secret, compute the HMAC-SHA256 of the raw request body with your secret and compare it with the header.

Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';

function isValid(rawBody, header, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
  return header && expected.length === header.length &&
    timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}

Responding

Return any 2xx status within a few seconds. Timeouts, 408, 425, 429 and 5xx responses are retried a few times with increasing delays; other 4xx responses are not retried. Process leads asynchronously if your work is slow, and deduplicate with event_id.

Last updated on