Skip to main content
By the end of this guide, you’ll have:
  • ✅ Created a webhook endpoint in your application
  • ✅ Registered it with Magic Hour
  • ✅ Tested it with a real API call
  • ✅ Verified webhook delivery works

How Webhooks Work

Webhooks let you receive real-time notifications when your API requests complete, instead of polling for status updates.

Step 1: Create Your Webhook Endpoint

First, let’s create a simple webhook handler that can receive and process events.
Using Jupyter/Colab? The server examples below are for standalone deployment. For notebook testing:
  1. Use webhook.site for instant webhook testing (no code needed). See the “webhook.site” tab in Step 2
  2. Or use the notebook-friendly code in the “Colab/Jupyter” tab below
from fastapi import FastAPI, Request
import json

app = FastAPI()

@app.post("/webhook")
async def webhook_handler(request: Request):
    # Get the event data
    event = await request.json()

    # Log the event for testing
    print(f"Received event: {event['type']}")
    print(f"Payload: {json.dumps(event['payload'], indent=2)}")

    # Handle different event types
    match event['type']:
        case 'video.started':
            print('🎬 Video processing started')
        case 'video.completed':
            print('✅ Video processing completed')
            # Download URL available in event['payload']['downloads']
        case 'video.errored':
            print('❌ Video processing failed')
        case 'image.completed':
            print('🖼️ Image processing completed')
        case 'image.errored':
            print('❌ Image processing failed')

    # Always return success
    return {"success": True}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Step 2: Make Your Endpoint Publicly Accessible

Your webhook endpoint needs to be accessible from the internet. For testing, use one of these options:

Step 3: Register Your Webhook

1

Visit Developer Hub

Go to Magic Hour Developer Hub, and click Create WebhookWebhook Table
2

Configure webhook

Enter your webhook details:
  • Endpoint URL: Your public HTTPS URL (e.g., https://abc123.ngrok.io/webhook)
  • Events: Select the events you want to receive:
    • video.started - When video processing begins
    • video.completed - When video is ready for download
    • video.errored - When video processing fails
    • image.started - When image processing begins
    • image.completed - When image is ready for download
    • image.errored - When image processing fails
    • audio.started - When audio processing begins
    • audio.completed - When audio is ready for download
    • audio.errored - When audio processing fails Create webhook modal
Click Create Webhook
3

Save webhook secret

Important: Copy and save the webhook secret - you’ll need this for security verification.Webhook Secret
Store this secret securely! It’s used to verify that webhooks are actually from Magic Hour.

Step 4: Test Your Webhook End-to-End

Now let’s verify everything works by making a real API call and watching for the webhook.
1

Start monitoring your webhook

If using your own server: Watch the console logs
# Your server should show:
🚀 Webhook server running on http://localhost:8000
If using Colab/Jupyter: Watch the cell output for webhook eventsIf using webhook.site: Keep the browser tab open to see incoming requests in real-time
2

Make a test API call

Create a simple image to trigger webhook events:
import magic_hour

client = magic_hour.Client(api_key="your-api-key")

# Create a simple AI image - this will trigger webhooks
result = client.v1.ai_image_generator.generate(
    prompt="A cute cat wearing sunglasses",
    width=512,
    height=512
)

print(f"Job created! ID: {result.id}")
print("Watch your webhook endpoint for events...")

# In Colab, you'll see the webhook events appear in the cell output above
3

Verify webhook delivery

Within seconds, you should see webhook events in your console:
Received event: image.completed
🖼️ Image processing completed
Payload: {
  "id": "clx7uu86w0a5qp55yxz315r6r",
  "status": "complete",
  "downloads": [
    {
      "url": "https://images.magichour.ai/id/output.png",
      "expires_at": "2024-10-19T05:16:19.027Z"
    }
  ]
}
Success! 🎉 Your webhook is working end-to-end.

Step 5: Download Your Result

Your webhook received the download URL. Let’s grab the generated image:
import requests

# Extract download URL from webhook payload
download_url = "https://images.magichour.ai/id/output.png"

# Download the image
response = requests.get(download_url)
with open("generated_image.png", "wb") as f:
    f.write(response.content)

print("✅ Image downloaded as generated_image.png")

🎉 Congratulations!

You’ve successfully:
  • ✅ Created a webhook endpoint
  • ✅ Registered it with Magic Hour
  • ✅ Tested it with a real API call
  • ✅ Received webhook notifications
  • ✅ Downloaded the generated content

Next Steps

Secure Your Webhook

Add signature verification to ensure webhooks are from Magic Hour

Event Types Reference

See all available webhook events and their payloads

Production Deployment

Deploy your webhook handler to production

Webhook Reference

Explore the complete webhook API reference

Troubleshooting

Webhook not receiving events?
  • ✅ Check your endpoint URL is publicly accessible
  • ✅ Ensure your server returns HTTP 2xx status codes
  • ✅ Verify the webhook is enabled in Developer Hub
  • ✅ Check server logs for errors
Colab/Jupyter specific issues:
  • ✅ Install required packages: !pip install fastapi uvicorn nest-asyncio pyngrok
  • ✅ Make sure the server thread started successfully
  • ✅ Check if ngrok tunnel is active and accessible
  • ✅ Try webhook.site as an alternative for quick testing
AsyncIO errors in notebooks?
  • ✅ Make sure you’re using the Colab/Jupyter code version with nest_asyncio.apply()
  • ✅ Don’t run uvicorn.run() directly in notebooks - use the threading approach shown above
Need help? Contact support at support@magichour.ai