Skip to main content

Overview

Podium processes inbound webhooks from external services and uses a reliable async event system for internal event processing. All webhook endpoints are public (no API key required) but authenticated via service-specific signature verification.

External Webhooks

Stripe

Stripe webhooks handle payment lifecycle events. Each endpoint verifies the Stripe-Signature header against the configured webhook secret before processing.
EndpointEventWhat Happens
/webhooks/stripe/payment-intent/succeededpayment_intent.succeededConfirms order, triggers purchase-processed event, creates CreatorPayout
/webhooks/stripe/payment-intent/processingpayment_intent.processingUpdates order status to PROCESSING
/webhooks/stripe/payment-intent/payment-failedpayment_intent.payment_failedMarks order payment as failed, triggers point revert
/webhooks/stripe/account/updatedaccount.updatedUpdates creator’s Stripe Connect account status
/webhooks/stripe/transfer/createdtransfer.createdRecords payout transfer, updates CreatorPayout to TRANSFERRED

Stripe Signature Verification

import Stripe from "stripe";

const stripe = new Stripe(STRIPE_SECRET_KEY);
const event = stripe.webhooks.constructEvent(
  rawBody,
  request.headers["stripe-signature"],
  STRIPE_WEBHOOK_SECRET
);
Every Stripe webhook validates the signature before processing. If verification fails, the endpoint returns 400.

Example Payload: payment_intent.succeeded

{
  "id": "evt_1234567890",
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_1234567890",
      "amount": 2900,
      "currency": "usd",
      "status": "succeeded",
      "metadata": {
        "orderId": "clord_xyz",
        "userId": "clxyz1234567890",
        "organizationId": "clorg_abc"
      }
    }
  }
}

Shopify

Shopify sends webhooks to a single endpoint that dispatches based on the X-Shopify-Topic header:
TopicHandlerWhat Happens
products/createSync productCreates ShopifyProduct + linked Product
products/updateSync productUpdates product data, variants, media
products/deleteArchive productSoft-deletes the linked product
app/uninstalledCleanupRemoves store connection
Shopify webhook verification uses HMAC-SHA256 with the app’s shared secret against the X-Shopify-Hmac-Sha256 header.

Shopify HMAC Verification

import crypto from 'crypto';

function verifyShopifyWebhook(rawBody: string, hmacHeader: string, secret: string): boolean {
  const hash = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
  return crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(hmacHeader));
}

Privy

Privy sends blockchain transaction confirmations:
Event TypeWhat Happens
transaction.confirmedUpdates transaction status, processes pending operations
transaction.execution_revertedMarks transaction as failed, queues retry if applicable
{
  "chainId": 8453,
  "eventType": "transaction.confirmed",
  "txHash": "0xabc...",
  "txId": "privy_tx_123",
  "walletId": "privy_wallet_456"
}

Task Verification (Oracle)

The verification oracle callback is used by external verification services:
POST /webhooks/task-verify/{taskId}
{
  "approved": true,
  "resolverSignature": "0xabc...",
  "timestamp": 1709827200,
  "resolutionMetadata": {
    "evaluationType": "ai",
    "confidence": 0.95,
    "notes": "Task output meets acceptance criteria"
  }
}
FieldTypeRequiredDescription
approvedbooleanYesWhether the task passed verification
resolverSignaturestringYesOracle’s cryptographic signature
timestampnumberYesUnix timestamp of resolution
resolutionMetadataobjectNoAdditional verification context

Async Event System

Podium’s async event system provides at-least-once delivery with automatic retries and dead-letter queues. All event handlers verify a cryptographic signature before processing.

Event Types (25 Queues)

Commerce Events

EventTriggerSide Effects
purchase-processedOrder payment confirmedAward purchase points, update inventory, notify creator
order-confirmationOrder createdSend confirmation email to buyer
creator-order-confirmationOrder for a creatorNotify creator of new order via email/push
shopify-order-pushShopify-linked orderPush order data to connected Shopify store

Campaign Events

EventTriggerSide Effects
campaign-publishedCampaign goes liveSend notifications to followers
campaign-endedCampaign closesCalculate final analytics, process reward distributions
campaign-reviewedAdmin review completedNotify creator of approval/rejection
campaign-voteNew vote castUpdate attribute tallies, check for campaign completion

Reward & Points Events

EventTriggerSide Effects
nft-receivedReward minted to userSend notification to user
nft-redeemedReward redeemedProcess redemption (create order, grant points, etc.)
nft-reward-publishedNew reward availableNotify eligible users
points-receivedPoints awardedSend notification, update leaderboard
airdropAirdrop triggeredQueue mints for all eligible users

User & Social Events

EventTriggerSide Effects
user-createdNew user registeredSend welcome email, create Stream Chat token
followUser followed a creatorNotify creator, update follower counts

Product Events

EventTriggerSide Effects
product-publishedProduct goes liveIndex in search, notify followers
shopify-products-syncShopify sync triggeredBatch sync products from Shopify store

Platform Events

EventTriggerSide Effects
api-key-changedAPI key created/rotated/revokedFlush caches across all instances
stripe-onboarding-reminderCreator hasn’t completed Stripe setupSend reminder email
presale-purchase-processedToken presale purchaseProcess presale reward, update presale state

Task Pool Events

EventTriggerSide Effects
task-pool-deployedNew TaskPool deployed for tenantRecord contract addresses
task-createdNew task in poolNotify registered solvers
task-verification-requestedTask submitted for verificationRoute to oracle or AI evaluator

Enrichment Events

EventTriggerSide Effects
enrichment-crawlIngestion triggeredFetch and process data from enrichment source
enrichment-extractRaw data ingestedExtract attributes via AI-powered extraction
enrichment-baselineExtraction completeRecompute attribute baselines

Retry & Idempotency

The event system provides automatic retries with exponential backoff:
  • Max retries: 3 (configurable per queue)
  • Backoff: Exponential with jitter
  • Dead letter: Failed events after max retries are logged for manual review
The event system delivers at-least-once. Your handlers should be idempotent — processing the same event twice must produce the same result. Use database unique constraints and conditional updates to guard against duplicate processing.

Idempotency Patterns

// Use unique constraints to prevent duplicate processing
const existing = await db.creatorPayout.findUnique({
  where: { orderId: event.orderId }
});
if (existing) return; // already processed

await db.creatorPayout.create({
  data: { orderId: event.orderId, /* ... */ }
});

Cron Jobs (8 Scheduled Tasks)

JobSchedulePurposeDetails
airdrop-monitorEvery 5 minProcess pending airdrop deliveriesChecks Airdrop records with PENDING status, queues mints
campaign-monitorEvery 15 minEnd campaigns past their deadlineSets ENDED status, triggers campaign-ended event
contract-monitorEvery 10 minSync on-chain contract stateVerifies deployment status of reward contracts
enrichment-baseline-recomputeEvery 6 hoursRecompute stale attribute baselinesRecalculates AttributeBaseline values for enrichment
mint-queueEvery 1 minProcess pending reward mintsBatches PENDING QueuedMints, executes via Privy server wallet
payouts-sweepEvery 30 minTransfer eligible creator payoutsQueries ELIGIBLE CreatorPayouts, executes Stripe transfers
stripe-onboarding-reminderDailyRemind incomplete Stripe setupsEmails creators who started but didn’t finish Connect onboarding
token-presale-monitorEvery 15 minMonitor presale status changesChecks presale deadlines and token distribution status
All cron jobs are triggered by scheduled messages to their respective webhook endpoints.

Webhook Security Summary

SourceVerification MethodHeader
StripeHMAC-SHA256 with webhook secretStripe-Signature
ShopifyHMAC-SHA256 with app secretX-Shopify-Hmac-Sha256
Event SystemSigning keysSignature header
PrivyPrivy webhook secretStandard signature header
Task OracleCustom signatureresolverSignature in body

Endpoint Summary

MethodPathDescription
POST/webhooks/stripe/payment-intent/succeededPayment confirmed
POST/webhooks/stripe/payment-intent/processingPayment processing
POST/webhooks/stripe/payment-intent/payment-failedPayment failed
POST/webhooks/stripe/account/updatedConnect account update
POST/webhooks/stripe/transfer/createdPayout transferred
POST/webhooks/shopifyShopify product/order events
POST/webhooks/privyBlockchain transaction events
POST/webhooks/task-verify/{taskId}Oracle verification callback
POST/webhooks/events/{event}Async event handler (25 queues)
POST/webhooks/cron/{job}Cron handler (8 jobs)