Skip to content
FoodPhoto.ai
← Back to Developer Hub

Webhooks

Subscribe to real-time events for photo enhancements, credit purchases, and more. Build async workflows with secure, reliable webhook delivery.

How webhooks work

Receive HTTP POST requests to your server when events occur

1

Configure endpoint

Add your webhook URL in the dashboard and select which events to receive

2

Receive events

We send HTTP POST requests to your endpoint when subscribed events occur

3

Process & respond

Handle the event in your app and return a 200 status code

Event types

Subscribe to specific events or receive all events

photo.enhancement.startedCommon

Fired when a photo enhancement job begins processing

photo.enhancement.completedCommon

Fired when a photo is successfully enhanced and all formats are ready

photo.enhancement.failedRare

Fired when a photo enhancement fails (invalid image, processing error, etc.)

photo.deletedUncommon

Fired when a photo is deleted from your account

credit.purchasedUncommon

Fired when credits are added to your account

credit.depletedRare

Fired when your credit balance reaches zero

Example webhook payload

What your endpoint will receive for a photo.enhancement.completed event

POST /your-webhook-endpoint
{
  "id": "evt_abc123xyz",
  "type": "photo.enhancement.completed",
  "createdAt": "2025-12-21T20:00:00Z",
  "data": {
    "photo": {
      "id": "photo_abc123",
      "status": "completed",
      "creditsUsed": 1,
      "original": {
        "url": "https://cdn.foodphoto.ai/originals/abc123.jpg",
        "width": 2000,
        "height": 1500
      },
      "enhanced": {
        "square": "https://cdn.foodphoto.ai/enhanced/abc123_sq.jpg",
        "portrait": "https://cdn.foodphoto.ai/enhanced/abc123_pt.jpg",
        "landscape": "https://cdn.foodphoto.ai/enhanced/abc123_ls.jpg"
      },
      "metadata": {
        "preset": "delivery-optimized",
        "processedAt": "2025-12-21T20:00:00Z",
        "processingTime": 2.4
      }
    }
  }
}

Webhook security

Verify webhook authenticity with HMAC signatures

Every webhook includes an X-FoodPhoto-Signature header containing an HMAC SHA-256 signature. Use your webhook signing secret to verify the request came from FoodPhoto.ai.

Verification Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hmac = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(hmac)
  );
}

// In your webhook handler
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-foodphoto-signature'];
  const isValid = verifyWebhook(req.body, signature, WEBHOOK_SECRET);

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process the webhook...
  res.status(200).send('OK');
});

Automatic retries

We automatically retry failed webhook deliveries with exponential backoff

AttemptDelayTotal elapsed
Attempt 1Immediately0s
Attempt 25 seconds5s
Attempt 330 seconds35s
Attempt 42 minutes~2m 35s
Attempt 510 minutes~12m 35s
Attempt 630 minutes~42m 35s
Attempt 71 hour~1h 42m 35s

Successful delivery requirements

Your endpoint must return a 2xx status code within 5 seconds to be considered successful. Non-2xx responses or timeouts will trigger automatic retries.

Best practices

Tips for building reliable webhook handlers

Respond quickly

Return a 200 status immediately and process the webhook asynchronously with a queue

Handle duplicates

Use the event ID to ensure idempotency in case we retry a successful delivery

Verify signatures

Always validate the HMAC signature to ensure the webhook came from FoodPhoto.ai

Use HTTPS

Webhook endpoints must use HTTPS in production for security

Monitor failures

Check your dashboard webhook logs regularly to catch and fix delivery failures

Test webhooks locally

Use tools like ngrok or localtunnel to expose your local server and test webhook delivery before deploying to production.

# Expose localhost:3000 with ngrok
ngrok http 3000

# Then use the HTTPS URL in your webhook settings
https://abc123.ngrok.io/webhook

Ready to set up webhooks?

Configure your webhook endpoint in the dashboard

Webhooks | FoodPhoto.ai Real-Time Event Notifications