Webhooks¶
Instead of polling for job status, you can receive results via webhook. Provide a webhook_url when calling the execute endpoint and the platform will POST to your URL when the job completes or fails.
Setup¶
Include webhook_url in your execute request:
{
"inputs": { "customerAge": 35, "propertyValue": 500000 },
"webhook_url": "https://your-app.com/webhooks/xlsxapi"
}
The URL must be http:// or https://.
Webhook Payloads¶
On Success¶
{
"job_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "completed",
"inputs": {
"customerAge": 35,
"propertyValue": 500000
},
"outputs": {
"premium": 1250.50,
"deductible": 1000,
"coverage": 500000
},
"created_at": "2026-03-18T10:30:00Z",
"completed_at": "2026-03-18T10:30:08Z",
"execution_time_ms": 1850
}
On Failure¶
{
"job_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "failed",
"error_message": "Could not process at the moment",
"created_at": "2026-03-18T10:30:00Z",
"updated_at": "2026-03-18T10:30:25Z"
}
Behavior¶
| Aspect | Detail |
|---|---|
| Method | POST |
| Content-Type | application/json |
| Timeout | 10 seconds |
| Retries | None — the webhook is sent once |
| Delivery guarantee | At-most-once |
Webhook failures don't affect jobs
If your webhook endpoint is down or returns an error, the job itself is unaffected. You can always fall back to polling GET /jobs/{job_id} to retrieve the results.
Tracking Delivery¶
The webhook delivery status is included in the job status response:
{
"job_id": "7c9e6679-...",
"status": "completed",
"webhook_url": "https://your-app.com/webhooks/xlsxapi",
"webhook_sent_at": "2026-03-18T10:30:09Z",
"webhook_response_status": 200
}
| Field | Description |
|---|---|
webhook_sent_at |
When the webhook POST was attempted |
webhook_response_status |
HTTP status code from your endpoint. 0 indicates a connection/timeout failure. |
Best Practices¶
- Return 200 quickly — do your processing asynchronously after acknowledging receipt
- Use the job_id for idempotency — in case you receive duplicate deliveries (unlikely but possible during infrastructure events)
- Have a polling fallback — since webhooks are at-most-once, poll for any jobs that haven't triggered your webhook within an expected timeframe
- Verify the payload — check that the
job_idcorresponds to a job you submitted
Example Webhook Receiver¶
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/webhooks/xlsxapi", methods=["POST"])
def handle_webhook():
payload = request.json
job_id = payload["job_id"]
status = payload["status"]
if status == "completed":
outputs = payload["outputs"]
# Process the results...
print(f"Job {job_id} completed: {outputs}")
elif status == "failed":
error = payload.get("error_message", "Unknown error")
# Handle the failure...
print(f"Job {job_id} failed: {error}")
return jsonify({"received": True}), 200
const express = require("express");
const app = express();
app.use(express.json());
app.post("/webhooks/xlsxapi", (req, res) => {
const { job_id, status, outputs, error_message } = req.body;
if (status === "completed") {
console.log(`Job ${job_id} completed:`, outputs);
// Process the results...
} else if (status === "failed") {
console.log(`Job ${job_id} failed: ${error_message}`);
// Handle the failure...
}
res.json({ received: true });
});