What You’ll Have Built
After implementing this workflow:- Export Jobs are detected and processed reliably, with sequential ordering guaranteed.
- Expenses are validated, mapped, and recorded correctly in the Accounting System.
- Attachments and bookkeeping logic are handled consistently for every Export Item.
- Export outcomes, both success and failure, are clearly reported back to Pleo for each item.
- The integration aligns with Pleo’s export guarantees and bookkeeping model.
Who This Guide Is For
This guide is intended for:- Integration developers
- Solution architects
- Accounting platform integrators
Before You Start
You should be familiar with:- Pleo’s supported authentication methods.
- The Export Lifecycle
Export Workflow Overview
When a bookkeeper queues expenses in Pleo’s Web App and clicks Export, Pleo creates an Export Job, a batch of Export Items (individual expenses), ready to be processed by the integration. The integration detects this job, verifies the Accounting System is ready, retrieves the items, and processes each one into an accounting entry. Once all items are processed, the integration reports the outcome for each item back to Pleo and sends a final event to close the job. Steps 1–4 and 6–7 interact directly with Pleo’s Export API. Step 5 (Process & Record Export Items) takes place inside the Accounting System or ERP and is covered in detail in the AS/ERP Processing Workflow Guide. Each step produces outputs that the next step depends on.Steps
1. Detect and Start Export Jobs
Purpose
When Pleo creates an Export Job, the integration must detect it and mark it as started before any processing can begin. Detection can happen via a webhook notification (preferred, as Pleo triggers the integration the moment a job is created) or via scheduled polling. In either case, the integration selects the oldest pending job and sends astarted event to Pleo’s Export API, which transitions the job to in_progress and establishes the integration’s exclusive processing rights.
On startup or after a connection loss, the integration may also detect an in_progress job it previously started. In this case, the started event is skipped and processing resumes from where it left off.
Input
- An Export Job created by Pleo when expenses are queued and exported via the Web App, with status
pending - A webhook notification (
export-job.created) or a scheduled polling trigger that initiates detection - On recovery: an Export Job already in
in_progressstate that was previously started by this integration but not completed
Workflow Process
Output
- The oldest eligible Export Job identified and selected for processing
- The Export Job marked as
in_progressvia thestartedevent, confirming the integration has taken responsibility for this batch - No other worker or integration instance will start the same job
Why It Matters
Export Jobs must be processed one at a time and in order to prevent accounting inconsistencies. Starting a job is the mechanism that establishes this exclusivity: only one integration instance can successfully send thestarted event for a given job. This prevents duplicate accounting entries from being created if multiple workers are briefly running simultaneously, and creates an auditable record of when processing began.
Integration Design
If you’re an integration developer or architect, read the Detect & Start Export Jobs integration design doc before implementing this step. It covers the detection mechanisms (webhook, polling, ad hoc trigger), sequencing requirements, how concurrent start conflicts are handled, and the rules for recovery scenarios.Step-by-Step Instructions
When you’re ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.2. Perform Pre-Export Validation
Purpose
Before any Export Items are processed, the integration verifies that the Accounting System is reachable and correctly configured for this Export Job. This check happens immediately after the job is started and before any accounting data is touched. If the Accounting System is unavailable, the integration is misconfigured, or the required bookkeeping method is not supported, the job is marked as failed with a clear, actionable reason, and processing stops cleanly.Input
- The started Export Job (status
in_progress), including metadata such ascompanyIdandvendorBasedBookkeeping - A valid connection to the target Accounting System, with credentials and required permissions in place
Workflow Process
Output
- Validation passed: the integration proceeds to retrieve Export Items for processing
- Validation failed: the Export Job is marked
failedwith a specificfailureReasonandfailureReasonType, and processing stops. The failure is surfaced to the user in Pleo’s Web App.
Why It Matters
Failing early is far less costly than failing mid-export. If validation were skipped and a problem were discovered halfway through processing, the Accounting System could be left in an inconsistent state, with some entries created and others missing. Pre-export validation ensures the integration either proceeds with confidence or fails cleanly before any accounting data is written.Integration Design
If you’re an integration developer or architect, read the Perform Pre-Export Validation integration design doc before implementing this step. It covers the required validation checks, the supported failure reason types, and when to fail the job versus when to handle issues at the item level.Step-by-Step Instructions
When you’re ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.3. Retrieve Export Job Items (Control Layer)
Purpose
Before fetching full accounting payloads, the integration retrieves a lightweight control list of all Export Job Items. Each item includes its uniqueaccountingEntryId and current processing status (pending, in_progress, successful, or failed), but not the full expense data. This establishes the processing scope: which items exist in this job and which still require work.
The control layer is also the recovery mechanism. If the integration restarts mid-export, it re-fetches this list, filters for items still in pending state, and resumes from where it left off without reprocessing already-completed items. Items in in_progress state are intentionally excluded from the recovery filter. They may have been partially processed before the crash, and retrying them risks creating duplicate accounting entries.
Input
- The Export Job ID (
jobId) from the started Export Job - On recovery: awareness that the job is already
in_progress, triggering a re-fetch to determine remaining work
Workflow Process
Output
- A complete, paginated list of all Export Job Items with their current statuses
- A defined processing scope: the set of items still requiring work, typically those with status
pending - A deterministic processing order established, ensuring consistent and auditable execution across retries
Why It Matters
Separating the control layer from the data layer keeps the workflow modular and resilient. The integration knows exactly what it needs to process before making heavier API calls for full payloads. This prevents partial processing, enables the workflow to resume safely after interruptions, and ensures no item is missed or inadvertently processed twice.Integration Design
If you’re an integration developer or architect, read the Retrieve Export Job Items integration design doc before implementing this step. It covers the control layer vs data layer distinction, pagination requirements, the recovery strategy, and how deterministic ordering should be implemented.Step-by-Step Instructions
When you’re ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.4. Fetch Export Item Data (Data Layer)
Purpose
With the processing scope established, the integration retrieves the full accounting payload for each Export Item. This is the data layer: each item contains all the information needed to create an accounting entry: amounts, dates, GL account codes, vendor details, tax codes, dimensions, attachment references, and the bookkeeping method to apply. This step is intentionally separate from the control layer. The integration first knows what to process (Step 3), then retrieves the data needed to process it (Step 4), keeping workflow control and data retrieval cleanly decoupled.Input
- The Export Job ID (
jobId) - The list of
accountingEntryIdvalues from the control layer (Step 3), defining which items require full data retrieval
Workflow Process
Output
- Full accounting payloads retrieved for each Export Item in the processing scope
- Each payload validated to confirm it contains the data required for the intended bookkeeping method
- Items ready to be passed into the Accounting System processing workflow
Why It Matters
The Export Item payload contains everything the integration needs to create a correct accounting entry. Fetching it as a separate step, after the processing scope is established, means the integration can validate completeness before committing to any accounting operations. It also means items can be handled individually, so a problem with one item’s data does not prevent others from being processed.Integration Design
If you’re an integration developer or architect, read the Fetch Export Item Data integration design doc before implementing this step. It covers the data layer structure, the fields available in the Export Item payload, pagination, validation requirements, and how to handle recovery.Step-by-Step Instructions
When you’re ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.5. Process & Record Export Items
Purpose
This step is where the integration processes each Export Item and records it into the Accounting System. For each item, the integration resolves the bookkeeping method, applies accounts and data mapping, handles attachments, assigns the correct accounting period, and creates the entry using the configured posting behaviour. Each Export Item is processed independently: a failure on one item does not stop the others from being processed.Input
- Full Export Item payloads from Step 4
- Integration configuration: accounts mapping, posting behaviour, and closed period strategy
- A valid connection to the Accounting System
Workflow Process
Output
- Draft or finalised accounting entries created in the Accounting System for each successfully processed item
- Attachments uploaded and linked to their corresponding accounting entries where applicable
- A success or failure result captured for each item, ready to be reported back to Pleo in Step 6
Why It Matters
This is where Pleo expense data becomes accounting records. Getting this step right, with correct GL accounts, accurate data mapping, and appropriate posting status, determines the quality and auditability of the Accounting System. Per-item failure isolation ensures that a single problematic expense does not block the rest of the batch.Step-by-Step Instructions
This step is covered in full in the AS/ERP Processing Workflow Guide, which walks through bookkeeping method resolution, accounts mapping, data mapping, attachment handling, accounting period assignment, and posting behaviour.6. Update Export Items
Purpose
After each Export Item is processed in the Accounting System, the integration reports the outcome back to Pleo. For successful items, this includes the external ID and URL of the entry created in the AS, providing a direct link between the Pleo expense and its accounting record. For failed items, this includes a clear, actionable failure reason. Pleo uses these updates to surface results to bookkeepers in the Export Queue. Items are sent in batches of up to 100 per API request.Input
- The success or failure result for each processed Export Item, captured during Step 5
- The
accountingEntryIdfor each item, from the control layer (Step 3) - For successful items: the external ID and URL assigned by the Accounting System
- For failed items: the failure reason and reason type, derived from the Accounting System’s response
Workflow Process
Output
- Every Export Item in the batch updated with a final status:
successfulorfailed - Successful items linked to their corresponding entries in the Accounting System via external ID and URL
- Failed items recorded with actionable error information, visible to bookkeepers for review and correction
Why It Matters
Reporting item-level outcomes back to Pleo is what makes the export visible and auditable for users. Without these updates, bookkeepers cannot see which expenses exported successfully, which failed, or why. Accurate and timely updates also enable Export Job completion: the final step cannot be triggered until all items have a recorded outcome.Integration Design
If you’re an integration developer or architect, read the Update Export Items integration design doc before implementing this step. It covers the supported status values, the required and optional fields for successful and failed items, and the failure reason type mappings for common Accounting System errors.Step-by-Step Instructions
When you’re ready to start implementing, follow the step-by-step instructions in the accompanying How-to article.7. Update & Complete Export Job
Purpose
Once all Export Items have been updated with their final statuses, the integration sends a completion event to close the Export Job. The event reflects the aggregated outcome of the entire batch:completed if all items succeeded, completed_with_errors if some failed, or failed if all items failed. This is the signal to Pleo that processing is finished and the full export result can be surfaced to users.
Input
- The final processing status of all Export Items, established in Step 6
- The Export Job ID (
jobId)
Workflow Process
Output
- The Export Job marked with its final status:
completed,completed_with_errors, orfailed - Export results fully visible to users in Pleo’s Export Queue, including per-item success and failure details
- The export lifecycle complete: no further updates can be made to this job