List products
curl --request GET \
--url https://api-eu.flexportal.io/v1/products \
--header 'Authorization: Bearer <token>' \
--header 'Tenant-ID: <tenant-id>'import requests
url = "https://api-eu.flexportal.io/v1/products"
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Tenant-ID': '<tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api-eu.flexportal.io/v1/products', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-eu.flexportal.io/v1/products",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Tenant-ID: <tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/products"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-eu.flexportal.io/v1/products")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"products": [
{
"productId": "<string>",
"tenantId": "<string>",
"productSku": "<string>",
"name": "<string>",
"specification": "<string>",
"category": "<string>",
"brand": "<string>",
"status": "active",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"images": [
"<string>"
],
"_sync": {
"source": "manual",
"externalId": "<string>",
"lastSyncedAt": "<string>",
"syncStatus": "synced",
"syncError": "<string>",
"readOnlyFields": [
"<string>"
]
},
"variants": [
{
"variantId": "<string>",
"tenantId": "<string>",
"productId": "<string>",
"productSku": "<string>",
"variantSku": "<string>",
"variantName": "<string>",
"grade": "<string>",
"pricing": [
{
"contractLength": 123,
"monthlyPrice": 123,
"setupFee": 123,
"discount": {
"type": "percentage",
"value": 123,
"description": "<string>"
},
"source": "suggested",
"calculatedAt": "<string>",
"presetUsed": "<string>"
}
],
"status": "active",
"createdAt": "<string>",
"updatedAt": "<string>",
"condition": "<string>",
"colorName": "<string>",
"images": [
"<string>"
],
"listPrice": 123,
"acquisitionCost": 123
}
]
}
],
"count": 123,
"limit": 123,
"hasMore": true,
"nextCursor": "<string>"
}Products
List Products
Returns a paginated list of products in your catalog.
GET
/
v1
/
products
List products
curl --request GET \
--url https://api-eu.flexportal.io/v1/products \
--header 'Authorization: Bearer <token>' \
--header 'Tenant-ID: <tenant-id>'import requests
url = "https://api-eu.flexportal.io/v1/products"
headers = {
"Tenant-ID": "<tenant-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'Tenant-ID': '<tenant-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api-eu.flexportal.io/v1/products', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-eu.flexportal.io/v1/products",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Tenant-ID: <tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api-eu.flexportal.io/v1/products"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Tenant-ID", "<tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-eu.flexportal.io/v1/products")
.header("Tenant-ID", "<tenant-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-eu.flexportal.io/v1/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Tenant-ID"] = '<tenant-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"products": [
{
"productId": "<string>",
"tenantId": "<string>",
"productSku": "<string>",
"name": "<string>",
"specification": "<string>",
"category": "<string>",
"brand": "<string>",
"status": "active",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"images": [
"<string>"
],
"_sync": {
"source": "manual",
"externalId": "<string>",
"lastSyncedAt": "<string>",
"syncStatus": "synced",
"syncError": "<string>",
"readOnlyFields": [
"<string>"
]
},
"variants": [
{
"variantId": "<string>",
"tenantId": "<string>",
"productId": "<string>",
"productSku": "<string>",
"variantSku": "<string>",
"variantName": "<string>",
"grade": "<string>",
"pricing": [
{
"contractLength": 123,
"monthlyPrice": 123,
"setupFee": 123,
"discount": {
"type": "percentage",
"value": 123,
"description": "<string>"
},
"source": "suggested",
"calculatedAt": "<string>",
"presetUsed": "<string>"
}
],
"status": "active",
"createdAt": "<string>",
"updatedAt": "<string>",
"condition": "<string>",
"colorName": "<string>",
"images": [
"<string>"
],
"listPrice": 123,
"acquisitionCost": 123
}
]
}
],
"count": 123,
"limit": 123,
"hasMore": true,
"nextCursor": "<string>"
}Overview
Retrieve a paginated list of products in your catalog. Products are the parent items that contain variants—each variant represents a specific configuration (e.g., color, storage size, grade) with its own SKU and pricing.Product vs Variant
Understanding the product hierarchy is key:| Concept | Example | Purpose |
|---|---|---|
| Product | MacBook Pro 16” | The base product/model |
| Variant | MacBook Pro 16” M3 Max, 64GB, Space Black | Specific configuration with SKU and pricing |
Common Use Cases
Product Catalog
Display your product catalog in e-commerce or customer-facing applications
Inventory Check
Verify products exist before creating orders or importing inventory
Admin Dashboard
Build product management interfaces for your operations team
Sync Systems
Keep product data synchronized with external systems
Filtering Products
# Get all active products
GET /v1/products?status=active
# Get products by category
GET /v1/products?category=laptops
# Get products by brand
GET /v1/products?brand=Apple
# Combine filters
GET /v1/products?status=active&category=laptops&brand=Apple
Response Fields
Key fields in each product object:| Field | Description |
|---|---|
productId | Unique product identifier |
productSku | Product-level SKU (parent SKU) |
name | Product display name |
category | Product category |
brand | Product brand/manufacturer |
status | active or discontinued |
variantCount | Number of variants for this product |
createdAt | ISO 8601 timestamp |
Product list responses include variant counts but not full variant details. Use Get Product to retrieve a product with all its variants, or List Variants to query variants directly.
Pagination
Results are paginated using cursor-based pagination. See Pagination for details.// Fetch all products
const allProducts = [];
let cursor = null;
do {
const params = new URLSearchParams({ limit: '100' });
if (cursor) params.set('startAfter', cursor);
const { products, nextCursor } = await fetchProducts(params);
allProducts.push(...products);
cursor = nextCursor;
} while (cursor);
Related Endpoints
- Get Product - Get product with all variants
- List Variants - Query variants directly
- Create Product - Add new products to catalog
- Import CSV - Bulk import products
Authorizations
API key obtained from FlexPortal dashboard
Headers
Your tenant identifier
Query Parameters
Items per page (default: 50, max: 100)
Cursor for pagination
Filter by status (active, discontinued)
Filter by category
Filter by brand
Was this page helpful?