Reference

Build on the Lucra API.

Drag a sticker to move it, or use the arrow keys while focused.

Webhooks

Events Lucra sends you, and verifying them.

Lucra POSTs an event to your server when something changes, so you don't have to poll.

Set up

Add a webhook URL when you create a key. Lucra shows a signing secret (whsec_…) once.

Events

Events name what changed and the IDs involved; fetch the details from the API. Ignore types you don't handle.

EventWhendata
application.createdA creator applies to a programprogram, application
application.approvedAn application is approvedprogram, application
application.rejectedAn application is rejectedprogram, application
application.withdrawnA creator withdraws an applicationprogram, application
submission.createdA creator submits workprogram, submission
submission.approvedA submission is approvedprogram, submission
submission.revision_requestedA reviewer asks for changesprogram, submission
submission.rejectedA submission is rejectedprogram, submission
submission.liveA submission goes liveprogram, submission
file.readyAn uploaded file finishes processingfile
file.failedAn uploaded file can't be usedfile
campaign.publishedA campaign goes live on its platformcampaign
campaign.partially_failedA launch succeeds on some platforms and fails on otherscampaign
campaign.failedA launch failscampaign
campaign.pausedA campaign is pausedcampaign
campaign.archivedA campaign is archivedcampaign
campaign.needs_attentionA campaign needs action on its ad platformcampaign
payment.succeededA payment to a creator succeedspayment, creator
payment.failedA payment to a creator failspayment
payment.disputedA payment is disputed during its holdpayment, creator
payment.refundedA payment is refunded in fullpayment
payout.paidEarnings reach a creator's (or this account's) balancepayout
payout.failedSending earnings to a balance failspayout
withdrawal.paidA withdrawal the account asked for reached the bankwithdrawal
withdrawal.failedA withdrawal the account asked for failedwithdrawal
retainer.acceptedA creator accepts a retainerretainer
retainer.rejectedA creator turns a retainer downretainer
retainer.canceledA retainer is canceledretainer
retainer.endedA retainer endsretainer
sample.createdA creator requests a samplesample
sample.approvedA sample request is approvedsample
sample.rejectedA sample request is rejectedsample
message.createdA message arrives in one of the account's threadsmessage, thread
brand.createdA partner provisions a brandbrand
creator.createdA partner adds a creator to its rostercreator
JSON
{
  "id": "evt_u5s9xZIdD99WBwmDjJPYc3e",
  "type": "submission.approved",
  "account": "acct_04Jm0JWUg20EhYo2lyNIEHo",
  "data": { "submission": "sub_14XA4WGiSOmaVI3B4QLm4Fs" }
}

Verify the signature

Lucra-Signature: t=<seconds>,v1=<hex> is an HMAC-SHA256 of <t>.<raw body> with your secret.

TypeScript
import { createHmac, timingSafeEqual } from "node:crypto"

export function verifyLucraWebhook(
  body: string,
  header: string,
  secret: string
) {
  const { t, v1 } = Object.fromEntries(
    header.split(",").map((part) => part.split("="))
  )
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false
  const expected = createHmac("sha256", secret)
    .update(`${t}.${body}`)
    .digest("hex")
  return (
    v1?.length === expected.length &&
    timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
  )
}

Retries

Answer 2xx within 10 seconds. Failed deliveries retry for 3 days. Events can repeat or arrive out of order, so deduplicate on id.