Skip to content

High-Level Architecture

The architecture consists of three main components: * the Experience API, * the Process API, * and the System API.

Each component has its own responsibilities and interacts with the other components to fulfill user/client requests, following the Integration Hub's XAPI → PAPI → SAPI pattern. Each layer is implemented as a separate AWS Lambda function, built on an internal framework called ipaas-framework.

A single request from Sapio passes synchronously down through all three layers and back, as illustrated in the diagram below.

  • XAPI (inthub-xapi-sapio-studies) – the entry point Sapio calls.
  • PAPI (inthub-papi-mlwh-studies) – a routing/orchestration layer with no business logic of its own.
  • SAPI (inthub-sapi-sequencescape) – a thin adapter that talks to the real Sequencescape application over HTTPS.

Supported Operations

The architecture below is shared by every operation * only the validation rules and downstream target change per operation.

Method Path Status
GET /sapio/studies/v1 Implemented, in UAT
POST /sapio/studies/v1 Implementation in progress
PATCH /sapio/studies/v1 Not Started

Architecture Diagram

flowchart TD

    A[Client/ Sapio]

    subgraph XAPI["Experience API"]
        direction TD
        X1[Validate<br/>Request]
        X2[Authenticate<br/>& Authorise]
        X3[Normalise<br/>Parameters]
        X4[Route to<br/>Process API]
    end

    subgraph PAPI["Process API"]
        direction TD
        P1[Build<br/>SQL Query]
        P2[Apply<br/>Pagination]
        P3[Transform<br/>Request Model]
        P4[Route to<br/>System API]
    end

    subgraph SAPI_SS["System API: SequenceScape"]
        direction TD
        SS1[Build HTTPS<br/>Request to<br/>SequenceScape API]
        SS2[Execute<br/>Query]
        SS3[Return<br/>JSON<br/>Response]
    end

    subgraph SAPI_MLWH["System API: MLWH"]
        direction TD
        SM1[Execute<br/>Query]
        SM2[Map Database<br/>Rows]
        SM3[Return<br/>JSON<br/>Response]
    end

    DB[(MLWH<br/>Database)]

    A --> XAPI
    XAPI --> PAPI
    PAPI --> SAPI_MLWH
    PAPI --> SAPI_SS
    SAPI_MLWH --> DB
  • Each layer is responsible for validating, transforming, and routing the request to the next layer, until it reaches the Sequencescape or MLWH application.
  • Every hop is a direct, blocking Lambda invocation (RequestResponse), so the response flows back up through the same three layers in reverse.

Components

XAPI — inthub-xapi-sapio-studies

  • Purpose: exposes the public-facing surface Sapio calls: GET /sapio/studies/v1 (lookup by name) and POST /sapio/studies/v1 (create a study record). -POST and PATCH endpoints are not yet validated in UAT, so this documentation focuses on the GET endpoint.-
  • Responsibilities: validates the inbound request shape, invokes PAPI, and reshapes PAPI's response (JMESPath transform) into the shape Sapio expects.
  • Dependencies: the PAPI Lambda, which is the only downstream target for this route.

PAPI — inthub-papi-mlwh-studies

  • Purpose: a routing layer — it contains no domain logic, only maps an inbound route to the correct downstream SAPI Lambda.
  • Responsibilities: for the Sapio-facing route (/sapio/studies/v1), forwards directly to the SAPI/Sequencescape adapter.
  • Dependencies: the SAPI/Sequencescape and SAPI/MLWH Lambdas, which are the downstream targets for this route.

SAPI — inthub-sapi-sequencescape

  • Purpose: adapter between PAPI and the real Sequencescape Rails application — not Sequencescape itself.
  • Responsibilities: builds an authenticated HTTPS request to Sequencescape's /api/v2/sapio/studies JSON:API endpoint, and normalises both success and error responses back into a consistent shape for PAPI.
  • Dependencies: the Sequencescape application, which is the downstream target for this route.

Data Flow

Every operation shares the same shape: a single blocking round trip down through XAPI → PAPI → SAPI and back, with no retry or fallback path today. * A failure or timeout at any layer surfaces as an error at every layer above it. What differs per operation is the validation applied and the downstream target. Each operation gets its own breakdown below.

GET — look up a study by name

  1. Sapio sends GET /sapio/studies/v1?name=... to the shared API Gateway.
  2. The custom Lambda authorizer validates the caller before the request reaches XAPI.
  3. XAPI validates the name query parameter, then synchronously invokes PAPI with the request.
  4. PAPI routes the request to the SAPI (Sequencescape) Lambda.
  5. SAPI calls Sequencescape's /api/v2/sapio/studies over HTTPS, authenticating with a secret-stored client-ID header and CA certificate.
  6. Sequencescape's response travels back up unchanged in shape until SAPI normalises it, then PAPI and XAPI each pass it back untouched to the caller.

POST — create a study record

-Implementation is in progress, but the flow will be similar to the GET operation above, except that the request body will be validated and transformed before being sent to Sequencescape, and the response will be normalised back into a shape Sapio expects.-

PATCH — update a study record

-Implementation is in progress, but the flow will be similar to the GET operation above.-

External Dependencies

  • Sequencescape – the system of record for study data, called by SAPI over HTTPS.
  • Shared API Gateway + custom Lambda authorizer – owned by another Integration Hub component; provides the only application-level authentication in the whole chain.
  • ipaas-framework – the internal Integration Hub framework all three Lambdas are built on.
  • AWS Secrets Manager – holds the Sequencescape client-ID and CA certificate used by SAPI.
  • AWS SSM Parameter Store – resolves shared infra values (VPC networking, authorizer ID, Lambda layer ARN) at deploy time.