The webhook endpoint lets any system push files into DriftOps for immediate comparison against a contract.

This is the outbound-push alternative to cloud connections (which pull files on a schedule). Use webhooks when your pipeline controls when files are ready and can make an HTTP request.

Endpoint

POST https://api.driftops.io/api/webhook/{token}

The {token} is unique per monitor. Find it on the monitor detail page in the DriftOps app.

Authentication

No API key or auth header is required. The webhook token acts as the credential. Keep it secret. If a token is compromised, delete the monitor and create a new one to rotate the token.

Request format

Send the file as a multipart form upload with the field name file.

Content-Type: multipart/form-data
Field: file = <your file>

curl:

curl -X POST https://api.driftops.io/api/webhook/{token} \
  -F "file=@/path/to/document.json"

Python:

import requests

with open("document.json", "rb") as f:
    resp = requests.post(
        "https://api.driftops.io/api/webhook/{token}",
        files={"file": ("document.json", f, "application/json")}
    )
resp.raise_for_status()

Node.js:

const FormData = require("form-data");
const fs = require("fs");
const fetch = require("node-fetch");

const form = new FormData();
form.append("file", fs.createReadStream("document.json"));

fetch("https://api.driftops.io/api/webhook/{token}", {
  method: "POST",
  body: form
});

Supported file types: JSON, EDI X12, XML, CSV, flat key-value. Maximum file size: 30 MB.

Response

Success (200):

{
  "success": true,
  "event_id": 4821,
  "has_drift": true,
  "drift_summary": {
    "additions": 0,
    "removals": 2,
    "changes": 1,
    "renames": 0
  },
  "alert_queued": true,
  "partner_notified": false
}

When no drift is detected, has_drift is false and drift_summary counts are all zero. An event record is still created (auto-resolved) so event_id is always present.

{
  "success": true,
  "event_id": 4822,
  "has_drift": false,
  "drift_summary": {
    "additions": 0,
    "removals": 0,
    "changes": 0,
    "renames": 0
  },
  "alert_queued": false,
  "partner_notified": false
}

Error codes

CodeReason
404Token not found. Check the token in the URL.
403Monitor is inactive. Enable it in the DriftOps app.
400File validation failed. Check file size and format.
429Rate limit exceeded (20 req/min per token).
500Server error. Retry after a short delay.

Rate limiting

Each token is limited to 20 requests per minute. The window resets automatically after 60 seconds.

Implement exponential backoff on 429 responses:

import time
import requests

def post_with_retry(url, file_path, max_retries=3):
    for attempt in range(max_retries):
        with open(file_path, "rb") as f:
            resp = requests.post(url, files={"file": f})
        if resp.status_code == 429:
            time.sleep(2 ** attempt)
            continue
        resp.raise_for_status()
        return resp.json()
    raise Exception("Max retries exceeded")

Security

  • Tokens are 32 bytes of cryptographically random data, URL-safe base64 encoded.
  • All traffic is TLS-encrypted.
  • DriftOps validates file content on upload. Oversized files, invalid content types, and suspicious payloads are rejected before processing.
  • Webhook delivery attempts and security events are logged for audit purposes.

If you suspect a token has been exposed, disable the monitor immediately and create a new one.