Skip to main content
Webhooks push events to your server as they happen, so you don’t have to poll. They cover the two moments that are asynchronous by design — publish approval and creator activity — plus everything downstream. Configure your webhook URL in dashboard settings. One URL per account receives all events.

Events

EventFires when
campaign.status_changedA campaign changes status — publish approval/denial, pauses, resumes
creator.appliedA creator applies to a campaign
creator.approvedA creator application is approved (via API or dashboard)
creator.rejectedA creator application is rejected
submission.createdA creator submits content for review, including revisions
submission.approvedA submission is approved (via API or dashboard)
submission.rejectedA submission is rejected
post.createdApproved content goes live
post.metrics_updatedA live post’s engagement metrics are refreshed (at most hourly per post)
Decision events (creator.*, submission.*) fire regardless of where the decision was made — so an integration stays in sync even when your team works in the dashboard.

Payloads

Every event is a JSON POST with the event type, campaign context, the affected resource, and a timestamp:
{
  "event_type": "submission.created",
  "campaign_id": "3f8e4567-e89b-12d3-a456-426614174000",
  "brand_id": "9a2b4567-e89b-12d3-a456-426614174000",
  "submission": {
    "id": "7c1d4567-e89b-12d3-a456-426614174000",
    "creator_id": "cr_8f14e45fceea",
    "creator_username": "somecreator",
    "task_id": "5b0a4567-e89b-12d3-a456-426614174000",
    "status": "in_review",
    "media_type": "video",
    "media_url": "https://cdn.launchpointhq.com/...",
    "revision_count": 0,
    "submitted_at": "2026-07-02T15:04:05Z"
  },
  "timestamp": "2026-07-02T15:04:06Z"
}
campaign.status_changed carries previous_status, status, and status_detail instead of a resource object. creator.* events carry a creator object; post.* events carry a post object — the same shapes the read endpoints return.

Verifying signatures

Each delivery is signed with HMAC-SHA256 using your webhook secret (shown alongside the URL in dashboard settings). The X-Launchpoint-Signature header contains the hex digest of the raw request body:
import { createHmac, timingSafeEqual } from "crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}
Always verify before trusting a payload, and compute the HMAC over the raw bytes — not the re-serialized JSON.

Delivery and retries

  • Respond with any 2xx status within 10 seconds to acknowledge receipt.
  • Failed deliveries are retried with exponential backoff for up to 24 hours.
  • Delivery is at least once: build your handler to be idempotent (the combination of event_type, resource id, and timestamp makes a good deduplication key).
  • Events may occasionally arrive out of order — trust the resource’s status, not the arrival sequence.