Skavio Processing API: verify the webhook, then authenticate the download
Skavio Processing API supports signed completion webhooks and authenticated result downloads, allowing your application to handle asynchronous processing without keeping the original request open. These features protect different boundaries: the webhook signature verifies the notification, while download authentication controls access to the output. A reliable integration keeps those checks separate—and records the event durably before acknowledging it.
1. Register the callback and attach it to the job
Start with a public HTTPS endpoint on your receiving server. Register it through the Skavio dashboard or through an administrator session using POST /v1/webhooks. Registration is not an ordinary Bearer-key operation. Save the webhook signing secret when it is shown: it is displayed once. Keep it in server-side secret storage, separate from the API key used to access jobs and download results. Pass the registration’s returned id as webhook_id when submitting a processing job. Also persist the relationship between your application’s request, the Skavio job and the company that owns it. That record lets a background worker connect a completion event to the correct internal workflow without trusting an incoming identifier alone. Use Skavio’s idempotent submission support when retrying a submission after a network timeout; webhook handling does not replace submission idempotency.
- Webhook signing secret: verifies incoming callback signatures.
- Scoped API key: authenticates server-side API requests and result retrieval.
- Local job record: connects the Skavio job to your application’s company and processing request.
2. Verify the unchanged request before acting on it
The documented completion and failure event types are job.completed and job.failed. The event envelope contains id, type, created_at and job; the request includes X-Skavio-Signature, X-Skavio-Timestamp and X-Skavio-Event-Id. Capture the exact request-body bytes before JSON parsing or reserialization. The expected signature is `v1=` followed by the hexadecimal HMAC-SHA256 of the timestamp, a literal period and the raw body bytes, keyed with the webhook signing secret. Changing whitespace or rebuilding JSON can change the signed content. The official Python verifier rejects malformed timestamps and timestamps more than 300 seconds in either direction from the receiver’s clock. It then uses hmac.compare_digest for constant-time signature comparison. Follow that construction rather than borrowing another provider’s header names or signing format. After verification, parse the body and validate the event. As an additional application-level check, require X-Skavio-Event-Id to match the id inside the verified body before deduplicating: the documented signature covers the timestamp and body, not that header separately. This matching check is a defensive recommendation, not a documented Skavio requirement.
- Reject missing or invalid signature inputs before starting downstream work.
- Keep the receiver’s clock synchronized so the timestamp check remains useful.
- Treat freshness and deduplication as separate controls: a valid, recent event can still be a duplicate.
3. Record durably, acknowledge promptly, process separately
Use a durable inbox rather than downloading files inside the callback request. After verification, transactionally insert the event into your database with a uniqueness constraint—for example, on the webhook registration and verified event id. Return a 2xx response only after that transaction commits. A background worker can then process pending inbox records independently. For a duplicate that is already durably recorded, return 2xx without repeating downstream effects. If persistence fails, do not acknowledge successful receipt: an early 2xx could leave Skavio considering the notification delivered while your application has no recoverable record. The worker should distinguish job.completed from job.failed before attempting retrieval. A failure notification belongs on your error-handling path, not on a download path. Record worker progress separately from receipt so a crash after acknowledgement does not strand the event. This transactional-inbox design is an integration recommendation, not a built-in Skavio queue. Event deduplication also does not by itself make later actions exactly once: file storage, notifications and business-system updates need their own retry-safe handling.
- Verified and newly recorded: acknowledge, then let the worker continue.
- Verified and already recorded: acknowledge without repeating the action.
- Unable to record durably: leave the delivery unsuccessful and alert on persistent failures.
4. Download through the authenticated API—not through trust in the callback
For a completed job, use the API-returned result.files download_path. Make the initial request from your backend with Bearer authentication and a suitably scoped company API key. A verified webhook is not a download credential, and its signing secret must not be used as one. Resolve the returned path against your configured Skavio API origin and validate that the initial request stays on that origin rather than accepting an arbitrary download host from incoming data. Preserve the company-to-job association when choosing credentials, and keep API keys out of browser code and URL query strings. Storage-backed downloads can return HTTP 307 to a short-lived signed URL. That storage URL needs no Skavio API key. Configure redirect handling so the Authorization header is not forwarded to the storage host. The official guide recommends curl -L without --location-trusted; check the equivalent behavior explicitly in your HTTP client. Treat the temporary signed URL as sensitive while it is valid: possession enables retrieval without an API key. Avoid logging it, verify that the download succeeded, and store the output under your application’s own access controls.
- Initial Skavio request: authenticated with the server-side API key.
- Redirected storage request: uses the temporary signed URL without forwarding the Skavio key.
- Application handoff: mark retrieval complete only after the output has been stored successfully.
5. Reconcile missing notifications before retention expires
Skavio documents at-least-once callback delivery with up to six attempts. Approximate retry delays are 60, 120, 240, 480 and 960 seconds; callback redirects are not followed. Configure the registered callback URL to reach the receiver directly rather than relying on a redirect. Bounded retries are not a guarantee that every event will eventually reach your application. Run periodic authenticated reconciliation for outstanding jobs, and send discovered completions through the same retry-safe processing path as webhook events. Do not submit a new processing job simply because its callback is missing. Plan around the seven-day retention period in Skavio’s supplied product information. Retrieve outputs promptly and alert on jobs that remain unresolved or completed but not downloaded. Do not assume extended retention without confirmation. Before deployment, test the failure paths as carefully as the successful download. The goal is not merely to receive a callback: it is to recover a result safely when requests are duplicated, storage is unavailable or your receiver restarts.
- Signature tests: altered body, missing headers, incorrect secret, malformed timestamp and timestamps beyond the permitted past or future window.
- Durability tests: concurrent duplicate deliveries, database failure and a worker crash after acknowledgement.
- Lifecycle tests: job.failed, missed notification, expired result and interrupted download.
- Redirect tests: confirm that no Skavio Authorization header reaches the storage host.