> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withflex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Product Creation Walkthrough

## Overview

This guide provides technical documentation for creating products and handling product webhooks with the Flex API. Products are the foundation of Flex's payment processing system, and Flex automatically determines HSA/FSA eligibility based on the product information you provide.

***

## Getting Started

### Test Mode vs Production Mode

Flex provides separate test and production environments to allow safe development and testing without affecting real customer data or payments.

### API Keys

API keys have different prefixes depending on the environment:

* **Test Mode**: `fsk_test_...` - Use for development and testing
* **Production Mode**: `fsk_...` - Use for real customer transactions

You can obtain both types of keys from your partner dashboard at [https://dashboard.withflex.com/apikeys](https://dashboard.withflex.com/apikeys).

### Test Mode Behavior

When using test mode API keys:

* **No real charges**: All payment processing is simulated
* **Simplified flows**: Some complex verification steps may be bypassed. No emails are sent in test mode.
* **Test data isolation**: Test mode data is completely separate from production data
* **Eligibility determination**: May use simplified logic or mock responses

### test\_mode Field

All API responses include a `test_mode` boolean field indicating the environment:

```json theme={null}
{
  "product": {
    "product_id": "fprod_...",
    "name": "Test Product",
    "test_mode": false,
    ...
  }
}
```

* `test_mode: true` - Resource created/retrieved in test environment
* `test_mode: false` - Resource created/retrieved in production environment

**Important**: Never mix test and production API keys. Resources created in one environment cannot be accessed or modified from the other environment.

### API Response Schemas

API responses in Flex are designed for forward compatibility to ensure your integrations remain stable as we add new features.

**Key Principles**:

* **Additional Fields**: API responses may include additional fields beyond what's documented in examples
* **Permissive Parsing**: Always parse responses permissively - do NOT validate that responses match exact documented schemas
* **Backwards Compatibility**: Flex guarantees that documented fields will NEVER be removed without advance deprecation notice
* **Future-Proof**: New fields may be added at any time to support new features without requiring changes to your integration

**Best Practices**:

* Extract only the fields your application needs from responses
* Ignore unknown or undocumented fields in responses
* Do not implement strict schema validation that rejects responses with extra fields
* Design your API client to be resilient to new fields

***

## Creating Products

### Overview

Products are the foundation of Flex's payment processing system. Each product represents an item or service you offer to customers. Flex automatically determines HSA/FSA eligibility for products based on the information you provide, eliminating the need for manual eligibility classification.

**When to create products**:

We recommend creating products in Flex when they are created in your existing systems, such as:

* **Product Management Systems**: When new products are added to your inventory management or PIM (Product Information Management) system
* **E-commerce Platforms**: When products are created in your e-commerce backend
* **CRM or ERP Systems**: When product records are established in your enterprise resource planning system

This approach ensures your Flex product catalog stays in sync with your source of truth, and eligibility determination happens as products are introduced to your system.

### Required Fields

All four fields below are required for enterprise integrations to enable Flex's eligibility determination pipeline:

| Field         | Type   | Description                                                                                                               |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- |
| `name`        | String | Product name displayed to customers                                                                                       |
| `description` | String | Product description used by Flex's eligibility pipeline                                                                   |
| `upc_code`    | String | Universal Product Code (UPC) or Global Trade Item Number (GTIN) for eligibility lookup against eligible product databases |
| `url`         | String | Publicly accessible product image URL for display and verification                                                        |

### Optional Fields

| Field      | Type   | Description                                                   |
| ---------- | ------ | ------------------------------------------------------------- |
| `metadata` | Object | Custom key-value pairs for storing additional structured data |

### Validation Rules

* All four required fields must be provided
* Product names are sanitized (null bytes removed automatically)
* URLs must be valid and publicly accessible
* UPC codes should follow standard format (12 digits)

### API Request Example

```bash theme={null}
curl --request POST \
  --url https://api.withflex.com/v1/products \
  --header 'authorization: Bearer fsk_test_your_api_key_here' \
  --header 'content-type: application/json' \
  --data '{
    "product": {
      "name": "Compression Socks - Medium",
      "description": "Graduated compression socks for improved circulation and reduced leg fatigue",
      "upc_code": "012345678905",
      "url": "https://example.com/images/compression-socks.jpg"
    }
  }'
```

### API Response Example

```json theme={null}
{
  "product": {
    "product_id": "fprod_01HW5MXAPBE79RHMMJJGB4ACAB",
    "name": "Compression Socks - Medium",
    "description": "Graduated compression socks for improved circulation and reduced leg fatigue",
    "upc_code": "012345678905",
    "url": "https://example.com/images/compression-socks.jpg",
    "hsa_fsa_eligibility": "auto_substantiation",
    "active": true,
    "created_at": "2024-04-23T14:14:16.029253Z",
    "visit_type": "notApplicable",
    "test_mode": false,
    "metadata": null
  }
}
```

**Important**: The `hsa_fsa_eligibility` field in the response is automatically determined by Flex's eligibility pipeline. You don't need to specify this field when creating products.

**Note**: The response may include additional fields not shown above. Always check the API response for the complete set of fields.

***

## HSA/FSA Eligibility Determination

Flex automatically determines HSA/FSA eligibility for all products using an intelligent multi-stage pipeline.

### How Eligibility is Determined

Flex's pipeline analyzes three key data points:

1. **Product Name & Description**: Natural language processing to understand product category and medical relevance
2. **UPC Code Lookup**: Cross-reference against eligible product databases and medical product classification systems
3. **Product Metadata**: Additional product information to refine classification

### Eligibility Types

| Type                          | Description                                                                                            |
| ----------------------------- | ------------------------------------------------------------------------------------------------------ |
| `auto_substantiation`         | Product is automatically eligible (found in eligible product databases or verified as medical product) |
| `letter_of_medical_necessity` | Product may be eligible with a letter from a medical professional                                      |
| `prescription`                | Prescription-required items                                                                            |
| `vision`                      | Vision correction products                                                                             |
| `not_eligible`                | Product is not HSA/FSA eligible                                                                        |

### Synchronous vs Asynchronous Determination

**Synchronous Determination**:

* Occurs for products with UPC codes already in Flex's database
* Eligibility is determined immediately and returned in the product creation response
* Check the `hsa_fsa_eligibility` field in the response to see the result

**Asynchronous Determination**:

* Occurs for products requiring additional analysis or UPC lookup
* Initial response may have `hsa_fsa_eligibility` as `null` or a provisional value
* A `product.updated` webhook is sent when final eligibility is determined
* **Always listen to the `product.updated` webhook to capture final eligibility**

### Key Points

* **No manual specification required**: Eligibility is determined automatically based on product data
* **Dynamic updates**: Eligibility can change over time as Flex's database and algorithms are updated
* **Query anytime**: Use `GET /v1/products/{product_id}` to retrieve current eligibility at any time

***

## Webhooks

Webhook events allow you to receive real-time notifications when products are created or updated.

### product.created

Triggered immediately when a new product is created via the API.

**Use cases**:

* Sync product creation to your internal systems
* Trigger downstream workflows
* Audit trail logging

### product.updated

Triggered when product information changes, including:

* **Asynchronous eligibility determination completes**
* Eligibility changes due to Flex database updates
* Manual product updates via dashboard or API

**Use cases**:

* Update eligibility in your product catalog
* Notify customers of eligibility changes
* Trigger re-pricing or availability updates

### Event Payload Structure

Both webhooks deliver a complete product object:

```json theme={null}
{
  "id": "evt_01HW5Q2A08N6A0YGZ6T1KARN8S",
  "type": "product.updated",
  "created_at": "2024-04-23T14:30:05.943282Z",
  "data": {
    "product": {
      "product_id": "fprod_01HW5MXAPBE79RHMMJJGB4ACAB",
      "name": "Compression Socks - Medium",
      "description": "Graduated compression socks for improved circulation and reduced leg fatigue",
      "upc_code": "012345678905",
      "url": "https://example.com/images/compression-socks.jpg",
      "hsa_fsa_eligibility": "auto_substantiation",
      "active": true,
      "created_at": "2024-04-23T14:14:16.029253Z",
      "updated_at": "2024-04-23T14:30:05.943282Z",
      "metadata": null
    }
  }
}
```

### Best Practices

**Critical**:

* **Always listen to `product.updated`**: Eligibility may be determined asynchronously or updated later
* **Check creation response first**: If `hsa_fsa_eligibility` is already set, eligibility was determined synchronously

**Reliability**:

* Implement idempotency using event IDs to prevent duplicate processing
* Respond with `200 OK` immediately, then process asynchronously
* Store event IDs in your database to track processed events
* Implement retry logic for failed webhook processing

**Security**:

* Verify webhook signatures (see Flex webhook documentation for signature verification)
* Use HTTPS endpoints only
* Validate event structure before processing

***

## Error Handling

### Common Errors

| Status Code                | Error Code              | Description                                                           |
| -------------------------- | ----------------------- | --------------------------------------------------------------------- |
| `400 Bad Request`          | `validation_error`      | Missing required fields (`name`, `description`, `upc_code`, or `url`) |
| `400 Bad Request`          | `invalid_format`        | Invalid field format (e.g., malformed URL or invalid UPC code)        |
| `401 Unauthorized`         | `authentication_failed` | Invalid or expired API key                                            |
| `422 Unprocessable Entity` | `validation_error`      | Validation errors (e.g., null bytes in product name)                  |

### Error Response Format

All errors return a JSON body with HTTP status code containing a `detail` array with error objects.

**Structure**:

* `detail`: Array of error objects
* `loc`: Location path to the error (array showing where in the request the error occurred)
* `msg`: Human-readable error message
* `type`: Machine-readable error type identifier

### Example Error Responses

**Missing Required Field**:

```json theme={null}
HTTP/1.1 422 Unprocessable Entity
{
  "detail": [
    {
      "loc": ["body", "product", "description"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

**Invalid URL Format**:

```json theme={null}
HTTP/1.1 422 Unprocessable Entity
{
  "detail": [
    {
      "loc": ["body", "product", "url"],
      "msg": "invalid or missing URL scheme",
      "type": "value_error.url.scheme"
    }
  ]
}
```

**Unauthorized**:

```json theme={null}
HTTP/1.1 401 Unauthorized
{
  "detail": "Unauthorized"
}
```

### Retry Strategies

**Transient Errors (5xx)**:

* Implement exponential backoff: 1s, 2s, 4s, 8s, 16s
* Maximum of 5 retry attempts
* Use jitter to prevent thundering herd

**Client Errors (4xx)**:

* Do not retry automatically
* Fix the request based on error details
* Log error for debugging

**Idempotency**:

* Use idempotency keys for safe retries: `Idempotency-Key: <unique_key>`
* Store idempotency keys with your requests
* Reuse the same key when retrying a failed request

**Rate Limiting**:

* Respect rate limit headers
* Implement request queuing for high-volume scenarios
* Contact Flex support for rate limit increases if needed

***

## Support

For technical support or questions about product creation and webhooks:

* **Documentation**: [https://docs.withflex.com](https://docs.withflex.com)
* **API Reference**: [https://api.withflex.com/docs](https://api.withflex.com/docs)
* **Support Email**: [support@withflex.com](mailto:support@withflex.com)
