Webhook Signature Verification
Pixop signs all outgoing webhook requests to allow you to verify their authenticity and integrity.
Each request includes the following HTTP headers:
X-Pixop-Signature
: A base64-encoded signature of the timestamp and request body.X-Pixop-Public-Key-Id
: The UUID of the public key used to verify the signature.X-Pixop-Timestamp
: A Unix timestamp (in seconds) indicating when the request was signed.X-Pixop-Algorithm
: The signing algorithm. Currently,SHA256withECDSA
.
Signature format:
<timestamp>.<payloadJson>
<timestamp>
is taken fromX-Pixop-Timestamp
<payloadJson>
is the raw request body as sent by Pixop
This string is signed using ECDSA (SHA256withECDSA
), and the result is base64-encoded.
Verifying the Signature
-
Concatenate the timestamp and request body:
timestamp + "." + rawRequestBody
-
Retrieve the public key using the
X-Pixop-Public-Key-Id
: -
Verify the signature using the specified algorithm and public key.
-
Reject requests with timestamps older than an acceptable threshold (e.g., 5 minutes) to mitigate replay attacks.
⏱ Webhook requests have a 10-second timeout. Respond promptly and handle long-running logic asynchronously to avoid delivery failures.
Although public key retrieval is typically fast, it's strongly recommended to cache it to reduce latency and improve performance.
Key Rotation
Pixop rotates webhook signing keys regularly. During rotation, two keys may be valid for a short grace period. Always verify the signature using the public key referenced by X-Pixop-Public-Key-Id
.
Code Example
A public Spring Boot example project will be available to demonstrate webhook signature verification.
Webhook Retry Behavior
Pixop automatically retries failed webhook deliveries using an exponential backoff strategy. Retry behavior can be customized per webhook.
A delivery is considered failed if:
- The response status code is not
2xx
- The request times out or encounters a network error
- The
WebhookRateLimitPerSecond
threshold is exceeded and no permit is acquired within 5 seconds
If a 429 Too Many Requests
response includes a Retry-After
header (or similar), Pixop honors it when scheduling the next retry attempt.
Retries continue until the maximum retry duration (maxTotalRetryDelayMinutes
) is reached.
Detailed delivery history — including status codes, response bodies, retry timing, and headers — is available via the GET /v1/webhooks/events
endpoint.
📅 Webhook event history is retained for 10 days, or 1 day for test events.
Event Ordering and Context
Webhook events are dispatched asynchronously and independently. While Pixop makes a best-effort attempt to deliver events in the order they occur, delivery order is not guaranteed.
For instance, a video_processing.done
event may arrive before the corresponding video_processing.started
event for the same videoId
.
To correctly handle events:
- Treat each event as self-contained
- Use the
occurredAt
date and time to determine the actual sequence of events - Design webhook receivers to be idempotent and resilient to out-of-order delivery
For additional context about a given event, query the related video resource using:
GET /v1/videos/{videoId}