SKAVIO / JOURNAL
SKAVIO JOURNAL · DEVELOPER HOW-TO
AWS Prescriptive Guidance — Transactional outbox pattern
Skavio Processing API combines Flow invoice extraction with idempotent job submissions, signed completion webhooks and authenticated result downloads. Those capabilities provide the processing side of an integration—not a built-in ERP connector. Your server-side adapter needs three separate duplicate controls: one for submitting extraction jobs, one for receiving completion events and one for writing reviewed invoices into the ERP.
1. Persist the invoice request before making API calls
Start with a durable record in your integration database. Give each intended extraction request a stable internal identifier, link it to the source invoice and company, and record the selected extraction workflow. Persist its submission idempotency key before sending the job request. This record supports recovery when a connection fails and the adapter cannot tell whether Skavio accepted the submission. Define the ERP field mapping separately from the extraction request. Supplier references, invoice dates, currency, totals and line items are examples of mapping decisions—not guaranteed API field names. Use the published documentation and OpenAPI contract for exact request and response schemas. The processing sequence is upload, estimate, then submit. Flow costs 100 company credits per page, with a minimum of 200 per document. Companies receive 1,000 trial credits without a card. Use the server estimate rather than a hardcoded example budget.
- Authenticate server-side requests with a scoped company API key using Bearer authentication.
- Upload the source through POST /v1/uploads, then obtain a quote through POST /v1/estimate.
- Submit through POST /v1/jobs with operation=flow-extract and set max_credits from estimated_credits.
- Persist the returned job identifier against the original integration request. Keep API keys and webhook secrets out of browser code and logs.
2. Retry the submission with the same key and parameters
A timeout is an uncertain outcome, not proof that a job failed to start. If the submission response is lost, retry the same request with the same Idempotency-Key. The documented key length is 8–128 characters; identical retries return the same job without another charge. Reusing the key with changed parameters returns 409. Confirm the idempotency retention window before deciding how long automated retries may continue. Store the submission parameters alongside the key so a retry does not silently pick up a modified workflow or payload. An intentional retry after a terminal processing failure requires a new key. Link that new submission to the original invoice request for audit purposes. Credit handling belongs to the processing boundary. The fixed quote is reserved atomically, consumed on successful processing and released once on failure. Keep that outcome separate from downstream ERP validation: an ERP rejection does not turn a successfully completed extraction into a failed processing job.
- Lost submission response: reuse the original key and unchanged request within the confirmed idempotency window.
- Changed request: resolve the conflict explicitly; do not treat 409 as a transient failure.
- Terminal processing failure: record the failure before authorizing a new submission with a new key.
- Duplicate invoice received through another channel: use your adapter’s business duplicate controls. Submission idempotency alone does not identify the same invoice.
3. Verify completion events before recording or acting on them
Register an HTTPS webhook through the company dashboard or the administrator-session POST /v1/webhooks operation. Securely retain the once-shown secret and include webhook_id when submitting the job. Documented events include job.completed and job.failed. The receiver must preserve the exact request-body bytes. Verify X-Skavio-Signature against v1=hex(HMAC-SHA256(secret, timestamp + '.' + raw_body)), using the value from X-Skavio-Timestamp. Compare signatures in constant time. Reject missing or malformed signatures and invalid timestamps; the documentation’s verification example rejects clock differences exceeding 300 seconds. Parsing and reserializing JSON before verification can change the signed bytes. After verification, durably record the event and pending processing work before returning 2xx. As an adapter design recommendation, use a database transaction to store both the receipt and a work item, then let an asynchronous worker handle downloads and ERP preparation. This addresses the gap between recording an event and publishing its work to a separate queue.
- Deduplicate X-Skavio-Event-Id with non-null columns and a database-enforced unique constraint on company plus event ID—not only an application-level lookup.
- Check that the event refers to a job associated with the expected company and integration request.
- Acknowledge already-recorded, verified duplicates without scheduling the work again.
- Expect at-least-once delivery, with up to six attempts. A valid signature does not establish that an event is new.
4. Download the result, review the invoice, then create an ERP draft
For a successful job, retrieve the JSON output through the authenticated download paths supplied in result.files. Flow also provides CSV, XLSX, source evidence and review warnings. Archive the required results and evidence within the seven-day retention period rather than treating Skavio storage as your accounting archive. Put a review gate between extraction and ERP transfer. Check invoice dates, totals and line items against the source, resolve warnings, and validate the mapping to the ERP’s supplier records and required fields. Extraction completion should not authorize posting. Give the ERP write its own duplicate control. Where supported, use the ERP’s documented idempotency mechanism or an enforced unique external reference. Persist that reference before attempting draft creation. If the ERP accepts a draft but its response is lost, reconcile the existing record before attempting another write. Without verified ERP-side controls, do not promise safe automatic retries or exactly-once posting.
- Submission key: deduplicates identical extraction-job submissions within the documented idempotency scope.
- Webhook event ID: deduplicates receipt and scheduling of the same completion notification; background work still needs idempotent handling.
- ERP external reference or documented idempotency key: controls duplicate draft creation independently.
- If review or ERP validation fails, retain the extracted result and resolve the issue without automatically launching another extraction.
5. Test uncertain outcomes—not just the successful path
Acceptance tests should cover cases where one system succeeds but the next system cannot observe it. Include concurrent webhook deliveries and a receiver crash after durable receipt but before background processing. Verify that pending work remains recoverable and that recovery does not create another ERP draft. Add reconciliation for jobs whose completion notifications never reach the receiver or exhaust delivery attempts. Compare your stored requests with job status using the documented API, recover available results and route unresolved cases to an operator. Monitor completed extractions that have neither a stored result nor a reviewed ERP draft, and retrieve required artifacts before retention expires. Before implementation, confirm the current OpenAPI schemas, idempotency retention and webhook-secret rotation procedure. The ERP’s authentication, draft-creation endpoint, field mapping and duplicate controls also need verification. This is an integration architecture, not a production-tested connector for an unspecified ERP.
- Lose a submission response, then retry with unchanged parameters; separately test a changed-payload 409 conflict.
- Reject altered bodies, missing or malformed signatures, and stale or excessively future-dated timestamps.
- Deliver the same event concurrently and verify that only one durable work item is created.
- Crash the receiver or worker at transaction boundaries and verify recovery.
- Simulate an ERP draft being accepted before its response is lost, then verify reconciliation rather than blind resubmission.
A signed completion event is a processing signal—not permission to post an invoice.
Sources
- Skavio Processing API — Developer documentation — Supplied research checked October 3, 2026 reports Bearer authentication, the upload–estimate–submit sequence, idempotency behavior, webhook registration and signature verification, delivery attempts, and authenticated result downloads.
- Stripe — Webhooks — Supports raw-body preservation, duplicate-event handling and asynchronous processing as engineering context—not as Skavio-specific contract details.
- PostgreSQL — Constraints — Supports database-enforced uniqueness across column combinations and non-null identifiers for durable event deduplication.
- AWS Prescriptive Guidance — Transactional outbox pattern — Supports atomically recording state and pending work to address dual-write failures, alongside idempotent downstream consumers.