Authentication
FlexPortal uses Bearer token authentication. Include your API key in the Authorization header of every request:
curl -X GET "https://api-eu.flexportal.io/v1/orders" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Tenant-ID: YOUR_BUSINESS_UNIT_ID" \
-H "Content-Type: application/json"
API keys are created in the Dashboard under Settings → API Keys . Each key is scoped to your organization with configurable permissions.
Every API request must include these headers:
Header Required Description AuthorizationYes Bearer YOUR_API_KEYTenant-IDYes Your Business Unit ID (found in Dashboard → Settings → General) Content-TypeYes (for POST/PUT/PATCH) application/json
Base URLs
FlexPortal is deployed across multiple regions. Use the base URL closest to your customers:
Region Base URL Europe https://api-eu.flexportal.ioUnited States https://api-us.flexportal.ioQatar https://api-qatar.flexportal.io
Data is region-specific. Orders created in the EU region are not visible from US endpoints. Choose your region during onboarding and use it consistently.
Rate Limits
Tier Requests per minute Starter 100 Growth Unlimited* Enterprise Unlimited*
*Fair use policy with abuse protection. Sustained high-volume usage may trigger temporary throttling.
When rate limited, you’ll receive a 429 Too Many Requests response with a Retry-After header indicating when to retry.
List endpoints use cursor-based pagination for reliable, consistent results even when data changes between requests.
Request Parameters
Parameter Type Default Description limitinteger 50 Items per page (max: 100) startAfterstring — Cursor from previous response to get next page sortBystring createdAtField to sort by (varies per endpoint) sortDirstring descSort direction: asc or desc
Response Structure
{
"orders" : [ ... ],
"count" : 50 ,
"limit" : 50 ,
"hasMore" : true ,
"nextCursor" : "ord_abc123xyz"
}
Iterating Through Pages
let cursor = null ;
let allOrders = [];
do {
const params = new URLSearchParams ({ limit: '100' });
if ( cursor ) params . set ( 'startAfter' , cursor );
const response = await fetch (
`https://api-eu.flexportal.io/v1/orders? ${ params } ` ,
{ headers: { 'Authorization' : 'Bearer YOUR_API_KEY' , 'Tenant-ID' : 'YOUR_TENANT' } }
);
const data = await response . json ();
allOrders . push ( ... data . orders );
cursor = data . nextCursor ;
} while ( cursor );
Use nextCursor value as startAfter for the next request. When hasMore is false or nextCursor is null, you’ve reached the end.
All request bodies must be valid JSON:
Content-Type: application/json
Success Responses
All successful responses include relevant data and metadata:
{
"success" : true ,
"message" : "Order created successfully" ,
"orderId" : "ord_abc123" ,
"order" : { ... }
}
For list endpoints:
{
"orders" : [ ... ],
"count" : 25 ,
"limit" : 50 ,
"hasMore" : false ,
"nextCursor" : null
}
Error Responses
Errors follow a consistent structure with machine-readable codes and human-friendly messages:
{
"error" : {
"code" : "VALIDATION_ERROR" ,
"message" : "Invalid request body" ,
"details" : [
{
"path" : "customer.email" ,
"message" : "Invalid email format" ,
"code" : "invalid_string"
}
]
}
}
HTTP Status Codes
Code Name Description 200OK Request succeeded 201Created Resource created successfully 400Bad Request Invalid request syntax or parameters 401Unauthorized Missing or invalid API key 403Forbidden Valid API key but insufficient permissions 404Not Found Resource doesn’t exist 409Conflict Resource conflict (e.g., duplicate serial number) 422Unprocessable Validation failed 429Too Many Requests Rate limit exceeded 500Internal Error Server error (contact support)
Error Codes Reference
Common error codes you may encounter:
Code HTTP Status Description Resolution AUTH_REQUIRED401 Missing Authorization header Add Authorization: Bearer YOUR_API_KEY header INVALID_TOKEN401 API key is invalid or expired Generate a new API key in Dashboard NO_TENANT_ACCESS403 Missing or invalid Tenant-ID header Add valid Tenant-ID header INSUFFICIENT_PERMISSIONS403 API key lacks required permissions Update API key permissions in Dashboard NOT_FOUND404 Resource doesn’t exist Verify the ID and tenant context VALIDATION_ERROR400 Request body failed validation Check details array for specific field errors ASSET_EXISTS409 Asset with serial number already exists Use a unique serial number or update existing VARIANT_IN_USE409 Cannot deactivate variant with active orders Complete or cancel orders using this variant first ORDER_NOT_CANCELLABLE400 Order status doesn’t allow cancellation Only pending/confirmed orders can be cancelled
Core Resources
FlexPortal’s API is organized around these key resources:
Resource Description Products Items in your catalog available for subscription, with variants for different configurations Customers End users who subscribe to products (individuals or businesses) Orders Subscription checkout transactions containing items, addresses, and payment info Subscriptions Active subscription contracts tracking billing, payments, and lifecycle events Assets Individual physical units tracked by serial number Payments Scheduled and completed billing transactions Billing Groups B2B feature for consolidating multiple subscriptions into single invoices Files Documents like contracts, invoices, and uploaded files
Products Create and manage your product catalog with variants and pricing
Orders Process subscription orders and track fulfillment
Subscriptions Manage active subscriptions, extensions, upgrades, and buyouts
Payments Track and manage scheduled billing payments
Filtering
Most list endpoints support filtering by key fields. Pass filter values as query parameters:
# Get all pending orders for a specific customer
GET /v1/orders?status=pending & customerId = cust_abc123
# Get all active subscriptions
GET /v1/subscriptions?status=active
# Get available assets of a specific SKU
GET /v1/assets?status=available & sku = LAPTOP-PRO-16
Custom Field Filtering (Orders)
If you’ve configured custom fields, filter by them using the customField_ prefix:
GET /v1/orders?customField_siebelId= 12345
GET /v1/orders?customField_vendorCode=ABC
Idempotency
For operations that create resources, FlexPortal uses natural idempotency keys:
Orders : Customer email + items combination within a short window
Assets : Serial number (unique per tenant)
Payments : Billing period + subscription ID
If you need to retry a failed request, it’s safe to do so. Duplicate create requests will return the existing resource rather than creating duplicates.
Webhooks
FlexPortal can send real-time notifications for key events. Configure webhook endpoints in the Dashboard under Settings → Webhooks .
Available Events
Event Description order.createdNew order submitted order.fulfilledAll items in order have active subscriptions subscription.createdNew subscription activated subscription.extendedSubscription period extended subscription.upgradedCustomer upgraded to different product subscription.endedSubscription completed or cancelled payment.scheduledNew payment scheduled payment.succeededPayment collected successfully payment.failedPayment attempt failed asset.assignedAsset linked to subscription asset.returnedAsset returned from subscription
Webhook Payload
{
"event" : "subscription.created" ,
"timestamp" : "2025-01-15T10:30:00Z" ,
"data" : {
"subscriptionId" : "sub_abc123" ,
"customerId" : "cust_xyz789" ,
"orderId" : "ord_def456" ,
...
}
}
SDKs & Libraries
Official SDKs are coming soon. In the meantime, you can use any HTTP client to interact with the API. See our Quickstart Guide for examples in various languages.
Need Help?