Skip to main content

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.

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:
{
  "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:
FieldTypeDescription
nameStringProduct name displayed to customers
descriptionStringProduct description used by Flex’s eligibility pipeline
upc_codeStringUniversal Product Code (UPC) or Global Trade Item Number (GTIN) for eligibility lookup against eligible product databases
urlStringPublicly accessible product image URL for display and verification

Optional Fields

FieldTypeDescription
metadataObjectCustom 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

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

{
  "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

TypeDescription
auto_substantiationProduct is automatically eligible (found in eligible product databases or verified as medical product)
letter_of_medical_necessityProduct may be eligible with a letter from a medical professional
prescriptionPrescription-required items
visionVision correction products
not_eligibleProduct 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:
{
  "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 CodeError CodeDescription
400 Bad Requestvalidation_errorMissing required fields (name, description, upc_code, or url)
400 Bad Requestinvalid_formatInvalid field format (e.g., malformed URL or invalid UPC code)
401 Unauthorizedauthentication_failedInvalid or expired API key
422 Unprocessable Entityvalidation_errorValidation 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:
HTTP/1.1 422 Unprocessable Entity
{
  "detail": [
    {
      "loc": ["body", "product", "description"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
Invalid URL Format:
HTTP/1.1 422 Unprocessable Entity
{
  "detail": [
    {
      "loc": ["body", "product", "url"],
      "msg": "invalid or missing URL scheme",
      "type": "value_error.url.scheme"
    }
  ]
}
Unauthorized:
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: