Webhooks
Receive real-time notifications when your renders complete instead of polling the status endpoint.
How It Works
- Include a
webhook_urlin your render request - Georender sends a POST request to your URL when the job completes
- Your server receives the video URL and job details
Setting Up Webhooks
POST /v1/render
{
"waypoints": [...],
"webhook_url": "https://your-server.com/webhooks/georender"
} Webhook Payload
When a render completes, you'll receive a POST request with this JSON body:
Success Payload
{
"event": "render.complete",
"job_id": "job_8f3k2m9x",
"status": "complete",
"video_url": "https://cdn.georender.io/renders/job_8f3k2m9x.mp4",
"thumbnail_url": "https://cdn.georender.io/renders/job_8f3k2m9x_thumb.jpg",
"duration_seconds": 12,
"resolution": "1920x1080",
"file_size_bytes": 18432000,
"expires_at": "2026-04-01T12:00:00Z",
"created_at": "2026-03-26T10:00:00Z",
"completed_at": "2026-03-26T10:01:30Z"
} Failure Payload
{
"event": "render.failed",
"job_id": "job_8f3k2m9x",
"status": "failed",
"error": "MARITIME_ROUTE_ERROR",
"message": "Could not calculate sea route between points. Land mass in the way.",
"created_at": "2026-03-26T10:00:00Z",
"failed_at": "2026-03-26T10:00:15Z"
} Batch Webhooks
For batch render jobs, you receive a single webhook when all jobs complete:
{
"event": "batch.complete",
"batch_id": "batch_xyz123",
"jobs": [
{
"job_id": "job_1",
"status": "complete",
"video_url": "https://cdn.georender.io/renders/job_1.mp4"
},
{
"job_id": "job_2",
"status": "complete",
"video_url": "https://cdn.georender.io/renders/job_2.mp4"
},
{
"job_id": "job_3",
"status": "failed",
"error": "ROAD_ROUTE_ERROR",
"message": "No road found between waypoints"
}
],
"completed": 2,
"failed": 1,
"total": 3
} Webhook Security
Verify that webhooks are genuinely from Georender by checking the signature header:
X-Georender-Signature: sha256=abc123... Verifying Signatures (Node.js)
import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expected}`)
);
}
// In your webhook handler
app.post('/webhooks/georender', (req, res) => {
const signature = req.headers['x-georender-signature'];
const isValid = verifyWebhook(
JSON.stringify(req.body),
signature,
process.env.GEORENDER_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook
const { event, job_id, video_url } = req.body;
// ...
}); Retry Policy
If your webhook endpoint returns a non-2xx status code, Georender will retry:
- 1st retry: 30 seconds after initial failure
- 2nd retry: 2 minutes after 1st retry
- 3rd retry: 10 minutes after 2nd retry
- 4th retry: 1 hour after 3rd retry
Important: Your webhook endpoint should respond within 30 seconds.
Process the video asynchronously and return a 200 immediately.
Testing Webhooks
Use tools like webhook.site or ngrok to test webhooks locally.
# Using ngrok
ngrok http 3000
# Then use the ngrok URL as your webhook_url
{
"waypoints": [...],
"webhook_url": "https://abc123.ngrok.io/webhooks/georender"
} Webhook Events
| Event | Description |
|---|---|
render.complete | Single render job completed successfully |
render.failed | Single render job failed |
batch.complete | All jobs in a batch finished (success or failure) |