> ## Documentation Index
> Fetch the complete documentation index at: https://docs.okrapdf.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Get notified when document processing completes.

## Overview

Instead of polling for completion, register a webhook URL to receive a POST request when your document finishes processing.

## Setup

Pass `webhook_url` when uploading a document:

```bash theme={null}
curl -X POST https://api.okra.app/v1/documents/doc-abc123/upload-url \
  -H "Authorization: Bearer okra_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/report.pdf",
    "webhook_url": "https://your-app.com/webhooks/okrapdf"
  }'
```

## Webhook payload

When the document completes, OkraPDF sends a POST request to your URL:

```json theme={null}
{
  "event": "document.completed",
  "document_id": "doc-abc123",
  "status": "completed",
  "file_name": "report.pdf",
  "total_pages": 12,
  "timestamp": "2025-01-15T10:30:00Z"
}
```

## Webhook handler example

```python theme={null}
from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route("/webhooks/okrapdf", methods=["POST"])
def handle_webhook():
    payload = request.json
    doc_id = payload["document_id"]

    if payload["status"] == "completed":
        # Fetch the markdown
        md = requests.get(
            f"https://api.okra.app/v1/documents/{doc_id}/full.md",
        ).text
        process_document(md)

    return jsonify({"received": True}), 200
```

## Retry behavior

* OkraPDF retries failed webhook deliveries up to 3 times
* Retries use exponential backoff (5s, 30s, 5min)
* Your endpoint must return a 2xx status to acknowledge receipt
* Non-2xx or timeout (30s) triggers a retry

## Best practices

1. **Return 200 quickly** - process the webhook payload asynchronously
2. **Use HTTPS** - webhook URLs must use HTTPS in production
3. **Verify the payload** - check that the `document_id` exists in your system
4. **Handle duplicates** - webhooks may be delivered more than once
