Webhooks
Receive real-time HTTP callbacks when job events occur. No more polling for status updates.
Available Events
| Event | Description |
|---|---|
job.created | A new order has been submitted |
job.processing | AI enhancement has started |
job.completed | Enhancement finished, ready for download |
job.failed | Processing encountered an error |
job.delivered | Results 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:
| Header | Description |
|---|---|
X-QuickHome-Signature | HMAC-SHA256 signature: sha256=HMAC(secret, body) |
X-QuickHome-Timestamp | Unix timestamp of the delivery |
X-QuickHome-Event | The event type (e.g. job.completed) |
X-QuickHome-Delivery | Unique 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"Related Documentation
- - Job Status API - Alternative: poll for status
- - Create Order API - Trigger job.created events
- - Download Results - Get results after job.completed