Webhooks

Learn how to receive real-time notifications when your jobs complete.

What are webhooks?

Webhooks allow offload.run to notify your application when a job completes. Instead of polling for job status, you provide a URL endpoint and we'll send an HTTP POST request with the job results when processing finishes.

This is ideal for long-running tasks where you don't want to keep a connection open or repeatedly check job status.

Setting up webhooks

To receive webhook notifications, provide a webhookUrl when enqueueing a job:

import { Offload } from '@offload/sdk'

const offload = new Offload(process.env.OFFLOAD_API_KEY)

await offload.enqueue('compress-video', {
  videoUrl: 'https://example.com/video.mp4',
  webhookUrl: 'https://yourapp.com/api/webhooks/offload'
})

Webhook payload

When a job completes, we'll send a POST request to your webhook URL with the following JSON payload:

{
  "jobId": "job_abc123",
  "type": "compress-video",
  "status": "completed",
  "result": {
    "url": "https://storage.offload.run/compressed-video.mp4",
    "size": 1024000,
    "duration": 120
  },
  "createdAt": "2024-01-15T10:30:00Z",
  "completedAt": "2024-01-15T10:32:30Z"
}

If the job fails, the payload will include an error field:

{
  "jobId": "job_abc123",
  "type": "compress-video",
  "status": "failed",
  "error": {
    "code": "PROCESSING_ERROR",
    "message": "Failed to process video"
  },
  "createdAt": "2024-01-15T10:30:00Z",
  "failedAt": "2024-01-15T10:32:30Z"
}

Creating a webhook endpoint

Here's an example webhook endpoint using Next.js:

// app/api/webhooks/offload/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
  const payload = await request.json()
  
  console.log('Job completed:', payload.jobId)
  
  if (payload.status === 'completed') {
    // Handle successful job
    const videoUrl = payload.result.url
    // Save to database, notify user, etc.
  } else if (payload.status === 'failed') {
    // Handle failed job
    console.error('Job failed:', payload.error)
  }
  
  return NextResponse.json({ received: true })
}

Security

To verify that webhook requests are coming from offload.run, we include a signature in the X-Offload-Signature header. You can verify this signature using your API key.

import crypto from 'crypto'

function verifyWebhook(payload: string, signature: string, apiKey: string) {
  const expectedSignature = crypto
    .createHmac('sha256', apiKey)
    .update(payload)
    .digest('hex')
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  )
}

Retry behavior

If your webhook endpoint returns a non-2xx status code or times out, we'll automatically retry the webhook delivery:

  • First retry: after 1 minute
  • Second retry: after 5 minutes
  • Third retry: after 30 minutes
  • Final retry: after 2 hours

After 4 failed attempts, we'll stop retrying. You can always retrieve the job result using the API.

Testing webhooks

During development, you can use tools like ngrok to expose your local server to the internet and receive webhook notifications.

# Start ngrok
ngrok http 3000

# Use the ngrok URL as your webhook URL
https://abc123.ngrok.io/api/webhooks/offload