Skip to main content

Documentation Index

Fetch the complete documentation index at: https://apidocs.hopnow.io/llms.txt

Use this file to discover all available pages before exploring further.

Return 200 Quickly

Respond immediately, process in the background:
@app.post("/webhooks")
async def handle_webhook(request):
    verify_signature(request)

    event = await request.json()
    background_tasks.add_task(process_event, event)

    return {"status": "received"}  # Return immediately

Handle Duplicates

Events may be delivered more than once. Use the event id to deduplicate:
def process_event(event):
    event_id = event["id"]

    if is_already_processed(event_id):
        return  # Skip duplicate

    handle_event(event)
    mark_as_processed(event_id)

Handle Out-of-Order Events

Events may arrive out of sequence. Use timestamps to determine the latest state:
def handle_payout_event(event):
    payout_id = event["data"]["id"]
    event_time = event["created"]

    current = db.get_payout(payout_id)
    if current and current["updated"] > event_time:
        return  # Ignore outdated event

    db.update_payout(payout_id, {
        "status": event["data"]["status"],
        "updated": event_time
    })

Retry Behavior

If your endpoint returns a non-2xx status, we retry with exponential backoff:
RetryDelay
11 minute
25 minutes
315 minutes
41 hour
56 hours
After 5 failed attempts, the endpoint is automatically disabled.

Error Handling

Log errors but don’t block the webhook response:
async def process_event(event):
    try:
        await handle_event(event)
    except Exception as e:
        logger.error(f"Webhook processing failed: {e}")
        # Don't re-raise if you've already returned 200

Local Testing

Use ngrok to test webhooks locally:
ngrok http 8000
Then register the ngrok URL as your webhook endpoint in the sandbox environment.