Webhooks

Receive real-time HTTP callbacks when job events occur. No more polling for status updates.

Available Events

EventDescription
job.createdA new order has been submitted
job.processingAI enhancement has started
job.completedEnhancement finished, ready for download
job.failedProcessing encountered an error
job.deliveredResults have been downloaded

Register a Webhook

curl -X POST https://www.quickhome.ai/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/quickhome",
    "events": ["job.completed", "job.failed"]
  }'

Response

{
  "id": "webhook_uuid",
  "url": "https://your-app.com/webhooks/quickhome",
  "events": ["job.completed", "job.failed"],
  "active": true,
  "secret": "whsec_...",  // Only returned on creation
  "createdAt": "2026-04-09T..."
}

Important: The signing secret is only returned when the webhook is created. Store it securely - you will need it to verify webhook signatures.

Webhook Payload

Each webhook delivery is a POST request to your URL with the following JSON body:

{
  "event": "job.completed",
  "timestamp": "2026-04-09T12:00:00.000Z",
  "data": {
    "jobId": "uuid",
    "status": "qc_review",
    "profileId": "uuid",
    "address": "123 Main St, City, ST 12345",
    "creditCost": 5,
    "photoCount": { "interior": 3, "exterior": 2 },
    "timestamp": "2026-04-09T12:00:00.000Z"
  }
}

Verify Webhook Signatures

Every webhook request includes signature headers for verification:

HeaderDescription
X-QuickHome-SignatureHMAC-SHA256 signature: sha256=HMAC(secret, body)
X-QuickHome-TimestampUnix timestamp of the delivery
X-QuickHome-EventThe event type (e.g. job.completed)
X-QuickHome-DeliveryUnique delivery ID for deduplication
import crypto from 'crypto';

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  const received = signature.replace('sha256=', '');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(received)
  );
}

// In your webhook handler:
app.post('/webhooks/quickhome', (req, res) => {
  const signature = req.headers['x-quickhome-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.QUICKHOME_WEBHOOK_SECRET
  );

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

  const { event, data } = req.body;
  console.log(`Received ${event} for job ${data.jobId}`);

  res.status(200).send('OK');
});

Retry Policy

Failed deliveries are retried with exponential backoff:

  • Attempt 1: Immediate
  • Attempt 2: After 30 seconds
  • Attempt 3: After 2 minutes
  • Attempt 4: After 10 minutes
  • Attempt 5: After 1 hour

After 5 failed attempts, the delivery is marked as failed. Your endpoint should return a 2xx status code within 10 seconds to be considered successful.

Manage Webhooks

List Webhooks

curl https://www.quickhome.ai/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY"

Delete a Webhook

curl -X DELETE "https://www.quickhome.ai/api/v1/webhooks?id=WEBHOOK_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
Webhooks - API Reference | Quickhome AI