Purpose and Features¶
The Cost Codes integration exists to get cost code data out of ERP/Finance and into the new Sapio LIMS instance, so that spend recorded in the LIMS can be assigned to the correct cost code.
Sapio needs cost codes to be present before they can be attached to spend, but the codes are owned and maintained in the finance domain. This project bridges that gap: it provides an API through which cost codes, their descriptions, and other required/optional properties, are loaded into Sapio as project records. Because the ERP is not yet available, the integration is being delivered in two phases:
- Phase 1: the Integration Hub receives a file of cost codes from Finance and pushes them into Sapio through a POST endpoint
- Phase 2: once the ERP is live, Sapio will pull cost codes directly through a GET endpoint.
Key Features¶
The integration provides three main capabilities: a simple way to load cost codes into Sapio in bulk, thorough validation with clear error reporting, and a layered architecture that is secure and traceable end to end.
Bulk loading of cost codes into Sapio¶
A single POST /cost_codes/v1 request loads one or many cost codes into Sapio at once. The request body is a JSON array of project payloads, matching the list of codes Finance sends in its file, and each successful load returns a 201 Created with the project ID and the record ID Sapio generated for it. This gives the caller immediate confirmation of exactly what was created. One thing to be aware of, the load is atomic (i.e all-or-nothing), so if any entry in the batch fails, the whole request is rejected.
Validation and clear error handling¶
Requests are checked before they go anywhere near Sapio. The Experience API validates the shape of the payload and the two mandatory fields, the project code and the project description, and rejects anything malformed with a 400 Bad Request that explains what was wrong and where. Downstream problems are translated too: rather than exposing raw Sapio errors, the system maps them to sensible statuses (for example, a duplicate cost code becomes a 503 rather than Sapio's internal 500) with messages phrased in terms the caller understands. This catches mistakes early and makes failures easy to diagnose.
Secure, traceable, layered architecture¶
The integration follows the API-led three-layer pattern — Experience, Process, and System APIs — so each concern lives in one place and the layers can evolve independently. When Phase 2 arrives, the consumer-facing layer changes while the Sapio integration underneath stays put. Every request must carry a valid token issued by the identity provider, traffic is encrypted throughout, and each response carries a correlation ID that lets a request be traced across all three layers. Behaviour is configuration-driven, so validation and routing rules can be adjusted without code changes.
Limitations¶
- Only two attributes are integrated. The integration covers the cost code and its description. Other attributes are included only if a corresponding field exists in the Sapio LIMS project object (either default or custom) — at present that means the lifecycle status and the effective start and end dates — and no data enrichment or transformation occurs.
- Creation only — no updates. Existing project records in Sapio cannot be modified through this API; the update endpoint is out of scope for this phase.
- Batches are atomic. A single bad entry, such as a cost code that already exists in Sapio, causes the entire batch to be rejected, so callers need to correct and resubmit the whole list.
- Phase 1 is file-driven and internal. Until the ERP is available, cost codes arrive as a file from Finance. The Integration Hub converts this file to JSON and calls the API internally. The response format is tailored for the Integration Hub and will change when Sapio becomes the consumer in Phase 2.