Snip Snipping Tool Chrome Extension Convert API Files API Secure Conversion Service
Make Documents Accessible Process Chemical Documents Collaborate on Documents Developer Solutions Train Language Models Support Academic Research Artificial Intelligence Fintech Edtech Pharma & Chemical Universities & Schools
Handwriting Recognition Digital Ink On-prem PDF Cloud Mathpix Markdown All Supported Languages Image Conversion PDF Conversion Markdown Conversion Table OCR Mathpix CLI PDF Search PDF Reader PDF Data Extraction Chrome Extension View Conversion Gallery
Snip APIs SCS
Mobile Desktop Web Chrome Extension
Mathpix Snip Apps Convert API Mathpix Markdown Python SDK
Blog
About Careers Contact
Contact Get Started
← Back to Blog

A serious webhooks implementation for serious document pipelines

2026-08-11 · api, updates
Today we’re excited to announce that webhooks are now available in the PDF API at no extra cost.
To start using webhooks, include your endpoint URL with your submission and choose which events you want to receive. When one of those events occurs, we’ll send a signed HTTP request to your endpoint notifying you that your results are available.

Submit to Mathpix with a callback URL

You submit documents the same as before, but with added parameters:
  • callback_url: your webhook endpoint URL, where we send this submission’s notifications.
  • callback_events: selects which events you receive, such as document completed (including any requested conversion results) or document batch completed. Optional.
  • callback_headers: headers we include on each notification with content of your choice. Optional.
Here is a submission that includes the webhook parameters:
# Example request (cURL; any tool that sends HTTP requests works the same way)
curl -X POST https://api.mathpix.com/files/v1/uri \
-H 'app_key: APP_KEY' \
-H 'Content-Type: application/json' \
--data '{
  "source_uri": "https://cdn.mathpix.com/examples/cs229-notes1.pdf",
  "callback_url": "https://your-app.example.com/mathpix/webhook",
  "callback_events": ["file.completed", "file.error"],
  "callback_headers": { "Authorization": "Bearer YOUR TOKEN" }
}'
Webhooks are supported on POST /v3/pdf, POST /files/v1, POST /files/v1/uri, and POST /files/v1/jobs.
Our Python client, mpxpy, supports them as well:
# Example: submit a document with a callback
from mpxpy.mathpix_client import MathpixClient

client = MathpixClient(app_id="your-app-id", app_key="your-app-key")

client.file_new(
    source_uri="https://cdn.mathpix.com/examples/cs229-notes1.pdf",
    callback_url="https://your-app.example.com/mathpix/webhook",
    callback_events=["file.completed", "file.error"],
)

The webhook endpoint handler

A notification is an HTTP POST request to the webhook endpoint URL you named. Your handler has three jobs:
  • Answer with HTTP status 200 as soon as the notification is read, and do the work afterward. Any server error, or an answer that takes too long, counts as a failed attempt and starts the retries.
  • Verify that the notification came from Mathpix before trusting the body. Every notification is signed with your signing secret, in the Mathpix-Signature header, and anything older than five minutes should be rejected.
  • Deduplicate. Delivery is at least once, so the same notification can arrive more than once. Skip a duplicate notification by matching on:
    • event plus file_id for file.completed and file.error
    • event plus job_id for job.completed.
If your endpoint is down, we’ll try again with increasing delays, up to eight times total over about an hour.
This is an example of a notification for a completed file:
{
  "event": "file.completed",
  "file_id": "b1c9c3a8-55e4-4a09-b7d0-218ba5de4c4d",
  "status": "completed",
  "num_pages": 30,
  "num_pages_completed": 30
}
A job sends job.completed once every document in it has finished and you have closed it to new submissions by calling POST /files/v1/jobs/{job_id}/finalize. A job you never finalize stays open, so it never sends that notification.
Here is how to set up an endpoint to handle a notification (using Flask, but you may use another framework):
# Example: the handler that receives, verifies, and acts on notifications
from flask import Flask, abort, request
from mpxpy.mathpix_client import MathpixClient
from mpxpy.webhooks import verify_signature

# Mathpix API client, for accessing your results
client = MathpixClient(app_id="your-app-id", app_key="your-app-key")
SIGNING_SECRET = client.webhook_config_get().signing_secret

# Server for handling webhook notifications
application = Flask(__name__)

@application.post("/mathpix/webhook")
def mathpix_webhook():
    # Verify the notification came from Mathpix
    if not verify_signature(request.headers.get("Mathpix-Signature", ""), request.get_data(), SIGNING_SECRET):
        abort(400)
    # Hand the notification to your queue and answer right away
    enqueue(request.get_json())
    return "", 200

def notification_key(notification):
    # Key to check for duplicate notifications
    identifier = "job_id" if notification["event"] == "job.completed" else "file_id"
    return notification["event"], notification[identifier]

def process_notification(notification):
    # What your worker runs, one notification at a time
    key = notification_key(notification)
    if is_already_processed(key):
        return
    # Processing file.completed results the same as before.
    if notification["event"] == "file.completed":
        file_id = notification["file_id"]
        result = client.file_get(file_id)
        markdown_text = result.to_md_text()
    record_processed(key)

Note on request volume

Notifications arrive at our processing pace, so submitting 100,000 documents subscribed to file.completed results in 100,000 requests to your server. For jobs where that is more traffic than you want, write results directly to your storage with destination_uri or subscribe to file.error alone.

Learn more

The webhooks guide contains the step-by-step instructions, covering the implementation journey from start to finish including how to retrieve your secret, troubleshoot your endpoint, and more. The webhooks reference goes into further detail, describing every endpoint, its parameters, and its responses.
Webhooks carry no separate pricing. A document costs the same whether its completion reaches you through a notification or through the status endpoints, and notifications are not billed as requests.
Webhooks are available today. Please reach out to support@mathpix.com if you have any questions.