Skip to main content

Product Implementation

The APEX Platform provides a standardized product flow that helps you surface your products to users. This guide explains how to implement the necessary components for successful integration.

Product Flow

When a tenant initiates a new product flow, the system goes through several steps to display content to the user:

  1. Initiation - The tenant initiates the start request to the platform, which is used by all tenants to surface products.

  2. Legal - The platform retrieves data from the product catalog for the specified product and checks for any legal requirements before proceeding.

  3. Start - The platform communicates with your product by calling the Start endpoint based on your product's configured base URL.

  4. Verify Inputs - If your Start endpoint indicates that user inputs are required, the platform displays your web component to collect data from the user, then sends this data to your Verify Inputs endpoint.

  5. Quoting - The platform generates a quote for the product. If the user has the appropriate contract permissions, the flow continues; otherwise, the quote displays for user input.

  6. Payment - After quote acceptance, the platform collects funds from the user through the specified payment method (debit order or credit card).

  7. Process - Once the previous steps complete successfully, the platform calls your Process endpoint to surface the final purchased product as a web component.

Product API Implementation

Your product needs to implement specific endpoints to be compatible with the platform. The APEX Platform library provides predefined response types to help you get your product running quickly.

Important Notes
  • All endpoints use POST method - Each endpoint receives a body payload and uses POST requests
  • Authentication required - All endpoints require proper authentication headers (x-ls-partyid and x-authenticated-tenantid)
  • Typed responses - Endpoints return specific domain objects, not generic JSON payloads

Start Endpoint

The Start endpoint initializes your product. The platform expects one of two responses:

  • ShowUIStartResponse - When user input is required
  • ContinueStartResponse - When no user input is needed

Response Type Definitions:

ShowUIStartResponse - Used when user input is required:

{
"elementName": "string", // Required: Name of the custom web component
"elementUrl": "string", // Required: URL where the component is hosted
"attributes": { // Optional: Key-value pairs set as HTML attributes
"key1": "value1",
"key2": "value2"
},
"body": "string" // Optional: JSON string passed to the component
}

ContinueStartResponse - Used when no user input is needed:

{
"productDescription": "string" // Required: Description of the product
}

Examples

When no user input is required:

public async override Task<ActionResult<StartResponse>> Start([FromBody] ProductFlowInstanceStartModel input)
{
return new ContinueStartResponse
{
ProductDescription = "PRODUCT NAME"
};
}

When user input is required:

public async override Task<ActionResult<StartResponse>> Start([FromBody] ProductFlowInstanceStartModel input)
{
return new ShowUIStartResponse
{
ElementName = INPUT_ELEMENT_NAME,
ElementUrl = INPUT_ELEMENT_URL
};
}

Validate Inputs Endpoint

When a user completes inputs from a ShowUIStartResponse, the inputs are posted to the Validate Inputs endpoint. You should validate the inputs and return an appropriate response. If validation fails, the platform will redisplay the inputs screen.

Example

public async override Task<ActionResult<ValidateInputResponse>> ValidateInputs([FromBody] ProductFlowInstanceInput<HelloWorldInput> input)
{
return new ValidateInputResponse()
{
Succesful = true
};
}

Process Endpoint

After successfully completing all previous steps, the platform calls the Process endpoint on your product API. This endpoint must return either a ContinueProcessResponse or a ShowUIProcessResponse based on the data received.

Examples

Simple continuation response:

public async override Task<ActionResult<ProcessResponse>> Process([FromBody] ProductFlowInstanceProcessModel<HelloWorldInput> input)
{
return new ContinueProcessResponse();
}

Response with UI component:

public async override Task<ActionResult<ProcessResponse>> Process([FromBody] ProductFlowInstanceProcessModel<HelloWorldInput> input)
{
return new ShowUIProcessResponse
{
Attributes = { { "name", input.Input.Data.Name } },
ElementName = FINAL_ELEMENT_NAME,
ElementUrl = FINAL_ELEMENT_URL,
Body = ""
};
}

Handle Error Endpoint

When an error occurs during the product flow process, the platform calls your product's HandleError endpoint. You can choose to display a custom error UI or use the platform's default error message.

Examples

Using platform's default error message:

public async override Task<ActionResult<HandleErrorResponse>> HandleError([FromBody] ProductFlowInstanceHandleErrorModel errorInput)
{
return new ContinueHandleErrorResponse();
}

Displaying custom error UI:

public async override Task<ActionResult<HandleErrorResponse>> HandleError([FromBody] ProductFlowInstanceHandleErrorModel errorInput)
{
return new ShowUIHandleErrorResponse
{
ElementName = ERROR_ELEMENT_NAME,
ElementUrl = ERROR_ELEMENT_URL,
Attributes = { { "error-status", errorInput.ProductFlowInstanceStatus }},
Body = ""
};
}

Attributes and Body Properties

When using ShowUI responses, you can customize the component rendering with:

  • Body - A JSON string containing data to pass to your custom web component
  • Attributes - Key-value pairs set as attributes for your custom web component

Usage in Product Lifecycle:

  • Attributes: Set as HTML attributes on your web component (e.g., <custom-component custom-attr="value">)
  • Body: Passed as complex data objects to your component's internal logic
  • Both properties work together to provide data and configuration to your micro front-end components

Example

return new ShowUIProcessResponse
{
Attributes = { { "custom-attr", "value" } },
ElementName = "custom-component"
};

This generates HTML like:

<custom-component custom-attr="value"></custom-component>

Micro Front Ends

Your product also needs to include Micro Front Ends as custom web components. The platform renders these components on the tenant side based on responses from your product API.

Inputs Micro Front End

The inputs micro front end collects additional information from users. It can consist of multiple pages and have its own web services to improve user experience.

The micro front end properties are populated by the API using the attributes property. The body of the custom web component can also pass complex data objects as a JSON string.

When input collection is complete, the component must raise a custom event to notify the product flow:

let inputComplete = new CustomEvent('capability-input-complete', {
detail: {
data: {}
},
bubbles: true,
composed: true
});

this.dispatchEvent(inputComplete);

Product Micro Front End

The final step in the product flow calls the Process endpoint of your API and passes any collected input data.

Your API can then set various attributes and complex data as the body of your custom web component, allowing you to render the final product to the client.

For a sample implementation using LitElement, refer to the samples project.

Domain Objects and Dependencies

C# Dependencies

C# implementations can use NuGet packages that provide the required domain objects and response types. These packages include all the necessary models like ProductFlowInstanceStartModel, ShowUIStartResponse, ContinueStartResponse, etc.

Java and Python Dependencies

For Java and Python implementations, the required domain objects are defined inline in the code examples above. You can use these as templates to create your own domain classes:

Key Domain Objects:

Input Models:

  • ProductFlowInstanceStartModel - Input model for Start endpoint
  • ProductFlowInstanceInput<T> - Input model for ValidateInputs endpoint
  • ProductFlowInstanceProcessModel<T> - Input model for Process endpoint
  • ProductFlowInstanceHandleErrorModel - Input model for HandleError endpoint

Response Models with JSON Schemas:

Start Endpoint Responses:

// ShowUIStartResponse
{
"elementName": "string",
"elementUrl": "string",
"attributes": { "key": "value" }, // Optional
"body": "string" // Optional
}

// ContinueStartResponse
{
"productDescription": "string"
}

ValidateInputs Endpoint Response:

// ValidateInputResponse
{
"successful": boolean,
"errorMessage": "string" // Optional, used when successful=false
}

Process Endpoint Responses:

// ShowUIProcessResponse
{
"elementName": "string",
"elementUrl": "string",
"attributes": { "key": "value" }, // Optional
"body": "string" // Optional
}

// ContinueProcessResponse
{
// Empty response indicating successful completion
}

HandleError Endpoint Responses:

// ShowUIHandleErrorResponse
{
"elementName": "string",
"elementUrl": "string",
"attributes": { "key": "value" }, // Optional
"body": "string" // Optional
}

// ContinueHandleErrorResponse
{
// Empty response using platform's default error handling
}

Refer to the code examples in each section for the complete class definitions and usage patterns.

Testing and Development

Local Testing

You can test your product implementation locally by:

  1. Sandbox Environment: Use APEX's sandbox environment for integration testing
  2. Mock Data: Create mock ProductFlowInstanceStartModel objects to test your endpoints
  3. Unit Testing: Test each endpoint individually with sample payloads
  4. Integration Testing: Test the complete flow using the sandbox environment

Simulating Product Workflow

To simulate a complete product workflow:

  1. Start with a mock Start request to your endpoint
  2. If your endpoint returns ShowUIStartResponse, simulate user input collection
  3. Test the ValidateInputs endpoint with the collected data
  4. Finally, test the Process endpoint to verify product delivery
  5. Test error scenarios using the HandleError endpoint
Development Best Practices
  • Store the productFlowInstanceId to maintain state across requests
  • Implement proper error handling and logging
  • Test thoroughly in sandbox before production deployment
  • Use the provided code samples as starting templates

Authentication and Billing

Product Flow Authentication

Product Flow endpoints require authentication headers for API calls:

  • x-ls-partyid - The party identifier
  • x-authenticated-tenantid - The authenticated tenant identifier

API Gateway and Product Flow Integration

The API Gateway and Product Flow work together in the following way:

  • API Gateway: Provides authentication, rate limiting, and automatically starts a "user not present" product flow to log transactions for billing and usage tracking
  • Product Flow: Can operate in two modes:
    • User Present: Interactive flows with user input and UI components (standard product delivery)
    • User Not Present: Background flows for transaction logging (triggered by API Gateway calls)

Billing Integration

  • Interactive Product Flows: Handle billing through the standardized workflow during the "Payment" step where users complete payment via the UI
  • API Gateway Transactions: Automatically create "user not present" product flows for transaction logging and billing purposes
  • This ensures all API usage is properly tracked and billed regardless of whether it's an interactive product flow or a direct API call