PowerPost APIv1
PowerPost APIv1
PowerPost APIQuickstartAuthenticationWorkspacesInput Types

API Reference

Upload MediaGenerate ContentGenerationsGenerate ImagesPosts & PublishingGet Credits

Guides

WebhooksError CodesChangelog

Webhooks

Receive real-time notifications when generations complete.

Get notified instantly when generations complete instead of polling.

Webhook configuration is per-workspace — each workspace can have its own webhook URL, secret, and subscribed events. See Workspaces for more on workspace scoping.

Setup

  1. Go to Settings → API in your dashboard
  2. Make sure you've selected the correct workspace
  3. Enter your webhook URL
  4. Select events to receive
  5. Save your configuration

Your webhook URL must:

  • Use HTTPS
  • Respond within 10 seconds
  • Return a 2xx status code

Events

EventDescription
generation.completedCaption generation completed
generation.failedCaption generation failed
image_generation.completedImage generation completed
image_generation.failedImage generation failed
post.publishedPost published successfully
post.failedPost publishing failed

Payload Examples

generation.completed

{
  "event": "generation.completed",
  "timestamp": "2026-01-10T18:35:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "generation_id": "660f9500-f30c-52e5-b827-557766551111",
    "status": "completed",
    "outputs": {
      "tiktok": "🌙 Dark mode activated! POV: your eyes at 2am... #darkmode #tech",
      "instagram": "✨ Dark mode is here!\n\nYour late-night scrolling just got easier... #DarkMode #AppUpdate"
    }
  }
}

YouTube outputs have a title and description object. All other platforms are plain strings with hashtags included.

generation.failed

{
  "event": "generation.failed",
  "timestamp": "2026-01-10T18:35:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "generation_id": "660f9500-f30c-52e5-b827-557766551111",
    "status": "failed",
    "error_code": "GENERATION_FAILED",
    "error_message": "Failed to generate content"
  }
}

image_generation.completed

{
  "event": "image_generation.completed",
  "timestamp": "2026-01-10T18:36:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "image_generation_id": "7a8b9c0d-e1f2-3456-abcd-ef7890123456",
    "status": "completed",
    "images": [
      {
        "media_id": "img-001-abcd-efgh"
      }
    ]
  }
}

image_generation.failed

{
  "event": "image_generation.failed",
  "timestamp": "2026-01-10T18:36:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "image_generation_id": "7a8b9c0d-e1f2-3456-abcd-ef7890123456",
    "status": "failed",
    "error_code": "IMAGE_GENERATION_FAILED",
    "error_message": "Failed to generate images"
  }
}

post.published

Sent when at least one item is published successfully. Individual items may have different statuses — check each item's status field.

{
  "event": "post.published",
  "timestamp": "2026-01-10T18:40:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "post_id": "post-660f9500-f30c-52e5-b827-557766551111",
    "status": "published",
    "items": [
      {
        "item_id": "item-001",
        "post_type": "instagram-reel",
        "platform": "instagram",
        "status": "posted",
        "platform_post_id": "17898455678012345"
      },
      {
        "item_id": "item-002",
        "post_type": "tiktok-video",
        "platform": "tiktok",
        "status": "failed",
        "error": "Access token expired. Please reconnect your TikTok account."
      }
    ]
  }
}

A post.published event may contain a mix of successful and failed items (partial success). Always check each item's status field individually.

post.failed

{
  "event": "post.failed",
  "timestamp": "2026-01-10T18:40:00Z",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "post_id": "post-660f9500-f30c-52e5-b827-557766551111",
    "status": "failed",
    "items": [
      {
        "item_id": "item-001",
        "post_type": "instagram-reel",
        "platform": "instagram",
        "status": "failed",
        "error": "Access token expired. Please reconnect your Instagram account."
      }
    ]
  }
}

Signature Verification

All webhooks are signed with HMAC-SHA256 for security.

Signature Header

X-PowerPost-Signature: t=1736534100,v1=abc123def456...
  • t — Unix timestamp when the webhook was sent
  • v1 — HMAC-SHA256 signature

Verification (Node.js)

import crypto from 'crypto'

function verifyWebhook(rawBody, signature, secret) {
  const [tPart, vPart] = signature.split(',')
  const timestamp = tPart.split('=')[1]
  const providedSig = vPart.split('=')[1]

  // Verify timestamp is recent (within 5 min)
  const now = Math.floor(Date.now() / 1000)
  if (Math.abs(now - parseInt(timestamp)) > 300) {
    return false // Replay attack
  }

  // Compute expected signature
  const signedPayload = `${timestamp}.${rawBody}`
  const expectedSig = crypto.createHmac('sha256', secret).update(signedPayload).digest('hex')

  // Timing-safe comparison
  return crypto.timingSafeEqual(Buffer.from(providedSig), Buffer.from(expectedSig))
}

Verification (Python)

import hmac
import hashlib
import time

def verify_webhook(raw_body: str, signature: str, secret: str) -> bool:
    parts = dict(p.split('=') for p in signature.split(','))
    timestamp = parts['t']
    provided_sig = parts['v1']

    # Check timestamp
    if abs(time.time() - int(timestamp)) > 300:
        return False

    # Compute signature
    signed_payload = f"{timestamp}.{raw_body}"
    expected_sig = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(provided_sig, expected_sig)

Webhook Secret

Your webhook secret is shown when you configure webhooks. Store it securely — it's used to verify that webhooks are genuinely from PowerPost.

Delivery Policy

Webhook delivery is best-effort with a single attempt. If your endpoint returns a non-2xx status code, times out (10 seconds), or is unreachable, the delivery is marked as failed.

You can view failed deliveries in your dashboard. Use the relevant GET endpoints to poll for status as a fallback if your webhook endpoint experiences downtime.

Debugging

Check the Webhook Deliveries section in your dashboard to see recent delivery attempts, status codes, and response bodies.

Get Credits

Check your current credit balance.

Error Codes

API error codes and how to handle them.

On this page

SetupEventsPayload Examplesgeneration.completedgeneration.failedimage_generation.completedimage_generation.failedpost.publishedpost.failedSignature VerificationSignature HeaderVerification (Node.js)Verification (Python)Webhook SecretDelivery PolicyDebugging