AicoNeo API Documentation¶
High-performance optimized API endpoints for products, customers, orders, and documents.
Base URL: /api
Authentication: All endpoints require auth:sanctum
Localization: Set Accept-Language header for translated content
🚀 Import into Postman¶
You can import all AicoNeo APIs into Postman using our OpenAPI specification file.
Option 1: Import from File¶
- Download the OpenAPI spec:
openapi-aiconeo.yaml - Open Postman
- Click Import (top-left corner)
- Drag and drop the file or click Upload Files
- Click Import
Option 2: Import via URL (if hosted)¶
- Open Postman
- Click Import → Link
- Paste the URL to the OpenAPI spec file
- Click Continue → Import
After Import¶
- Set the
{{baseUrl}}variable to your AICO instance URL (e.g.,https://app.aico.swiss/12345/api) - Set the
{{bearerToken}}variable with your Sanctum API token - All endpoints will be organized by tags (Products, Orders, Tasks, etc.)
Features Included¶
✅ All endpoints with full path and method
✅ Query parameters with descriptions and examples
✅ Request body schemas with examples
✅ Response schemas
✅ Filter operators documentation
✅ Authentication configuration
Table of Contents¶
- AicoNeo Optimized Endpoints
- Products List
- Product Detail
- Product Create
- Product Update (Collaborative Editing)
- Product Focus (Optional)
- Product Presence Channel
- Data Types & Update Scopes
- Product Prices
- Product Stocks
- Product Stock Changes
- Articles
- Categories
- Product Types
- Product Units
- Product Statuses
- Collections
- B2B Customers
- B2B Detail
- B2B Create
- B2B Update (Collaborative Editing)
- B2C Customers
- B2C Create
- B2C Update (Collaborative Editing)
- Orders
- Order Documents
- Ecommerce Orders
- Tasks
- Task Detail
- Task Logs
- Task Comments
- Warehouses
- Time Tracking
- Shopify Shops
- List Shopify Shops
- Trigger Bulk Shopify Sync
- Languages
- Languages List
- Language Detail
- Filter Operators Reference
AicoNeo Optimized Endpoints¶
High-performance endpoints using direct SQL queries for optimal speed.
Products List¶
Endpoint: GET /api/aiconeo/products
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -id |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
brand |
Brand with translated name | ✓ |
category |
Category with translated name | ✓ |
tags |
Product tags | ✓ |
crmTags |
CRM tags | ✓ |
shopifyShops |
Shopify shop connections | ✓ |
productPrices |
Product prices with currencies | ✗ |
variants |
Product variants | ✗ |
customFields |
Custom fields, currencies, stock | ✗ |
productUnit |
Product unit with translations (name, shortName) | ✗ |
categorySets |
Additional category sets beyond main category hierarchy | ✗ |
sellers |
Associated sellers | ✗ |
suppliers |
B2B suppliers with manufacturer SKU | ✗ |
nutritionalValues |
Nutritional values with translations | ✗ |
Include Response Structures¶
productUnit¶
| Field | Type | Description |
|---|---|---|
id |
integer | Product unit ID |
name |
string | Translated unit name |
shortName |
string | Translated short name |
isDefault |
boolean | Whether this is the default unit |
hasUnitContents |
boolean | Whether the unit has contents |
categorySets¶
[
{
"id": 1,
"category": {
"id": 10,
"name": "Electronics",
"webName": "electronics",
"image": "https://example.com/storage/categories/electronics.jpg"
},
"subCategory": {
"id": 20,
"name": "Phones",
"webName": "phones",
"image": "https://example.com/storage/categories/phones.jpg"
},
"subSubCategory": null
}
]
| Field | Type | Description |
|---|---|---|
id |
integer | Category set ID |
category |
object|null | Main category with id, name, webName, image |
subCategory |
object|null | Subcategory with id, name, webName, image |
subSubCategory |
object|null | Sub-subcategory with id, name, webName, image |
sellers¶
| Field | Type | Description |
|---|---|---|
id |
integer | Seller ID |
name |
string | Seller name |
isActive |
boolean | Whether the seller is active |
suppliers¶
| Field | Type | Description |
|---|---|---|
id |
integer | Supplier (B2B) ID |
name |
string | Supplier company name |
manufacturerSku |
string|null | Manufacturer SKU for this supplier |
isPrimary |
boolean | Whether this is the primary supplier |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Product ID |
sku |
SKU |
barcode |
Barcode |
manufacturerSku |
Manufacturer SKU |
urlHandle |
URL handle/slug |
weightValue |
Weight value |
weightUnit |
Weight unit |
provenance |
Provenance/origin |
hsCode |
HS code |
createdAt |
Creation date |
updatedAt |
Last update date |
name |
Product name (translated) |
webName |
Web name (translated) |
externalName |
External name (translated) |
brandName |
Brand name (translated) |
categoryName |
Category name (translated) |
statusName |
Status name |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[sku] |
SKU |
filter[barcode] |
Barcode |
filter[manufacturerSku] |
Manufacturer SKU |
filter[urlHandle] |
URL handle |
filter[hsCode] |
HS code |
filter[provenance] |
Provenance |
filter[weightUnit] |
Weight unit |
filter[name] |
Product name |
filter[webName] |
Web name |
filter[externalName] |
External name |
filter[description] |
Description |
filter[smallDescription] |
Small description |
filter[pageTitle] |
Page title |
filter[metaDescription] |
Meta description |
DateTime Filters¶
Supports all datetime filter operators.
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Product ID(s) | filter[id]=1,2,3 |
filter[brandId] |
Brand ID(s) | filter[brandId]=5,10 |
filter[categoryId] |
Category ID(s) | filter[categoryId]=3 |
filter[statusId] |
Status ID(s) | filter[statusId]=1,2 |
filter[tagId] |
Tag ID(s) | filter[tagId]=5,8 |
filter[crmTagId] |
CRM tag ID(s) | filter[crmTagId]=2 |
filter[shopifyShopId] |
Shopify shop ID(s) | filter[shopifyShopId]=1 |
Numeric Filters¶
| Filter | Description | Example |
|---|---|---|
filter[weightValueMin] |
Minimum weight | filter[weightValueMin]=0.5 |
filter[weightValueMax] |
Maximum weight | filter[weightValueMax]=10 |
Boolean Filters¶
| Filter | Description | Example |
|---|---|---|
filter[hasVariants] |
Has variants | filter[hasVariants]=true |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: SKU, barcode, manufacturer SKU, URL handle, HS code, name, web name, external name |
Example Requests¶
# Basic request
GET /api/aiconeo/products
# With includes and pagination
GET /api/aiconeo/products?include=brand,category,productPrices,variants&page[number]=1&page[size]=50
# With text filter
GET /api/aiconeo/products?filter[sku][startsWith]=PRD-
# With date filter
GET /api/aiconeo/products?filter[createdAt][dateBetween]=2024-01-01,2024-12-31
Product Detail¶
Endpoint: GET /api/aiconeo/products/{id}
Get comprehensive details for a single product, optimized for product detail pages.
Response Includes¶
| Data | Description |
|---|---|
| Basic fields | SKU, barcode, manufacturer SKU, URL handle, product type, flags, dates |
| Date fields | saleFrom, saleUntil, releaseDate, releaseStartTime, releaseEndTime |
| Weight & Dimensions | All gross/net weight, length, height, width, diameter, volume fields with units |
| Production & Origin | provenance, productionCountry, hsCode, eacNumber |
| Product specifications | warranty, numberOfItemsInPackage, deliveryPeriod, shelfLife, totalShelfLife, consumptionPeriod, specification, storageConditions, unitContents |
| Shipping configuration | isSuitableForShipping (boolean), shippingDestination (translated: Everywhere/EU Only/USA Only), isMondayBlocked, isTuesdayBlocked, isWednesdayBlocked, isThursdayBlocked, isFridayBlocked, isSaturdayBlocked, isSundayBlocked (all boolean), isCustomerDayBlockEnabled (boolean) |
| Translations | All locales with name, web name, description, SEO fields, ingredients, image URLs |
| Product unit | Product unit with name and short name |
| File groups | Documents, images, videos, marketing documents, manufacturing documents |
| Main image | Convenience field with the main product image |
| Variants | All variants with options, pricing, manufacturing details, and image URLs |
| Variation options | Option definitions (size, color, etc.) with values and image URLs |
| Tax classes | Tax information per tax area with current rates |
| Categories | Main category, subcategory, and sub-subcategory with image URLs |
| Category sets | Additional category mappings beyond the main hierarchy |
| Shopify shops | All connected Shopify shops with sync status |
| Custom fields | All custom field values for the product |
| Sellers | Associated sellers with name and status |
| Suppliers | B2B suppliers with manufacturer SKU and primary flag |
| Nutritional values | Nutritional information with value, unit, and translated text |
URL Fields¶
All image/file URLs in the response are full URLs generated via Laravel Storage:
| Location | Fields |
|---|---|
translations[].image |
Product translation images |
variants[].image |
Variant images |
variationOptions[].values[].image |
Variation option value images (e.g., color swatches) |
categories.*.image |
Category images |
fileGroups.*.files[].translations[].fileUrl |
File URLs |
fileGroups.*.files[].translations[].optimizedFileUrl |
Optimized file URLs |
Example Request¶
Example Response¶
{
"data": {
"id": 1773,
"type": "products",
"attributes": {
"sku": "93583658",
"barcode": null,
"manufacturerSku": null,
"urlHandle": "product-1773",
"productType": "PHYSICAL",
"isBundle": false,
"isAvailable": false,
"isGiftCard": false,
"isDiscontinued": false,
"isAgeRestricted": false,
"isAvailableOnAicoPos": false,
"isAvailableInAppShop": false,
"releaseDate": null,
"createdAt": "2025-12-23 13:50:30",
"updatedAt": "2025-12-23 13:50:46",
"archivedAt": null,
"version": 1,
"saleFrom": null,
"saleUntil": null,
"releaseStartTime": null,
"releaseEndTime": null,
"weightValue": null,
"weightUnit": null,
"grossLength": null,
"grossHeight": null,
"grossWidth": null,
"grossDiameter": null,
"dimensionUnit": null,
"netWeightValue": null,
"netWeightUnit": null,
"netLength": null,
"netHeight": null,
"netWidth": null,
"netDiameter": null,
"grossVolume": null,
"netVolume": null,
"grossVolumeUnit": null,
"netVolumeUnit": null,
"provenance": null,
"productionCountry": null,
"hsCode": null,
"eacNumber": null,
"warranty": null,
"numberOfItemsInPackage": null,
"deliveryPeriod": null,
"shelfLife": null,
"totalShelfLife": null,
"consumptionPeriod": null,
"specification": null,
"storageConditions": null,
"maxQuantityPerOrder": null,
"unitContents": null,
"isSuitableForShipping": false,
"shippingDestination": "Everywhere",
"isMondayBlocked": false,
"isTuesdayBlocked": false,
"isWednesdayBlocked": false,
"isThursdayBlocked": false,
"isFridayBlocked": false,
"isSaturdayBlocked": false,
"isSundayBlocked": false,
"isCustomerDayBlockEnabled": false,
"taxCode": null,
"fibuProceeds": null,
"fibuExpenses": null,
"translations": [
{
"locale": "de_CH",
"name": "Test Fabian",
"webName": "Test Fabian",
"externalName": null,
"description": null,
"smallDescription": null,
"image": null,
"manufacturer": null,
"ingredients": null,
"pageTitle": null,
"metaDescription": null,
"translatedUrlHandle": "product-1773",
"notes": null,
"sideEffects": null,
"contraindications": null,
"interactions": null,
"usageInstructions": null
}
],
"status": {
"id": 4,
"name": "OUT",
"color": "#e50000"
},
"brand": null,
"productUnit": null,
"categories": {
"category": null,
"subCategory": null,
"subSubCategory": null
},
"categorySets": [],
"variants": [
{
"id": 15156,
"sku": "93583658_87494",
"manufacturerSku": null,
"barcode": null,
"name": "Test Fabian, A",
"image": null,
"price": null,
"priceCHF": null,
"discountPriceCHF": null,
"buyingPrice": null,
"order": 0,
"weightValue": null,
"weightUnit": null,
"grossLength": null,
"grossHeight": null,
"grossWidth": null,
"netWeightValue": null,
"netWeightUnit": null,
"provenance": null,
"hsCode": null,
"maxQuantityPerOrder": null,
"deliveryStatus": 0,
"shouldNotSyncToShopify": false,
"createdAt": "2025-12-23 13:52:07",
"updatedAt": "2025-12-23 13:52:07",
"options": [
{
"id": 988458,
"name": "Wert",
"value": "A",
"variationOptionValueId": null
}
]
},
{
"id": 15157,
"sku": "93583658_34841",
"manufacturerSku": null,
"barcode": null,
"name": "Test Fabian, B",
"image": null,
"price": null,
"priceCHF": null,
"discountPriceCHF": null,
"buyingPrice": null,
"order": 1,
"weightValue": null,
"weightUnit": null,
"grossLength": null,
"grossHeight": null,
"grossWidth": null,
"netWeightValue": null,
"netWeightUnit": null,
"provenance": null,
"hsCode": null,
"maxQuantityPerOrder": null,
"deliveryStatus": 0,
"shouldNotSyncToShopify": false,
"createdAt": "2025-12-23 13:52:07",
"updatedAt": "2025-12-23 13:52:07",
"options": [
{
"id": 988459,
"name": "Wert",
"value": "B",
"variationOptionValueId": null
}
]
}
],
"variationOptions": [
{
"id": 578,
"name": "Wert",
"isColorOption": false,
"sortOrder": null,
"values": [
{
"id": 940048,
"value": "A",
"image": null,
"sortOrder": null
},
{
"id": 940049,
"value": "B",
"image": null,
"sortOrder": null
}
]
}
],
"fileGroups": {
"images": {
"id": 8484,
"mainProductFileId": 70389,
"files": []
},
"mainImage": null
},
"mainImage": null,
"taxClasses": [
{
"id": 5558,
"taxArea": {
"id": 2,
"state": null,
"country": "Germany",
"name": "Germany"
},
"taxClass": {
"id": 7,
"name": "Mehrwertsteuerfrei"
},
"currentRate": null
},
{
"id": 5559,
"taxArea": {
"id": 3,
"state": null,
"country": "Hong Kong",
"name": "Hong Kong"
},
"taxClass": {
"id": 8,
"name": "Mehrwertsteuerfrei"
},
"currentRate": null
},
{
"id": 5560,
"taxArea": {
"id": 1,
"state": null,
"country": "Switzerland",
"name": "Switzerland"
},
"taxClass": {
"id": 1,
"name": "Umsatz 8.1 (NS)"
},
"currentRate": {
"value": 8.1,
"validFrom": "2023-06-30 22:00:00"
}
}
],
"shopifyShops": [],
"customFields": {
"1_spielername": null,
"4_waschanleitung": null,
"5_url_360": null,
"7_docnum": null,
"9_mestyp": null,
"15_trikotorder": null,
"currency_1_chf": null,
"warehouse_5_fanshop_sjp_stadion": null,
"total_stock": 44,
"warehouse_8_1050__kiosk": null,
"warehouse_9_1060__vip": null,
"warehouse_10_1100__backoffice": 21,
"warehouse_11_1200__stadion": null,
"warehouse_12_1250__schraege": null,
"warehouse_13_1300__logistik": null,
"warehouse_14_1400__arlesheim": null,
"warehouse_15_1600__creadiva": null,
"warehouse_16_1000__fanshop": null,
"currency_2_eur": 0,
"currency_3_usd": null,
"currency_10_hkd": null,
"25_mitgliedschaftprodukt": null
},
"sellers": [],
"suppliers": [],
"nutritionalValues": []
}
}
}
Product Create¶
Endpoint: POST /api/aiconeo/products
Create a new product with minimal data. The product is created immediately with just SKU, then initialization (default prices, Shopify sync, etc.) happens in a background job.
Request Body (JSON:API format)¶
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "products" |
data.attributes.sku |
string | No | Product SKU (auto-generated if not provided) |
Response (201 Created)¶
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"sku": "93583659",
"version": 1,
"status": "initializing",
"createdAt": "2026-01-07T06:22:07+01:00"
}
}
}
Bad Request (400):
{
"errors": [{
"status": "400",
"title": "Bad Request",
"detail": "Invalid or missing resource type. Expected \"products\".",
"source": { "pointer": "/data/type" }
}]
}
Pusher Event¶
When background initialization completes, a ProductInitialized event is broadcast on the presence channel:
- Channel:
{workspaceId}.product.{productId}(presence channel) - Event:
.initialized - Payload:
Example Request¶
curl -X POST "http://127.0.0.1/api/aiconeo/products" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"data": {"type": "products", "attributes": {"sku": "MY-SKU-123"}}}'
Product Update (Collaborative Editing)¶
Endpoint: PATCH /api/aiconeo/products/{id}
Update product fields with optimistic locking. Requires the current version to prevent conflicts when multiple users edit simultaneously.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
int | Product ID |
Request Body (JSON:API format)¶
Basic field update:
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"sku": "NEW-SKU",
"isAvailable": true,
"version": 2
}
}
}
Translations update (flat array format):
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"version": 2,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name", "description": "Beschreibung"},
{"locale": "en", "name": "English Name"}
]
}
}
}
Mixed update (translations + regular fields):
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"version": 2,
"sku": "NEW-SKU",
"isAvailable": true,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name"},
{"locale": "en", "name": "English Name"}
]
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "products" |
data.id |
string | No | Resource ID (if provided, must match URL) |
data.attributes.version |
int | Yes | Current version of the record (for conflict detection) |
data.attributes.sku |
string | No | Product SKU |
data.attributes.isAvailable |
boolean | No | Availability flag |
data.attributes.translations |
array | No | Array of translation objects |
| ...other attributes | mixed | No | Any other Product fields (camelCase) |
Translation Object Structure (flat array format):
Each object in translations array contains locale plus any translatable fields:
| Field | Type | Required | Description |
|---|---|---|---|
locale |
string | Yes | Locale code (e.g., "de_CH", "en", "fr_CH") |
name |
string | No | Product name |
description |
string | No | Product description |
webName |
string | No | Web display name |
| ...other fields | mixed | No | Any translatable field in camelCase |
Benefits of flat array format: - Group multiple fields per locale in a single object - More intuitive and compact than field-by-field updates - One version increment for all translations
Response (200 OK)¶
For regular fields:
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"version": 3,
"updatedAt": "2026-01-18T18:28:35+01:00",
"sku": "NEW-SKU",
"isAvailable": true
}
}
}
For translations:
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"version": 3,
"updatedAt": "2026-01-18T18:28:25+01:00",
"translations": [
{"locale": "de_CH", "name": "Deutscher Name", "description": "Beschreibung"},
{"locale": "en", "name": "English Name"}
]
}
}
}
For mixed update:
{
"data": {
"type": "products",
"id": "1774",
"attributes": {
"version": 3,
"updatedAt": "2026-01-18T18:28:35+01:00",
"sku": "NEW-SKU",
"isAvailable": true,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name"},
{"locale": "en", "name": "English Name"}
]
}
}
}
Not Found (404):
Conflict (409):
Returned when the provided version doesn't match the current version:
{
"errors": [{
"status": "409",
"title": "Conflict",
"detail": "This record was modified by another user.",
"meta": {
"currentVersion": 3,
"currentData": {
"sku": "OTHER-SKU"
}
}
}]
}
Pusher Event¶
On successful update, a ProductFieldUpdated event is broadcast to other users:
- Channel:
{workspaceId}.product.{productId}(presence channel) - Event:
.field.updated - Payload:
Example Request¶
Translations update (flat array format):
curl -X PATCH "http://127.0.0.1/api/aiconeo/products/457" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"data": {
"type": "products",
"id": "457",
"attributes": {
"version": 2,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name", "description": "Beschreibung"},
{"locale": "en", "name": "English Name"}
]
}
}
}'
Mixed update (translations + regular fields):
curl -X PATCH "http://127.0.0.1/api/aiconeo/products/457" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"data": {
"type": "products",
"id": "457",
"attributes": {
"version": 2,
"sku": "NEW-SKU-123",
"isAvailable": true,
"translations": [
{"locale": "de_CH", "webName": "produkt-web"},
{"locale": "en", "webName": "product-web"}
]
}
}
}'
Product Focus (Optional)¶
Endpoint: POST /api/aiconeo/products/{id}/focus
Broadcast a focus change to other users viewing the same product. This is optional - clients can also use Pusher whispers directly.
Request Body¶
Or to clear focus:
Response (200 OK)¶
Not Found (404):
Pusher Event¶
- Channel:
{workspaceId}.product.{productId}(presence channel) - Event:
.focus.changed - Payload:
Product Presence Channel¶
For collaborative editing, clients should subscribe to the product's presence channel:
Channel: presence-{workspaceId}.product.{productId}
Where workspaceId is extracted from the APP_URL path (e.g., https://app.aico.swiss/12345 → 12345).
Channel Events¶
| Event | Description |
|---|---|
pusher:subscription_succeeded |
Initial list of users viewing the product |
pusher:member_added |
New user started viewing |
pusher:member_removed |
User stopped viewing |
.field.updated |
Product field was updated |
.initialized |
Background initialization completed |
.focus.changed |
User focus changed |
User Object in Presence¶
The color is deterministically generated from the user ID for consistent display.
Data Types & Update Scopes¶
The product update endpoint (PATCH /api/aiconeo/products/{id}) uses optimistic locking (version checking) to prevent conflicts. Here's how different data types are handled:
Protected by Product Version (Phase 1)¶
These fields increment the product version and are conflict-checked:
Direct Product Fields¶
All fields in the Product model's $fillable array can be updated via the PATCH endpoint. Use camelCase in API requests:
| Category | Fields (camelCase for API) |
|---|---|
| Identifiers | sku, barcode, manufacturerSku, urlHandle |
| Availability | isAvailable, isBundle, isGiftCard, isDiscontinued, isAgeRestricted, isAvailableOnAicoPos, isAvailableInAppShop, releaseDate |
| Manufacturing | weightValue, weightUnit, grossLength, grossHeight, grossWidth, grossDiameter, dimensionUnit, netWeightValue, netWeightUnit, netLength, netHeight, netWidth, netDiameter, grossVolume, netVolume, provenance, hsCode, maxQuantityPerOrder, unitContents |
| Shipping | isSuitableForShipping, isMondayBlocked, isTuesdayBlocked, isWednesdayBlocked, isThursdayBlocked, isFridayBlocked, isSaturdayBlocked, isSundayBlocked, isCustomerDayBlockEnabled |
| Accounting | fibuProceeds, fibuExpenses, taxCode |
| Foreign Keys | categoryId, subcategoryId, subsubcategoryId, brandId, statusId, manufacturerId, colorId |
Example - Update category:
Example - Update unit contents:
Translations¶
Update via the translations array using flat array format (locale + field values per object). These also increment the product version.
| Field | Description |
|---|---|
name |
Product name |
webName |
Web display name |
externalName |
External/export name |
description |
Full description |
smallDescription |
Short description |
image |
Translation-specific image path |
manufacturer |
Manufacturer text |
ingredients |
Ingredients text |
pageTitle |
SEO page title |
metaDescription |
SEO meta description |
notes, sideEffects, contraindications, interactions, usageInstructions |
Additional text fields |
Example - Translations update (flat array format):
{
"data": {
"version": 3,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name", "description": "Deutsche Beschreibung"},
{"locale": "en", "name": "English Name"}
]
}
}
Benefits of flat array format: - Group multiple fields per locale in a single object - More intuitive and compact than field-by-field updates - One version increment for all translations - Atomic operation - all translations succeed or none - Can be combined with regular field updates in the same request
Example - Mixed update (translations + regular fields):
{
"data": {
"version": 3,
"sku": "NEW-SKU",
"isAvailable": true,
"translations": [
{"locale": "de_CH", "name": "Deutscher Name"}
]
}
}
Custom Fields¶
Custom fields are stored in a flattened table (custom_fields_products) keyed by product_id and locale. The read endpoint returns them as a dynamic object:
{
"customFields": {
"1_spielername": "John Doe",
"currency_1_chf": 49.90,
"warehouse_10_1100__backoffice": 21,
"total_stock": 44
}
}
How custom fields work:
- Field names are prefixed with their ID (e.g., 1_spielername = custom field #1)
- Special computed fields: currency_* (prices), warehouse_* (stock by warehouse), total_stock
- Custom fields are read-only in the current aiconeo API
- For updates, use the existing custom fields service or v1 API
Relation Updates via Foreign Keys¶
To update relations like brand or category, pass the foreign key ID in camelCase:
The response will include the updated version, and the next read will show the related entity data.
Product Prices¶
Endpoint: GET /api/aiconeo/products/{id}/prices
Get all product prices and variant prices for a specific product.
Response Structure¶
| Field | Description |
|---|---|
productPrices |
Array of product-level prices |
variantPrices |
Array of variant-level prices |
Price Fields¶
| Field | Type | Description |
|---|---|---|
id |
int | Price ID |
value |
float | Base price value |
buyingPrice |
float | Buying/cost price |
discountPrice |
float | Discounted price |
unitPrice |
float | Unit price (for price per kg, etc.) |
priceType |
string | Price type (BASE, SCHEDULED, etc.) |
activeFrom |
datetime | Start date for scheduled prices |
activeUntil |
datetime | End date for scheduled prices |
isActive |
boolean | Whether price is currently active |
currency |
object | Currency info (id, name) |
Example Request¶
Example Response¶
{
"data": {
"id": 123,
"type": "product-prices",
"attributes": {
"productPrices": [
{
"id": 1,
"value": 99.90,
"discountPrice": 79.90,
"priceType": "BASE",
"isActive": true,
"currency": { "id": 1, "name": "CHF" }
}
],
"variantPrices": [
{
"id": 10,
"variantId": 5,
"variantSku": "PRD-001-S",
"variantName": "Small",
"value": 99.90,
"currency": { "id": 1, "name": "CHF" }
}
]
}
}
}
Product Stocks¶
Endpoint: GET /api/aiconeo/products/{id}/stocks
Get all stock levels for a product across all warehouses.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 100 | 500 | Items per page |
filter[warehouseId] |
string | - | - | Filter by warehouse ID(s) |
filter[variantId] |
string | - | - | Filter by variant ID(s), use 'null' for product-level |
Stock Fields¶
| Field | Type | Description |
|---|---|---|
id |
int | Stock record ID |
sku |
string | Stock SKU |
amount |
int | Current stock amount |
minimumStockAmount |
int | Minimum stock threshold |
unconfirmedReservedAmount |
int | Pending reservations |
overallAvailableAmount |
int | Total available stock |
blockedAmount |
int | Manually blocked stock |
warehouse |
object | Warehouse info |
variant |
object | Variant info (if variant-level stock) |
binLocation |
object | Bin location info (id, code, barcode) |
Example Request¶
# Get all stocks
GET /api/aiconeo/products/123/stocks
# Filter by warehouse
GET /api/aiconeo/products/123/stocks?filter[warehouseId]=1,2
# Get only product-level stocks (no variants)
GET /api/aiconeo/products/123/stocks?filter[variantId]=null
Example Response¶
{
"data": {
"id": 123,
"type": "product-stocks",
"attributes": {
"stocks": [
{
"id": 1,
"sku": "PRD-001",
"amount": 150,
"minimumStockAmount": 10,
"overallAvailableAmount": 150,
"warehouse": { "id": 1, "name": "Main Warehouse", "country": "CH" },
"variant": null,
"binLocation": { "id": 5, "code": "A-1-1", "barcode": "BIN-A-1-1" }
}
]
}
},
"meta": {
"page": { "currentPage": 1, "total": 25, "perPage": 100 }
}
}
Product Stock Changes¶
Endpoint: GET /api/aiconeo/products/{id}/stock-changes
Get the history of all stock changes for a product.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 50 | 200 | Items per page |
sort |
string | -createdAt |
- | Sort field (id, createdAt, changeAmount, newAmount) |
filter[warehouseId] |
string | - | - | Filter by warehouse ID(s) |
filter[variantId] |
string | - | - | Filter by variant ID(s) |
filter[changeTypeId] |
string | - | - | Filter by change type ID(s) |
filter[createdAt] |
mixed | - | - | Filter by date (supports dateBetween, before, after) |
Stock Change Fields¶
| Field | Type | Description |
|---|---|---|
id |
int | Change record ID |
oldAmount |
int | Stock amount before change |
changeAmount |
int | Amount changed (+/-) |
newAmount |
int | Stock amount after change |
author |
string | Who made the change |
note |
string | Change note/reason |
changeType |
object | Type of change (Sale, Restock, Correction, etc.) |
warehouse |
object | Warehouse info |
variant |
object | Variant info |
user |
object | User who made the change |
shopifyShop |
object | Shopify shop (for online sales) |
createdAt |
datetime | When the change occurred |
Example Request¶
# Get recent changes
GET /api/aiconeo/products/123/stock-changes
# Filter by date range
GET /api/aiconeo/products/123/stock-changes?filter[createdAt][dateBetween]=2025-01-01,2025-12-31
# Filter by warehouse and sort by change amount
GET /api/aiconeo/products/123/stock-changes?filter[warehouseId]=1&sort=-changeAmount
Example Response¶
{
"data": {
"id": 123,
"type": "product-stock-changes",
"attributes": {
"stockChanges": [
{
"id": 500,
"oldAmount": 150,
"changeAmount": -5,
"newAmount": 145,
"author": "System",
"note": "Online sale #12345",
"changeType": { "id": 1, "name": "Shopify Online Sale" },
"warehouse": { "id": 1, "name": "Main Warehouse" },
"variant": null,
"shopifyShop": { "id": 1, "name": "My Store" },
"createdAt": "2025-01-03 14:30:00"
}
]
}
},
"meta": {
"page": { "currentPage": 1, "total": 1250, "perPage": 50 }
}
}
Articles¶
Endpoint: GET /api/aiconeo/articles
Returns a combined view of products and variants as "articles": - Products with variants: only the variants show up as individual articles (product itself is hidden) - Products without variants: the product shows up as an article
This provides a unified SKU-level view for inventory and sales purposes.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -productUpdatedAt |
- | Sort field(s), prefix with - for descending |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Article ID (variant ID or product ID) |
variantId |
Variant ID |
productId |
Product ID |
sku |
SKU (uses variant SKU if available, otherwise product SKU) |
variantSku |
Variant SKU only |
productSku |
Product SKU only |
barcode |
Barcode (uses variant if available) |
name |
Product name |
productName |
Product name |
variantName |
Variant name |
brandName |
Brand name |
categoryName |
Category name |
price |
Price (uses variant price if available) |
productPrice |
Product price |
variantPrice |
Variant price |
createdAt / productCreatedAt |
Product creation date |
updatedAt / productUpdatedAt |
Product update date |
stock{WarehouseKey} |
Stock amount for specific warehouse |
Filters¶
| Filter | Description |
|---|---|
filter[sku] |
Search by SKU (both product and variant) |
filter[barcode] |
Search by barcode (both product and variant) |
filter[name] |
Search by name (both product and variant) |
filter[productId] |
Filter by product ID(s), comma-separated |
filter[variantId] |
Filter by variant ID(s), comma-separated |
filter[brandId] |
Filter by brand ID(s), comma-separated |
filter[brandName] |
Filter by brand name |
filter[categoryId] |
Filter by category ID(s), includes all category levels |
filter[hasVariants] |
true = only variants, false = only products without variants |
filter[search] |
Global search (SKU, barcode, name) |
filter[createdAt] |
Date filter (supports operators) |
filter[updatedAt] |
Date filter (supports operators) |
filter[stock{WarehouseKey}] |
Stock amount filter per warehouse |
Stock Filter Operators¶
| Operator | Example | Description |
|---|---|---|
eq |
filter[stockWarehouse1][eq]=10 |
Exact amount |
gt |
filter[stockWarehouse1][gt]=0 |
Greater than |
gte |
filter[stockWarehouse1][gte]=5 |
Greater than or equal |
lt |
filter[stockWarehouse1][lt]=10 |
Less than |
lte |
filter[stockWarehouse1][lte]=5 |
Less than or equal |
inStock |
filter[stockWarehouse1][inStock]=true |
Has stock (> 0) |
outOfStock |
filter[stockWarehouse1][outOfStock]=true |
Out of stock (≤ 0 or null) |
Includes¶
| Include | Description |
|---|---|
shopifyShops |
Shopify shop connections |
tags |
Product tags |
URL Fields (Full Storage URLs)¶
| Field | Description |
|---|---|
image |
Article image (variant image if available, otherwise product image) |
productImage |
Product image |
variantImage |
Variant image |
Response Structure¶
{
"data": [
{
"id": "v13922",
"type": "articles",
"attributes": {
"articleType": "variant",
"productId": 1066,
"variantId": 13922,
"sku": "2408007",
"barcode": "8056009571906",
"manufacturerSku": null,
"name": "Team Polo 24/25, 4XL",
"productName": "Team Polo 24/25",
"productWebName": "Team Polo 24/25",
"variantName": "Team Polo 24/25, 4XL",
"image": "http://example.com/storage/images/2408.png",
"productImage": "http://example.com/storage/images/2408.png",
"variantImage": null,
"brand": { "id": 1, "name": "Nike" },
"category": { "id": 20739, "name": "Trikot & Training" },
"price": 63.83,
"discountPrice": 18.50,
"productPrice": 63.83,
"productDiscountPrice": 18.50,
"variantPrice": 63.83,
"variantDiscountPrice": 18.50,
"createdAt": "2024-06-21 11:01:18",
"updatedAt": "2025-12-19 14:02:23",
"stocks": {
"warehouse_1_main": {
"warehouseId": 1,
"warehouseName": "Main Warehouse",
"amount": 25,
"availableAmount": 20
},
"warehouse_2_outlet": {
"warehouseId": 2,
"warehouseName": "Outlet",
"amount": 5,
"availableAmount": 5
}
},
"shopifyShops": [
{ "id": 4, "name": "FCB Fanshop", "isActive": true }
],
"tags": ["new", "sale"]
}
},
{
"id": "p1649",
"type": "articles",
"attributes": {
"articleType": "product",
"productId": 1649,
"variantId": null,
"sku": "801",
"barcode": "4055134004505",
"name": "Halskette mit Logoanhänger",
"productName": "Halskette mit Logoanhänger",
"variantName": null,
"price": 23.13,
"stocks": { ... }
}
}
],
"meta": {
"page": { "currentPage": 1, "total": 5000, "perPage": 25 },
"warehouses": [
{ "id": 1, "key": "warehouse_1_main", "name": "Main Warehouse" },
{ "id": 2, "key": "warehouse_2_outlet", "name": "Outlet" }
]
},
"links": { "first": "...", "last": "...", "prev": null, "next": "..." }
}
Notes¶
- Article
idis prefixed withvfor variants (e.g.,v13922) andpfor products (e.g.,p1649) articleTypeis either"variant"or"product"- Unified fields (
sku,barcode,name,price,image) use variant values when available, otherwise product values - Stock amounts are included for all warehouses, listed in the
meta.warehousesarray - The default currency for prices is CHF
Categories¶
Endpoint: GET /api/aiconeo/categories
Returns categories in a hierarchical structure by default, with main categories (parent_id = null) containing nested subcategories.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
nested |
bool | true | - | Return hierarchical structure (true) or flat list (false) |
maxDepth |
int | 3 | 5 | Maximum nesting depth for hierarchical structure |
page[number] |
int | 1 | - | Page number (only for flat list) |
page[size] |
int | 100 | 500 | Items per page (only for flat list) |
Filters¶
| Filter | Description |
|---|---|
filter[id] |
Category ID(s), comma-separated |
filter[parentId] |
Parent category ID(s), use null for main categories |
filter[isAvailableInAppShop] |
Filter by app shop availability |
filter[isFeaturedInBanner] |
Filter by featured in banner |
filter[search] |
Search by name or web name |
Includes¶
| Include | Description |
|---|---|
shopifyShops |
Shopify shop connections with shopify ID and handle |
productCount |
Number of products in category (includes all category levels) |
URL Fields (Full Storage URLs)¶
| Field | Description |
|---|---|
image |
Category main image |
video |
Category video file |
itemImage |
Category item image |
Response Structure (Hierarchical)¶
{
"data": [
{
"id": 10210,
"type": "categories",
"attributes": {
"parentId": null,
"name": "Bekleidung",
"webName": "Bekleidung",
"description": "<p>...</p>",
"smallDescription": null,
"seoText": "<p>...</p>",
"urlHandle": "bekleidung",
"pageTitle": null,
"image": "http://example.com/storage/images/category.png",
"video": null,
"videoUrl": null,
"itemImage": null,
"color": null,
"hasQuickOfferVisibility": true,
"isOverridingProductDescriptionAllowed": false,
"shouldRandomizeColorSort": false,
"landingPageId": null,
"hasDropInterval": false,
"dropStartDate": null,
"dropEndDate": null,
"isAvailableInAppShop": false,
"isFeaturedInBanner": false,
"createdAt": "2022-04-08 08:11:58",
"updatedAt": "2025-09-23 09:39:28",
"subCategories": [
{
"id": 20744,
"type": "categories",
"attributes": {
"parentId": 10210,
"name": "Männer",
"webName": "Männer",
"urlHandle": "bekleidung-männer",
"subCategories": [...]
}
}
],
"productCount": 179
}
}
],
"meta": {
"totalCategories": 84,
"mainCategories": 6
}
}
Response Structure (Flat List)¶
{
"data": [
{
"id": 10210,
"type": "categories",
"attributes": {
"parentId": null,
"name": "Bekleidung",
"productCount": 179
}
}
],
"meta": {
"page": { "currentPage": 1, "total": 84, "perPage": 100 }
},
"links": { "first": "...", "last": "...", "prev": null, "next": "..." }
}
Product Types¶
Endpoint: GET /api/aiconeo/product-types
Returns all available product types. This is a static list based on the ProductType enum.
Response Structure¶
{
"data": [
{ "name": "PHYSICAL", "label": "Default" },
{ "name": "SERVICE", "label": "Service" },
{ "name": "INGREDIENT", "label": "Ingredient" },
{ "name": "OPERATING_RESOURCE", "label": "Operating resource" },
{ "name": "PACKAGING", "label": "Packaging" }
]
}
Response Fields¶
| Field | Type | Description |
|---|---|---|
name |
string | The enum case name (e.g., "PHYSICAL", "SERVICE") - use this value for API requests |
label |
string | Human-readable label for display in UI |
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/product-types" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Product Units¶
Endpoint: GET /api/aiconeo/product-units
Returns product units with pagination, filtering, and sorting following the JSON:API specification.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | id |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships to include |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Product unit ID |
name |
Translated name |
shortName |
Translated short name |
isDefault |
Whether this is the default unit |
createdAt |
Creation timestamp |
updatedAt |
Last update timestamp |
Filter Parameters¶
| Filter | Type | Description |
|---|---|---|
filter[id] |
int/string | Filter by ID(s), comma-separated |
filter[name] |
string | Filter by name (contains) |
filter[shortName] |
string | Filter by short name (contains) |
filter[isDefault] |
bool | Filter by default status |
filter[hasUnitContents] |
bool | Filter by unit contents flag |
filter[search] |
string | Global search on name and short name |
Include Options¶
| Include | Description |
|---|---|
translations |
All available translations for the product unit |
Response Structure¶
{
"data": [
{
"id": 1,
"type": "product-units",
"attributes": {
"name": "Std",
"shortName": "Std",
"isDefault": false,
"hasUnitContents": false,
"createdAt": "2025-02-01 19:49:48",
"updatedAt": "2025-02-01 19:49:48",
"translations": [
{
"id": 1,
"locale": "en",
"name": "Hours",
"shortName": "Hours"
},
{
"id": 2,
"locale": "de_CH",
"name": "Std",
"shortName": "Std"
}
]
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 1,
"perPage": 25,
"to": 7,
"total": 7
}
},
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": null
}
}
Product Unit Attributes¶
| Field | Type | Description |
|---|---|---|
name |
string | Translated name (based on Accept-Language header) |
shortName |
string | Translated short name |
isDefault |
bool | Whether this is the default unit |
hasUnitContents |
bool | Whether the unit has contents |
createdAt |
datetime | Creation timestamp |
updatedAt |
datetime | Last update timestamp |
translations |
array | All translations (only with include=translations) |
Example Requests¶
Basic request:
curl -X GET "http://127.0.0.1/api/aiconeo/product-units" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
With search filter and translations:
curl -X GET "http://127.0.0.1/api/aiconeo/product-units?filter%5Bsearch%5D=St&include=translations" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Filter by default status:
curl -X GET "http://127.0.0.1/api/aiconeo/product-units?filter%5BisDefault%5D=true" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Product Statuses¶
Endpoints for retrieving product statuses used to track product workflow states.
Product Statuses List¶
Endpoint: GET /api/aiconeo/product-statuses
Returns a paginated list of product statuses.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | id |
- | Sort field(s), prefix with - for descending |
filter[id] |
int/string | - | - | Filter by ID (comma-separated for multiple) |
filter[name] |
string | - | - | Filter by name (supports text operators) |
filter[color] |
string | - | - | Filter by color |
filter[isComplete] |
boolean | - | - | Filter by completion status |
filter[isInProgress] |
boolean | - | - | Filter by in-progress status |
filter[search] |
string | - | - | Global search in name and web_name |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Status ID |
name |
Status name |
color |
Status color |
groupOrderNumber |
Order within the status group |
isComplete |
Completion flag |
isInProgress |
In-progress flag |
createdAt |
Creation timestamp |
updatedAt |
Last update timestamp |
Response Structure¶
{
"data": [
{
"id": 49,
"type": "product-statuses",
"attributes": {
"name": "Draft",
"webName": "Draft",
"color": "#cccccc",
"groupOrderNumber": 27,
"isComplete": false,
"isInProgress": false,
"createdAt": "2022-04-06 09:22:13",
"updatedAt": "2022-04-06 09:22:13"
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 1,
"perPage": 25,
"to": 5,
"total": 5
}
},
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": null
}
}
Response Fields¶
| Field | Type | Description |
|---|---|---|
id |
integer | Status ID |
name |
string | Internal status name |
webName |
string/null | Display name for web interfaces |
color |
string | Hex color code (e.g., "#cccccc") |
groupOrderNumber |
integer | Order position within the status group |
isComplete |
boolean | Whether this status indicates completion |
isInProgress |
boolean | Whether this status indicates work in progress |
createdAt |
string | Creation timestamp |
updatedAt |
string | Last update timestamp |
Example Requests¶
Get all product statuses:
curl -X GET "http://127.0.0.1/api/aiconeo/product-statuses" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Filter by name:
curl -X GET "http://127.0.0.1/api/aiconeo/product-statuses?filter%5Bname%5D=Draft" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Sort by name descending:
curl -X GET "http://127.0.0.1/api/aiconeo/product-statuses?sort=-name" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Product Status Detail¶
Endpoint: GET /api/aiconeo/product-statuses/{id}
Returns a single product status by ID.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
integer | The product status ID |
Response Structure¶
{
"data": {
"id": 49,
"type": "product-statuses",
"attributes": {
"name": "Draft",
"webName": "Draft",
"color": "#cccccc",
"groupOrderNumber": 27,
"isComplete": false,
"isInProgress": false,
"createdAt": "2022-04-06 09:22:13",
"updatedAt": "2022-04-06 09:22:13"
}
}
}
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/product-statuses/49" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
Error Response (404)¶
{
"errors": [
{
"status": "404",
"title": "Not Found",
"detail": "Product status with ID 999 not found."
}
]
}
Collections¶
Endpoint: GET /api/aiconeo/collections
Returns product collections with optional includes for Shopify shops, conditions, and product count.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -id |
- | Sort field(s), prefix with - for descending |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Collection ID |
name |
Collection name |
webName |
Web name |
conditionType |
Condition type |
sortOrder |
Sort order |
createdAt |
Creation date |
updatedAt |
Last update date |
Filters¶
| Filter | Description |
|---|---|
filter[id] |
Collection ID(s), comma-separated |
filter[name] |
Filter by name (supports operators) |
filter[webName] |
Filter by web name (supports operators) |
filter[urlHandle] |
Filter by URL handle (supports operators) |
filter[conditionType] |
Filter by condition type (AND/OR) |
filter[isPimMaster] |
Filter by PIM master status |
filter[shopifyShopId] |
Filter by Shopify shop ID(s) |
filter[search] |
Search by name, web name, or description |
filter[createdAt] |
Filter by creation date (supports date operators) |
filter[updatedAt] |
Filter by update date (supports date operators) |
Includes¶
| Include | Description |
|---|---|
shopifyShops |
Shopify shop connections with sync status |
conditions |
Collection conditions (type, operator, value) |
productCount |
Number of products in collection |
URL Fields (Full Storage URLs)¶
| Field | Description |
|---|---|
image |
Collection main image |
Response Structure¶
{
"data": [
{
"id": 2,
"type": "collections",
"attributes": {
"name": "Meisterkollektion",
"webName": "Meisterkollektion",
"description": null,
"internalDescription": null,
"pageTitle": "Meisterkollektion",
"metaDescription": null,
"urlHandle": "meisterkollektion",
"image": "http://example.com/storage/images/collection.png",
"isNameTranslatable": false,
"conditionType": "AND",
"sortOrder": "NONE",
"isPimMaster": false,
"createdAt": "2022-02-15 13:50:08",
"updatedAt": "2022-03-03 15:17:29",
"shopifyShops": [
{
"id": 4,
"name": "FCB Fanshop",
"shopifyId": "gid://shopify/Collection/282260045964",
"shopifyHandle": "meisterkollektion",
"isActive": true,
"existsInShop": true,
"lastSyncStatus": "SYNCED"
}
],
"conditions": [
{
"id": 1,
"type": "tag",
"operator": "equals",
"value": "meister"
}
],
"productCount": 15
}
}
],
"meta": {
"page": { "currentPage": 1, "total": 10, "perPage": 25 }
},
"links": { "first": "...", "last": "...", "prev": null, "next": "..." }
}
B2B Customers¶
Endpoint: GET /api/aiconeo/b2b
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -id |
- | Sort field(s) |
include |
string | - | - | Comma-separated relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
customerGroups |
Customer groups with translated names | ✓ |
crmTags |
CRM tags with translated names | ✓ |
customerTags |
Customer tags with title and color | ✓ |
sellers |
Associated sellers | ✗ |
brands |
Associated brands | ✗ |
customFields |
Custom fields | ✗ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
B2B ID |
customerNumber |
Customer number |
company |
Company name |
firstName |
First name |
lastName |
Last name |
fullName |
Full name |
email |
Email address |
telephoneNumber |
Phone number |
plz |
Postal code |
address |
Address |
location |
Location |
website |
Website |
createdAt |
Creation date |
updatedAt |
Last update date |
countryName |
Country name |
customerReferenceNumber |
Reference number |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[customerNumber] |
Customer number |
filter[company] |
Company name |
filter[firstName] |
First name |
filter[lastName] |
Last name |
filter[email] |
|
filter[telephoneNumber] |
Phone |
filter[plz] |
Postal code |
filter[address] |
Address |
filter[location] |
Location |
filter[website] |
Website |
filter[customerReferenceNumber] |
Reference number |
filter[countryName] |
Country name |
DateTime Filters¶
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
B2B ID(s) | filter[id]=1,2,3 |
filter[countryId] |
Country ID(s) | filter[countryId]=1,2 |
filter[customerGroupId] |
Customer group ID(s) | filter[customerGroupId]=5 |
filter[crmTagId] |
CRM tag ID(s) | filter[crmTagId]=2,3 |
filter[customerTagId] |
Customer tag ID(s) | filter[customerTagId]=1 |
filter[sellerId] |
Seller ID(s) | filter[sellerId]=4 |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: customer number, company, first name, last name, email, phone |
Example Requests¶
# Basic request
GET /api/aiconeo/b2b
# With includes
GET /api/aiconeo/b2b?include=customerGroups,crmTags,sellers
# Filter by customer group
GET /api/aiconeo/b2b?filter[customerGroupId]=5&sort=company
Response¶
{
"data": [
{
"id": 1,
"type": "b2b",
"attributes": {
"customerNumber": 1234567,
"company": "Example Company",
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"email": "john@example.com",
"telephoneNumber": "+41 12 345 67 89",
"plz": "8000",
"address": "Main Street 1",
"location": "Zurich",
"website": "https://example.com",
"customerReferenceNumber": "REF-001",
"createdAt": "2026-01-15 10:30:00",
"updatedAt": "2026-01-15 11:00:00",
"version": 1,
"image": null,
"country": {
"id": 1,
"name": "Switzerland"
},
"customerGroups": [
{ "id": 1, "name": "Retail" }
],
"crmTags": [
{ "id": 1, "name": "VIP" }
],
"customerTags": [
{ "id": 1, "title": "Priority", "color": "#FF0000" }
]
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 10,
"perPage": 25,
"to": 25,
"total": 250
}
},
"links": {
"first": "...",
"last": "...",
"prev": null,
"next": "..."
}
}
B2B Detail¶
Endpoint: GET /api/aiconeo/b2b/{id}
Returns comprehensive details for a single B2B customer.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
int | B2B ID |
Response¶
Success (200):
{
"data": {
"id": 1,
"type": "b2b",
"attributes": {
"customerNumber": 1234567,
"customerReferenceNumber": "REF-001",
"formOfAddress": "Mr",
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"company": "Example Company",
"addressSupplement": null,
"plz": "8000",
"location": "Zurich",
"canton": "ZH",
"address": "Main Street 1",
"poBox": null,
"coAddress": null,
"email": "john@example.com",
"emailExtended": null,
"telephoneNumber": "+41 12 345 67 89",
"telephoneNumberExtended": null,
"secondaryPhoneNr": null,
"fax": null,
"website": "https://example.com",
"secondWebsite": null,
"vatNumber": "CHE-123.456.789",
"companyNumber": "CH-123.4.567.890-1",
"bankDetails": null,
"businessCenterNumber": null,
"collectiveAccount": null,
"proceedsAccount": null,
"proposalKst": null,
"paymentConditionNumber": null,
"birthDate": null,
"generalInterest": null,
"keywords": null,
"description": "Company description",
"communicationFormality": "formal",
"invoicingMethod": "NORMAL",
"productReturnMethod": "TRUST_BASIS",
"priority": null,
"latitude": 47.3769,
"longitude": 8.5417,
"isLead": false,
"isSupplier": false,
"isActive": true,
"shouldStopAutomaticFlow": false,
"image": "https://storage.example.com/images/b2b/1.jpg",
"highResImage": null,
"coverPhoto": null,
"highResCoverPhoto": null,
"createdAt": "2026-01-15 10:30:00",
"updatedAt": "2026-01-15 11:00:00",
"archivedAt": null,
"lastMovementDate": null,
"version": 5,
"country": {
"id": 1,
"name": "Switzerland",
"code": "CH"
},
"currency": {
"id": 1,
"name": "Swiss Franc",
"key": "CHF"
},
"mainContact": {
"id": 10,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com",
"telephoneNumber": "+41 12 345 67 90"
},
"documentLanguage": {
"id": 1,
"name": "German",
"locale": "de_CH"
},
"emailLanguage": {
"id": 1,
"name": "German",
"locale": "de_CH"
},
"customerGroups": [
{ "id": 1, "name": "Retail" }
],
"crmTags": [
{ "id": 1, "name": "VIP" }
],
"customerTags": [
{ "id": 1, "title": "Priority", "color": "#FF0000" }
],
"sellers": [
{ "id": 1, "name": "John Sales", "logo": null, "isActive": true }
],
"brands": [
{ "id": 1, "name": "Brand A" }
],
"contacts": [
{
"id": 10,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com",
"phone": "+41 12 345 67 90",
"image": null
}
],
"customFields": {
"custom_field_1": "value1"
}
}
}
}
Not Found (404):
Forbidden (403):
{
"errors": [
{
"status": "403",
"title": "Forbidden",
"detail": "You do not have permission to access this B2B."
}
]
}
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/b2b/1" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
B2B Create¶
Endpoint: POST /api/aiconeo/b2b
Creates a new B2B entity with minimal data.
Request Body (JSON:API format)¶
{
"data": {
"type": "b2b",
"attributes": {
"company": "Company Name",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com"
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "b2b" |
data.attributes.company |
string | No | Company name |
data.attributes.firstName |
string | No | First name |
data.attributes.lastName |
string | No | Last name |
data.attributes.email |
string | No | Email address |
Note: The customerNumber is auto-generated and cannot be set via the API.
Response¶
Success (201 Created):
{
"data": {
"type": "b2b",
"id": "1",
"attributes": {
"company": "Company Name",
"customerNumber": 1234567,
"version": 1,
"createdAt": "2026-01-15T10:30:00+00:00"
}
}
}
Validation Error (400) - Invalid Type:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Invalid or missing resource type. Expected \"b2b\".",
"source": {
"pointer": "/data/type"
}
}
]
}
Example Request¶
curl -X POST "http://127.0.0.1/api/aiconeo/b2b" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"data": {"type": "b2b", "attributes": {"company": "New Company", "email": "contact@company.com"}}}'
B2B Update (Collaborative Editing)¶
Endpoint: PATCH /api/aiconeo/b2b/{id}
Updates B2B fields with optimistic locking (version checking) to prevent conflicts during collaborative editing.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
int | B2B ID |
Request Body (JSON:API format)¶
{
"data": {
"type": "b2b",
"id": "123",
"attributes": {
"company": "Updated Company Name",
"email": "newemail@example.com",
"version": 5
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "b2b" |
data.id |
string | No | Resource ID (if provided, must match URL) |
data.attributes.version |
int | Yes | Current version of the record (for conflict detection) |
data.attributes.company |
string | No | Company name |
data.attributes.customerNumber |
string | No | Customer number |
data.attributes.firstName |
string | No | First name |
data.attributes.lastName |
string | No | Last name |
data.attributes.email |
string | No | Email address |
| ...other attributes | mixed | No | Any other B2B fields |
Response¶
Success (200 OK):
{
"data": {
"type": "b2b",
"id": "123",
"attributes": {
"company": "Updated Company Name",
"customerNumber": 1234567,
"version": 6,
"updatedAt": "2026-01-15T11:00:00+00:00"
}
}
}
Not Found (404):
Validation Error (400) - Invalid Type:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Invalid or missing resource type. Expected \"b2b\".",
"source": {
"pointer": "/data/type"
}
}
]
}
Validation Error (400) - ID Mismatch:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Resource ID in body does not match URL.",
"source": {
"pointer": "/data/id"
}
}
]
}
Validation Error (400) - Missing Version:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Version is required for updates.",
"source": {
"pointer": "/data/attributes/version"
}
}
]
}
Conflict (409):
When another user has modified the record since you last loaded it:
{
"errors": [
{
"status": "409",
"title": "Conflict",
"detail": "This record was modified by another user.",
"meta": {
"currentVersion": 6,
"currentData": {
"company": "Other User's Update",
"email": "other@example.com"
}
}
}
]
}
Example Request¶
curl -X PATCH "http://127.0.0.1/api/aiconeo/b2b/123" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"data": {"type": "b2b", "id": "123", "attributes": {"company": "Updated Name", "version": 5}}}'
B2C Customers¶
Endpoint: GET /api/aiconeo/b2c
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -id |
- | Sort field(s) |
include |
string | - | - | Comma-separated relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
companies |
Associated B2B companies | ✓ |
customerGroups |
Customer groups with translated names | ✓ |
crmTags |
CRM tags with translated names | ✓ |
customerTags |
Customer tags with title and color | ✓ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
B2C ID |
contactNumber |
Contact number |
firstName |
First name |
lastName |
Last name |
fullName |
Full name |
email |
Email address |
phone |
Phone number |
plz |
Postal code |
address |
Address |
city |
City |
createdAt |
Creation date |
updatedAt |
Last update date |
customerReferenceNumber |
Reference number |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[contactNumber] |
Contact number |
filter[firstName] |
First name |
filter[lastName] |
Last name |
filter[email] |
|
filter[phone] |
Phone |
filter[plz] |
Postal code |
filter[address] |
Address |
filter[city] |
City |
filter[customerReferenceNumber] |
Reference number |
DateTime Filters¶
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
B2C ID(s) | filter[id]=1,2,3 |
filter[customerGroupId] |
Customer group ID(s) | filter[customerGroupId]=5 |
filter[crmTagId] |
CRM tag ID(s) | filter[crmTagId]=2,3 |
filter[customerTagId] |
Customer tag ID(s) | filter[customerTagId]=1 |
filter[companyId] |
B2B company ID(s) | filter[companyId]=10,20 |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: contact number, email, first name, last name, phone, full name |
Example Requests¶
# Basic request
GET /api/aiconeo/b2c
# With includes
GET /api/aiconeo/b2c?include=companies,customerGroups
# Filter by company
GET /api/aiconeo/b2c?filter[companyId]=123
B2C Detail¶
Endpoint: GET /api/aiconeo/b2c/{id}
Returns comprehensive details for a single B2C contact.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
int | B2C ID |
Response¶
Success (200):
{
"data": {
"id": 1,
"type": "b2c",
"attributes": {
"contactNumber": "CNT-001",
"customerReferenceNumber": "REF-001",
"title": "Mr",
"formOfAddress": "Mr",
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"company": "Example Company",
"addressSupplement": null,
"plz": "8000",
"city": "Zurich",
"canton": "ZH",
"address": "Main Street 1",
"poBox": null,
"coAddress": null,
"email": "john@example.com",
"phone": "+41 12 345 67 89",
"secondaryPhoneNr": null,
"fax": null,
"fatherMobile": null,
"fatherEmail": null,
"motherMobile": null,
"motherEmail": null,
"website": "https://example.com",
"secondWebsite": null,
"facebook": null,
"youtube": null,
"xing": null,
"instagram": null,
"linkedin": "https://linkedin.com/in/johndoe",
"twitter": null,
"whatsapp": null,
"birthDate": "1985-05-15",
"birthplace": "Zurich",
"nationality": "Swiss",
"height": null,
"weight": null,
"hobbies": null,
"ahvNumber": null,
"sflId": null,
"jsNumber": null,
"playerPassNumber": null,
"parentClub": null,
"currentClub": null,
"soccerNation": null,
"collectiveAccount": null,
"proceedsAccount": null,
"proposalKst": null,
"paymentConditionNumber": null,
"position": "Manager",
"description": "Contact description",
"keywords": null,
"language": "de_CH",
"generalInterest": 3,
"communicationFormality": "ALWAYS_FORMAL_YOU",
"invoicingMethod": "NORMAL",
"author": null,
"latitude": "47.3769",
"longitude": "8.5417",
"isLead": false,
"isCustomer": true,
"isActive": true,
"isSpamContact": false,
"isNewsletterActive": true,
"isRegistrationRequest": false,
"shouldDisplayOnWebsite": false,
"isEmailVisibleOnLandingpageShopify": false,
"shouldStopAutomaticFlow": false,
"isUsingOwnPopUps": false,
"isDefaultPosCustomer": false,
"image": "https://storage.example.com/images/b2c/1.jpg",
"coverPhoto": null,
"gif": null,
"createdAt": "2026-01-15 10:30:00",
"updatedAt": "2026-01-15 11:00:00",
"archivedAt": null,
"lastMovementDate": null,
"entryDate": null,
"exitDate": null,
"activeFrom": null,
"activeUntil": null,
"version": 5,
"country": {
"id": 1,
"name": "Switzerland",
"code": "CH"
},
"customerGroups": [
{ "id": 1, "name": "Retail" }
],
"crmTags": [
{ "id": 1, "name": "VIP" }
],
"customerTags": [
{ "id": 1, "title": "Priority", "color": "#FF0000" }
],
"companies": [
{
"id": 10,
"company": "Example Company",
"customerNumber": 1234567,
"email": "info@example.com",
"telephoneNumber": "+41 12 345 67 00"
}
]
}
}
}
Not Found (404):
Forbidden (403):
{
"errors": [
{
"status": "403",
"title": "Forbidden",
"detail": "You do not have permission to access this B2C."
}
]
}
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/b2c/1" \
-H "Accept: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN"
B2C Create¶
Endpoint: POST /api/aiconeo/b2c
Creates a new B2C entity with minimal data.
Request Body (JSON:API format)¶
{
"data": {
"type": "b2c",
"attributes": {
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"phone": "+41 79 123 45 67"
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "b2c" |
data.attributes.firstName |
string | No | First name |
data.attributes.lastName |
string | No | Last name |
data.attributes.email |
string | No | Email address |
data.attributes.phone |
string | No | Phone number |
Note: The contactNumber is auto-generated and cannot be set via the API.
Response¶
Success (201 Created):
{
"data": {
"type": "b2c",
"id": "1",
"attributes": {
"firstName": "Jane",
"lastName": "Smith",
"contactNumber": "CNT-001",
"version": 1,
"createdAt": "2026-01-15T10:30:00+00:00"
}
}
}
Bad Request (400):
{
"errors": [{
"status": "400",
"title": "Bad Request",
"detail": "Invalid or missing resource type. Expected \"b2c\".",
"source": { "pointer": "/data/type" }
}]
}
Example Request¶
curl -X POST "http://127.0.0.1/api/aiconeo/b2c" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"data": {"type": "b2c", "attributes": {"firstName": "Jane", "lastName": "Smith", "email": "jane@example.com"}}}'
B2C Update (Collaborative Editing)¶
Endpoint: PATCH /api/aiconeo/b2c/{id}
Updates B2C fields with optimistic locking (version checking) to prevent conflicts during collaborative editing.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
int | B2C ID |
Request Body (JSON:API format)¶
{
"data": {
"type": "b2c",
"id": "456",
"attributes": {
"firstName": "Janet",
"email": "janet.new@example.com",
"version": 3
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
data.type |
string | Yes | Resource type, must be "b2c" |
data.id |
string | No | Resource ID (if provided, must match URL) |
data.attributes.version |
int | Yes | Current version of the record (for conflict detection) |
data.attributes.firstName |
string | No | First name |
data.attributes.lastName |
string | No | Last name |
data.attributes.email |
string | No | Email address |
data.attributes.phone |
string | No | Phone number |
| ...other attributes | mixed | No | Any other B2C fields |
Response¶
Success (200 OK):
{
"data": {
"type": "b2c",
"id": "456",
"attributes": {
"version": 4,
"updatedAt": "2026-01-15T11:00:00+00:00",
"firstName": "Janet",
"email": "janet.new@example.com"
}
}
}
Not Found (404):
Bad Request (400):
{
"errors": [{
"status": "400",
"title": "Bad Request",
"detail": "Version is required for updates.",
"source": { "pointer": "/data/attributes/version" }
}]
}
Conflict (409):
When another user has modified the record since you last loaded it:
{
"errors": [{
"status": "409",
"title": "Conflict",
"detail": "This record was modified by another user.",
"meta": {
"currentVersion": 4,
"currentData": {
"firstName": "Other User's Update",
"email": "other@example.com"
}
}
}]
}
Example Request¶
curl -X PATCH "http://127.0.0.1/api/aiconeo/b2c/456" \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"data": {"type": "b2c", "id": "456", "attributes": {"firstName": "Janet", "version": 3}}}'
Orders¶
Endpoint: GET /api/aiconeo/orders
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -createdAt |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
salesArea |
Sales area | ✓ |
salesChannel |
Sales channel/workflow | ✓ |
project |
Associated project with deal status | ✓ |
createdByUser |
User who created the order | ✓ |
warehouse |
Warehouse | ✓ |
shopifyShop |
Shopify shop (via ecommerce order) | ✗ |
preorder |
Preorder info with welcome message | ✗ |
orderDocuments |
Count of order documents | ✗ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Order ID |
orderNumber |
Order number |
externalOrderNumber |
External order number |
title |
Order title |
date |
Order date |
preorderDate |
Preorder date |
buyerName |
Buyer name |
openAmount |
Open amount |
createdAt |
Creation date |
updatedAt |
Last update date |
statusName |
Status name |
substatusName |
Substatus name |
salesAreaName |
Sales area name |
salesChannelName |
Sales channel name |
warehouseName |
Warehouse name |
sellerName |
Seller name |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[orderNumber] |
Order number |
filter[externalOrderNumber] |
External order number |
filter[title] |
Order title |
filter[buyerName] |
Buyer name |
filter[statusName] |
Status name |
filter[substatusName] |
Substatus name |
filter[salesAreaName] |
Sales area name |
filter[salesChannelName] |
Sales channel name |
filter[warehouseName] |
Warehouse name |
filter[currencyName] |
Currency name |
DateTime Filters¶
Supports all datetime filter operators.
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
filter[date] |
Order date |
filter[preorderDate] |
Preorder date |
filter[archivedAt] |
Archived date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Order ID(s) | filter[id]=1,2,3 |
filter[statusId] |
Status ID(s) | filter[statusId]=5,10 |
filter[substatusId] |
Substatus ID(s) | filter[substatusId]=3 |
filter[salesAreaId] |
Sales area ID(s) | filter[salesAreaId]=1,2 |
filter[salesChannelId] |
Sales channel ID(s) | filter[salesChannelId]=1 |
filter[warehouseId] |
Warehouse ID(s) | filter[warehouseId]=3 |
filter[projectId] |
Project ID(s) | filter[projectId]=100 |
filter[currencyId] |
Currency ID(s) | filter[currencyId]=1 |
filter[ecommerceOrderId] |
Ecommerce order ID(s) | filter[ecommerceOrderId]=50 |
Boolean Filters¶
| Filter | Description | Example |
|---|---|---|
filter[isChecked] |
Is checked | filter[isChecked]=true |
filter[isFlowRunning] |
Is flow running | filter[isFlowRunning]=false |
filter[isArchived] |
Is archived | filter[isArchived]=false |
Numeric Filters¶
| Filter | Description | Example |
|---|---|---|
filter[openAmountMin] |
Minimum open amount | filter[openAmountMin]=100 |
filter[openAmountMax] |
Maximum open amount | filter[openAmountMax]=1000 |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: order number, external order number, title, buyer name |
Example Requests¶
# Basic request
GET /api/aiconeo/orders
# With includes and pagination
GET /api/aiconeo/orders?include=salesArea,project,warehouse&page[number]=1&page[size]=50
# Filter by status
GET /api/aiconeo/orders?filter[statusId]=5&sort=-createdAt
# Filter by date range
GET /api/aiconeo/orders?filter[date][dateBetween]=2024-01-01,2024-12-31
# Active orders only
GET /api/aiconeo/orders?filter[isArchived]=false&filter[statusId]=1,2,3
# Complex query
GET /api/aiconeo/orders?include=project,shopifyShop&filter[salesAreaId]=2&filter[openAmountMin]=500&sort=-openAmount
Order Documents¶
Endpoint: GET /api/aiconeo/order-documents
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -createdAt |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
warehouse |
Warehouse information | ✓ |
createdByUser |
User who created the document | ✓ |
currency |
Currency (id, name) | ✓ |
positionGroup |
Position group totals | ✗ |
trackingNumbers |
Tracking numbers | ✗ |
payments |
Payment matchings | ✗ |
childDocuments |
Count of child documents | ✗ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Document ID |
documentNumber |
Document number |
type |
Document type |
date |
Document date |
validUntil |
Valid until date |
totalExclVat |
Total excl. VAT |
totalInclVat |
Total incl. VAT |
deliveryDate |
Delivery date |
dueDate |
Due date |
createdAt |
Creation date |
updatedAt |
Last update date |
orderNumber |
Order number |
buyerName |
Buyer name |
orderTitle |
Order title |
documentTypeName |
Document type name |
documentStatusName |
Document status name |
warehouseName |
Warehouse name |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[documentNumber] |
Document number |
filter[type] |
Document type |
filter[referenceNumber] |
Reference number |
filter[titleText] |
Title text |
filter[orderNumber] |
Order number |
filter[orderTitle] |
Order title |
filter[buyerName] |
Buyer name |
filter[externalOrderNumber] |
External order number |
filter[documentTypeName] |
Document type name |
filter[documentStatusName] |
Document status name |
filter[warehouseName] |
Warehouse name |
DateTime Filters¶
Supports all datetime filter operators.
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
filter[date] |
Document date |
filter[validUntil] |
Valid until |
filter[deliveryDate] |
Delivery date |
filter[dueDate] |
Due date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Document ID(s) | filter[id]=1,2,3 |
filter[orderId] |
Order ID(s) | filter[orderId]=10,20 |
filter[orderDocumentTypeId] |
Document type ID(s) | filter[orderDocumentTypeId]=1,2 |
filter[documentStatusId] |
Status ID(s) | filter[documentStatusId]=5 |
filter[warehouseId] |
Warehouse ID(s) | filter[warehouseId]=3 |
filter[parentDocumentId] |
Parent document ID(s) | filter[parentDocumentId]=100 |
Boolean Filters¶
| Filter | Description | Example |
|---|---|---|
filter[isCancelled] |
Is cancelled | filter[isCancelled]=true |
filter[isActive] |
Is active | filter[isActive]=true |
filter[isArchived] |
Is archived | filter[isArchived]=false |
Numeric Filters¶
| Filter | Description | Example |
|---|---|---|
filter[totalExclVatMin] |
Minimum total excl. VAT | filter[totalExclVatMin]=100 |
filter[totalExclVatMax] |
Maximum total excl. VAT | filter[totalExclVatMax]=1000 |
filter[totalInclVatMin] |
Minimum total incl. VAT | filter[totalInclVatMin]=100 |
filter[totalInclVatMax] |
Maximum total incl. VAT | filter[totalInclVatMax]=1000 |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: document number, reference number, order number, buyer name, order title |
Example Requests¶
# Basic request
GET /api/aiconeo/order-documents
# With includes and pagination
GET /api/aiconeo/order-documents?include=warehouse,positionGroup,trackingNumbers&page[number]=1&page[size]=50
# Filter by order
GET /api/aiconeo/order-documents?filter[orderId]=123
# Filter invoices by date range
GET /api/aiconeo/order-documents?filter[orderDocumentTypeId]=3&filter[date][dateBetween]=2024-01-01,2024-12-31
# Active non-cancelled documents only
GET /api/aiconeo/order-documents?filter[isActive]=true&filter[isCancelled]=false&filter[isArchived]=false
Ecommerce Orders¶
Endpoint: GET /api/aiconeo/ecommerce-orders
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -createdAt |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
seller |
Seller via debtor | ✓ |
currency |
Currency (id, name) | ✓ |
aicoShopOrder |
Aico shop order with payment session status | ✗ |
shippingCountry |
Shipping country | ✗ |
billingCountry |
Billing country | ✗ |
lineItems |
Order line items | ✗ |
order |
Associated AICO order | ✗ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Order ID |
orderNumber |
Order number |
externalOrderNumber |
External order number |
sageOrderNumber |
Sage order number |
date |
Order date |
totalPrice |
Total price |
financialStatus |
Financial status |
fulfillmentStatus |
Fulfillment status |
shipmentStatus |
Shipment status |
createdAt |
Creation date |
updatedAt |
Last update date |
customerName |
Customer name |
organisationName |
Organisation/company name |
shopifyShopName |
Shopify shop name |
sellerName |
Seller name |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[orderNumber] |
Order number |
filter[externalOrderNumber] |
External order number |
filter[sageOrderNumber] |
Sage order number |
filter[sageExternalNumber] |
Sage external number |
filter[customerName] |
Customer name (computed) |
filter[organisationName] |
B2B company name |
filter[shopifyShopName] |
Shopify shop name |
filter[sellerName] |
Seller name |
filter[financialStatus] |
Financial status |
filter[fulfillmentStatus] |
Fulfillment status |
filter[shipmentStatus] |
Shipment status |
filter[tags] |
Tags |
filter[note] |
Note |
filter[paymentType] |
Payment type |
filter[cancelReason] |
Cancel reason |
filter[shippingCity] |
Shipping city |
filter[shippingZip] |
Shipping zip |
filter[billingCity] |
Billing city |
filter[billingZip] |
Billing zip |
DateTime Filters¶
Supports all datetime filter operators.
| Filter | Column |
|---|---|
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
filter[date] |
Order date |
filter[deliveryDate] |
Delivery date |
filter[cancelledAt] |
Cancelled date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Order ID(s) | filter[id]=1,2,3 |
filter[shopId] |
Shop ID(s) | filter[shopId]=5,10 |
filter[customerId] |
Customer ID(s) | filter[customerId]=100 |
filter[aicoPosOrderId] |
AICO POS order ID(s) | filter[aicoPosOrderId]=50 |
Boolean Filters¶
| Filter | Description | Example |
|---|---|---|
filter[isCancelled] |
Is cancelled | filter[isCancelled]=false |
filter[isPos] |
Is POS order | filter[isPos]=true |
filter[hasTransactionNumber] |
Has transaction number | filter[hasTransactionNumber]=true |
Numeric Filters¶
| Filter | Description | Example |
|---|---|---|
filter[totalPriceMin] |
Minimum total price | filter[totalPriceMin]=50 |
filter[totalPriceMax] |
Maximum total price | filter[totalPriceMax]=500 |
Global Search¶
| Filter | Description |
|---|---|
filter[search] |
Searches: order number, external order number, sage order number, customer name, organisation name |
Example Requests¶
# Basic request
GET /api/aiconeo/ecommerce-orders
# With includes and pagination
GET /api/aiconeo/ecommerce-orders?include=seller,currency,lineItems&page[number]=1&page[size]=50
# Filter by shop
GET /api/aiconeo/ecommerce-orders?filter[shopId]=5&sort=-createdAt
# Filter by status
GET /api/aiconeo/ecommerce-orders?filter[fulfillmentStatus][equals]=fulfilled&filter[isCancelled]=false
# Filter by date range
GET /api/aiconeo/ecommerce-orders?filter[date][dateBetween]=2024-01-01,2024-12-31
# POS orders only
GET /api/aiconeo/ecommerce-orders?filter[isPos]=true
# Complex query
GET /api/aiconeo/ecommerce-orders?include=lineItems,order&filter[shopId]=3&filter[financialStatus][equals]=paid&filter[totalPriceMin]=100
Tasks¶
Endpoint: GET /api/aiconeo/tasks
High-performance task list endpoint with advanced filtering, sorting, and relationship loading.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | -id |
- | Sort field(s), prefix with - for descending |
include |
string | - | - | Comma-separated list of relationships |
filter[field] |
mixed | - | - | Filter by field |
Includes¶
| Include | Description | Default |
|---|---|---|
mainAssignee |
Main assignee user with profile photo | ✓ |
creator |
User who created the task | ✓ |
project |
Associated project | ✓ |
type |
Task type with color | ✓ |
customer |
B2B customer | ✗ |
assignees |
All assignees (JSON aggregation) | ✗ |
watchers |
Task watchers (JSON aggregation) | ✗ |
tags |
Task tags (JSON aggregation) | ✗ |
subTasks |
Subtasks count | ✗ |
timer |
Timer information | ✗ |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Task ID |
title |
Task title |
startDate |
Start date |
dueDate |
Due date |
deadline |
Deadline |
priority |
Priority |
estimation |
Time estimation |
billingStatus |
Billing status |
createdAt |
Creation date |
updatedAt |
Last update date |
statusName |
Status name |
projectName |
Project name |
taskTypeName |
Task type name |
Text Filters¶
Supports all text filter operators.
| Filter | Column |
|---|---|
filter[title] |
Task title |
filter[description] |
Description |
filter[website] |
Website |
filter[notes] |
Notes |
DateTime Filters¶
Supports all datetime filter operators.
| Filter | Column |
|---|---|
filter[startDate] |
Start date |
filter[dueDate] |
Due date |
filter[deadline] |
Deadline |
filter[createdAt] |
Creation date |
filter[updatedAt] |
Last update date |
Relationship Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Task ID(s) | filter[id]=1,2,3 |
filter[statusId] |
Status ID(s) | filter[statusId]=5,10 |
filter[projectId] |
Project ID(s) | filter[projectId]=3 |
filter[taskTypeId] |
Task type ID(s) | filter[taskTypeId]=1,2 |
filter[assigneeId] |
Main assignee ID(s) | filter[assigneeId]=5 |
filter[creatorId] |
Creator ID(s) | filter[creatorId]=10 |
filter[parentId] |
Parent task ID(s), use null for top-level |
filter[parentId]=null |
Other Filters¶
| Filter | Description | Example |
|---|---|---|
filter[priority] |
Priority value(s) | filter[priority]=High,Critical |
filter[billingStatus] |
Billing status value(s) | filter[billingStatus]=Billable |
filter[isPrivate] |
Is private task | filter[isPrivate]=false |
filter[isHardDeadline] |
Has hard deadline | filter[isHardDeadline]=true |
filter[isCompleted] |
Is completed | filter[isCompleted]=false |
filter[search] |
Global search (title, description, website) | filter[search]=urgent |
Visibility & Permissions¶
- Respects user permissions (
CAN_SEE_ALL_TASKS,CAN_SEE_OWN_TASKS) - Filters private tasks (only visible to creator and main assignee)
- Guest users see only tasks for their associated organizations
- Users with
CAN_SEE_OWN_TASKSsee tasks where they are: - Main assignee
- Creator
- Additional assignee
- Watcher
Example Requests¶
# Basic request
GET /api/aiconeo/tasks
# With includes and pagination
GET /api/aiconeo/tasks?include=mainAssignee,project,type,assignees&page[number]=1&page[size]=50
# Filter by status and project
GET /api/aiconeo/tasks?filter[statusId]=1,2,3&filter[projectId]=10&sort=-dueDate
# Filter by date range
GET /api/aiconeo/tasks?filter[dueDate][dateBetween]=2024-01-01,2024-12-31
# Active tasks only (not completed)
GET /api/aiconeo/tasks?filter[isCompleted]=false&filter[priority]=High,Critical
# My tasks
GET /api/aiconeo/tasks?filter[assigneeId]=5&filter[isCompleted]=false&sort=-priority
# Search tasks
GET /api/aiconeo/tasks?filter[search]=urgent&include=mainAssignee,project
Response Structure¶
{
"data": [
{
"id": 123,
"type": "tasks",
"attributes": {
"title": "Implement new feature",
"description": "Add user authentication",
"startDate": "2024-01-15",
"dueDate": "2024-01-30",
"deadline": null,
"priority": "High",
"estimation": 8,
"url": null,
"website": "https://example.com/task/123",
"billingStatus": "Billable",
"isPrivate": false,
"isHardDeadline": false,
"notes": null,
"createdAt": "2024-01-10 09:00:00",
"updatedAt": "2024-01-15 14:30:00",
"status": {
"id": 2,
"name": "In Progress",
"color": "#3B82F6",
"webName": "In Progress"
},
"mainAssignee": {
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
},
"creator": {
"id": 10,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com"
},
"project": {
"id": 3,
"name": "Website Redesign",
"statusId": 1
},
"type": {
"id": 1,
"name": "Development",
"color": "#10B981"
},
"assignees": [
{
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
}
],
"subTasksCount": 3,
"timer": {
"id": 50,
"totalTime": 14400,
"isRunning": false
}
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 5,
"perPage": 25,
"to": 25,
"total": 125
}
},
"links": {
"first": "http://example.com/api/aiconeo/tasks?page[number]=1&page[size]=25",
"last": "http://example.com/api/aiconeo/tasks?page[number]=5&page[size]=25",
"prev": null,
"next": "http://example.com/api/aiconeo/tasks?page[number]=2&page[size]=25"
}
}
Task Detail¶
Endpoint: GET /api/aiconeo/tasks/{id}
Get comprehensive details for a single task with all related data.
Response Includes¶
| Data | Description |
|---|---|
| Basic fields | Title, description, dates, priority, estimation, billing status, flags |
| Status | Status with color and web name |
| Main assignee | User with profile photo |
| Creator | User who created the task |
| Project | Project details with status |
| Task type | Type with color |
| Customer | B2B customer information |
| Timer | Timer with all time logs |
| Assignees | All assigned users |
| Watchers | All watchers |
| Attachments | Task attachments with file info |
| Sub-tasks | All subtasks with their status |
Example Request¶
Example Response¶
{
"data": {
"id": 123,
"type": "tasks",
"attributes": {
"title": "Implement new feature",
"description": "Add user authentication with OAuth2",
"startDate": "2024-01-15",
"dueDate": "2024-01-30",
"deadline": null,
"startTime": "09:00:00",
"dueTime": "17:00:00",
"priority": "High",
"estimation": 8,
"url": "https://jira.example.com/PROJ-123",
"website": "https://example.com/task/123",
"billingStatus": "Billable",
"isPrivate": false,
"isHardDeadline": false,
"notes": "Remember to update documentation",
"createdAt": "2024-01-10 09:00:00",
"updatedAt": "2024-01-15 14:30:00",
"status": {
"id": 2,
"name": "In Progress",
"color": "#3B82F6",
"webName": "In Progress"
},
"mainAssignee": {
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
},
"creator": {
"id": 10,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com"
},
"project": {
"id": 3,
"name": "Website Redesign",
"statusId": 1
},
"type": {
"id": 1,
"name": "Development",
"color": "#10B981"
},
"customer": {
"id": 50,
"company": "Acme Corp"
},
"timer": {
"id": 50,
"logs": [
{
"id": 100,
"userId": 5,
"startTime": "2024-01-15 09:00:00",
"endTime": "2024-01-15 12:00:00",
"trackedTime": 10800,
"createdAt": "2024-01-15 12:00:00"
}
]
},
"assignees": [
{
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
},
{
"id": 7,
"firstName": "Bob",
"lastName": "Wilson",
"email": "bob@example.com",
"profilePhotoPath": "/storage/photos/bob.jpg"
}
],
"watchers": [
{
"id": 10,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com"
}
],
"attachments": [
{
"id": 1,
"fileName": "requirements.pdf",
"filePath": "/storage/attachments/requirements.pdf",
"fileSize": 1024000,
"mimeType": "application/pdf",
"createdAt": "2024-01-10 10:00:00"
}
],
"subTasks": [
{
"id": 124,
"title": "Setup OAuth provider",
"dueDate": "2024-01-20",
"priority": "High",
"status": {
"id": 3,
"name": "Complete",
"color": "#10B981"
}
},
{
"id": 125,
"title": "Implement login flow",
"dueDate": "2024-01-25",
"priority": "High",
"status": {
"id": 2,
"name": "In Progress",
"color": "#3B82F6"
}
}
]
}
}
}
Task Logs¶
Endpoint: GET /api/aiconeo/tasks/{id}/logs
Get the change history for a task, showing all modifications made to the task.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 50 | 200 | Items per page |
Log Fields¶
| Field | Type | Description |
|---|---|---|
id |
int | Log ID |
changeType |
string | Type of change (new, edit, delete, reminder, etc.) |
modelId |
int | Task ID |
emailPreview |
string | Email preview text (for reminders) |
createdAt |
datetime | When the change occurred |
logHistory |
object | History record with user information |
logChanges |
array | Detailed field changes |
Change Types¶
| Type | Description |
|---|---|
new |
Task created |
edit |
Task edited |
delete |
Task deleted |
reminder |
Reminder sent |
slack_reminder |
Slack reminder sent |
email_reminder |
Email reminder sent |
stop_timer |
Timer stopped |
edit_timer |
Timer edited |
delete_timer |
Timer deleted |
Example Request¶
Example Response¶
{
"data": [
{
"id": 500,
"type": "logs",
"attributes": {
"changeType": "edit",
"modelId": 123,
"emailPreview": null,
"createdAt": "2024-01-15 14:30:00",
"updatedAt": "2024-01-15 14:30:00",
"logHistory": {
"id": 450,
"userId": 5,
"user": {
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
}
},
"logChanges": [
{
"id": 1000,
"fieldChanged": "status",
"oldValue": "To Do",
"newValue": "In Progress",
"createdAt": "2024-01-15 14:30:00",
"updatedAt": "2024-01-15 14:30:00"
},
{
"id": 1001,
"fieldChanged": "priority",
"oldValue": "Medium",
"newValue": "High",
"createdAt": "2024-01-15 14:30:00",
"updatedAt": "2024-01-15 14:30:00"
}
]
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 3,
"perPage": 50,
"to": 50,
"total": 150
}
},
"links": {
"first": "http://example.com/api/aiconeo/tasks/123/logs?page[number]=1&page[size]=50",
"last": "http://example.com/api/aiconeo/tasks/123/logs?page[number]=3&page[size]=50",
"prev": null,
"next": "http://example.com/api/aiconeo/tasks/123/logs?page[number]=2&page[size]=50"
}
}
Task Comments¶
Endpoint: GET /api/aiconeo/tasks/{id}/comments
Get all comments for a task with attachments and reactions.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 50 | 200 | Items per page |
Comment Fields¶
| Field | Type | Description |
|---|---|---|
id |
int | Comment ID |
text |
string | Comment text |
author |
string | Author name (for external comments) |
chatBoxId |
int | Chat box ID |
createdAt |
datetime | When comment was created |
updatedAt |
datetime | Last update time |
user |
object | User who created the comment |
attachments |
array | File attachments |
reactions |
array | Emoji reactions |
Example Request¶
Example Response¶
{
"data": [
{
"id": 1000,
"type": "chatMessages",
"attributes": {
"text": "I've completed the OAuth setup. Ready for review.",
"author": null,
"chatBoxId": 50,
"createdAt": "2024-01-20 15:30:00",
"updatedAt": "2024-01-20 15:30:00",
"user": {
"id": 5,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"profilePhotoPath": "/storage/photos/john.jpg"
},
"attachments": [
{
"id": 10,
"fileName": "oauth-config.json",
"filePath": "/storage/chat/oauth-config.json",
"fileSize": 2048,
"mimeType": "application/json",
"createdAt": "2024-01-20 15:30:00"
}
],
"reactions": [
{
"id": 1,
"reaction": "👍",
"userId": 10,
"userName": "Jane Smith"
},
{
"id": 2,
"reaction": "🎉",
"userId": 7,
"userName": "Bob Wilson"
}
]
}
},
{
"id": 999,
"type": "chatMessages",
"attributes": {
"text": "Great! I'll review it today.",
"author": null,
"chatBoxId": 50,
"createdAt": "2024-01-20 16:00:00",
"updatedAt": "2024-01-20 16:00:00",
"user": {
"id": 10,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"profilePhotoPath": "/storage/photos/jane.jpg"
},
"attachments": [],
"reactions": []
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 2,
"perPage": 50,
"to": 50,
"total": 75
}
},
"links": {
"first": "http://example.com/api/aiconeo/tasks/123/comments?page[number]=1&page[size]=50",
"last": "http://example.com/api/aiconeo/tasks/123/comments?page[number]=2&page[size]=50",
"prev": null,
"next": "http://example.com/api/aiconeo/tasks/123/comments?page[number]=2&page[size]=50"
}
}
Warehouses¶
Base Endpoint: GET /api/v1/warehouses
Standard JSON:API endpoint for warehouse management.
Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/warehouses |
List all warehouses |
| GET | /api/v1/warehouses/{id} |
Get single warehouse |
| GET | /api/v1/warehouses/virtual-warehouse-availability |
Get virtual warehouse availability |
| GET | /api/v1/warehouses/virtual-warehouse-availability-display |
Get availability display message |
| GET | /api/v1/warehouses/virtual-warehouse-next-stock-increases |
Get next stock increases |
| GET | /api/v1/warehouses/{id}/bin-locations |
Get bin locations by warehouse |
| GET | /api/v1/warehouses/{id}/articles |
Get articles by warehouse |
| GET | /api/v1/warehouses/articles/{articleId}/stocks |
Get warehouses with stocks by article |
| GET | /api/v1/warehouses/articles/stocks |
Get warehouses with article stocks |
| GET | /api/v1/warehouses/{id}/products/{productId}/stocks |
Get product stocks for warehouse |
| GET | /api/v1/warehouses/products/{productId}/stocks |
Get product stocks for all warehouses |
| GET | /api/v1/warehouses/{id}/inventories |
Get inventory for warehouse |
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
page[number] |
int | 1 | Page number |
page[size] |
int | - | Items per page |
Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Warehouse ID(s) | filter[id]=1,2,3 |
filter[shopifyShop.id] |
Shopify shop ID | filter[shopifyShop.id]=5 |
filter[wmsVisibility] |
WMS visibility | filter[wmsVisibility]=true |
Sortable Fields¶
| Field | Description |
|---|---|
createdAt |
Creation date |
updatedAt |
Last update date |
Response Fields¶
| Field | Type | Description |
|---|---|---|
id |
integer | Warehouse ID |
name |
string | Warehouse name |
country |
string | Country |
address |
string | Address |
createdAt |
datetime | Creation timestamp |
updatedAt |
datetime | Last update timestamp |
Example Requests¶
# List all warehouses
GET /api/v1/warehouses
# Get single warehouse
GET /api/v1/warehouses/5
# With pagination
GET /api/v1/warehouses?page[number]=1&page[size]=25
# Get product stocks
GET /api/v1/warehouses/products/123/stocks
Time Tracking¶
Base URL: https://app.aico.swiss/{workspaceId}/api/v1
Time tracking endpoints for managing timer logs, weekly views, and team time sheets.
Timer Logs Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /timer-logs/results-for-date |
Get user timer results for a specific date |
| GET | /timer-logs/results-for-interval |
Get user timer results for a date interval |
| GET | /timer-logs/projects |
Get projects list for timer selection |
| GET | /timer-logs/weekly |
Get weekly timer logs with daily aggregations |
| GET | /timer-logs/team |
Get team timer logs (Admin only) |
| GET | /timer-logs/staff-search |
Search staff members for dropdown (Admin only) |
| GET | /timer-logs/reports |
Get time tracking reports (day/week/month/year) |
| POST | /timer-logs/create |
Create a new timer log entry |
| POST | /timer-logs/manual-entry |
Create a manual time entry |
| POST | /timer-logs/{id}/start |
Start a timer for existing timer log |
| POST | /timer-logs/{id}/restart |
Restart a stopped timer |
| POST | /timer-logs/{id}/stop |
Stop an active timer |
| PUT | /timer-logs/{id} |
Update a timer log entry |
| DELETE | /timer-logs/{id} |
Delete a timer log entry |
Staff Member Timer Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /staff-members/{id}/timer-results-for-interval |
Get staff member's timer results for interval |
| GET | /staff-members/{id}/active-timer |
Get staff member's active timer |
| POST | /staff-members/{id}/start |
Start timer for staff member |
| POST | /staff-members/{id}/stop |
Stop timer for staff member |
GET /timer-logs/results-for-date¶
Get user timer results for a specific date.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
date |
number | Yes | Unix timestamp for the date |
page[number] |
number | No | Page number for pagination |
page[size] |
number | No | Page size for pagination |
Response¶
{
"data": [
{
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T09:00:00+00:00",
"endTime": "2026-01-14T11:30:00+00:00",
"trackedTime": "02:30:00",
"isActive": false,
"notes": "Work description"
}
],
"paginator": { ... }
}
GET /timer-logs/results-for-interval¶
Get user timer results for a date interval.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
startDate |
number | Yes | Unix timestamp for start date |
endDate |
number | No | Unix timestamp for end date (defaults to now) |
page[number] |
number | No | Page number for pagination |
page[size] |
number | No | Page size for pagination |
Response¶
{
"data": [
{
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T09:00:00+00:00",
"endTime": "2026-01-14T11:30:00+00:00",
"trackedTime": "02:30:00",
"isActive": false,
"notes": "Work description"
}
],
"paginator": { ... }
}
GET /timer-logs/weekly¶
Fetch timer logs for a specific week with daily aggregations.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
weekStart |
number | Yes | Unix timestamp (Monday 00:00:00) |
weekEnd |
number | Yes | Unix timestamp (Sunday 23:59:59) |
Response¶
{
"data": {
"userId": 123,
"staffMemberId": 456,
"dailyTotals": {
"mon": 28800,
"tue": 32400,
"wed": 25200,
"thu": 28800,
"fri": 21600,
"sat": 0,
"sun": 0
},
"weekTotal": 136800,
"trackedHours": 38.0,
"isTracking": true,
"activeEntry": {
"id": 456,
"taskId": 789,
"taskName": "Task Title",
"startTime": "2026-01-14T09:00:00+00:00"
},
"entries": [
{
"id": 123,
"date": "2026-01-14",
"startTime": "09:03",
"endTime": "11:05",
"durationSeconds": 7320,
"isActive": false,
"description": "Work notes",
"task": {
"id": 456,
"name": "Task Title",
"urlKey": "task-123",
"url": "https://app.aico.swiss/tasks/task-123",
"estimatedHours": "8h",
"totalTrackedSeconds": 28800
},
"project": {
"id": 789,
"name": "Project Name",
"projectType": "CLIENT",
"clientName": "Customer Inc"
}
}
],
"report": {
"internalCost": 2850.00,
"billableCost": 3800.00,
"billableTotal": 3800.00,
"margin": 25.0,
"marginAmount": 950.00
}
}
}
Notes:
- dailyTotals values are in seconds (calculated from timer_logs)
- weekTotal is the total tracked seconds (from cached staff_member_reports if available)
- trackedHours is the tracked hours as decimal (from cached report)
- activeEntry is null if no timer is currently running
- Active entries have endTime: null and isActive: true
- report contains cached financial data from staff_member_reports table (null if no cached report exists)
GET /timer-logs/team (Admin Only)¶
Fetch timer logs for all team members.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
weekStart |
number | Yes | Unix timestamp |
weekEnd |
number | Yes | Unix timestamp |
page |
number | No | Page number (default: 1) |
pageSize |
number | No | Items per page (default: 50) |
searchTerm |
string | No | Filter by staff name |
Response¶
{
"data": [
{
"userId": 123,
"staffMemberId": 456,
"userName": "John Doe",
"userAvatar": "https://ui-avatars.com/api/?name=John+Doe",
"dailyTotals": {
"mon": 28800,
"tue": 32400,
"wed": 25200,
"thu": 28800,
"fri": 21600,
"sat": 0,
"sun": 0
},
"weekTotal": 136800,
"trackedHours": 38.0,
"isTracking": true,
"currentTaskName": "Current Task Title",
"entries": [],
"report": {
"internalCost": 2850.00,
"billableCost": 3800.00,
"billableTotal": 3800.00,
"margin": 25.0,
"marginAmount": 950.00
}
}
],
"meta": {
"total": 25,
"page": 1,
"pageSize": 50
},
"permissions": {
"canViewTeam": true,
"canEditTeam": true
}
}
Permission Check:
- Returns empty data with permissions.canViewTeam: false if user lacks admin permissions
- Requires can_view_team_time_tracking or can_read_staff_members_tracker_results permission
- report contains cached financial data from staff_member_reports table (null if no cached report exists)
GET /timer-logs/staff-search (Admin Only)¶
Search staff members for the teammate selector dropdown.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
searchTerm |
string | No | Search by name or email |
weekStart |
number | No | Include week stats if provided |
weekEnd |
number | No | Include week stats if provided |
Response¶
{
"data": [
{
"staffMemberId": "550e8400-e29b-41d4-a716-446655440000",
"externalId": 123,
"name": "John Doe",
"avatar": "https://ui-avatars.com/api/?name=John+Doe",
"email": "john.doe@example.com",
"weekTotal": 136800,
"isTracking": true
}
]
}
Notes:
- weekTotal and isTracking are only included if weekStart and weekEnd are provided
- Returns 403 Forbidden if user lacks admin permissions
- Limited to 50 results
GET /timer-logs/reports¶
Get time tracking reports for day, week, month, or year periods. Uses cached data from staff_member_reports table when available.
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
period |
string | Yes | Report period: day, week, month, or year |
date |
number | Yes | Unix timestamp for the reference date |
Response¶
{
"data": {
"userId": 123,
"staffMemberId": 456,
"userName": "John Doe",
"period": "week",
"requestedDate": "2026-01-14",
"totalTrackedHours": 152.5,
"totalTrackedSeconds": 549000,
"reports": [
{
"startDate": "2026-01-06",
"endDate": "2026-01-12",
"label": "W2",
"trackedHours": 38.0,
"trackedSeconds": 136800,
"internalCost": 2850.00,
"billableCost": 3800.00,
"billableTotal": 3800.00,
"margin": 25.0,
"marginAmount": 950.00,
"isCached": true
},
{
"startDate": "2026-01-13",
"endDate": "2026-01-19",
"label": "W3",
"trackedHours": 40.0,
"trackedSeconds": 144000,
"isCached": false
}
]
}
}
Period Behaviors:
| Period | Returns | Label Format |
|---|---|---|
day |
Each day of the week containing the date | Mon, Tue, etc. |
week |
Each week of the month containing the date | W1, W2, etc. |
month |
Each month of the year containing the date | Jan, Feb, etc. |
year |
Last 5 years including the current year | 2022, 2023, etc. |
Notes:
- isCached: true indicates data is from staff_member_reports table (includes financial data)
- isCached: false indicates data is calculated on-the-fly from timer_logs (no financial data)
- Financial fields (internalCost, billableCost, etc.) are only included when isCached: true
- Returns 404 if staff member not found for user
POST /timer-logs/create¶
Create a new timer log entry and start tracking.
Request Body¶
| Parameter | Type | Required | Description |
|---|---|---|---|
taskId |
number | Conditional | Required if no projectId |
projectId |
number | Conditional | Required if no taskId |
userId |
number | No | AICO user ID (defaults to current user) |
notes |
string | No | Description/notes |
trackedTime |
string | No | Pre-tracked time (format: HH:mm:ss) |
createdAt |
number | No | Unix timestamp for entry date |
Response¶
{
"data": {
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T09:00:00+00:00",
"endTime": null,
"trackedTime": "00:00:00",
"isActive": true,
"notes": null
}
}
POST /timer-logs/manual-entry¶
Create a manual time entry with specific start and end times.
Request Body¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
taskId |
number | Yes | AICO task ID |
date |
string | Yes | Date in YYYY-MM-DD format |
startTime |
string | Yes | Start time in HH:mm format |
endTime |
string | Yes | End time in HH:mm format |
description |
string | No | Work description |
Response¶
{
"data": {
"id": 123,
"date": "2026-01-14",
"startTime": "09:00",
"endTime": "11:30",
"durationSeconds": 9000,
"isActive": false,
"description": "Work description",
"task": {
"id": 456,
"name": "Task Title",
"urlKey": "task-123",
"url": "https://app.aico.swiss/tasks/task-123",
"estimatedHours": "8h",
"totalTrackedSeconds": 28800
},
"project": {
"id": 789,
"name": "Project Name",
"projectType": "CLIENT",
"clientName": "Customer Inc"
}
}
}
Validation:
- endTime must be after startTime
- Task must exist and be accessible
- Returns 409 Conflict if entry overlaps with existing entries on the same day
POST /timer-logs/{id}/start¶
Start a new timer based on an existing timer log entry.
URL Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | Timer log ID |
Request Body¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
Response¶
{
"data": {
"id": 124,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T14:00:00+00:00",
"endTime": null,
"trackedTime": "00:00:00",
"isActive": true
}
}
Notes: - Creates a new timer log entry with the same timer_id - Automatically stops any other active timer for the user
POST /timer-logs/{id}/restart¶
Restart a stopped timer log entry.
URL Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | Timer log ID |
Request Body¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userId |
number | No | AICO user ID (defaults to current user) |
Response¶
{
"data": {
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T14:00:00+00:00",
"endTime": null,
"trackedTime": "02:30:00",
"isActive": true
}
}
Notes: - Resumes tracking on the same timer log entry - Preserves previously tracked time - Automatically stops any other active timer for the user
POST /timer-logs/{id}/stop¶
Stop an active timer.
URL Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | Timer log ID |
Response¶
{
"data": {
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T09:00:00+00:00",
"endTime": "2026-01-14T11:30:00+00:00",
"trackedTime": "02:30:00",
"isActive": false
}
}
PUT /timer-logs/{id}¶
Update a timer log entry.
URL Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | Timer log ID |
Request Body¶
| Parameter | Type | Required | Description |
|---|---|---|---|
notes |
string | No | Description/notes |
trackedTime |
string | No | Tracked time (format: HH:mm:ss) |
createdAt |
number | No | Unix timestamp for entry date |
Response¶
{
"data": {
"id": 123,
"timerId": 456,
"userId": 789,
"startTime": "2026-01-14T09:00:00+00:00",
"endTime": "2026-01-14T11:30:00+00:00",
"trackedTime": "02:30:00",
"isActive": false,
"notes": "Updated notes"
}
}
Authorization:
- User can edit their own entries
- Admins with can_edit_team_time_tracking permission can edit any entry
DELETE /timer-logs/{id}¶
Delete a timer log entry.
URL Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
number | Yes | Timer log ID |
Response¶
Authorization:
- User can delete their own entries
- Admins with can_edit_team_time_tracking permission can delete any entry
Time Tracking Data Types¶
TimerLogEntry¶
interface TimerLogEntry {
id: number;
date: string; // "2026-01-14"
startTime: string; // "09:03"
endTime: string | null; // "11:05" or null if currently tracking
durationSeconds: number;
isActive: boolean;
description: string | null;
task: {
id: number;
name: string;
urlKey: string;
url: string; // Full URL to task
estimatedHours: string | null;
totalTrackedSeconds: number; // Total tracked on this task (all users)
} | null;
project: {
id: number;
name: string;
projectType: string; // "INTERNAL", "CLIENT", etc.
clientName: string | null;
} | null;
}
DailyTotals¶
interface DailyTotals {
mon: number; // seconds
tue: number;
wed: number;
thu: number;
fri: number;
sat: number;
sun: number;
}
TeamMemberTimeLogs¶
interface TeamMemberTimeLogs {
userId: number;
staffMemberId: string; // UUID from staff_members table
userName: string;
userAvatar: string | null;
dailyTotals: DailyTotals;
weekTotal: number; // seconds
isTracking: boolean;
currentTaskName: string | null;
entries: TimerLogEntry[];
}
Time Tracking Permissions¶
Required Permissions for Admin Endpoints¶
| Permission | Description |
|---|---|
can_view_team_time_tracking |
View team time tracking data |
can_edit_team_time_tracking |
Edit team time tracking entries |
can_read_staff_members_tracker_results |
Alternative permission for viewing team data |
Authorization Rules¶
- Own Entries: Users can always view, create, edit, and delete their own timer entries
- Team View: Requires
can_view_team_time_trackingorcan_read_staff_members_tracker_results - Team Edit: Requires
can_edit_team_time_tracking - Staff Search: Same permissions as Team View
Time Tracking Error Responses¶
| Status Code | Description |
|---|---|
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Authentication required |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource not found |
| 409 | Conflict - Overlapping time entries |
| 422 | Unprocessable Entity - Validation error |
Shopify Shops¶
List Shopify Shops¶
Endpoint: GET /api/aiconeo/shopify-shops
Returns a paginated list of all Shopify shops.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | name |
- | Sort field |
Filters¶
| Filter | Description | Example |
|---|---|---|
filter[id] |
Shop ID(s), comma-separated | filter[id]=1,2 |
filter[isActive] |
Filter by active status | filter[isActive]=true |
filter[isPosShop] |
Filter by POS shop status | filter[isPosShop]=false |
filter[currencyId] |
Filter by currency ID(s) | filter[currencyId]=1 |
filter[countryId] |
Filter by country ID(s) | filter[countryId]=216 |
filter[search] |
Search by name, short name, or domain | filter[search]=fanshop |
Response Structure¶
{
"data": [
{
"id": 4,
"type": "shopify-shops",
"attributes": {
"name": "FCB Fanshop",
"shortName": null,
"isActive": true,
"locale": "de_CH",
"apiDomain": "fcb-fanshop.myshopify.com",
"isTaxable": true,
"isPosShop": false,
"lastSyncStatus": "SYNCED",
"lastSyncStartedAt": "2026-01-06 23:30:18",
"lastSyncCompletedAt": "2026-01-07 00:01:40",
"createdAt": "2022-08-18 08:43:23",
"updatedAt": "2026-01-07 00:01:40",
"currency": {
"id": 1,
"name": "CHF"
},
"country": {
"id": 216,
"name": "Switzerland"
}
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 1,
"perPage": 25,
"to": 3,
"total": 3
}
}
}
Trigger Bulk Shopify Sync¶
Endpoint: POST /api/aiconeo/products/bulk-shopify-sync
Triggers a bulk Shopify sync for all products. By default, syncs all shops. Optionally sync only a specific shop by providing shopifyShopId.
Request Body (Optional)¶
| Field | Type | Required | Description |
|---|---|---|---|
data.shopifyShopId |
int | No | ID of a specific Shopify shop to sync. If omitted, syncs all shops. |
Response (All Shops)¶
{
"data": {
"type": "bulk-shopify-sync",
"attributes": {
"message": "Bulk Shopify sync has been queued for all shops",
"shopCount": 3
}
}
}
Response (Single Shop)¶
{
"data": {
"type": "bulk-shopify-sync",
"attributes": {
"message": "Bulk Shopify sync has been queued for shop 'FCB Fanshop'",
"shopCount": 1,
"shopifyShopId": 4,
"shopifyShopName": "FCB Fanshop"
}
}
}
Error Response (Shop Not Found)¶
{
"errors": [
{
"status": "404",
"title": "Not Found",
"detail": "Shopify shop with ID 99999 not found."
}
]
}
Languages¶
High-performance endpoints for managing languages.
Languages List¶
Endpoint: GET /api/aiconeo/languages
Returns a paginated list of languages.
Query Parameters¶
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page[number] |
int | 1 | - | Page number |
page[size] |
int | 25 | 100 | Items per page |
sort |
string | id |
- | Sort field(s), prefix with - for descending |
filter[field] |
mixed | - | - | Filter by field |
include |
string | - | - | Comma-separated list of includes |
Sortable Fields¶
| Field | Description |
|---|---|
id |
Language ID |
name |
Language name |
locale |
Locale code |
fallbackLanguageId |
Fallback language ID |
createdAt |
Creation timestamp |
updatedAt |
Last update timestamp |
Filter Parameters¶
| Parameter | Type | Description | Operators |
|---|---|---|---|
filter[id] |
string | Filter by ID(s), comma-separated | - |
filter[name] |
string | Filter by language name | Text operators |
filter[locale] |
string | Filter by locale code | Text operators |
filter[fallbackLanguageId] |
string | Filter by fallback language ID (use 'null' for no fallback) | - |
filter[search] |
string | Global search in name and locale | - |
filter[createdAt] |
mixed | Filter by creation date | DateTime operators |
filter[updatedAt] |
mixed | Filter by update date | DateTime operators |
Includes¶
| Include | Description |
|---|---|
fallbackLanguage |
Fallback language details (id, name, locale) |
aicoShopsCount |
Count of associated aico shops |
warehousesCount |
Count of associated warehouses |
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/languages?page[size]=10&include=fallbackLanguage,aicoShopsCount" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response¶
{
"data": [
{
"id": 1,
"type": "languages",
"attributes": {
"name": "German (Switzerland)",
"locale": "de_CH",
"fallbackLanguageId": null,
"createdAt": "2024-01-15T10:30:00.000000Z",
"updatedAt": "2024-01-15T10:30:00.000000Z",
"aicoShopsCount": 3
}
},
{
"id": 2,
"type": "languages",
"attributes": {
"name": "French (Switzerland)",
"locale": "fr_CH",
"fallbackLanguageId": 1,
"createdAt": "2024-01-15T10:30:00.000000Z",
"updatedAt": "2024-01-15T10:30:00.000000Z",
"fallbackLanguage": {
"id": 1,
"name": "German (Switzerland)",
"locale": "de_CH"
},
"aicoShopsCount": 2
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 1,
"perPage": 25,
"to": 2,
"total": 2
}
},
"links": {
"first": "http://example.com/api/aiconeo/languages?page[number]=1&page[size]=25",
"last": "http://example.com/api/aiconeo/languages?page[number]=1&page[size]=25",
"prev": null,
"next": null
}
}
Language Detail¶
Endpoint: GET /api/aiconeo/languages/{id}
Returns a single language by ID.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
id |
integer | Language ID |
Query Parameters¶
| Parameter | Type | Description |
|---|---|---|
include |
string | Comma-separated list of includes |
Includes¶
| Include | Description |
|---|---|
fallbackLanguage |
Fallback language details (id, name, locale) |
aicoShopsCount |
Count of associated aico shops |
warehousesCount |
Count of associated warehouses |
Example Request¶
curl -X GET "http://127.0.0.1/api/aiconeo/languages/1?include=fallbackLanguage,aicoShopsCount,warehousesCount" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response¶
{
"data": {
"id": 1,
"type": "languages",
"attributes": {
"name": "German (Switzerland)",
"locale": "de_CH",
"fallbackLanguageId": null,
"createdAt": "2024-01-15T10:30:00.000000Z",
"updatedAt": "2024-01-15T10:30:00.000000Z",
"aicoShopsCount": 3,
"warehousesCount": 5
}
}
}
Error Response (404)¶
Filter Operators Reference¶
Text Filter Operators¶
Available for all text fields in AicoNeo endpoints.
| Operator | Description | Example |
|---|---|---|
| (simple) | Contains (default) | filter[name]=shirt |
contains |
Contains value | filter[name][contains]=shirt |
notContains |
Does not contain | filter[name][notContains]=test |
equals / eq |
Exact match | filter[sku][equals]=ABC-123 |
notEquals / neq |
Not equal to | filter[sku][notEquals]=OLD |
startsWith |
Starts with | filter[sku][startsWith]=PRD- |
endsWith |
Ends with | filter[sku][endsWith]=-2024 |
blank / empty |
Is empty or null | filter[description][blank]=1 |
notBlank / notEmpty |
Is not empty | filter[description][notBlank]=1 |
DateTime Filter Operators¶
Available for all datetime fields in AicoNeo endpoints.
Full DateTime Operators¶
| Operator | Description | Example |
|---|---|---|
| (simple) | Date equals | filter[createdAt]=2024-06-15 |
equals / eq |
Exact datetime match | filter[createdAt][eq]=2024-06-15 10:30:00 |
before / lt |
Before datetime | filter[createdAt][before]=2024-06-15 |
after / gt |
After datetime | filter[createdAt][after]=2024-01-01 |
between |
DateTime range | filter[createdAt][between]=2024-01-01,2024-12-31 |
blank / empty |
Is null | filter[updatedAt][blank]=1 |
notBlank / notEmpty |
Is not null | filter[updatedAt][notBlank]=1 |
Date-Only Operators¶
| Operator | Description | Example |
|---|---|---|
dateEquals |
Date matches (ignores time) | filter[createdAt][dateEquals]=2024-06-15 |
dateBefore |
Before date | filter[createdAt][dateBefore]=2024-06-15 |
dateAfter |
After date | filter[createdAt][dateAfter]=2024-01-01 |
dateBetween |
Date range | filter[createdAt][dateBetween]=2024-01-01,2024-12-31 |
Response Format¶
All AicoNeo endpoints return JSON:API style responses with pagination metadata:
{
"data": [
{
"id": 123,
"type": "orders",
"attributes": {
"orderNumber": "ORD-2024-001",
"buyerName": "Customer Name",
...
}
}
],
"meta": {
"page": {
"currentPage": 1,
"from": 1,
"lastPage": 10,
"perPage": 25,
"to": 25,
"total": 250
}
},
"links": {
"first": "http://example.com/api/aiconeo/orders?page[number]=1&page[size]=25",
"last": "http://example.com/api/aiconeo/orders?page[number]=10&page[size]=25",
"prev": null,
"next": "http://example.com/api/aiconeo/orders?page[number]=2&page[size]=25"
}
}
Notes¶
- Authentication: All endpoints require
auth:sanctumauthentication - Access Control: Endpoints respect user permissions and role-based access
- Soft Deletes: Only non-deleted records are returned
- Performance: AicoNeo endpoints use optimized raw SQL queries
- Translations: Set
Accept-Languageheader for localized content - File/Image URLs: All file and image URLs are returned as full URLs generated via Laravel Storage (e.g.,
http://example.com/storage/path/to/image.jpg), not relative paths
File URL Fields by Endpoint¶
| Endpoint | Field | Description |
|---|---|---|
/api/aiconeo/products |
translations[].image |
Product translation images |
/api/aiconeo/products/{id} |
translations[].image |
Product translation images |
/api/aiconeo/products/{id} |
variants[].image |
Variant images |
/api/aiconeo/products/{id} |
variationOptions[].values[].image |
Variation option value images |
/api/aiconeo/products/{id} |
categories.*.image |
Category images |
/api/aiconeo/products/{id} |
fileGroups.*.files[].translations[].fileUrl |
File URLs |
/api/aiconeo/products/{id} |
fileGroups.*.files[].translations[].optimizedFileUrl |
Optimized file URLs |
/api/aiconeo/articles |
image |
Article image (variant or product) |
/api/aiconeo/articles |
productImage |
Product image |
/api/aiconeo/articles |
variantImage |
Variant image |
/api/aiconeo/categories |
image |
Category main image |
/api/aiconeo/categories |
video |
Category video file |
/api/aiconeo/categories |
itemImage |
Category item image |
/api/aiconeo/collections |
image |
Collection main image |
/api/aiconeo/b2b |
image |
B2B customer/company image |
/api/aiconeo/b2c |
image |
B2C customer image |
/api/aiconeo/order-documents |
documentUrl |
Document PDF URL |