AI Commerce Cloud GraphQL API
Public GraphQL schema reference for AI Commerce Cloud integrations.
Browse the live schema
Review available queries, mutations, arguments, input types, and response fields before building an integration.
Build production requests
Use the examples to shape GraphQL POST requests for the production endpoint at https://api.aicommerce.fi/graphql.
Authenticate per tenant
Every request uses tenant credentials and an AI Commerce GraphQL access token issued during onboarding.
API Endpoints
https://api.aicommerce.fi/graphql
Headers
# Required AI Commerce Cloud API access token.
X-GraphQL-Secret: <your-graphql-secret>
# Required tenant identifier.
X-Tenant-ID: your-tenant-id
# Required tenant-specific secret.
X-Tenant-Secret: <your-tenant-secret>
# Required for GraphQL JSON requests.
Content-Type: application/json
Overview
AI Commerce Cloud exposes a single GraphQL API for ecommerce catalog, customer, order, quote, payment, and operational data.
The public reference is generated from the same schema files used by the running API. Field-level behavior, authorization, and tenant data access are enforced by the live API.
Authentication
All requests use the production endpoint:
https://api.aicommerce.fi/graphql
Every request must include these headers:
| Header | Value |
|---|---|
X-GraphQL-Secret |
API access token issued during onboarding |
X-Tenant-ID |
Tenant identifier issued during onboarding |
X-Tenant-Secret |
Tenant-specific secret issued during onboarding |
Content-Type |
application/json |
Do not expose API secrets in browser-side code or public repositories.
Tenant Model
AI Commerce Cloud uses one GraphQL endpoint for all tenants.
Tenant selection is header-based. The API reads X-Tenant-ID and X-Tenant-Secret on each request and routes authorized operations to the matching tenant data.
The schema is shared across tenants. Tenant identity controls data access, not schema shape.
Pagination
List-style queries across the schema follow the same pagination convention: pass limit and offset as integer arguments and walk the result set in fixed-size pages.
Convention
| Argument | Default | Notes |
|---|---|---|
limit |
10–30 (varies per query) | Maximum number of rows returned in this page. Different queries use different defaults — check the field signature on the reference page for the specific query. |
offset |
0 |
Zero-based offset into the result set. |
Both arguments are optional on every list query that exposes them. Negative values are rejected; the resolver throws when limit or offset is below zero.
Example
query OrdersPage1 {
orders(limit: 25, offset: 0) {
id
customerName
status
datePurchased
}
}
To fetch the next page:
query OrdersPage2 {
orders(limit: 25, offset: 25) {
id
customerName
status
datePurchased
}
}
Total counts
Most list queries do not return a total-count field — the response is the page itself, and the caller stops paging when a page comes back shorter than limit. A small number of admin / audit queries return a wrapper type that includes total alongside entries (for example actionRecorderEntries returns an ActionRecorderPage); use those when the calling UI needs to render "showing N of M" without a second round-trip.
Ordering
List queries return rows in a stable, query-specific order — typically by primary id ascending, by dateAdded / datePurchased descending for time-series queries (orders, history, audit logs), or by an explicit sortOrder column where one exists. The ordering for a specific query is documented on its reference page.
Errors
The API surfaces three error layers: edge-level rejections (WAF), transport-level limits (rate limiting), and application-level errors (GraphQL errors[]). Each layer has a different shape.
Edge: missing or invalid X-GraphQL-Secret
Requests without a valid X-GraphQL-Secret header are rejected at the WAF before they reach the API. The response is a generic edge rejection — typically HTTP 403 Forbidden with no GraphQL body. Treat any non-JSON response as an edge-level block and verify the header is set correctly.
Transport: rate limiting
Each tenant is rate-limited at 100 requests per 5-minute window, keyed by X-Tenant-ID. When the limit is exceeded the API returns:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{ "error": "Too many requests, please try again later." }
This is the only response shape that uses a top-level error field instead of GraphQL's errors[]. Back off and retry after the window rolls over.
Application: authentication failures
When X-Tenant-ID or X-Tenant-Secret is missing, references an unknown tenant, or carries the wrong secret, the request reaches the GraphQL layer and fails inside the resolver. The HTTP status is 200 OK (GraphQL convention), and the body carries:
{
"data": null,
"errors": [
{ "message": "Authentication failed" }
]
}
Always check errors[] even on a 200 response — never key on HTTP status alone for application errors.
Application: validation and resolver errors
Validation failures (missing required input fields, invalid enum values, references to ids that do not exist) and resolver-thrown errors return the same GraphQL shape:
{
"data": null,
"errors": [
{ "message": "Customer with this email address already exists." }
]
}
Examples of resolver-thrown errors include Customer with this email address already exists. from createCustomer, paymentCode validation in createOrder (which lists the modules currently installed for the tenant), Quote not found from quote-status mutations, and Shared basket item expired when a shared-basket edit is attempted past expiresAt. The message text is the integration's primary signal — check it before reacting.
Partial success
Some queries can return a partially-populated data object alongside errors[] when one resolver in the selection set fails but others succeed. Treat the response as a partial result: consume the data fields that came back populated and surface or log any messages in errors[].
Server errors
Genuine server-side failures (database unavailable, unhandled exceptions) return HTTP 500 with a generic GraphQL error body. These are transient and should be retried with exponential backoff after a short delay.
Versioning
The API runs on a single, versionless endpoint at https://api.aicommerce.fi/graphql. There are no /v1 / /v2 paths or version-pinning headers — every integration consumes the schema as it stands at the time of the request.
Compatible changes
The following changes are made without notice and are considered backwards-compatible:
- Adding new types, queries, mutations, fields, or input arguments.
- Adding new optional arguments to existing fields (existing callers continue to work without supplying them).
- Adding new values to free-form code fields documented as "Example values" rather than as enums (e.g. new
typecodes onProductMedia, newmodulecodes onActionRecorderEntry, new tenant-definedgroupsTypecodes onCustomerGroup). - Updating descriptions, examples, and reference text in the docs.
Build integrations defensively against these — treat unknown enum-like string values as opaque rather than asserting on the documented set.
Breaking changes
Renaming or removing types, queries, mutations, fields, or required arguments is a breaking change. AI Commerce Cloud coordinates breaking changes directly with affected integrators ahead of the change rather than publishing a changelog feed. If you maintain an integration, make sure your contact is on file via info@petrosoft.fi so you receive the heads-up.
Tenant-defined extensions
Several surfaces document a canonical id set across tenants but allow tenants to extend it — order statuses, quote statuses, language ids, custom-option types, payment / shipping module codes. The canonical set is described on the relevant reference page, but always resolve dynamically rather than hardcoding ids:
orderStatuses(languageId: …)for order-status ids and labelsquoteStatuses(languageId: …)for quote-status ids and labelslanguagesfor the available language idscurrenciesfor enabled currenciesconfigurationsfor tenant-specific module / setting values
Tenant extensions are not breaking changes — code reading a status id it doesn't recognise should treat it as an opaque value rather than failing.
Schema introspection
GraphQL introspection is enabled on the production endpoint. Tools like GraphQL Code Generator, Apollo Codegen, and IDE plugins can introspect the live schema directly — that's the most reliable way to track changes between releases of an integration.
Reference
A pointer to the cross-cutting code lists used across many fields. None of the values below are authoritative for a given tenant — every list is tenant-extensible, and tenants may remove ids that aren't used in their setup. Always resolve at runtime through the queries listed alongside each section. The values shown are the platform defaults across most tenants, useful as a sanity check while reading reference pages, not as a hardcoded truth source.
Languages
Several fields take a languageId: Int argument or expose a languageId on per-language description rows. Resolve dynamically via the languages query.
| Default id | Code | Language |
|---|---|---|
| 1 | en |
English |
| 5 | sv |
Swedish |
| 6 | fi |
Finnish |
| 9 | es |
Spanish |
| 14 | it |
Italian |
Tenants may add ids beyond this list. Code reading a languageId it does not recognise should treat it as opaque.
Order statuses
Order.status and OrderStatusHistory.statusId carry numeric ids. Resolve labels via the orderStatuses(languageId: …) query, scoped to the tenant the request is authenticated for.
| Default id | Label |
|---|---|
| 1 | Received |
| 2 | Packing |
| 3 | Shipped |
| 9 | Under investigation |
| 10 | To be picked up |
| 11 | Packed |
| 15 | Awaiting payment |
| 16 | Cancelled |
| 17 | Returned |
| 21 | Uncollected |
| 23 | Backorder |
Tenants extend this set with custom workflow stages and payment-provider intermediate states. Build status-driven logic against the codes you've fetched, not against hardcoded ids.
Quote statuses
Quote.statusId and QuoteStatusEntry.statusId mirror the order-status pattern. Resolve via the quoteStatuses(languageId: …) query.
| Default id | Label |
|---|---|
| 1 | Open |
| 2 | Accepted |
| 3 | Cancelled |
| 4 | Ordered |
| 5 | Proposal sent |
| 50 | Pending approval |
Currencies
Currency.code is ISO 4217 (e.g. EUR, USD, GBP). Enumerate the tenant's enabled currencies via the currencies query; the result includes the active exchange rate against the tenant's primary currency. Per-country defaults are exposed through Country.defaultCurrencyId.
Discount and customer-group enums
Several pricing fields share an enum-like shape (discountType on DiscountCoupon / CustomerGroup / Order, customerType on CustomerGroup / DiscountCoupon). The values are defined in PHP and stored as strings — there's no GraphQL enum constraint.
| Field | Example values | Notes |
|---|---|---|
discountType |
fixed, percent, shipping |
fixed = currency amount off; percent = percentage off; shipping = applies as a shipping subsidy. |
customerType |
all, vatid, regular |
all matches everyone; vatid is B2B (customer carries a VAT id); regular is consumer (no VAT id). |
minOrderType |
price, quantity |
Threshold semantics on coupons / customer groups. |
groupsType |
fixed, dynamic, matrix, list |
Group-shape classifier on CustomerGroup. |
pricePrefix |
+, empty string |
Variant price-delta application: + additive, empty replaces the base price. |
Treat these as free-form codes — tenants and platform releases can extend the set.
Payment and shipping module codes
Order.paymentCode and Order.shippingCode reference the modules a tenant has installed. The valid sets are stored in tenant configuration, not in this schema:
- Payment:
MODULE_PAYMENT_INSTALLED— semicolon-separated list, e.g.Cod;NetsBank;VivawalletCreditcard. - Shipping:
MODULE_SHIPPING_INSTALLED— semicolon-separated list, e.g.Flat;Matkahuolto;Smartpost.
Read both via the configurations(groupId: …) query to discover what's available for the connected tenant. The createOrder mutation validates paymentCode / shippingCode against these lists and returns a loud error listing the modules currently installed if a free-form value is supplied.
ProductMedia file types
ProductMedia.type is a free-form short code captured at upload time, with mixed casing in production from historical drift. Example values seen across tenants: PDF / pdf (datasheets, manuals); JPG / JPEG / PNG / GIF / WEBP / AVIF / SVG (images); IES (lighting profiles); DWG / DXF / DWF (CAD); DOC / DOCX / XLS / XLSX / TXT (office). The full whitelist is enforced server-side at upload time — treat the rendered values as opaque codes rather than asserting on a fixed set.
Examples
Fetch products:
query Products {
products(limit: 5, offset: 0) {
id
name
model
price
}
}
Fetch one product:
query Product($id: ID!) {
product(id: $id) {
id
name
price
description
}
}
Fetch categories:
query Categories {
categories(limit: 10, offset: 0) {
id
parentId
descriptions {
languageId
name
}
}
}
Fetch orders:
query Orders {
orders(limit: 5, offset: 0) {
id
customerName
customerEmail
status
datePurchased
}
}
Create an order:
mutation CreateOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
status
customerEmail
}
}
Onboarding
Access to live tenant data requires onboarding.
Contact info@petrosoft.fi to request API access, tenant credentials, integration support, or rate limit changes.
Queries
_empty
Response
Returns a String
Example
Query
query _empty {
_empty
}
Response
{"data": {"_empty": "abc123"}}
actionRecorderEntries
Description
Page through the audit log, newest first. All filters are optional and AND-composable: pass module to scope to one event source, userId to follow one principal, and success to bracket only the failures (handy for brute-force detection on login modules).
Used by the admin's security dashboard, by compliance export jobs, and by oncall when investigating an incident. The entries are append-only — there's no way to amend or delete a row through this surface.
Response
Returns an ActionRecorderPage!
Arguments
| Name | Description |
|---|---|
module - String
|
Restrict to entries from one module (see ActionRecorderEntry.module for example values). |
userId - Int
|
Restrict to entries about one user id. |
success - Boolean
|
Restrict to successful (true) or failed (false) entries. Omit to include all outcomes (including null-status informational rows). |
limit - Int
|
Maximum number of entries to return on this page. Defaults to 25 in the resolver. |
offset - Int
|
Offset for pagination. |
Example
Query
query actionRecorderEntries(
$module: String,
$userId: Int,
$success: Boolean,
$limit: Int,
$offset: Int
) {
actionRecorderEntries(
module: $module,
userId: $userId,
success: $success,
limit: $limit,
offset: $offset
) {
total
entries {
id
module
userId
userName
identifier
userAgent
success
dateAdded
}
}
}
Variables
{
"module": "xyz789",
"userId": 987,
"success": true,
"limit": 987,
"offset": 123
}
Response
{
"data": {
"actionRecorderEntries": {
"total": 987,
"entries": [ActionRecorderEntry]
}
}
}
addressBookEntries
Description
List the address-book entries belonging to one customer. Each row is a shipping address with optional alternate-billing fields filled in when the customer wants invoices routed to a different recipient.
Used by the storefront's address picker at checkout, by the customer account 'My addresses' page, and by admin order-creation to load a customer's saved addresses. For a customer's standalone billing-only book see billingAddresses; for snapshots of billing/delivery on a finalized order see the order ecosystem instead.
Response
Returns [AddressBook]
Example
Query
query addressBookEntries(
$customerId: ID!,
$limit: Int,
$offset: Int
) {
addressBookEntries(
customerId: $customerId,
limit: $limit,
offset: $offset
) {
id
customerId
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
Variables
{"customerId": 4, "limit": 123, "offset": 987}
Response
{
"data": {
"addressBookEntries": [
{
"id": "4",
"customerId": 987,
"gender": "xyz789",
"company": "xyz789",
"firstname": "xyz789",
"lastname": "xyz789",
"streetAddress": "abc123",
"vatid": "abc123",
"postcode": "abc123",
"city": "abc123",
"state": "xyz789",
"countryId": 123,
"zoneId": 987,
"comments": "abc123",
"billingStreetAddress": "abc123",
"billingFirstname": "xyz789",
"billingLastname": "xyz789",
"billingPostcode": "xyz789",
"billingCity": "abc123",
"billingCountryId": "xyz789",
"billingCompany": "xyz789",
"billingVatid": "xyz789",
"billingZoneId": "abc123",
"billingState": "abc123",
"billingOperatorId": 987,
"billingInvoiceAddress": "abc123",
"billingReference": "xyz789",
"billingReferenceRequired": false
}
]
}
}
addressFormats
Description
List address-format templates, optionally filtered by id. Pass ids to look up specific formats (e.g. the ones referenced by the visible countries); omit ids to enumerate every format the tenant has defined.
Used by the address renderer when generating shipping labels, invoice addresses, and admin display strings — paired with each Country's addressFormatId to pick the right template per destination. For the raw address data see addressBookEntries / billingAddresses; this surface only carries the templates.
Response
Returns [AddressFormat]
Example
Query
query addressFormats(
$ids: [ID!],
$limit: Int,
$offset: Int
) {
addressFormats(
ids: $ids,
limit: $limit,
offset: $offset
) {
id
addressFormat
addressSummary
}
}
Variables
{"ids": ["4"], "limit": 123, "offset": 987}
Response
{
"data": {
"addressFormats": [
{
"id": 4,
"addressFormat": "abc123",
"addressSummary": "abc123"
}
]
}
}
adminNotifications
Description
List admin-facing error notifications in insertion order. Used by the admin dashboard's notification inbox to render the operator alert queue, by the email-dispatch worker that emails un-emailed entries, and by oncall runbooks that need to inspect what's been raised recently.
No filter args today — paginate with limit / offset to walk the full queue. For per-action audit entries (logins, exports, password changes) see actionRecorderEntries instead; this surface is for error-class operator alerts, not action audits.
Response
Returns [AdminNotification]
Example
Query
query adminNotifications(
$limit: Int,
$offset: Int
) {
adminNotifications(
limit: $limit,
offset: $offset
) {
id
errorText
createdAt
emailErrorSent
errorCleared
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"adminNotifications": [
{
"id": "4",
"errorText": "abc123",
"createdAt": "abc123",
"emailErrorSent": false,
"errorCleared": true
}
]
}
}
adminTrackingCreate
Description
List product-creation / lifecycle audit entries, newest first. Pass productId to scope to one product's history (the admin product editor's 'history' tab uses this), userId to scope to one admin's activity (auditing what one operator has touched), or omit both to walk the full feed.
Used by the admin product editor's history view, by accountability reports surfacing 'who created what' across the catalog, and by ERP reconciliation flows. For per-price audit see productPriceHistory; for the broader cross-module audit log see actionRecorderEntries.
Response
Returns [AdminTrackingCreate]
Example
Query
query adminTrackingCreate(
$productId: Int,
$userId: Int,
$limit: Int,
$offset: Int
) {
adminTrackingCreate(
productId: $productId,
userId: $userId,
limit: $limit,
offset: $offset
) {
id
productId
userId
userName
action
dateAdded
}
}
Variables
{"productId": 123, "userId": 987, "limit": 123, "offset": 123}
Response
{
"data": {
"adminTrackingCreate": [
{
"id": 4,
"productId": 987,
"userId": 123,
"userName": "xyz789",
"action": "xyz789",
"dateAdded": "abc123"
}
]
}
}
administrators
Description
List admin user accounts for the tenant. Used by the admin user-management page (visible to superadmins), by access reviews that audit who has the right to do what, and by the SSO bridge to map an external identity to a local admin record.
No filter args today — paginate with limit / offset to walk the full list. For the audit trail of what each admin has done, see actionRecorderEntries.
Response
Returns [Administrator]
Example
Query
query administrators(
$limit: Int,
$offset: Int
) {
administrators(
limit: $limit,
offset: $offset
) {
id
userName
email
twoFactor
superadmin
writePermission
grantAccess
}
}
Variables
{"limit": 987, "offset": 123}
Response
{
"data": {
"administrators": [
{
"id": "4",
"userName": "xyz789",
"email": "abc123",
"twoFactor": false,
"superadmin": false,
"writePermission": false,
"grantAccess": "xyz789"
}
]
}
}
apiProcessQueue
Description
Page through the outbound-API job queue. All filters are optional and AND-composable: scope by api / endpoint / jobId for targeted investigations, and by status to split the queue into 'queued' (no error) vs 'failed' (last attempt errored).
Used by the admin queue dashboard to surface stuck jobs, by oncall runbooks investigating ERP-sync incidents, and by maintenance jobs that retry or expire failed entries.
Response
Returns [ApiProcessJob]
Arguments
| Name | Description |
|---|---|
status - String
|
Filter to one status. Example values: 'queued', 'failed'. |
api - String
|
Filter to jobs targeting one external API (e.g. 'netvisor'). |
endpoint - String
|
Filter to jobs hitting one endpoint path. |
jobId - String
|
Filter to one worker-side job id. |
limit - Int
|
Maximum number of jobs to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query apiProcessQueue(
$status: String,
$api: String,
$endpoint: String,
$jobId: String,
$limit: Int,
$offset: Int
) {
apiProcessQueue(
status: $status,
api: $api,
endpoint: $endpoint,
jobId: $jobId,
limit: $limit,
offset: $offset
) {
id
jobId
api
endpoint
method
data
createdAt
error
status
}
}
Variables
{
"status": "abc123",
"api": "xyz789",
"endpoint": "abc123",
"jobId": "abc123",
"limit": 123,
"offset": 123
}
Response
{
"data": {
"apiProcessQueue": [
{
"id": "4",
"jobId": "abc123",
"api": "abc123",
"endpoint": "xyz789",
"method": "abc123",
"data": {},
"createdAt": "abc123",
"error": "xyz789",
"status": "xyz789"
}
]
}
}
availabilities
Description
List availability labels, optionally filtered by language. Pass languageId to get only the labels for one storefront language; omit it to receive every (id, languageId) pair the tenant has defined.
Response
Returns [Availability]
Arguments
| Name | Description |
|---|---|
languageId - Int
|
Example
Query
query availabilities($languageId: Int) {
availabilities(languageId: $languageId) {
id
languageId
name
hexCode
}
}
Variables
{"languageId": 987}
Response
{
"data": {
"availabilities": [
{
"id": 4,
"languageId": 987,
"name": "abc123",
"hexCode": "xyz789"
}
]
}
}
bankPayments
Description
List bank-transfer settlements, newest first. Filters compose with AND: pass ordersId to fetch one order's settlements (typically reached via Order.bankPayments instead), and use the date-range pairs to scope to a posting-date or value-date window for reconciliation reports.
Used by the admin's invoice / accounts-receivable tab, by ERP / accounting export jobs, and by 'where's my money?' reports comparing expected and received payments. For card / mobile-wallet payments use ordersNets / ordersVivawallet instead.
Response
Returns [BankPayment!]!
Arguments
| Name | Description |
|---|---|
ordersId - Int
|
Restrict to settlements for one order id. |
invoiceDateFrom - String
|
Lower bound for invoicePaymentDate (inclusive). ISO-8601 date. |
invoiceDateTo - String
|
Upper bound for invoicePaymentDate (inclusive). ISO-8601 date. |
valueDateFrom - String
|
Lower bound for invoicePaymentValueDate (inclusive). ISO-8601 date. |
valueDateTo - String
|
Upper bound for invoicePaymentValueDate (inclusive). ISO-8601 date. |
limit - Int
|
Maximum number of settlements to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query bankPayments(
$ordersId: Int,
$invoiceDateFrom: String,
$invoiceDateTo: String,
$valueDateFrom: String,
$valueDateTo: String,
$limit: Int,
$offset: Int
) {
bankPayments(
ordersId: $ordersId,
invoiceDateFrom: $invoiceDateFrom,
invoiceDateTo: $invoiceDateTo,
valueDateFrom: $valueDateFrom,
valueDateTo: $valueDateTo,
limit: $limit,
offset: $offset
) {
id
orderId
invoicePaymentDate
invoicePaymentValueDate
amount
}
}
Variables
{
"ordersId": 123,
"invoiceDateFrom": "abc123",
"invoiceDateTo": "abc123",
"valueDateFrom": "xyz789",
"valueDateTo": "abc123",
"limit": 123,
"offset": 123
}
Response
{
"data": {
"bankPayments": [
{
"id": 4,
"orderId": 987,
"invoicePaymentDate": "abc123",
"invoicePaymentValueDate": "xyz789",
"amount": 123.45
}
]
}
}
billingAddresses
Description
List the billing-only addresses belonging to one customer, in insertion order. Used by the storefront's checkout when a B2B customer has multiple invoice recipients to pick from, by the customer account's 'Invoice addresses' page, and by admin order-creation when routing an invoice to a non-shipping recipient.
For shipping addresses (with optional alternate billing in the same row) see addressBookEntries. For the address-rendering templates that turn these fields into a printed block, see addressFormats.
Response
Returns [BillingAddress]
Example
Query
query billingAddresses(
$customerId: ID!,
$limit: Int,
$offset: Int
) {
billingAddresses(
customerId: $customerId,
limit: $limit,
offset: $offset
) {
id
customerId
company
firstname
lastname
streetAddress
postcode
city
state
countryId
zoneId
vatid
operatorId
invoiceAddress
reference
referenceRequired
}
}
Variables
{
"customerId": "4",
"limit": 123,
"offset": 123
}
Response
{
"data": {
"billingAddresses": [
{
"id": "4",
"customerId": 987,
"company": "xyz789",
"firstname": "xyz789",
"lastname": "abc123",
"streetAddress": "abc123",
"postcode": "abc123",
"city": "abc123",
"state": "abc123",
"countryId": "abc123",
"zoneId": "xyz789",
"vatid": "abc123",
"operatorId": 987,
"invoiceAddress": "xyz789",
"reference": "abc123",
"referenceRequired": false
}
]
}
}
browseHistory
Description
Page through browse-history entries, newest first. Filters compose with AND: pass customerId to follow one logged-in customer's journey, sessionKey to reconstruct one anonymous (or pre-login) session, or use the date-range pair for timeboxed analytics queries.
Used by the 'Recently viewed' surface, by funnel-analytics dashboards, and by abuse / scraping investigations needing the IP + user-agent trail. Note that anonymous and logged-in views can share a sessionKey — joining the two halves of a journey across the login boundary.
Response
Returns [BrowseHistory]
Arguments
| Name | Description |
|---|---|
customerId - Int
|
Restrict to one logged-in customer's history. |
sessionKey - String
|
Restrict to one storefront session's history. |
startDate - String
|
Inclusive lower bound on the page-view timestamp. ISO-8601 datetime. |
endDate - String
|
Inclusive upper bound on the page-view timestamp. ISO-8601 datetime. |
limit - Int
|
Maximum number of entries to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query browseHistory(
$customerId: Int,
$sessionKey: String,
$startDate: String,
$endDate: String,
$limit: Int,
$offset: Int
) {
browseHistory(
customerId: $customerId,
sessionKey: $sessionKey,
startDate: $startDate,
endDate: $endDate,
limit: $limit,
offset: $offset
) {
id
customerId
sessionKey
loadTimeMsec
categoryId
productId
manufacturerId
color
size
geoipCountry
ipAddress
date
timestamp
topPicks
keywords
}
}
Variables
{
"customerId": 987,
"sessionKey": "xyz789",
"startDate": "xyz789",
"endDate": "abc123",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"browseHistory": [
{
"id": "4",
"customerId": 123,
"sessionKey": "xyz789",
"loadTimeMsec": 123,
"categoryId": 123,
"productId": 123,
"manufacturerId": 987,
"color": 123,
"size": 987,
"geoipCountry": "xyz789",
"ipAddress": "abc123",
"date": "xyz789",
"timestamp": 987,
"topPicks": false,
"keywords": "abc123"
}
]
}
}
categories
Description
Page through categories across the full tree. Returns each category with all of its CategoryDescription rows attached, so a single fetch can render any language. Used by sitemap builders, by exports / ERP sync, and by the admin's category browser.
For a single category by id, use category instead — it lets you scope to one language to skip extraneous CategoryDescription rows.
Response
Returns [Category]
Example
Query
query categories(
$limit: Int,
$offset: Int
) {
categories(
limit: $limit,
offset: $offset
) {
id
code
image
banner
parentId
sortOrder
position
descriptions {
languageId
name
url
path
pathOld
description
descriptionTop
metaTitle
metaDescription
featureTitle
typeTitle
bannerText
bannerButton
bannerUrl
redirectStatus
}
}
}
Variables
{"limit": 123, "offset": 987}
Response
{
"data": {
"categories": [
{
"id": 4,
"code": "abc123",
"image": "abc123",
"banner": "abc123",
"parentId": 987,
"sortOrder": 123,
"position": 123,
"descriptions": [CategoryDescription]
}
]
}
}
category
Description
Fetch a single category by id. Pass languageId to receive only that language's CategoryDescription row in the descriptions array (the storefront uses this on category page render); omit it to receive every language for the category (the admin category editor uses this).
Response
Returns a Category
Example
Query
query category(
$id: ID!,
$languageId: Int
) {
category(
id: $id,
languageId: $languageId
) {
id
code
image
banner
parentId
sortOrder
position
descriptions {
languageId
name
url
path
pathOld
description
descriptionTop
metaTitle
metaDescription
featureTitle
typeTitle
bannerText
bannerButton
bannerUrl
redirectStatus
}
}
}
Variables
{"id": 4, "languageId": 987}
Response
{
"data": {
"category": {
"id": 4,
"code": "xyz789",
"image": "xyz789",
"banner": "xyz789",
"parentId": 123,
"sortOrder": 123,
"position": 123,
"descriptions": [CategoryDescription]
}
}
}
configurationGroups
Description
List every configuration group, in display order. Returns just the group metadata — for a flat list of every setting (or per-group) use configurations; for groups eagerly hydrated with their settings in one round-trip, use configurationGroupsWithSettings.
Response
Returns [ConfigurationGroup]
Example
Query
query configurationGroups {
configurationGroups {
id
title
description
sortOrder
configurations {
id
title
key
value
description
groupId
sortOrder
lastModified
dateAdded
useFunction
setFunction
group {
...ConfigurationGroupFragment
}
}
}
}
Response
{
"data": {
"configurationGroups": [
{
"id": "4",
"title": "xyz789",
"description": "xyz789",
"sortOrder": 987,
"configurations": [Configuration]
}
]
}
}
configurationGroupsWithSettings
Description
List every configuration group with its settings hydrated in one response. The resolver runs a single LEFT JOIN across configuration_group + configuration, ordered by group sort order, and folds the rows into a tree shape — groups with their nested configurations[] field populated.
Use this when the admin UI needs the full settings tree for a rendering pass (e.g. when the configuration editor first loads). For a flat list of just the groups, or settings filtered by group, use configurationGroups / configurations — those are lighter when you don't need every setting in every group.
Response
Returns [ConfigurationGroup]
Example
Query
query configurationGroupsWithSettings {
configurationGroupsWithSettings {
id
title
description
sortOrder
configurations {
id
title
key
value
description
groupId
sortOrder
lastModified
dateAdded
useFunction
setFunction
group {
...ConfigurationGroupFragment
}
}
}
}
Response
{
"data": {
"configurationGroupsWithSettings": [
{
"id": 4,
"title": "abc123",
"description": "abc123",
"sortOrder": 987,
"configurations": [Configuration]
}
]
}
}
configurations
Description
Page through configuration settings. Pass groupId to scope to one section of the admin UI (and the resolved group field will be hydrated in the same response); omit it to enumerate every setting across the platform.
Used by the admin's configuration editor, by tooling that audits platform settings, and by deploy / migration scripts that diff settings across tenants. For a tree-shaped fetch (groups + nested configurations) see configurationGroupsWithSettings.
Response
Returns [Configuration]
Example
Query
query configurations(
$groupId: Int,
$limit: Int,
$offset: Int
) {
configurations(
groupId: $groupId,
limit: $limit,
offset: $offset
) {
id
title
key
value
description
groupId
sortOrder
lastModified
dateAdded
useFunction
setFunction
group {
id
title
description
sortOrder
configurations {
...ConfigurationFragment
}
}
}
}
Variables
{"groupId": 123, "limit": 987, "offset": 123}
Response
{
"data": {
"configurations": [
{
"id": 4,
"title": "xyz789",
"key": "xyz789",
"value": "abc123",
"description": "xyz789",
"groupId": 123,
"sortOrder": 123,
"lastModified": "abc123",
"dateAdded": "xyz789",
"useFunction": "abc123",
"setFunction": "xyz789",
"group": ConfigurationGroup
}
]
}
}
countries
Description
List the countries the tenant supports. Used everywhere an address is captured: customer registration, checkout, address book, admin order builder. The storefront also picks the shopper's default currency from Country.defaultCurrencyId on first visit, and renders printed addresses with the AddressFormat referenced by Country.addressFormatId.
For the address-rendering templates themselves see addressFormats; for the currency definitions see currencies.
Response
Returns [Country]
Example
Query
query countries(
$limit: Int,
$offset: Int
) {
countries(
limit: $limit,
offset: $offset
) {
id
name
iso2
iso3
dutyRate
dutyLimit
addressFormatId
defaultCurrencyId
}
}
Variables
{"limit": 123, "offset": 123}
Response
{
"data": {
"countries": [
{
"id": 4,
"name": "xyz789",
"iso2": "abc123",
"iso3": "abc123",
"dutyRate": 123.45,
"dutyLimit": 123.45,
"addressFormatId": 987,
"defaultCurrencyId": 987
}
]
}
}
currencies
Description
List the currencies enabled for the tenant. Used by the storefront's currency switcher to render the available options, by the price formatter to look up the active currency's symbols and rate, and by the admin panel's currency settings tab.
For the country-level default-currency mapping (which currency a shopper from a given country sees by default) check Country.defaultCurrencyId on the countries query — this surface enumerates the currencies themselves.
Response
Returns [Currency]
Example
Query
query currencies(
$limit: Int,
$offset: Int
) {
currencies(
limit: $limit,
offset: $offset
) {
id
title
code
symbolLeft
symbolRight
value
lastUpdated
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"currencies": [
{
"id": "4",
"title": "abc123",
"code": "abc123",
"symbolLeft": "abc123",
"symbolRight": "xyz789",
"value": 987.65,
"lastUpdated": "abc123"
}
]
}
}
customer
Description
Fetch a single customer by id. Returns null when the id doesn't resolve. Includes the activity-stats sidecar and the customer's addresses in the same response.
Example
Query
query customer($id: ID!) {
customer(id: $id) {
id
gender
firstname
lastname
emailAddress
defaultAddressId
defaultDeliveryAddressId
telephone
newsletter
freeShipping
admin
type
group
approved
undeliveredOrders
blockPayments
blockShipments
temporaryCustomer
emailSent
apiId
apiBillingId
grantWhatsapp
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
info {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
addresses {
id
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"id": "4"}
Response
{
"data": {
"customer": {
"id": "4",
"gender": "xyz789",
"firstname": "abc123",
"lastname": "xyz789",
"emailAddress": "xyz789",
"defaultAddressId": 987,
"defaultDeliveryAddressId": 123,
"telephone": "abc123",
"newsletter": false,
"freeShipping": 987.65,
"admin": 123,
"type": 123,
"group": "abc123",
"approved": true,
"undeliveredOrders": 123,
"blockPayments": "xyz789",
"blockShipments": "abc123",
"temporaryCustomer": true,
"emailSent": false,
"apiId": "abc123",
"apiBillingId": 987,
"grantWhatsapp": true,
"billingOperatorId": 123,
"billingInvoiceAddress": "abc123",
"billingReference": "xyz789",
"billingReferenceRequired": true,
"info": CustomerInfo,
"addresses": [Address]
}
}
}
customerByEmail
Description
Fetch a customer by email. Email lookup is restricted to registered (non-temporary) customers; the resolver excludes temporary_customer rows, so guest checkouts sharing an email with a registered account won't be returned.
Response
Returns a Customer
Arguments
| Name | Description |
|---|---|
emailAddress - String!
|
Email address to look up. Case-insensitive in practice — emails are normalized to lowercase at registration. |
Example
Query
query customerByEmail($emailAddress: String!) {
customerByEmail(emailAddress: $emailAddress) {
id
gender
firstname
lastname
emailAddress
defaultAddressId
defaultDeliveryAddressId
telephone
newsletter
freeShipping
admin
type
group
approved
undeliveredOrders
blockPayments
blockShipments
temporaryCustomer
emailSent
apiId
apiBillingId
grantWhatsapp
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
info {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
addresses {
id
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"emailAddress": "abc123"}
Response
{
"data": {
"customerByEmail": {
"id": 4,
"gender": "abc123",
"firstname": "xyz789",
"lastname": "xyz789",
"emailAddress": "abc123",
"defaultAddressId": 123,
"defaultDeliveryAddressId": 123,
"telephone": "xyz789",
"newsletter": false,
"freeShipping": 123.45,
"admin": 123,
"type": 987,
"group": "xyz789",
"approved": false,
"undeliveredOrders": 987,
"blockPayments": "xyz789",
"blockShipments": "xyz789",
"temporaryCustomer": false,
"emailSent": false,
"apiId": "xyz789",
"apiBillingId": 123,
"grantWhatsapp": false,
"billingOperatorId": 987,
"billingInvoiceAddress": "abc123",
"billingReference": "abc123",
"billingReferenceRequired": false,
"info": CustomerInfo,
"addresses": [Address]
}
}
}
customerGroupPriceList
Description
Page through group-based price-list rules across all customer groups, with optional filters. This is the cross-group surface — equivalent in shape to CustomerGroup.priceList but reachable without first loading a parent group, useful when the caller has a productId in hand and wants every group's override for it, or wants to validate price rules around a specific date.
Pass validOn to bracket only rules active on a specific date (the resolver compares against valid_from / valid_to inclusive). Filters compose with AND. Used by admin pricing reports, by ERP / PIM sync flows that mirror group price overrides outward, and by the customer pricing audit. For per-group hydration via the group object, use customerGroups and consume the priceList field on each group.
Response
Returns [CustomerGroupPriceRule]
Arguments
| Name | Description |
|---|---|
customerGroupId - ID
|
Restrict to one customer group's rules. |
productId - Int
|
Restrict to rules for one product. |
validOn - String
|
Date the rule must be active on (compared inclusive against valid_from / valid_to). ISO-8601 date. |
limit - Int
|
Maximum number of rules to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query customerGroupPriceList(
$customerGroupId: ID,
$productId: Int,
$validOn: String,
$limit: Int,
$offset: Int
) {
customerGroupPriceList(
customerGroupId: $customerGroupId,
productId: $productId,
validOn: $validOn,
limit: $limit,
offset: $offset
) {
id
groupId
productId
productStockId
price
validFrom
validTo
customerGroup {
id
description
discountAmount
discountType
dateStart
dateEnd
minOrder
minOrderType
customerType
discountedProducts
groupsType
dynamicDiscounts {
...CustomerGroupDynamicDiscountFragment
}
priceList {
...CustomerGroupPriceRuleFragment
}
}
product {
id
name
model
image
price
description
shortDescription
material
}
}
}
Variables
{
"customerGroupId": 4,
"productId": 987,
"validOn": "abc123",
"limit": 987,
"offset": 987
}
Response
{
"data": {
"customerGroupPriceList": [
{
"id": 4,
"groupId": "xyz789",
"productId": 987,
"productStockId": 123,
"price": 987.65,
"validFrom": "xyz789",
"validTo": "xyz789",
"customerGroup": CustomerGroup,
"product": Product
}
]
}
}
customerGroups
Description
List customer groups available to the requesting context, with each group's dynamicDiscounts and priceList eagerly hydrated. The resolver also reads the X-Customer-Type header and filters to groups whose customerType is 'all' or matches the header — so a B2C front-end and a B2B portal hitting the same endpoint see different group sets without explicit filter args.
Pass type to scope to a specific groupsType (e.g. 'dynamic' to fetch only the matrix groups), and activeOnly = true to drop groups outside their dateStart / dateEnd window. Used by the storefront's pricing engine, by the admin's group editor, and by ERP exports. For per-rule cross-group fetch see customerGroupPriceList.
Response
Returns [CustomerGroup]
Example
Query
query customerGroups(
$type: String,
$activeOnly: Boolean
) {
customerGroups(
type: $type,
activeOnly: $activeOnly
) {
id
description
discountAmount
discountType
dateStart
dateEnd
minOrder
minOrderType
customerType
discountedProducts
groupsType
dynamicDiscounts {
id
groupId
amount
dateStart
dateEnd
manufacturer
category
sort
}
priceList {
id
groupId
productId
productStockId
price
validFrom
validTo
customerGroup {
...CustomerGroupFragment
}
product {
...ProductFragment
}
}
}
}
Variables
{"type": "xyz789", "activeOnly": true}
Response
{
"data": {
"customerGroups": [
{
"id": "4",
"description": "xyz789",
"discountAmount": 987.65,
"discountType": "abc123",
"dateStart": "xyz789",
"dateEnd": "abc123",
"minOrder": 987.65,
"minOrderType": "xyz789",
"customerType": "xyz789",
"discountedProducts": 123,
"groupsType": "xyz789",
"dynamicDiscounts": [
CustomerGroupDynamicDiscount
],
"priceList": [CustomerGroupPriceRule]
}
]
}
}
customerInfo
Description
Fetch the activity-stats side car for one customer: login counters, last-login timestamps, failed-login tally, account creation / modification dates, and marketing-source attribution.
Used by the admin's customer detail page to render 'Last login' and 'Failed attempts' badges, by security alerting on unusually high failed-login counts, and by lifecycle marketing flows. For the customer's profile, addresses, and group memberships see the customer query.
Response
Returns a CustomerInfo
Arguments
| Name | Description |
|---|---|
customerId - ID!
|
Customer to fetch the activity-stats side car for. |
Example
Query
query customerInfo($customerId: ID!) {
customerInfo(customerId: $customerId) {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
}
Variables
{"customerId": "4"}
Response
{
"data": {
"customerInfo": {
"dateOfLastLogon": "xyz789",
"numberOfLogons": 987,
"numberOfFailedLogins": 987,
"dateOfLastLoginFail": "abc123",
"dateAccountCreated": "abc123",
"dateAccountLastModified": "abc123",
"sourceId": 987,
"globalProductNotifications": 123
}
}
}
customerPrice
Response
Returns a CustomerPrice
Example
Query
query customerPrice(
$customerId: Int!,
$productId: Int!,
$validOn: String
) {
customerPrice(
customerId: $customerId,
productId: $productId,
validOn: $validOn
) {
id
customerId
productId
price
currency
validFrom
validTo
}
}
Variables
{
"customerId": 987,
"productId": 123,
"validOn": "xyz789"
}
Response
{
"data": {
"customerPrice": {
"id": 4,
"customerId": 987,
"productId": 123,
"price": 987.65,
"currency": "abc123",
"validFrom": "xyz789",
"validTo": "abc123"
}
}
}
customers
Description
Page through registered customers (excluding guest / temporary rows). Used by the admin's customer list, by export jobs, and by CRM integrations. For a single customer by id, use customer; by email, use customerByEmail.
Response
Returns [Customer]
Example
Query
query customers(
$limit: Int,
$offset: Int
) {
customers(
limit: $limit,
offset: $offset
) {
id
gender
firstname
lastname
emailAddress
defaultAddressId
defaultDeliveryAddressId
telephone
newsletter
freeShipping
admin
type
group
approved
undeliveredOrders
blockPayments
blockShipments
temporaryCustomer
emailSent
apiId
apiBillingId
grantWhatsapp
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
info {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
addresses {
id
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"customers": [
{
"id": "4",
"gender": "abc123",
"firstname": "xyz789",
"lastname": "xyz789",
"emailAddress": "abc123",
"defaultAddressId": 123,
"defaultDeliveryAddressId": 987,
"telephone": "abc123",
"newsletter": true,
"freeShipping": 987.65,
"admin": 987,
"type": 123,
"group": "xyz789",
"approved": true,
"undeliveredOrders": 123,
"blockPayments": "xyz789",
"blockShipments": "abc123",
"temporaryCustomer": true,
"emailSent": true,
"apiId": "xyz789",
"apiBillingId": 987,
"grantWhatsapp": true,
"billingOperatorId": 123,
"billingInvoiceAddress": "xyz789",
"billingReference": "xyz789",
"billingReferenceRequired": true,
"info": CustomerInfo,
"addresses": [Address]
}
]
}
}
customersApi
Description
List ERP-mirrored customer records, with optional filters. Used by the admin's ERP-status panel to inspect what the platform has cached from the source ERP, by B2B portals that need contract-side fields (credit limit, payment term, sales rep) at order placement, and by reconciliation reports comparing the ERP cache with the platform-side Customer record.
Filter args use the Finnish ERP field names: asiakaskoodi (customer code), email, alennusryhma (discount group). For the platform-side customer record (logins, addresses, group membership), join on Customer.apiId = CustomersApiCustomer.asiakaskoodi via the customer query.
Response
Returns [CustomersApiCustomer!]!
Arguments
| Name | Description |
|---|---|
asiakaskoodi - String
|
Filter to one ERP customer code (Finnish 'asiakaskoodi'). |
email - String
|
Filter to one email address (case-sensitive — matches the ERP-side normalization). |
alennusryhma - String
|
Filter to one ERP discount-group code (Finnish 'alennusryhma'). |
limit - Int
|
Maximum number of records to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query customersApi(
$asiakaskoodi: String,
$email: String,
$alennusryhma: String,
$limit: Int,
$offset: Int
) {
customersApi(
asiakaskoodi: $asiakaskoodi,
email: $email,
alennusryhma: $alennusryhma,
limit: $limit,
offset: $offset
) {
asiakaskoodi
name
secondaryName
addressLine1
addressLine2
addressLine3
deliveryName1
deliveryName2
deliveryName3
billingCustomerId
paymentTerm
customerGroup
chain
salesCode
creditLimit
deliveryBlock
email
website
phone
fax
deliveryMethod
discountGroup
discountPercent
secondaryDiscountPercent
languageCode
comment1
comment2
contactPerson
contactPersonId
lastLoginAt
vatLiability
currency
modifiedAt
businessId
billingAddress
intermediaryService
netvisorKey
}
}
Variables
{
"asiakaskoodi": "xyz789",
"email": "abc123",
"alennusryhma": "abc123",
"limit": 123,
"offset": 987
}
Response
{
"data": {
"customersApi": [
{
"asiakaskoodi": "xyz789",
"name": "xyz789",
"secondaryName": "abc123",
"addressLine1": "xyz789",
"addressLine2": "xyz789",
"addressLine3": "abc123",
"deliveryName1": "xyz789",
"deliveryName2": "abc123",
"deliveryName3": "xyz789",
"billingCustomerId": 123,
"paymentTerm": "abc123",
"customerGroup": "abc123",
"chain": "abc123",
"salesCode": "abc123",
"creditLimit": "abc123",
"deliveryBlock": "xyz789",
"email": "abc123",
"website": "abc123",
"phone": "abc123",
"fax": "xyz789",
"deliveryMethod": "abc123",
"discountGroup": "xyz789",
"discountPercent": 987.65,
"secondaryDiscountPercent": 987.65,
"languageCode": "xyz789",
"comment1": "xyz789",
"comment2": "xyz789",
"contactPerson": "abc123",
"contactPersonId": 123,
"lastLoginAt": "xyz789",
"vatLiability": "abc123",
"currency": "xyz789",
"modifiedAt": "abc123",
"businessId": "xyz789",
"billingAddress": "xyz789",
"intermediaryService": "xyz789",
"netvisorKey": 987
}
]
}
}
customersBasket
Description
List the saved-basket lines for one customer, newest line first. Pass cartId to scope to one named cart (lets a single customer hold multiple parallel baskets — saved-for-later vs. active checkout vs. a B2B quote draft).
Used by the storefront to rehydrate the cart on login, by the abandoned-basket email job, by the admin order-builder when an operator wants to create an order on behalf of a logged-in customer, and by B2B portal flows that quote off saved baskets. For finalized order lines see ordersProducts; for shared-basket flows see sharedBasket.
Response
Returns [CustomersBasketItem]
Example
Query
query customersBasket(
$customersId: ID!,
$cartId: String
) {
customersBasket(
customersId: $customersId,
cartId: $cartId
) {
id
cartId
customersId
itemId
productId
variants
productOptions
comment
customOptions
quantity
specialPrice
bundleId
includes
dateAdded
emailSent
emailLast
variableImage
allowSubstitute
}
}
Variables
{"customersId": 4, "cartId": "abc123"}
Response
{
"data": {
"customersBasket": [
{
"id": 4,
"cartId": "abc123",
"customersId": 987,
"itemId": "xyz789",
"productId": 987,
"variants": "abc123",
"productOptions": "xyz789",
"comment": "abc123",
"customOptions": "abc123",
"quantity": 123,
"specialPrice": 123.45,
"bundleId": "abc123",
"includes": "abc123",
"dateAdded": "abc123",
"emailSent": 987,
"emailLast": "abc123",
"variableImage": "abc123",
"allowSubstitute": false
}
]
}
}
customersBlacklist
Description
List blacklist entries, newest first. All filters are optional and AND-composable: pass customerId to fetch one customer's full history, status to scope to active blocks vs. lifted ones, or omit both to walk the tenant's full blacklist for a moderation review.
Used by the admin's customer detail view to render the block badge + history, by checkout middleware that reads the latest status to decide whether to short-circuit the order, and by fraud-investigation reports. For per-method bans see Customer.blockPayments / blockShipments; for product-allowlist flows see customersProductsInclusions.
Response
Returns [CustomerBlacklistEntry!]!
Example
Query
query customersBlacklist(
$customerId: Int,
$status: Int,
$limit: Int,
$offset: Int
) {
customersBlacklist(
customerId: $customerId,
status: $status,
limit: $limit,
offset: $offset
) {
id
customerId
status
reason
lastModified
}
}
Variables
{"customerId": 123, "status": 123, "limit": 123, "offset": 123}
Response
{
"data": {
"customersBlacklist": [
{
"id": "4",
"customerId": 987,
"status": 987,
"reason": "xyz789",
"lastModified": "xyz789"
}
]
}
}
customersBraintreeTokens
Description
List the saved Braintree cards for one customer. Used by the storefront's checkout to render the saved-cards picker, by the customer-account 'Payment methods' page to show / remove cards, and by the admin to audit which cards a customer has on file.
The token returned here is intended for server-side charging — pass it to Braintree's transaction.sale call. The masked number and card type are cached locally for display purposes only.
Response
Returns [CustomersBraintreeToken!]!
Example
Query
query customersBraintreeTokens(
$customersId: Int!,
$cardType: String,
$limit: Int,
$offset: Int
) {
customersBraintreeTokens(
customersId: $customersId,
cardType: $cardType,
limit: $limit,
offset: $offset
) {
id
customersId
braintreeToken
cardType
numberFiltered
expiryDate
dateAdded
}
}
Variables
{
"customersId": 987,
"cardType": "xyz789",
"limit": 123,
"offset": 123
}
Response
{
"data": {
"customersBraintreeTokens": [
{
"id": "4",
"customersId": 987,
"braintreeToken": "abc123",
"cardType": "xyz789",
"numberFiltered": "xyz789",
"expiryDate": "xyz789",
"dateAdded": "abc123"
}
]
}
}
customersHistory
Description
Page through the change log for one customer, newest first. Filters compose with AND: sourceTable scopes to one logical table (e.g. 'address_book' to see only address edits), userId scopes to one admin's edits to the customer.
Used by the admin's customer detail history tab, by GDPR / data-subject-access requests that need a complete edit trail, and by abuse / fraud investigation. For the cross-module action audit see actionRecorderEntries; for product-record edits see adminTrackingCreate.
Response
Returns [CustomerHistoryEntry!]!
Arguments
| Name | Description |
|---|---|
customerId - Int!
|
Customer to fetch history for. |
userId - Int
|
Filter to changes made by one admin id. |
sourceTable - String
|
Filter to changes on one source table (e.g. 'customers', 'address_book', 'customers_info'). |
limit - Int
|
Maximum number of entries to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query customersHistory(
$customerId: Int!,
$userId: Int,
$sourceTable: String,
$limit: Int,
$offset: Int
) {
customersHistory(
customerId: $customerId,
userId: $userId,
sourceTable: $sourceTable,
limit: $limit,
offset: $offset
) {
id
customerId
addressBookId
userId
userName
sourceTable
fieldName
oldValue
newValue
page
dateAdded
}
}
Variables
{
"customerId": 987,
"userId": 987,
"sourceTable": "abc123",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"customersHistory": [
{
"id": 4,
"customerId": 987,
"addressBookId": 987,
"userId": 987,
"userName": "xyz789",
"sourceTable": "xyz789",
"fieldName": "abc123",
"oldValue": "abc123",
"newValue": "xyz789",
"page": "abc123",
"dateAdded": "xyz789"
}
]
}
}
customersPrices
Response
Returns [CustomerPrice!]!
Example
Query
query customersPrices(
$customerId: Int,
$productId: Int,
$validOn: String,
$limit: Int,
$offset: Int
) {
customersPrices(
customerId: $customerId,
productId: $productId,
validOn: $validOn,
limit: $limit,
offset: $offset
) {
id
customerId
productId
price
currency
validFrom
validTo
}
}
Variables
{
"customerId": 987,
"productId": 987,
"validOn": "xyz789",
"limit": 987,
"offset": 987
}
Response
{
"data": {
"customersPrices": [
{
"id": "4",
"customerId": 987,
"productId": 987,
"price": 123.45,
"currency": "xyz789",
"validFrom": "abc123",
"validTo": "xyz789"
}
]
}
}
deliveryAddresses
Description
List the modern delivery-address entries for one customer. The response can side-load the legacy AddressBook bridge for entries that were migrated from the old schema — pass includeLegacy=true when the calling code still needs to reach the legacy billing fields on the original row.
Used by the storefront's checkout shipping picker on tenants running the modern address split, by the customer-account 'Delivery addresses' page, and by admin order-creation flows. For the legacy single-table address book see addressBookEntries; for the standalone billing book see billingAddresses.
Response
Returns [DeliveryAddress]
Arguments
| Name | Description |
|---|---|
customerId - ID!
|
Customer to fetch delivery addresses for. |
limit - Int
|
Maximum number of addresses to return. |
offset - Int
|
Offset for pagination. |
includeLegacy - Boolean
|
When true, side-load the legacy AddressBook row referenced by each entry's legacyAddressBookId. When false (default), legacyAddress is left null even if a bridge id exists. |
Example
Query
query deliveryAddresses(
$customerId: ID!,
$limit: Int,
$offset: Int,
$includeLegacy: Boolean
) {
deliveryAddresses(
customerId: $customerId,
limit: $limit,
offset: $offset,
includeLegacy: $includeLegacy
) {
id
customerId
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
legacyAddressBookId
legacyAddress {
id
customerId
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"customerId": 4, "limit": 987, "offset": 987, "includeLegacy": true}
Response
{
"data": {
"deliveryAddresses": [
{
"id": "4",
"customerId": 987,
"gender": "abc123",
"company": "xyz789",
"firstname": "xyz789",
"lastname": "xyz789",
"streetAddress": "abc123",
"vatid": "xyz789",
"postcode": "xyz789",
"city": "abc123",
"state": "abc123",
"countryId": 987,
"zoneId": 123,
"comments": "abc123",
"legacyAddressBookId": 987,
"legacyAddress": AddressBook
}
]
}
}
discountCoupon
Description
Fetch one coupon by id, with applicability arrays and counters fully hydrated. Returns null when the id doesn't resolve. Used by the storefront's 'enter code' flow to validate a single code and look up its discount value before applying it to the basket.
Response
Returns a DiscountCoupon
Arguments
| Name | Description |
|---|---|
id - ID!
|
Coupon id to fetch. |
Example
Query
query discountCoupon($id: ID!) {
discountCoupon(id: $id) {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
}
Variables
{"id": 4}
Response
{
"data": {
"discountCoupon": {
"id": 4,
"description": "abc123",
"amount": 123.45,
"discountType": "abc123",
"dateStart": "xyz789",
"dateEnd": "abc123",
"maxUse": 123,
"minOrder": 123.45,
"minOrderType": "xyz789",
"numberAvailable": 987,
"customerType": "abc123",
"discountedProducts": 123,
"discountedProductsOld": 987,
"allowedProducts": "xyz789",
"categories": [987],
"products": [123],
"customers": [123],
"orders": [987],
"manufacturers": [987],
"shippingMethods": ["xyz789"],
"zones": [987]
}
}
}
discountCoupons
Description
Page through every coupon definition in the tenant. Each coupon is returned with all its applicability arrays (categories / products / customers / orders / manufacturers / shippingMethods / zones) and the redemption counters (maxUse vs numberAvailable).
Used by the admin's coupon list / editor, by the storefront self-service 'enter code' flow that pre-validates a code on the fly, and by reconciliation reports. For per-order applied-coupons see discountCouponsToOrders / Order.discountCoupons; for per-customer attach / revoke see the customer-coupon mutations.
Response
Returns [DiscountCoupon]
Example
Query
query discountCoupons(
$limit: Int,
$offset: Int
) {
discountCoupons(
limit: $limit,
offset: $offset
) {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"discountCoupons": [
{
"id": 4,
"description": "xyz789",
"amount": 987.65,
"discountType": "abc123",
"dateStart": "xyz789",
"dateEnd": "abc123",
"maxUse": 123,
"minOrder": 987.65,
"minOrderType": "xyz789",
"numberAvailable": 123,
"customerType": "xyz789",
"discountedProducts": 987,
"discountedProductsOld": 987,
"allowedProducts": "xyz789",
"categories": [123],
"products": [987],
"customers": [123],
"orders": [987],
"manufacturers": [123],
"shippingMethods": ["xyz789"],
"zones": [123]
}
]
}
}
discountCouponsToOrders
Description
Page through coupon-to-order links. Filters compose with AND: pass orderId to fetch every coupon redeemed against one order (typically reached via Order.discountCoupons instead), or couponCode to walk the redemption history of one coupon (also reachable via DiscountCoupon.orders).
Used by coupon-performance reports (top-redeemed coupons, redemption-by-week dashboards), by refund flows that need to audit which coupons applied to a returned order, and by ERP / accounting exports.
Response
Returns [DiscountCouponOrderLink]
Example
Query
query discountCouponsToOrders(
$orderId: ID,
$couponCode: ID,
$limit: Int,
$offset: Int
) {
discountCouponsToOrders(
orderId: $orderId,
couponCode: $couponCode,
limit: $limit,
offset: $offset
) {
couponCode
orderId
coupon {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
order {
id
customerId
customerName
customerEmail
customer {
...OrderPartyFragment
}
deliveryAddress {
...OrderPartyFragment
}
billingAddress {
...OrderPartyFragment
}
status
datePurchased
lastModified
currency
currencyValue
paymentMethod
paymentCode
shippingMethod
shippingCode
shippingCost
deliveryQuantity
deliveryWeight
deliveryLength
deliveryWidth
deliveryHeight
deliveryComments
shippingLocationId
shippingLocationName
shippingLocationStreetAddress
shippingLocationPostcode
shippingLocationCity
paymentApiId
paymentProvider
paymentField
paymentInput
paymentTermId
shippingApiId
shippingApiTermId
shippingCostCentreId
shippingContractId
shippingContractCourier
warehouseCode
discountType
discountAmount
trackingCode
trackingLink
customerNotifiedFlag
trollyLocker
transactionId
ipAddress
ipIsp
pdfFiles
returnReason
referralId
ordersApiId
apiSent
emailSent
apiMessage
apiMessageDate
apiOrderStatusMessage
apiOrderStatusMessageDate
ordersPackingRulesJson
discountCoupons {
...DiscountCouponFragment
}
items {
...OrderItemFragment
}
totals {
...OrderTotalFragment
}
bankPayments {
...BankPaymentFragment
}
vivawalletPayments {
...OrderVivawalletPaymentFragment
}
}
}
}
Variables
{
"orderId": "4",
"couponCode": 4,
"limit": 123,
"offset": 987
}
Response
{
"data": {
"discountCouponsToOrders": [
{
"couponCode": 4,
"orderId": "4",
"coupon": DiscountCoupon,
"order": Order
}
]
}
}
domains
Description
List active storefront-domain configurations (status = 1). Pass locale to scope to one language code (matches Domain.code, e.g. 'fi' or 'en'); omit it to enumerate every domain the tenant has enabled.
Used by the storefront's bootstrap to pick the active domain's pixel ids and hreflang at render time, by the language switcher to enumerate alternate-language domains, and by the per-domain AI chat-widget bootstrap to load the right assistant + vector-store. For language metadata not specific to a domain, see the languages query.
Response
Returns [Domain]
Example
Query
query domains(
$locale: String,
$limit: Int,
$offset: Int
) {
domains(
locale: $locale,
limit: $limit,
offset: $offset
) {
id
languageId
code
hreflang
domain
cctld
flag
sortOrder
googlePixel
googleApiSecret
adwordsPixel
adwordsPhone
adwordsPurchase
adwordsContact
adwordsQuote
metaPixel
metaApiSecret
tiktokPixel
tiktokApiSecret
msAdsPixel
msAdsPhone
msAdsContact
msAdsPurchase
msAdsQuote
pinterestPixel
msClarityPixel
hotjarPixel
wpDomain
openaiChatInstructions
openaiVectorStoreId
openaiChatAssistantId
}
}
Variables
{
"locale": "xyz789",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"domains": [
{
"id": "4",
"languageId": 987,
"code": "xyz789",
"hreflang": "xyz789",
"domain": "xyz789",
"cctld": "xyz789",
"flag": "xyz789",
"sortOrder": 123,
"googlePixel": "abc123",
"googleApiSecret": "xyz789",
"adwordsPixel": "xyz789",
"adwordsPhone": "abc123",
"adwordsPurchase": "abc123",
"adwordsContact": "abc123",
"adwordsQuote": "abc123",
"metaPixel": "xyz789",
"metaApiSecret": "xyz789",
"tiktokPixel": "xyz789",
"tiktokApiSecret": "abc123",
"msAdsPixel": "xyz789",
"msAdsPhone": "abc123",
"msAdsContact": "xyz789",
"msAdsPurchase": "abc123",
"msAdsQuote": "abc123",
"pinterestPixel": "xyz789",
"msClarityPixel": "abc123",
"hotjarPixel": "abc123",
"wpDomain": "abc123",
"openaiChatInstructions": "xyz789",
"openaiVectorStoreId": "xyz789",
"openaiChatAssistantId": "abc123"
}
]
}
}
faqCategories
Description
List FAQ categories with their nested questions. Pass languageId to scope description rows to one language (skipping non-matching FaqCategoryDescription / FaqQuestionDescription rows in the response). visibleOnly = true filters out hidden categories AND questions; includeHiddenQuestions overrides the visibility filter for questions only (categories still respect visibleOnly). sortByOrder = true sorts categories and questions by their sortOrder fields.
Used to render the storefront's help-center landing page, the accordion-style FAQ sections on product / category pages, and to seed the AI assistant's grounding corpus. For a single question by id or slug, use faqQuestion.
Response
Returns [FaqCategory]
Arguments
| Name | Description |
|---|---|
languageId - Int
|
Language to scope description rows to. Omit for all languages. |
visibleOnly - Boolean
|
When true, drop hidden categories and (unless includeHiddenQuestions overrides) hidden questions. |
includeHiddenQuestions - Boolean
|
When true, include hidden questions inside visible categories — overrides the question-side filter applied by visibleOnly. |
sortByOrder - Boolean
|
When true, sort categories and questions by their sortOrder fields. When false, fall back to id ordering. |
Example
Query
query faqCategories(
$languageId: Int,
$visibleOnly: Boolean,
$includeHiddenQuestions: Boolean,
$sortByOrder: Boolean
) {
faqCategories(
languageId: $languageId,
visibleOnly: $visibleOnly,
includeHiddenQuestions: $includeHiddenQuestions,
sortByOrder: $sortByOrder
) {
id
icon
image
visibility
googleIndex
sortOrder
descriptions {
languageId
name
url
description
metaTitle
metaDescription
}
questions {
id
image
sortOrder
visibility
googleIndex
enableUrl
categories
descriptions {
...FaqQuestionDescriptionFragment
}
}
}
}
Variables
{
"languageId": 123,
"visibleOnly": false,
"includeHiddenQuestions": false,
"sortByOrder": false
}
Response
{
"data": {
"faqCategories": [
{
"id": 4,
"icon": "abc123",
"image": "xyz789",
"visibility": 987,
"googleIndex": 123,
"sortOrder": 123,
"descriptions": [FaqCategoryDescription],
"questions": [FaqQuestion]
}
]
}
}
faqQuestion
Description
Fetch a single FAQ question by id or by slug. Pass id to look up the question directly; pass slug to look it up by the per-language FaqQuestionDescription.url field (the routable form when enableUrl = 1). Use languageId to scope returned descriptions to one language; visibleOnly = true returns null when the question is hidden.
Response
Returns a FaqQuestion
Arguments
| Name | Description |
|---|---|
id - ID
|
Question id to fetch. |
slug - String
|
Slug to look up. Resolves against FaqQuestionDescription.url; pair with languageId for unambiguous matching. |
languageId - Int
|
Language to scope the slug match and the returned descriptions. |
visibleOnly - Boolean
|
When true, return null for questions whose visibility = 0. |
Example
Query
query faqQuestion(
$id: ID,
$slug: String,
$languageId: Int,
$visibleOnly: Boolean
) {
faqQuestion(
id: $id,
slug: $slug,
languageId: $languageId,
visibleOnly: $visibleOnly
) {
id
image
sortOrder
visibility
googleIndex
enableUrl
categories
descriptions {
languageId
question
answer
shortAnswer
url
metaTitle
metaDescription
}
}
}
Variables
{
"id": "4",
"slug": "abc123",
"languageId": 987,
"visibleOnly": true
}
Response
{
"data": {
"faqQuestion": {
"id": "4",
"image": "xyz789",
"sortOrder": 987,
"visibility": 987,
"googleIndex": 987,
"enableUrl": 123,
"categories": [987],
"descriptions": [FaqQuestionDescription]
}
}
}
languages
Description
List the languages enabled for the tenant. Used by the storefront's language switcher, by the admin's language picker, and by any integration that needs the tenant's full set of canonical language ids before resolving per-language description rows on other types.
Returns the platform's shared core ids plus any tenant-defined extensions. The image / directory fields come back nested under metadata to keep the i18n-bundle plumbing separate from the user-facing identity (id / code / name).
Response
Returns [Language]
Example
Query
query languages(
$limit: Int,
$offset: Int
) {
languages(
limit: $limit,
offset: $offset
) {
id
code
name
metadata {
image
directory
}
}
}
Variables
{"limit": 987, "offset": 123}
Response
{
"data": {
"languages": [
{
"id": "4",
"code": "abc123",
"name": "abc123",
"metadata": LanguageMetadata
}
]
}
}
manufacturer
Description
Fetch a single brand by id. Pass languageId to receive only that language's ManufacturerInfo row in the infos array (the storefront uses this on brand-page render); omit it to receive every language (the admin brand editor uses this).
Response
Returns a Manufacturer
Example
Query
query manufacturer(
$id: ID!,
$languageId: Int
) {
manufacturer(
id: $id,
languageId: $languageId
) {
id
name
code
image
brandPageImage
listingImage
sortOrder
status
dateAdded
lastModified
fitValue
specialDiscount
cmsDescription
countryApprovedProduct
displayFrontpage
infos {
languageId
urlClicked
dateLastClick
description
descriptionTop
}
}
}
Variables
{"id": "4", "languageId": 987}
Response
{
"data": {
"manufacturer": {
"id": 4,
"name": "abc123",
"code": "xyz789",
"image": "xyz789",
"brandPageImage": "abc123",
"listingImage": "abc123",
"sortOrder": 123,
"status": 123,
"dateAdded": "xyz789",
"lastModified": "abc123",
"fitValue": "xyz789",
"specialDiscount": 987,
"cmsDescription": 123,
"countryApprovedProduct": "xyz789",
"displayFrontpage": 123,
"infos": [ManufacturerInfo]
}
}
}
manufacturers
Description
Page through the brands in the catalog. Returns each manufacturer with all its ManufacturerInfo rows attached, so a single fetch can render any language. Used by the storefront's brand index, by sitemap builders, and by ERP exports.
For one brand by id (with the option to scope description rows to one language), use manufacturer.
Response
Returns [Manufacturer]
Example
Query
query manufacturers(
$limit: Int,
$offset: Int
) {
manufacturers(
limit: $limit,
offset: $offset
) {
id
name
code
image
brandPageImage
listingImage
sortOrder
status
dateAdded
lastModified
fitValue
specialDiscount
cmsDescription
countryApprovedProduct
displayFrontpage
infos {
languageId
urlClicked
dateLastClick
description
descriptionTop
}
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"manufacturers": [
{
"id": 4,
"name": "xyz789",
"code": "xyz789",
"image": "abc123",
"brandPageImage": "xyz789",
"listingImage": "abc123",
"sortOrder": 987,
"status": 123,
"dateAdded": "xyz789",
"lastModified": "xyz789",
"fitValue": "xyz789",
"specialDiscount": 987,
"cmsDescription": 123,
"countryApprovedProduct": "abc123",
"displayFrontpage": 123,
"infos": [ManufacturerInfo]
}
]
}
}
order
Description
Fetch a single order by id, with the full record hydrated. Returns null when the id doesn't resolve. Sub-fields (items, totals, discountCoupons, vivawalletPayments, etc.) lazy-load on demand, so a minimal selection still does a fast single-row read.
Example
Query
query order($id: ID!) {
order(id: $id) {
id
customerId
customerName
customerEmail
customer {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
deliveryAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
billingAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
status
datePurchased
lastModified
currency
currencyValue
paymentMethod
paymentCode
shippingMethod
shippingCode
shippingCost
deliveryQuantity
deliveryWeight
deliveryLength
deliveryWidth
deliveryHeight
deliveryComments
shippingLocationId
shippingLocationName
shippingLocationStreetAddress
shippingLocationPostcode
shippingLocationCity
paymentApiId
paymentProvider
paymentField
paymentInput
paymentTermId
shippingApiId
shippingApiTermId
shippingCostCentreId
shippingContractId
shippingContractCourier
warehouseCode
discountType
discountAmount
trackingCode
trackingLink
customerNotifiedFlag
trollyLocker
transactionId
ipAddress
ipIsp
pdfFiles
returnReason
referralId
ordersApiId
apiSent
emailSent
apiMessage
apiMessageDate
apiOrderStatusMessage
apiOrderStatusMessageDate
ordersPackingRulesJson
discountCoupons {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
items {
id
orderId
productId
productModel
productEan
productName
quantity
quantityReturned
price
originalPrice
tax
stockVariants
lineType
comment
customOptions
productCategories
productWeight
productLocation
variableImage
allowSubstitute
confirmFlag
confirmProductsQuantity
autoComment
variants {
...OrderItemVariantFragment
}
}
totals {
id
orderId
title
text
value
valueUnreturned
taxRate
taxAmount
class
sortOrder
}
bankPayments {
id
orderId
invoicePaymentDate
invoicePaymentValueDate
amount
}
vivawalletPayments {
id
orderId
customerId
paymentMethod
notificationId
orderCode
transactionUuid
sessionId
}
}
}
Variables
{"id": "4"}
Response
{
"data": {
"order": {
"id": 4,
"customerId": 987,
"customerName": "abc123",
"customerEmail": "xyz789",
"customer": OrderParty,
"deliveryAddress": OrderParty,
"billingAddress": OrderParty,
"status": 987,
"datePurchased": "xyz789",
"lastModified": "xyz789",
"currency": "xyz789",
"currencyValue": 123.45,
"paymentMethod": "abc123",
"paymentCode": "xyz789",
"shippingMethod": "abc123",
"shippingCode": "abc123",
"shippingCost": 123.45,
"deliveryQuantity": 987,
"deliveryWeight": 987.65,
"deliveryLength": 123.45,
"deliveryWidth": 123.45,
"deliveryHeight": 987.65,
"deliveryComments": "abc123",
"shippingLocationId": "xyz789",
"shippingLocationName": "abc123",
"shippingLocationStreetAddress": "xyz789",
"shippingLocationPostcode": "xyz789",
"shippingLocationCity": "xyz789",
"paymentApiId": "xyz789",
"paymentProvider": "xyz789",
"paymentField": "abc123",
"paymentInput": "abc123",
"paymentTermId": "xyz789",
"shippingApiId": "abc123",
"shippingApiTermId": "xyz789",
"shippingCostCentreId": "xyz789",
"shippingContractId": "xyz789",
"shippingContractCourier": "abc123",
"warehouseCode": "abc123",
"discountType": "xyz789",
"discountAmount": 123.45,
"trackingCode": "abc123",
"trackingLink": "abc123",
"customerNotifiedFlag": 987,
"trollyLocker": 123.45,
"transactionId": "abc123",
"ipAddress": "abc123",
"ipIsp": "xyz789",
"pdfFiles": "abc123",
"returnReason": "xyz789",
"referralId": "xyz789",
"ordersApiId": "xyz789",
"apiSent": 123,
"emailSent": 123,
"apiMessage": "abc123",
"apiMessageDate": "xyz789",
"apiOrderStatusMessage": "xyz789",
"apiOrderStatusMessageDate": "abc123",
"ordersPackingRulesJson": "abc123",
"discountCoupons": [DiscountCoupon],
"items": [OrderItem],
"totals": [OrderTotal],
"bankPayments": [BankPayment],
"vivawalletPayments": [OrderVivawalletPayment]
}
}
}
orderItems
Description
Return every line on a single order, including each line's variants. Use this when rendering an order detail view where you need the line breakdown separately from the order header.
The same data is exposed through Order.items, which is preferable when you're already fetching the order and want to avoid a round trip. To modify lines on an existing order, see the addOrdersProduct / updateOrdersProduct / removeOrdersProduct mutations, which write to the same underlying orders_products row.
Response
Returns [OrderItem!]!
Arguments
| Name | Description |
|---|---|
orderId - ID!
|
Example
Query
query orderItems($orderId: ID!) {
orderItems(orderId: $orderId) {
id
orderId
productId
productModel
productEan
productName
quantity
quantityReturned
price
originalPrice
tax
stockVariants
lineType
comment
customOptions
productCategories
productWeight
productLocation
variableImage
allowSubstitute
confirmFlag
confirmProductsQuantity
autoComment
variants {
id
orderProductId
optionId
optionName
optionValue
price
pricePrefix
}
}
}
Variables
{"orderId": "4"}
Response
{
"data": {
"orderItems": [
{
"id": "4",
"orderId": 123,
"productId": 123,
"productModel": "abc123",
"productEan": "xyz789",
"productName": "abc123",
"quantity": 987,
"quantityReturned": 987,
"price": 987.65,
"originalPrice": 987.65,
"tax": 123.45,
"stockVariants": "xyz789",
"lineType": "xyz789",
"comment": "abc123",
"customOptions": {},
"productCategories": "abc123",
"productWeight": 987.65,
"productLocation": "xyz789",
"variableImage": "abc123",
"allowSubstitute": 123,
"confirmFlag": 123,
"confirmProductsQuantity": 987,
"autoComment": 123,
"variants": [OrderItemVariant]
}
]
}
}
orderStatusHistory
Description
Paginated status-transition timeline for one order, returned newest-first. Use this to render the "status history" widget on an admin order detail view, or to investigate when an order entered a particular state.
Pass statusId to filter to one specific status (e.g. only the Shipped transitions). For the broader change-log including non-status edits see ordersHistory; to record a new transition see the addOrdersStatusHistory mutation.
Response
Returns [OrderStatusHistory]
Example
Query
query orderStatusHistory(
$orderId: Int!,
$statusId: Int,
$limit: Int,
$offset: Int
) {
orderStatusHistory(
orderId: $orderId,
statusId: $statusId,
limit: $limit,
offset: $offset
) {
id
orderId
statusId
statusName
dateAdded
customerNotified
comments
}
}
Variables
{"orderId": 123, "statusId": 987, "limit": 123, "offset": 123}
Response
{
"data": {
"orderStatusHistory": [
{
"id": 4,
"orderId": 987,
"statusId": 123,
"statusName": "xyz789",
"dateAdded": "xyz789",
"customerNotified": 123,
"comments": "abc123"
}
]
}
}
orderStatuses
Description
Return every order status defined for the connected tenant in the requested language. Use this to render status filters and badges in the admin panel, and to translate Order.status / OrderStatusHistory.statusId numeric ids to display labels.
Tenants extend the canonical id set with custom workflow stages and payment-provider intermediate states; resolve dynamically rather than hardcoding. For per-order transition history use orderStatusHistory; to record a new status transition use addOrdersStatusHistory.
Response
Returns [OrderStatus]
Arguments
| Name | Description |
|---|---|
languageId - Int!
|
Language id to fetch labels in (1=EN, 5=SV, 6=FI, 9=ES, 14=IT). |
Example
Query
query orderStatuses($languageId: Int!) {
orderStatuses(languageId: $languageId) {
id
languageId
code
name
apiFlag
apiId
colorCode
}
}
Variables
{"languageId": 123}
Response
{
"data": {
"orderStatuses": [
{
"id": "4",
"languageId": 123,
"code": "xyz789",
"name": "abc123",
"apiFlag": 987,
"apiId": "xyz789",
"colorCode": "abc123"
}
]
}
}
orderTotals
Description
Return the totals breakdown for one order — the rows that render as the "Subtotal / Tax / Shipping / Discount / Grand total" block on an invoice or order summary.
Pass class to scope to one row category (e.g. just 'Tax' to render the tax breakdown). Omit it to receive every row sorted by sortOrder so the result can be rendered top-to-bottom directly.
Order.totals exposes the same data with the same arguments and is preferable when you're already fetching the order header.
Response
Returns [OrderTotal!]!
Example
Query
query orderTotals(
$orderId: ID!,
$class: String
) {
orderTotals(
orderId: $orderId,
class: $class
) {
id
orderId
title
text
value
valueUnreturned
taxRate
taxAmount
class
sortOrder
}
}
Variables
{"orderId": 4, "class": "xyz789"}
Response
{
"data": {
"orderTotals": [
{
"id": "4",
"orderId": 987,
"title": "xyz789",
"text": "xyz789",
"value": 123.45,
"valueUnreturned": 123.45,
"taxRate": 123.45,
"taxAmount": 987.65,
"class": "abc123",
"sortOrder": 123
}
]
}
}
orders
Description
Page through orders, newest first. Pass customerId to scope to one customer's order history (used by the customer account 'My orders' page and admin customer detail). Used by the admin order list, by fulfilment dashboards, by ERP / accounting exports, and by reports that walk the full order book.
For one order's full detail (line items, totals, status history, payment notifications) use order with the appropriate sub-fields.
Response
Returns [Order]
Example
Query
query orders(
$limit: Int,
$offset: Int,
$customerId: Int
) {
orders(
limit: $limit,
offset: $offset,
customerId: $customerId
) {
id
customerId
customerName
customerEmail
customer {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
deliveryAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
billingAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
status
datePurchased
lastModified
currency
currencyValue
paymentMethod
paymentCode
shippingMethod
shippingCode
shippingCost
deliveryQuantity
deliveryWeight
deliveryLength
deliveryWidth
deliveryHeight
deliveryComments
shippingLocationId
shippingLocationName
shippingLocationStreetAddress
shippingLocationPostcode
shippingLocationCity
paymentApiId
paymentProvider
paymentField
paymentInput
paymentTermId
shippingApiId
shippingApiTermId
shippingCostCentreId
shippingContractId
shippingContractCourier
warehouseCode
discountType
discountAmount
trackingCode
trackingLink
customerNotifiedFlag
trollyLocker
transactionId
ipAddress
ipIsp
pdfFiles
returnReason
referralId
ordersApiId
apiSent
emailSent
apiMessage
apiMessageDate
apiOrderStatusMessage
apiOrderStatusMessageDate
ordersPackingRulesJson
discountCoupons {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
items {
id
orderId
productId
productModel
productEan
productName
quantity
quantityReturned
price
originalPrice
tax
stockVariants
lineType
comment
customOptions
productCategories
productWeight
productLocation
variableImage
allowSubstitute
confirmFlag
confirmProductsQuantity
autoComment
variants {
...OrderItemVariantFragment
}
}
totals {
id
orderId
title
text
value
valueUnreturned
taxRate
taxAmount
class
sortOrder
}
bankPayments {
id
orderId
invoicePaymentDate
invoicePaymentValueDate
amount
}
vivawalletPayments {
id
orderId
customerId
paymentMethod
notificationId
orderCode
transactionUuid
sessionId
}
}
}
Variables
{"limit": 123, "offset": 123, "customerId": 987}
Response
{
"data": {
"orders": [
{
"id": 4,
"customerId": 987,
"customerName": "xyz789",
"customerEmail": "xyz789",
"customer": OrderParty,
"deliveryAddress": OrderParty,
"billingAddress": OrderParty,
"status": 987,
"datePurchased": "xyz789",
"lastModified": "abc123",
"currency": "abc123",
"currencyValue": 987.65,
"paymentMethod": "abc123",
"paymentCode": "xyz789",
"shippingMethod": "xyz789",
"shippingCode": "xyz789",
"shippingCost": 123.45,
"deliveryQuantity": 987,
"deliveryWeight": 123.45,
"deliveryLength": 987.65,
"deliveryWidth": 987.65,
"deliveryHeight": 123.45,
"deliveryComments": "xyz789",
"shippingLocationId": "abc123",
"shippingLocationName": "xyz789",
"shippingLocationStreetAddress": "abc123",
"shippingLocationPostcode": "abc123",
"shippingLocationCity": "xyz789",
"paymentApiId": "xyz789",
"paymentProvider": "xyz789",
"paymentField": "abc123",
"paymentInput": "xyz789",
"paymentTermId": "xyz789",
"shippingApiId": "abc123",
"shippingApiTermId": "abc123",
"shippingCostCentreId": "abc123",
"shippingContractId": "abc123",
"shippingContractCourier": "xyz789",
"warehouseCode": "abc123",
"discountType": "abc123",
"discountAmount": 987.65,
"trackingCode": "xyz789",
"trackingLink": "xyz789",
"customerNotifiedFlag": 987,
"trollyLocker": 987.65,
"transactionId": "abc123",
"ipAddress": "abc123",
"ipIsp": "abc123",
"pdfFiles": "abc123",
"returnReason": "xyz789",
"referralId": "xyz789",
"ordersApiId": "abc123",
"apiSent": 123,
"emailSent": 987,
"apiMessage": "abc123",
"apiMessageDate": "abc123",
"apiOrderStatusMessage": "xyz789",
"apiOrderStatusMessageDate": "xyz789",
"ordersPackingRulesJson": "xyz789",
"discountCoupons": [DiscountCoupon],
"items": [OrderItem],
"totals": [OrderTotal],
"bankPayments": [BankPayment],
"vivawalletPayments": [OrderVivawalletPayment]
}
]
}
}
ordersHistory
Description
Paginated audit log of changes for one order, returned newest-first. Use this for the "history" tab on an order detail view, for compliance audits, or to reconstruct who changed what and when on an order that's now in dispute.
Filter by userId to see only one administrator's edits, or by date range (startDate / endDate, ISO YYYY-MM-DD) to scope to one investigation window. For status-only transitions there's a more focused view via orderStatusHistory.
Response
Returns [OrderHistoryEntry!]!
Arguments
| Name | Description |
|---|---|
orderId - Int!
|
Order to fetch the change log for. |
userId - Int
|
Filter to changes made by this administrator user id. |
startDate - String
|
ISO date (YYYY-MM-DD) — return only entries on or after this date. |
endDate - String
|
ISO date (YYYY-MM-DD) — return only entries on or before this date. |
limit - Int
|
Maximum rows to return (default 10). |
offset - Int
|
Number of rows to skip for pagination (default 0). |
Example
Query
query ordersHistory(
$orderId: Int!,
$userId: Int,
$startDate: String,
$endDate: String,
$limit: Int,
$offset: Int
) {
ordersHistory(
orderId: $orderId,
userId: $userId,
startDate: $startDate,
endDate: $endDate,
limit: $limit,
offset: $offset
) {
id
orderId
entityType
entityId
columnName
oldValue
newValue
actionType
userId
userName
page
createdAt
}
}
Variables
{
"orderId": 123,
"userId": 123,
"startDate": "xyz789",
"endDate": "xyz789",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"ordersHistory": [
{
"id": 4,
"orderId": 123,
"entityType": "xyz789",
"entityId": 987,
"columnName": "abc123",
"oldValue": "xyz789",
"newValue": "abc123",
"actionType": "xyz789",
"userId": 987,
"userName": "abc123",
"page": "abc123",
"createdAt": "abc123"
}
]
}
}
ordersVivawallet
Description
Look up Vivawallet payment records, by order, by transaction UUID, or by Vivawallet's orderCode. Use this for reconciliation against Vivawallet's merchant reports, for chargeback investigations (filter by transactionUuid), or to render the payment-trail block on an admin order detail.
For all order-attached payments at once, prefer Order.vivawalletPayments when you're already fetching the order. For Nets-provider notifications see ordersNets / OrderNetsNotification (separate table with a different shape).
Response
Returns [OrderVivawalletPayment!]!
Arguments
| Name | Description |
|---|---|
orderId - Int
|
Filter to records for this single order. |
transactionUuid - String
|
Filter to a specific Vivawallet transaction UUID (chargeback / refund lookup). |
orderCode - String
|
Filter to Vivawallet's orderCode for the payment session. |
limit - Int
|
Maximum rows to return. |
offset - Int
|
Number of rows to skip for pagination. |
Example
Query
query ordersVivawallet(
$orderId: Int,
$transactionUuid: String,
$orderCode: String,
$limit: Int,
$offset: Int
) {
ordersVivawallet(
orderId: $orderId,
transactionUuid: $transactionUuid,
orderCode: $orderCode,
limit: $limit,
offset: $offset
) {
id
orderId
customerId
paymentMethod
notificationId
orderCode
transactionUuid
sessionId
}
}
Variables
{
"orderId": 123,
"transactionUuid": "xyz789",
"orderCode": "abc123",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"ordersVivawallet": [
{
"id": "4",
"orderId": 987,
"customerId": 123,
"paymentMethod": "xyz789",
"notificationId": 123,
"orderCode": "abc123",
"transactionUuid": "abc123",
"sessionId": "xyz789"
}
]
}
}
product
Description
Fetch a single product by id, with its localized description rows. Pass languageId to scope the description / shortDescription / material to one language; omit it to receive the row with the lowest language_id (the resolver orders ASC and takes the first).
Used to render the storefront's product detail page header and the admin product editor's overview tab. For configurable options see productAttributes; for variant-level stock and pricing see productStock; for the variant-aware image gallery see productExtraImages; for PDFs / CAD / videos see productsMedia.
Response
Returns a Product
Example
Query
query product(
$id: ID!,
$languageId: Int
) {
product(
id: $id,
languageId: $languageId
) {
id
name
model
image
price
description
shortDescription
material
}
}
Variables
{"id": 4, "languageId": 123}
Response
{
"data": {
"product": {
"id": "4",
"name": "xyz789",
"model": "abc123",
"image": "abc123",
"price": 987.65,
"description": "abc123",
"shortDescription": "xyz789",
"material": "abc123"
}
}
}
productAttributes
Description
List the configurable options for one product, with each option's selectable values, in the requested language.
Use this to render the variant selector on product detail pages, to populate option pickers in the admin order builder, and to validate incoming OrderItemVariant choices on createOrder. For per-product catalog attributes (size charts, technical specs, EAV-style fields), see the products query — those live on the eav_attribute system, distinct from this product-options system.
Response
Returns [ProductOption]
Example
Query
query productAttributes(
$productId: ID!,
$languageId: Int
) {
productAttributes(
productId: $productId,
languageId: $languageId
) {
id
name
code
description
sort
values {
id
name
code
specification
weight
sort
hex
priceDelta
pricePrefix
apiId
}
}
}
Variables
{"productId": "4", "languageId": 123}
Response
{
"data": {
"productAttributes": [
{
"id": "4",
"name": "abc123",
"code": "xyz789",
"description": "abc123",
"sort": 987,
"values": [ProductOptionValue]
}
]
}
}
productExtraImages
Description
List the extra (non-main) images attached to one product, in display order, with localized captions.
Use this on product detail pages alongside the main Product.image, and for variant-aware galleries (filter the result by optionId == selected variant's option-value id, plus optionId == 0 for variant-agnostic images). For other media types — PDFs, datasheets, videos, CAD — use productsMedia instead.
Response
Returns [ProductExtraImage]
Example
Query
query productExtraImages(
$productId: ID!,
$languageId: Int
) {
productExtraImages(
productId: $productId,
languageId: $languageId
) {
id
code
url
sort
optionId
description
}
}
Variables
{"productId": 4, "languageId": 123}
Response
{
"data": {
"productExtraImages": [
{
"id": "4",
"code": "xyz789",
"url": "xyz789",
"sort": 123,
"optionId": 987,
"description": "xyz789"
}
]
}
}
productPriceHistory
Description
List historical price changes for a product, newest first. Pass stockId to scope to one variant, omit it to receive every variant's history plus the product-level changes (stockId = 0). Filter by startDate / endDate to bracket a time window, by userName to audit one admin's pricing edits, and use limit / offset to page through long histories.
Used by the admin pricing tab's history view, by the reporting dashboard that surfaces frequent price changers, and by ERP reconciliation flows that need to verify an external price update landed. For the current live price use ProductStock.price (per-variant) or the price field on Product (product-level).
Response
Returns [ProductPriceHistory]
Arguments
| Name | Description |
|---|---|
productId - ID!
|
Product to fetch the price history for. |
stockId - ID
|
Variant (products_stock) id to scope the history to a single SKU. Pass 0 for product-level changes only. Omit for everything. |
startDate - String
|
Lower bound of the date filter (inclusive). ISO-8601 date or datetime. |
endDate - String
|
Upper bound of the date filter (inclusive). ISO-8601 date or datetime. |
userName - String
|
Filter to changes made by this admin username. |
limit - Int
|
Maximum number of history rows to return. |
offset - Int
|
Offset for pagination. |
Example
Query
query productPriceHistory(
$productId: ID!,
$stockId: ID,
$startDate: String,
$endDate: String,
$userName: String,
$limit: Int,
$offset: Int
) {
productPriceHistory(
productId: $productId,
stockId: $stockId,
startDate: $startDate,
endDate: $endDate,
userName: $userName,
limit: $limit,
offset: $offset
) {
id
productId
stockId
price
date
userName
}
}
Variables
{
"productId": 4,
"stockId": "4",
"startDate": "abc123",
"endDate": "abc123",
"userName": "abc123",
"limit": 987,
"offset": 987
}
Response
{
"data": {
"productPriceHistory": [
{
"id": 4,
"productId": 4,
"stockId": "4",
"price": 123.45,
"date": "abc123",
"userName": "xyz789"
}
]
}
}
productStock
Description
List the stock rows for one product. Pass variant to scope to a single SKU (matching ProductStock.variant); omit it to receive every variant of the product.
Use this for product detail pages that need per-variant availability, for the admin product editor's stock tab, and for ERP reconciliation flows. For per-warehouse split see warehouseStock; for the price-change audit trail see productPriceHistory.
Response
Returns [ProductStock]
Example
Query
query productStock(
$productId: ID!,
$variant: String
) {
productStock(
productId: $productId,
variant: $variant
) {
id
productId
variant
quantity
price
priceOriginal
shelf
}
}
Variables
{"productId": 4, "variant": "xyz789"}
Response
{
"data": {
"productStock": [
{
"id": 4,
"productId": "4",
"variant": "abc123",
"quantity": 987,
"price": 987.65,
"priceOriginal": 987.65,
"shelf": "xyz789"
}
]
}
}
productVolumeAddonPrices
Description
List the per-product step-pricing tiers for one product, ordered by minimum quantity. Used by the storefront's quantity input to show the next price break, by the basket to apply the active tier, and by the quoting flow to compute line totals at the right unit price.
For percentage-based discounts gated on customer group / type, see productVolumeDiscounts. For the price-change audit trail, see productPriceHistory.
Response
Returns [ProductVolumeAddonPriceTier]
Arguments
| Name | Description |
|---|---|
productId - ID!
|
Product to fetch step-pricing tiers for. |
Example
Query
query productVolumeAddonPrices($productId: ID!) {
productVolumeAddonPrices(productId: $productId) {
minimumQuantity
unitPrice
}
}
Variables
{"productId": "4"}
Response
{
"data": {
"productVolumeAddonPrices": [{"minimumQuantity": 987, "unitPrice": 123.45}]
}
}
productVolumeDiscounts
Description
List the group-based volume-discount tiers for one product, in threshold order. Used to render wholesale price ladders on B2B product pages, to apply contract pricing at checkout, and to expose tier eligibility in the admin pricing tab.
For per-product step pricing (replace-the-unit-price ladders), see productVolumeAddonPrices. For the price-change audit trail, see productPriceHistory.
Response
Returns [ProductVolumeDiscountTier]
Arguments
| Name | Description |
|---|---|
productId - ID!
|
Product to fetch volume-discount tiers for. |
Example
Query
query productVolumeDiscounts($productId: ID!) {
productVolumeDiscounts(productId: $productId) {
minimumQuantity
discountPercentage
customerGroupId
customerId
customerType
}
}
Variables
{"productId": 4}
Response
{
"data": {
"productVolumeDiscounts": [
{
"minimumQuantity": 987,
"discountPercentage": 987.65,
"customerGroupId": "abc123",
"customerId": 987,
"customerType": "abc123"
}
]
}
}
products
Description
Page through the catalog's products. Returns the headline fields only (id, name from model, image, price) — there's no language selector on this query, so descriptions / material aren't included. Used for catalog feeds, sitemaps, and admin / ERP exports that need a product enumeration without per-language hydration.
For the full product detail (with descriptions, in a specific language) use product. For category-scoped product fetches join via productsToCategories.
Response
Returns [Product]
Example
Query
query products(
$limit: Int,
$offset: Int
) {
products(
limit: $limit,
offset: $offset
) {
id
name
model
image
price
description
shortDescription
material
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"products": [
{
"id": 4,
"name": "abc123",
"model": "abc123",
"image": "xyz789",
"price": 123.45,
"description": "xyz789",
"shortDescription": "abc123",
"material": "abc123"
}
]
}
}
productsMedia
Description
List the media attachments for one product (PDFs, CAD files, lighting profiles, etc.), in display order, with localized descriptions.
Used to render the storefront's "Documents & downloads" block on product detail pages, and by the admin product editor's media tab. Pass includeCategory=true (the default) to resolve each row's ProductMediaCategory in the same round-trip; set false when you only need the file list and want to skip the category JOIN.
For images that go in the main product gallery (with variant- specific filtering), use productExtraImages instead.
Response
Returns [ProductMedia]
Arguments
| Name | Description |
|---|---|
productId - ID!
|
Product to fetch media for. |
languageId - Int
|
Language id for the localized name + description (1=EN, 5=SV, 6=FI, 9=ES, 14=IT — tenants may extend; resolve dynamically via the languages query). |
includeCategory - Boolean
|
Whether to resolve each media row's category in the same response. Defaults to true. Default = true |
Example
Query
query productsMedia(
$productId: ID!,
$languageId: Int,
$includeCategory: Boolean
) {
productsMedia(
productId: $productId,
languageId: $languageId,
includeCategory: $includeCategory
) {
id
productId
categoryId
file
sortOrder
type
size
description
category {
id
code
sortOrder
name
}
}
}
Variables
{"productId": 4, "languageId": 987, "includeCategory": true}
Response
{
"data": {
"productsMedia": [
{
"id": 4,
"productId": "4",
"categoryId": 123,
"file": "xyz789",
"sortOrder": 987,
"type": "xyz789",
"size": "abc123",
"description": "xyz789",
"category": ProductMediaCategory
}
]
}
}
productsToCategories
Description
List product-to-category link rows. All filters are optional and composable: pass productId to get every category one product belongs to, pass categoryId to get every product in one category, or pass both to check for the existence of a single link. Use limit / offset to page through large categories (the storefront's category listing pages do).
For full Product or Category records (with their fields, prices, descriptions), follow the resolved product / category fields, or query products / categories directly — productsToCategories is a navigation / membership surface, not a full product or category fetch.
Response
Returns [ProductCategoryLink]
Example
Query
query productsToCategories(
$productId: ID,
$categoryId: ID,
$limit: Int,
$offset: Int
) {
productsToCategories(
productId: $productId,
categoryId: $categoryId,
limit: $limit,
offset: $offset
) {
productId
categoryId
product {
id
name
model
image
price
description
shortDescription
material
}
category {
id
code
image
banner
parentId
sortOrder
position
descriptions {
...CategoryDescriptionFragment
}
}
}
}
Variables
{
"productId": 4,
"categoryId": "4",
"limit": 987,
"offset": 123
}
Response
{
"data": {
"productsToCategories": [
{
"productId": "4",
"categoryId": "4",
"product": Product,
"category": Category
}
]
}
}
quote
Description
Fetch a single quote by id, with line items hydrated. Returns null when the id doesn't resolve. Used by the admin quote editor's detail view, by the customer-facing 'My quote' page, and by the quote-to-order conversion flow when an operator accepts a quote.
Example
Query
query quote($id: ID!) {
quote(id: $id) {
id
customerId
sessionId
ipAddress
statusId
dateAdded
dateModified
dateReminder
dateFollowUp
sendReminder
sendFollowUp
discountType
discountAmount
comment
cc
shipmentMethod
shipmentCode
shipmentPrice
warehouseId
items {
id
quoteId
productId
variant
quantity
discountedPrice
productGroup
comment
customOptions
bundleId
}
}
}
Variables
{"id": 4}
Response
{
"data": {
"quote": {
"id": "4",
"customerId": 987,
"sessionId": "abc123",
"ipAddress": "abc123",
"statusId": 987,
"dateAdded": "abc123",
"dateModified": "xyz789",
"dateReminder": "abc123",
"dateFollowUp": "abc123",
"sendReminder": "xyz789",
"sendFollowUp": "abc123",
"discountType": "abc123",
"discountAmount": 987.65,
"comment": "xyz789",
"cc": "abc123",
"shipmentMethod": "abc123",
"shipmentCode": "xyz789",
"shipmentPrice": 987.65,
"warehouseId": 123,
"items": [QuoteProduct]
}
}
}
quoteFiles
Description
List the attachments belonging to one quote, in id order. Used by the admin quote editor's 'Files' tab, by the customer-facing quote view that shows the proposal PDF alongside any uploaded briefs, and by the quote-to-order conversion flow when the seller wants to forward attachments through to the resulting order.
Response
Returns [QuoteFile]
Arguments
| Name | Description |
|---|---|
quoteId - ID!
|
Quote to fetch attachments for. |
Example
Query
query quoteFiles($quoteId: ID!) {
quoteFiles(quoteId: $quoteId) {
id
quoteId
file
}
}
Variables
{"quoteId": 4}
Response
{
"data": {
"quoteFiles": [
{
"id": "4",
"quoteId": 987,
"file": "xyz789"
}
]
}
}
quoteGroups
Description
List the quote groups defined for the tenant in the requested language. Used to render the group dropdown on the storefront's quote-request form, and the same selector in the admin quote editor when an operator creates a quote on a customer's behalf.
Resolves only to rows matching the languageId — the resolver doesn't fall back to other languages, so ensure the language has been seeded with the full group set or pass a known language id.
Response
Returns [QuoteGroup!]!
Arguments
| Name | Description |
|---|---|
languageId - Int!
|
Language to fetch group labels in. Required. |
Example
Query
query quoteGroups($languageId: Int!) {
quoteGroups(languageId: $languageId) {
id
languageId
name
}
}
Variables
{"languageId": 987}
Response
{
"data": {
"quoteGroups": [
{
"id": "4",
"languageId": 987,
"name": "xyz789"
}
]
}
}
quoteStatusHistory
Description
Return the status-transition timeline for one quote. Mirrors orderStatusHistory but for quotes. Used by the admin quote detail's history tab; to record a new transition (and optionally notify the customer) use addQuoteStatusHistory.
Response
Returns [QuoteStatusEntry]
Arguments
| Name | Description |
|---|---|
quoteId - ID!
|
Quote to fetch the timeline for. |
Example
Query
query quoteStatusHistory($quoteId: ID!) {
quoteStatusHistory(quoteId: $quoteId) {
id
quoteId
statusId
statusName
dateAdded
customerNotified
comments
}
}
Variables
{"quoteId": 4}
Response
{
"data": {
"quoteStatusHistory": [
{
"id": 4,
"quoteId": 123,
"statusId": 987,
"statusName": "abc123",
"dateAdded": "xyz789",
"customerNotified": 123,
"comments": "xyz789"
}
]
}
}
quoteStatuses
Description
Return the quote-status definitions in the requested language. Used to render status filters and badges in the admin quote list, and to translate Quote.statusId / QuoteStatusEntry.statusId numeric ids to display labels.
Tenants may extend the canonical id set with custom workflow stages; resolve dynamically rather than hardcoding.
Response
Returns [QuoteStatus]
Arguments
| Name | Description |
|---|---|
languageId - Int!
|
Language to fetch labels in. Required. |
Example
Query
query quoteStatuses($languageId: Int!) {
quoteStatuses(languageId: $languageId) {
id
languageId
name
code
}
}
Variables
{"languageId": 123}
Response
{
"data": {
"quoteStatuses": [
{
"id": 4,
"languageId": 987,
"name": "xyz789",
"code": "xyz789"
}
]
}
}
quotesByCustomer
Description
List quotes for one customer, optionally scoped to one statusId. Used by the customer account 'My quotes' page (typically scoped to 'Open' + 'Proposal sent') and by the admin's per-customer quote list.
Response
Returns [Quote!]!
Example
Query
query quotesByCustomer(
$customerId: Int!,
$statusId: Int,
$limit: Int
) {
quotesByCustomer(
customerId: $customerId,
statusId: $statusId,
limit: $limit
) {
id
customerId
sessionId
ipAddress
statusId
dateAdded
dateModified
dateReminder
dateFollowUp
sendReminder
sendFollowUp
discountType
discountAmount
comment
cc
shipmentMethod
shipmentCode
shipmentPrice
warehouseId
items {
id
quoteId
productId
variant
quantity
discountedPrice
productGroup
comment
customOptions
bundleId
}
}
}
Variables
{"customerId": 123, "statusId": 987, "limit": 123}
Response
{
"data": {
"quotesByCustomer": [
{
"id": "4",
"customerId": 987,
"sessionId": "xyz789",
"ipAddress": "abc123",
"statusId": 123,
"dateAdded": "xyz789",
"dateModified": "xyz789",
"dateReminder": "abc123",
"dateFollowUp": "abc123",
"sendReminder": "abc123",
"sendFollowUp": "abc123",
"discountType": "abc123",
"discountAmount": 987.65,
"comment": "abc123",
"cc": "xyz789",
"shipmentMethod": "xyz789",
"shipmentCode": "abc123",
"shipmentPrice": 987.65,
"warehouseId": 123,
"items": [QuoteProduct]
}
]
}
}
quotesBySession
Description
List quotes for one anonymous session — quotes captured before the customer logged in or registered. Used to migrate anonymous quotes onto a fresh customer account at sign-up time.
Response
Returns [Quote!]!
Example
Query
query quotesBySession(
$sessionId: String!,
$statusId: Int,
$limit: Int
) {
quotesBySession(
sessionId: $sessionId,
statusId: $statusId,
limit: $limit
) {
id
customerId
sessionId
ipAddress
statusId
dateAdded
dateModified
dateReminder
dateFollowUp
sendReminder
sendFollowUp
discountType
discountAmount
comment
cc
shipmentMethod
shipmentCode
shipmentPrice
warehouseId
items {
id
quoteId
productId
variant
quantity
discountedPrice
productGroup
comment
customOptions
bundleId
}
}
}
Variables
{
"sessionId": "abc123",
"statusId": 123,
"limit": 987
}
Response
{
"data": {
"quotesBySession": [
{
"id": "4",
"customerId": 123,
"sessionId": "xyz789",
"ipAddress": "abc123",
"statusId": 123,
"dateAdded": "xyz789",
"dateModified": "abc123",
"dateReminder": "abc123",
"dateFollowUp": "abc123",
"sendReminder": "abc123",
"sendFollowUp": "xyz789",
"discountType": "abc123",
"discountAmount": 987.65,
"comment": "xyz789",
"cc": "abc123",
"shipmentMethod": "abc123",
"shipmentCode": "xyz789",
"shipmentPrice": 987.65,
"warehouseId": 987,
"items": [QuoteProduct]
}
]
}
}
reviewSummaries
Description
Aggregate review counts and ratings across one or many products. Pass productId to fetch the summary for a single product (powering the rating badge on a product page); omit it to walk every product's aggregate (used by sitemap / feed builders that emit aggregate rating microdata).
Response
Returns [ReviewSummary]
Example
Query
query reviewSummaries(
$productId: ID,
$limit: Int,
$offset: Int
) {
reviewSummaries(
productId: $productId,
limit: $limit,
offset: $offset
) {
productId
reviewsCount
ratingSummary
}
}
Variables
{"productId": 4, "limit": 123, "offset": 123}
Response
{
"data": {
"reviewSummaries": [
{"productId": 4, "reviewsCount": 987, "ratingSummary": 123}
]
}
}
reviews
Description
Page through reviews. Filters compose with AND: pass productId to scope to one product (powering the product-page review widget), statusId to filter by moderation state (e.g. 'approved' for storefront, 'pending' for the admin moderation queue), languageId to scope ReviewDetail rows to one language.
Used by the storefront's product-page review listing, by the admin moderation tools, and by review-syndication exports. For aggregate counts and average ratings (without the full review bodies) see reviewSummaries.
Response
Returns [Review]
Example
Query
query reviews(
$productId: ID,
$statusId: Int,
$languageId: Int,
$limit: Int,
$offset: Int
) {
reviews(
productId: $productId,
statusId: $statusId,
languageId: $languageId,
limit: $limit,
offset: $offset
) {
id
productId
customerId
nickname
country
isRecommended
verifiedBuyer
count
statusId
statusCode
dates {
createdAt
orderDate
answerDate
}
details {
languageId
title
detail
answer
}
}
}
Variables
{
"productId": 4,
"statusId": 123,
"languageId": 987,
"limit": 123,
"offset": 987
}
Response
{
"data": {
"reviews": [
{
"id": "4",
"productId": 4,
"customerId": 987,
"nickname": "abc123",
"country": "abc123",
"isRecommended": true,
"verifiedBuyer": false,
"count": 123,
"statusId": 987,
"statusCode": "abc123",
"dates": ReviewDates,
"details": [ReviewDetail]
}
]
}
}
serviceCategories
Description
List service categories in the requested language, optionally scoped to one branch of the tree (parentId) or to footer-visible categories only (displayFooter). Returns the categories with their children nested in-place, so a single fetch can render the full storefront CMS navigation tree.
Used by the storefront's CMS-page navigation, by the footer layout, and by the admin's service-category editor. For the individual service pages living under each category, see the services query.
Response
Returns [ServiceCategory]
Arguments
| Name | Description |
|---|---|
languageId - Int!
|
Language to fetch description rows in. Required. |
parentId - Int
|
Restrict to children of one parent category id. Pass 0 to scope to top-level categories; omit to span all. |
displayFooter - Boolean
|
When true, restrict to categories with displayFooter = 1 (footer-visible only). |
Example
Query
query serviceCategories(
$languageId: Int!,
$parentId: Int,
$displayFooter: Boolean
) {
serviceCategories(
languageId: $languageId,
parentId: $parentId,
displayFooter: $displayFooter
) {
id
parentId
sortOrder
displayFooter
svgIcon
descriptions {
languageId
name
url
html
}
children {
id
parentId
sortOrder
displayFooter
svgIcon
descriptions {
...ServiceCategoryDescriptionFragment
}
children {
...ServiceCategoryFragment
}
}
}
}
Variables
{"languageId": 123, "parentId": 987, "displayFooter": false}
Response
{
"data": {
"serviceCategories": [
{
"id": "4",
"parentId": 123,
"sortOrder": 987,
"displayFooter": 987,
"svgIcon": "xyz789",
"descriptions": [ServiceCategoryDescription],
"children": [ServiceCategory]
}
]
}
}
services
Description
List service pages in the requested language. Pass categoryId to scope to one CMS section (e.g. the 'Help' branch); pass displayFooter = true to restrict to footer-visible pages only.
Used by the storefront's CMS routing layer to render individual information pages, by the footer layout to enumerate footer links, and by sitemap builders. For the navigation tree of categories see serviceCategories; for product-catalog content see products / categories.
Response
Returns [Service]
Example
Query
query services(
$languageId: Int!,
$categoryId: Int,
$displayFooter: Boolean
) {
services(
languageId: $languageId,
categoryId: $categoryId,
displayFooter: $displayFooter
) {
id
categoryId
image
sortOrder
displayFooter
googleFeed
css
externalJs
externalCss
svgIcon
descriptions {
languageId
name
url
html
metaTitle
metaDescription
}
category {
id
parentId
sortOrder
displayFooter
svgIcon
descriptions {
...ServiceCategoryDescriptionFragment
}
children {
...ServiceCategoryFragment
}
}
}
}
Variables
{"languageId": 987, "categoryId": 987, "displayFooter": true}
Response
{
"data": {
"services": [
{
"id": "4",
"categoryId": 123,
"image": "xyz789",
"sortOrder": 123,
"displayFooter": 987,
"googleFeed": 987,
"css": "xyz789",
"externalJs": "abc123",
"externalCss": "xyz789",
"svgIcon": "xyz789",
"descriptions": [ServiceDescription],
"category": ServiceCategory
}
]
}
}
warehouseStock
Description
List per-warehouse on-hand quantities. All filters are optional: pass productId to get a product's split across all warehouses, pass warehouseId to list every product's quantity at one warehouse, or pass both to get the single (warehouse, product) row.
Used by the storefront's 'check stock at your local store' UI, by the admin's warehouse inventory reports, and by fulfilment routing logic. For variant-level totals across warehouses see productStock; for the full warehouse master list (locations, codes, defaults) see the warehouses query.
Response
Returns [WarehouseStock]
Example
Query
query warehouseStock(
$warehouseId: Int,
$productId: Int
) {
warehouseStock(
warehouseId: $warehouseId,
productId: $productId
) {
id
warehouseId
productId
quantity
}
}
Variables
{"warehouseId": 123, "productId": 987}
Response
{
"data": {
"warehouseStock": [
{"id": 4, "warehouseId": 123, "productId": 987, "quantity": 987}
]
}
}
warehouses
Description
Page through the warehouses the tenant has configured. Used by the storefront's 'Find a store' / store-locator picker, by the admin's warehouse list, by the order-creation flow when an operator picks where to ship from, and by ERP / WMS reconciliation reports.
For per-warehouse on-hand quantities, follow Warehouse.stock or use the warehouseStock query directly. For the variant-level stock totals (across all warehouses), see productStock.
Response
Returns [Warehouse]
Example
Query
query warehouses(
$limit: Int,
$offset: Int
) {
warehouses(
limit: $limit,
offset: $offset
) {
id
name
code
phone
email
visible
stock {
id
warehouseId
productId
quantity
}
}
}
Variables
{"limit": 987, "offset": 987}
Response
{
"data": {
"warehouses": [
{
"id": "4",
"name": "xyz789",
"code": "abc123",
"phone": "abc123",
"email": "xyz789",
"visible": false,
"stock": [WarehouseStock]
}
]
}
}
Mutations
_empty
Response
Returns a String
Example
Query
mutation _empty {
_empty
}
Response
{"data": {"_empty": "abc123"}}
addOrdersProduct
Description
Add a new line to an existing order. Use this from the admin panel or an ERP integration to extend an order after it has been placed — e.g. to add an upsold accessory, an apology gift, or a manual correction line. Returns the inserted OrdersProduct including its assigned id.
To attach configurable-option selections to the new line, follow up with addOrdersProductsVariant once you have the returned id.
Response
Returns an OrdersProduct!
Arguments
| Name | Description |
|---|---|
input - AddOrdersProductInput!
|
Example
Query
mutation addOrdersProduct($input: AddOrdersProductInput!) {
addOrdersProduct(input: $input) {
id
orderId
productId
productModel
productEan
productName
price
originalPrice
tax
quantity
quantityReturned
stockVariants
lineType
comment
customOptions
}
}
Variables
{"input": AddOrdersProductInput}
Response
{
"data": {
"addOrdersProduct": {
"id": 4,
"orderId": 987,
"productId": 987,
"productModel": "xyz789",
"productEan": "abc123",
"productName": "xyz789",
"price": 987.65,
"originalPrice": 987.65,
"tax": 987.65,
"quantity": 987,
"quantityReturned": 123,
"stockVariants": "xyz789",
"lineType": "abc123",
"comment": "abc123",
"customOptions": {}
}
}
}
addOrdersProductsVariant
Description
Attach a new variant selection to an existing order line. Use this after addOrdersProduct (or on an existing line) to record a size/colour/personalisation choice that affects the line's total via pricePrefix. Returns the inserted OrdersProductsVariant.
Response
Returns an OrdersProductsVariant!
Arguments
| Name | Description |
|---|---|
input - AddOrdersProductsVariantInput!
|
Example
Query
mutation addOrdersProductsVariant($input: AddOrdersProductsVariantInput!) {
addOrdersProductsVariant(input: $input) {
id
orderId
orderProductId
optionId
optionName
optionValue
price
pricePrefix
}
}
Variables
{"input": AddOrdersProductsVariantInput}
Response
{
"data": {
"addOrdersProductsVariant": {
"id": "4",
"orderId": 123,
"orderProductId": 123,
"optionId": 123,
"optionName": "xyz789",
"optionValue": "xyz789",
"price": 987.65,
"pricePrefix": "abc123"
}
}
}
addOrdersStatusHistory
Description
Record a new status transition on an order. Used by the admin panel and integrations to advance an order through its workflow (Received → Packing → Shipped → Delivered) and to optionally notify the customer in the same call.
Two side-effect flags:
- notifyCustomer: when true, emits an order-status notification email to the customer using the tenant's notification template for the new status.
- updateOrderStatus: when true (default), also writes the new statusId to orders.orders_status so it becomes the order's current status. Set false to record an audit-only transition without changing the visible status.
The transition is also surfaced through the orderStatusHistory read query and as an OrderHistoryEntry on the broader audit log.
Response
Returns an OrdersStatusHistoryEntry!
Arguments
| Name | Description |
|---|---|
input - OrdersStatusHistoryInput!
|
Example
Query
mutation addOrdersStatusHistory($input: OrdersStatusHistoryInput!) {
addOrdersStatusHistory(input: $input) {
id
orderId
statusId
dateAdded
customerNotified
comments
}
}
Variables
{"input": OrdersStatusHistoryInput}
Response
{
"data": {
"addOrdersStatusHistory": {
"id": 4,
"orderId": 123,
"statusId": 123,
"dateAdded": "abc123",
"customerNotified": 987,
"comments": "xyz789"
}
}
}
addQuoteFile
Description
Record a new attachment on a quote. The file is expected to already be uploaded to the tenant's quote-files directory; this mutation persists the filename in quote_files so it shows up in the quote's attachment list. Returns the persisted QuoteFile including its assigned id.
Response
Returns a QuoteFile!
Example
Query
mutation addQuoteFile(
$quoteId: ID!,
$file: String!
) {
addQuoteFile(
quoteId: $quoteId,
file: $file
) {
id
quoteId
file
}
}
Variables
{
"quoteId": "4",
"file": "abc123"
}
Response
{
"data": {
"addQuoteFile": {
"id": 4,
"quoteId": 987,
"file": "abc123"
}
}
}
addQuoteStatusHistory
Description
Record a new status transition on a quote. Persists the row to quotes_status_history and, when updateNotifications is set, also flips the parent quote's reminder / follow-up flags so the auto-reminder system picks up the new state. Returns the persisted timeline entry, including the assigned id and timestamp.
Use this for the admin quote editor's status-change dropdown, for automated workflow steps that move quotes through approval, and for the quote-to-order conversion flow that closes the quote out by moving it to 'Ordered'. To read the timeline see quoteStatusHistory.
Response
Returns a QuoteStatusEntry
Arguments
| Name | Description |
|---|---|
input - AddQuoteStatusHistoryInput!
|
The status transition to record. |
updateNotifications - QuoteNotificationFlagsInput
|
Optional reminder / follow-up flag updates applied to the parent Quote in the same call. |
Example
Query
mutation addQuoteStatusHistory(
$input: AddQuoteStatusHistoryInput!,
$updateNotifications: QuoteNotificationFlagsInput
) {
addQuoteStatusHistory(
input: $input,
updateNotifications: $updateNotifications
) {
id
quoteId
statusId
statusName
dateAdded
customerNotified
comments
}
}
Variables
{
"input": AddQuoteStatusHistoryInput,
"updateNotifications": QuoteNotificationFlagsInput
}
Response
{
"data": {
"addQuoteStatusHistory": {
"id": 4,
"quoteId": 123,
"statusId": 123,
"statusName": "xyz789",
"dateAdded": "xyz789",
"customerNotified": 123,
"comments": "xyz789"
}
}
}
attachDiscountCouponToCustomer
Description
Issue a coupon to a specific customer. Verifies the coupon and the customer both exist, then writes a discount_coupons_to_customers row (idempotent — repeated calls don't create duplicates). Used by admin tools that hand out named-account / VIP coupons, by loyalty rule engines that earn coupons for specific customers, and by onboarding flows that issue welcome coupons.
Once attached, the coupon's customers[] list (visible via the discountCoupon query) includes this customer, and the customer becomes eligible to redeem the coupon at checkout.
Response
Returns a DiscountCouponCustomerLink!
Arguments
| Name | Description |
|---|---|
input - DiscountCouponCustomerLinkInput!
|
The (couponCode, customerId) pair to attach. |
Example
Query
mutation attachDiscountCouponToCustomer($input: DiscountCouponCustomerLinkInput!) {
attachDiscountCouponToCustomer(input: $input) {
couponCode
customerId
}
}
Variables
{"input": DiscountCouponCustomerLinkInput}
Response
{"data": {"attachDiscountCouponToCustomer": {"couponCode": 4, "customerId": 4}}}
createCustomer
Description
Create a registered customer account with a password. Email address must be unique across registered customers in the tenant — the resolver throws when the email collides with an existing registered account. Password is bcrypt-hashed before storage. Returns the created Customer including its assigned id.
Response
Returns a Customer!
Arguments
| Name | Description |
|---|---|
input - CreateCustomerInput!
|
Example
Query
mutation createCustomer($input: CreateCustomerInput!) {
createCustomer(input: $input) {
id
gender
firstname
lastname
emailAddress
defaultAddressId
defaultDeliveryAddressId
telephone
newsletter
freeShipping
admin
type
group
approved
undeliveredOrders
blockPayments
blockShipments
temporaryCustomer
emailSent
apiId
apiBillingId
grantWhatsapp
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
info {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
addresses {
id
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"input": CreateCustomerInput}
Response
{
"data": {
"createCustomer": {
"id": 4,
"gender": "abc123",
"firstname": "xyz789",
"lastname": "abc123",
"emailAddress": "xyz789",
"defaultAddressId": 987,
"defaultDeliveryAddressId": 123,
"telephone": "abc123",
"newsletter": false,
"freeShipping": 987.65,
"admin": 123,
"type": 987,
"group": "xyz789",
"approved": false,
"undeliveredOrders": 987,
"blockPayments": "xyz789",
"blockShipments": "abc123",
"temporaryCustomer": true,
"emailSent": true,
"apiId": "xyz789",
"apiBillingId": 123,
"grantWhatsapp": false,
"billingOperatorId": 123,
"billingInvoiceAddress": "abc123",
"billingReference": "xyz789",
"billingReferenceRequired": true,
"info": CustomerInfo,
"addresses": [Address]
}
}
}
createFavorite
Description
Add a product to a customer's wishlist. Inserts a new row in customers_favorites; the same (customer, product) pair can appear only once per the table's uniqueness constraint, so attempting to re-add an existing favorite errors at the DB layer.
Used by the storefront's 'heart' / 'save for later' button on product cards and product detail pages.
Response
Returns a CustomerFavorite
Arguments
| Name | Description |
|---|---|
input - AddCustomerFavoriteInput!
|
Example
Query
mutation createFavorite($input: AddCustomerFavoriteInput!) {
createFavorite(input: $input) {
id
customersId
productsId
}
}
Variables
{"input": AddCustomerFavoriteInput}
Response
{
"data": {
"createFavorite": {
"id": "4",
"customersId": 123,
"productsId": 123
}
}
}
createGuestCustomer
Description
Create a guest customer for one-time checkout, without a password. The resolver sets temporary_customer to the current Unix timestamp so admin tooling can later sweep stale guest rows. Guest customers may share email addresses with each other and with registered customers. Returns the created Customer including its assigned id.
Response
Returns a Customer!
Arguments
| Name | Description |
|---|---|
input - CreateGuestCustomerInput!
|
Example
Query
mutation createGuestCustomer($input: CreateGuestCustomerInput!) {
createGuestCustomer(input: $input) {
id
gender
firstname
lastname
emailAddress
defaultAddressId
defaultDeliveryAddressId
telephone
newsletter
freeShipping
admin
type
group
approved
undeliveredOrders
blockPayments
blockShipments
temporaryCustomer
emailSent
apiId
apiBillingId
grantWhatsapp
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
info {
dateOfLastLogon
numberOfLogons
numberOfFailedLogins
dateOfLastLoginFail
dateAccountCreated
dateAccountLastModified
sourceId
globalProductNotifications
}
addresses {
id
gender
company
firstname
lastname
streetAddress
vatid
postcode
city
state
countryId
zoneId
comments
billingStreetAddress
billingFirstname
billingLastname
billingPostcode
billingCity
billingCountryId
billingCompany
billingVatid
billingZoneId
billingState
billingOperatorId
billingInvoiceAddress
billingReference
billingReferenceRequired
}
}
}
Variables
{"input": CreateGuestCustomerInput}
Response
{
"data": {
"createGuestCustomer": {
"id": "4",
"gender": "abc123",
"firstname": "abc123",
"lastname": "abc123",
"emailAddress": "abc123",
"defaultAddressId": 123,
"defaultDeliveryAddressId": 987,
"telephone": "abc123",
"newsletter": true,
"freeShipping": 987.65,
"admin": 123,
"type": 123,
"group": "xyz789",
"approved": true,
"undeliveredOrders": 987,
"blockPayments": "abc123",
"blockShipments": "xyz789",
"temporaryCustomer": true,
"emailSent": true,
"apiId": "abc123",
"apiBillingId": 123,
"grantWhatsapp": false,
"billingOperatorId": 123,
"billingInvoiceAddress": "abc123",
"billingReference": "abc123",
"billingReferenceRequired": false,
"info": CustomerInfo,
"addresses": [Address]
}
}
}
createOrder
Description
Create an order with line items, addresses, and chosen payment + shipping methods. The resolver validates paymentCode against the tenant's MODULE_PAYMENT_INSTALLED configuration and shippingCode against MODULE_SHIPPING_INSTALLED — both are required and free-form or removed-module values are rejected loud (with the error message listing what's available).
Status defaults to 1 (Received) unless explicitly set. The customer-side party snapshot is captured on the order so later edits to the customer's profile or saved addresses don't retroactively change the order. To record subsequent status transitions use addOrdersStatusHistory; to add / edit / remove line items after creation use addOrdersProduct / updateOrdersProduct / removeOrdersProduct.
Response
Returns an Order!
Arguments
| Name | Description |
|---|---|
input - CreateOrderInput!
|
The order to create — placing customer, delivery / billing parties, payment + shipping methods, and line items. |
Example
Query
mutation createOrder($input: CreateOrderInput!) {
createOrder(input: $input) {
id
customerId
customerName
customerEmail
customer {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
deliveryAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
billingAddress {
name
company
vatId
streetAddress
city
postcode
state
country
telephone
emailAddress
addressFormatId
invoiceAddress
operatorId
reference
}
status
datePurchased
lastModified
currency
currencyValue
paymentMethod
paymentCode
shippingMethod
shippingCode
shippingCost
deliveryQuantity
deliveryWeight
deliveryLength
deliveryWidth
deliveryHeight
deliveryComments
shippingLocationId
shippingLocationName
shippingLocationStreetAddress
shippingLocationPostcode
shippingLocationCity
paymentApiId
paymentProvider
paymentField
paymentInput
paymentTermId
shippingApiId
shippingApiTermId
shippingCostCentreId
shippingContractId
shippingContractCourier
warehouseCode
discountType
discountAmount
trackingCode
trackingLink
customerNotifiedFlag
trollyLocker
transactionId
ipAddress
ipIsp
pdfFiles
returnReason
referralId
ordersApiId
apiSent
emailSent
apiMessage
apiMessageDate
apiOrderStatusMessage
apiOrderStatusMessageDate
ordersPackingRulesJson
discountCoupons {
id
description
amount
discountType
dateStart
dateEnd
maxUse
minOrder
minOrderType
numberAvailable
customerType
discountedProducts
discountedProductsOld
allowedProducts
categories
products
customers
orders
manufacturers
shippingMethods
zones
}
items {
id
orderId
productId
productModel
productEan
productName
quantity
quantityReturned
price
originalPrice
tax
stockVariants
lineType
comment
customOptions
productCategories
productWeight
productLocation
variableImage
allowSubstitute
confirmFlag
confirmProductsQuantity
autoComment
variants {
...OrderItemVariantFragment
}
}
totals {
id
orderId
title
text
value
valueUnreturned
taxRate
taxAmount
class
sortOrder
}
bankPayments {
id
orderId
invoicePaymentDate
invoicePaymentValueDate
amount
}
vivawalletPayments {
id
orderId
customerId
paymentMethod
notificationId
orderCode
transactionUuid
sessionId
}
}
}
Variables
{"input": CreateOrderInput}
Response
{
"data": {
"createOrder": {
"id": 4,
"customerId": 123,
"customerName": "abc123",
"customerEmail": "xyz789",
"customer": OrderParty,
"deliveryAddress": OrderParty,
"billingAddress": OrderParty,
"status": 987,
"datePurchased": "xyz789",
"lastModified": "abc123",
"currency": "abc123",
"currencyValue": 987.65,
"paymentMethod": "abc123",
"paymentCode": "xyz789",
"shippingMethod": "abc123",
"shippingCode": "xyz789",
"shippingCost": 123.45,
"deliveryQuantity": 123,
"deliveryWeight": 123.45,
"deliveryLength": 987.65,
"deliveryWidth": 987.65,
"deliveryHeight": 123.45,
"deliveryComments": "xyz789",
"shippingLocationId": "abc123",
"shippingLocationName": "xyz789",
"shippingLocationStreetAddress": "xyz789",
"shippingLocationPostcode": "xyz789",
"shippingLocationCity": "abc123",
"paymentApiId": "abc123",
"paymentProvider": "abc123",
"paymentField": "xyz789",
"paymentInput": "xyz789",
"paymentTermId": "xyz789",
"shippingApiId": "xyz789",
"shippingApiTermId": "xyz789",
"shippingCostCentreId": "xyz789",
"shippingContractId": "abc123",
"shippingContractCourier": "xyz789",
"warehouseCode": "xyz789",
"discountType": "abc123",
"discountAmount": 123.45,
"trackingCode": "xyz789",
"trackingLink": "abc123",
"customerNotifiedFlag": 123,
"trollyLocker": 123.45,
"transactionId": "abc123",
"ipAddress": "xyz789",
"ipIsp": "xyz789",
"pdfFiles": "xyz789",
"returnReason": "abc123",
"referralId": "xyz789",
"ordersApiId": "xyz789",
"apiSent": 123,
"emailSent": 123,
"apiMessage": "abc123",
"apiMessageDate": "abc123",
"apiOrderStatusMessage": "xyz789",
"apiOrderStatusMessageDate": "xyz789",
"ordersPackingRulesJson": "abc123",
"discountCoupons": [DiscountCoupon],
"items": [OrderItem],
"totals": [OrderTotal],
"bankPayments": [BankPayment],
"vivawalletPayments": [OrderVivawalletPayment]
}
}
}
createProductCustomOption
Description
Attach a ProductOption to a product as a custom (per-product) override, with its own required-flag, display position, and input type. Used by the admin product editor when a tenant wants this option to render differently on this specific product than its global default.
Response
Returns a ProductCustomOption
Arguments
| Name | Description |
|---|---|
input - CreateProductCustomOptionInput!
|
Example
Query
mutation createProductCustomOption($input: CreateProductCustomOptionInput!) {
createProductCustomOption(input: $input) {
id
productId
productsOptionsId
required
position
type
}
}
Variables
{"input": CreateProductCustomOptionInput}
Response
{
"data": {
"createProductCustomOption": {
"id": "4",
"productId": 123,
"productsOptionsId": 987,
"required": false,
"position": 987,
"type": "xyz789"
}
}
}
createQuote
Description
Create a quote (B2B request-for-pricing) with one or more line items. Captures the requester (customer id or anonymous session id), the requested shipping method, the preferred warehouse, and the line set. The resolver writes the quote header and its QuoteProduct lines in a single transaction.
Used by the storefront's quote-request form, by the admin's 'Create quote on customer's behalf' flow, and by integrations that ingest quote requests from external systems. To attach files (briefs, drawings) afterwards see addQuoteFile; to record status transitions see addQuoteStatusHistory.
Response
Returns a Quote!
Arguments
| Name | Description |
|---|---|
input - CreateQuoteInput!
|
The quote to create — header fields plus line items. |
Example
Query
mutation createQuote($input: CreateQuoteInput!) {
createQuote(input: $input) {
id
customerId
sessionId
ipAddress
statusId
dateAdded
dateModified
dateReminder
dateFollowUp
sendReminder
sendFollowUp
discountType
discountAmount
comment
cc
shipmentMethod
shipmentCode
shipmentPrice
warehouseId
items {
id
quoteId
productId
variant
quantity
discountedPrice
productGroup
comment
customOptions
bundleId
}
}
}
Variables
{"input": CreateQuoteInput}
Response
{
"data": {
"createQuote": {
"id": "4",
"customerId": 987,
"sessionId": "abc123",
"ipAddress": "abc123",
"statusId": 987,
"dateAdded": "xyz789",
"dateModified": "abc123",
"dateReminder": "xyz789",
"dateFollowUp": "abc123",
"sendReminder": "abc123",
"sendFollowUp": "xyz789",
"discountType": "xyz789",
"discountAmount": 123.45,
"comment": "xyz789",
"cc": "abc123",
"shipmentMethod": "xyz789",
"shipmentCode": "xyz789",
"shipmentPrice": 123.45,
"warehouseId": 123,
"items": [QuoteProduct]
}
}
}
deleteFavorite
Description
Remove favorites matching the input filter. The filter must include at least one of id / customersId / productsId — the resolver throws when none are provided. Returns true when at least one row was deleted, false when nothing matched.
Used by the storefront's 'unsave' button (id or customersId+productsId), by 'clear wishlist' actions (customersId only), and by admin tooling that retires a product and wants to clean up everyone's favorites of it (productsId only).
Response
Returns a Boolean
Arguments
| Name | Description |
|---|---|
input - RemoveCustomerFavoriteInput!
|
Example
Query
mutation deleteFavorite($input: RemoveCustomerFavoriteInput!) {
deleteFavorite(input: $input)
}
Variables
{"input": RemoveCustomerFavoriteInput}
Response
{"data": {"deleteFavorite": false}}
grantCustomerProductAccess
Description
Add a product to a customer's private allowlist. When this is the customer's first inclusion row, the catalog flips to private mode for them — they immediately stop seeing all non-listed products. Used when onboarding a B2B account onto a contract assortment.
Response
Returns a CustomerProductInclusion!
Arguments
| Name | Description |
|---|---|
input - CustomerProductInclusionInput!
|
Example
Query
mutation grantCustomerProductAccess($input: CustomerProductInclusionInput!) {
grantCustomerProductAccess(input: $input) {
id
customerId
productId
}
}
Variables
{"input": CustomerProductInclusionInput}
Response
{
"data": {
"grantCustomerProductAccess": {"id": 4, "customerId": 123, "productId": 987}
}
}
removeDiscountCouponFromCustomer
Description
Detach a coupon from a customer. Returns true on success, false when no link row matched. Used to revoke a previously-issued private coupon, e.g. when the recipient no longer qualifies for the offer or the coupon was attached in error.
Response
Returns a Boolean!
Arguments
| Name | Description |
|---|---|
input - DiscountCouponCustomerLinkInput!
|
The (couponCode, customerId) pair to detach. |
Example
Query
mutation removeDiscountCouponFromCustomer($input: DiscountCouponCustomerLinkInput!) {
removeDiscountCouponFromCustomer(input: $input)
}
Variables
{"input": DiscountCouponCustomerLinkInput}
Response
{"data": {"removeDiscountCouponFromCustomer": false}}
removeOrdersProduct
Description
Delete an order line. Returns true on success, false when no row matched the given id. Variants attached to the line are deleted by cascade. This is a hard delete — for refunds prefer adding a 'refund' line via addOrdersProduct, which preserves the audit trail.
removeOrdersProductsVariant
Description
Delete a variant selection from an order line. Returns true on success, false when no row matched. Hard delete — does not change the parent line's price; recompute the line price separately if needed.
removeProductCustomOption
Description
Detach a custom option from a product. The underlying ProductOption is untouched; only this product's override is removed.
revokeCustomerProductAccess
Description
Remove one product from a customer's private allowlist. When this leaves the customer with zero inclusion rows, the catalog flips back to public mode for them and they regain visibility into the standard catalog.
Response
Returns a Boolean!
Arguments
| Name | Description |
|---|---|
input - CustomerProductInclusionInput!
|
Example
Query
mutation revokeCustomerProductAccess($input: CustomerProductInclusionInput!) {
revokeCustomerProductAccess(input: $input)
}
Variables
{"input": CustomerProductInclusionInput}
Response
{"data": {"revokeCustomerProductAccess": false}}
updateOrdersProduct
Description
Partially update an existing order line. Only the fields included in the input payload are written; omitted fields are left as-is. Returns the updated OrdersProduct.
For variant selections on the line, use updateOrdersProductsVariant instead — they live on a separate table.
Response
Returns an OrdersProduct!
Arguments
| Name | Description |
|---|---|
id - ID!
|
|
input - UpdateOrdersProductInput!
|
Example
Query
mutation updateOrdersProduct(
$id: ID!,
$input: UpdateOrdersProductInput!
) {
updateOrdersProduct(
id: $id,
input: $input
) {
id
orderId
productId
productModel
productEan
productName
price
originalPrice
tax
quantity
quantityReturned
stockVariants
lineType
comment
customOptions
}
}
Variables
{"id": 4, "input": UpdateOrdersProductInput}
Response
{
"data": {
"updateOrdersProduct": {
"id": 4,
"orderId": 123,
"productId": 123,
"productModel": "abc123",
"productEan": "abc123",
"productName": "abc123",
"price": 123.45,
"originalPrice": 123.45,
"tax": 123.45,
"quantity": 987,
"quantityReturned": 987,
"stockVariants": "xyz789",
"lineType": "xyz789",
"comment": "abc123",
"customOptions": {}
}
}
}
updateOrdersProductsVariant
Description
Partially update an existing variant selection. Only the fields in the input payload are written. Useful for correcting an option name or price delta after the order was placed without removing and re-adding the variant. Returns the updated OrdersProductsVariant.
Response
Returns an OrdersProductsVariant!
Arguments
| Name | Description |
|---|---|
id - ID!
|
|
input - UpdateOrdersProductsVariantInput!
|
Example
Query
mutation updateOrdersProductsVariant(
$id: ID!,
$input: UpdateOrdersProductsVariantInput!
) {
updateOrdersProductsVariant(
id: $id,
input: $input
) {
id
orderId
orderProductId
optionId
optionName
optionValue
price
pricePrefix
}
}
Variables
{"id": 4, "input": UpdateOrdersProductsVariantInput}
Response
{
"data": {
"updateOrdersProductsVariant": {
"id": "4",
"orderId": 987,
"orderProductId": 123,
"optionId": 123,
"optionName": "xyz789",
"optionValue": "xyz789",
"price": 123.45,
"pricePrefix": "xyz789"
}
}
}
updateProductCustomOption
Description
Update an existing per-product option override — typically to change the required flag, reorder, or switch the input rendering between radio / select / checkbox / etc.
Response
Returns a ProductCustomOption
Arguments
| Name | Description |
|---|---|
id - ID!
|
|
input - UpdateProductCustomOptionInput!
|
Example
Query
mutation updateProductCustomOption(
$id: ID!,
$input: UpdateProductCustomOptionInput!
) {
updateProductCustomOption(
id: $id,
input: $input
) {
id
productId
productsOptionsId
required
position
type
}
}
Variables
{"id": 4, "input": UpdateProductCustomOptionInput}
Response
{
"data": {
"updateProductCustomOption": {
"id": 4,
"productId": 987,
"productsOptionsId": 987,
"required": true,
"position": 987,
"type": "xyz789"
}
}
}
upsertOrdersNetsNotification
Description
Idempotently record a Nets payment notification. Inserts a new orders_nets row on first call; on a duplicate ordersPaytrailId it updates the row with the latest webhook payload (newer notificationId, transactionId, stamp, reference, amount, error).
Use this from the Nets webhook handler so retries and out-of-order deliveries from Nets's side don't create duplicate rows. Returns the persisted OrderNetsNotification, or null on a no-op.
For Vivawallet, see ordersVivawallet (separate table with a different shape).
Response
Returns an OrderNetsNotification
Arguments
| Name | Description |
|---|---|
input - OrdersNetsNotificationInput!
|
Example
Query
mutation upsertOrdersNetsNotification($input: OrdersNetsNotificationInput!) {
upsertOrdersNetsNotification(input: $input) {
ordersPaytrailId
customersId
notificationId
sessionId
transactionId
stamp
reference
amount
error
}
}
Variables
{"input": OrdersNetsNotificationInput}
Response
{
"data": {
"upsertOrdersNetsNotification": {
"ordersPaytrailId": 987,
"customersId": 987,
"notificationId": 123,
"sessionId": "abc123",
"transactionId": "xyz789",
"stamp": "abc123",
"reference": "xyz789",
"amount": 987.65,
"error": "xyz789"
}
}
}
Types
ActionRecorderEntry
Description
One audit-trail entry written by the platform's action recorder. The recorder logs sensitive admin and customer events (login attempts, password resets, export jobs, anything that needs an after-the-fact paper trail) so security and compliance reports can answer 'who did what, when, from where, and did it succeed?' against the same surface.
Rows are append-only. Filter by module to scope to one event source, by userId to follow one principal across modules, and by success to reconcile failed-vs-successful attempt rates (e.g. brute-force detection).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the audit entry. |
module - String!
|
Source module that wrote the row — a free-form code identifying which code path emitted the audit entry. Example values seen in production code (aicc-admin/pub/login.php, action_recorder_log.php):
|
userId - Int
|
Id of the user the entry is about. Null for anonymous attempts (e.g. failed login with an unknown email). |
userName - String
|
Username / email of the user the entry is about. Captured at write time so the row stays readable even if the user is later deleted. |
identifier - String!
|
Free-form context captured by the module — for ar_admin_login / ar_admin_logoff this holds the request IP, for ar_admin_force_action it holds the action description (e.g. 'Force Reset Redis'). |
userAgent - String
|
User-Agent string of the request, captured for forensics. Null when the module didn't have request headers in scope. |
success - Boolean
|
Outcome of the recorded action. true = succeeded, false = failed, null = the module wrote a status-less informational entry. |
dateAdded - String!
|
Timestamp the entry was written. Append-only — the recorder never updates a row after creation. |
Example
{
"id": 4,
"module": "abc123",
"userId": 123,
"userName": "abc123",
"identifier": "xyz789",
"userAgent": "xyz789",
"success": false,
"dateAdded": "xyz789"
}
ActionRecorderPage
Description
A page of audit entries plus the unfiltered total, so paginated UIs can show 'showing N of M' without a second count round-trip.
Fields
| Field Name | Description |
|---|---|
total - Int!
|
Total entries matching the filter (across all pages). |
entries - [ActionRecorderEntry!]!
|
The current page of entries, newest first. |
Example
{"total": 123, "entries": [ActionRecorderEntry]}
AddCustomerFavoriteInput
AddOrdersProductInput
Description
Input shape for adding a new line to an existing order via addOrdersProduct.
Fields
| Input Field | Description |
|---|---|
orderId - ID!
|
Order to attach the new line to. |
productId - Int
|
Catalog product id, when the line corresponds to a real product. Null for free-form lines. |
productModel - String
|
Product SKU / model identifier to capture on the line. |
productEan - String
|
EAN / barcode to capture on the line. |
productName - String!
|
Display name shown on the receipt. Required. |
price - Float!
|
Unit price to charge. |
originalPrice - Float
|
Catalog price for discount-tracking. Falls back to price when omitted. |
tax - Float
|
Tax rate as percentage. Falls back to 0 when omitted. |
quantity - Int!
|
Quantity to add on the new line. |
stockVariants - String
|
Comma- or JSON-encoded snapshot of the variant stock-id selection. |
lineType - String
|
Line type — defaults to 'item'. Pass 'refund' for a return-credit line. |
comment - String
|
Free-form comment to attach to the line (gift message, configuration notes). |
customOptions - JSON
|
Module-specific custom-options payload (JSON-encoded) when the product carries configurable options. |
Example
{
"orderId": "4",
"productId": 123,
"productModel": "abc123",
"productEan": "abc123",
"productName": "xyz789",
"price": 123.45,
"originalPrice": 987.65,
"tax": 123.45,
"quantity": 123,
"stockVariants": "xyz789",
"lineType": "abc123",
"comment": "xyz789",
"customOptions": {}
}
AddOrdersProductsVariantInput
Description
Input shape for attaching a new variant selection to an existing order line.
Fields
| Input Field | Description |
|---|---|
orderId - ID!
|
Order this line belongs to. |
orderProductId - ID!
|
Order line to attach the variant to. |
optionId - Int!
|
Product option id from the catalog. |
optionName - String!
|
Display label of the option. |
optionValue - String!
|
Selected value. |
price - Float!
|
Price delta this variant contributes. |
pricePrefix - String
|
How price is applied — defaults to '+' (additive) when omitted. |
Example
{
"orderId": 4,
"orderProductId": 4,
"optionId": 123,
"optionName": "xyz789",
"optionValue": "abc123",
"price": 123.45,
"pricePrefix": "abc123"
}
AddQuoteStatusHistoryInput
Fields
| Input Field | Description |
|---|---|
quoteId - Int!
|
Quote to record the status transition against. |
statusId - Int!
|
Numeric status id to move the quote to. Resolves against quoteStatuses. |
customerNotified - Int
|
Whether to flag the entry as having dispatched a customer notification (0 = not notified, 1 = notified). |
comments - String
|
Free-form operator comment attached to the transition (e.g. 'Awaiting customer signature'). |
Example
{
"quoteId": 987,
"statusId": 123,
"customerNotified": 987,
"comments": "abc123"
}
Address
Description
An address-book entry for a customer, returned through Customer.addresses. Holds the shipping fields in the entry_* columns with optional alternate billing fields in the billing_* columns of the same row — same shape as the standalone addressBookEntries query, just hydrated as part of the customer record. For the dedicated query see addressBookEntries; for billing-only address books see billingAddresses.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the address-book entry (address_book_id). |
gender - String
|
Salutation / gender code on the shipping side. |
company - String
|
Company name on the shipping side. |
firstname - String!
|
Recipient first name on the shipping side. |
lastname - String!
|
Recipient last name on the shipping side. |
streetAddress - String!
|
Street address on the shipping side. |
vatid - String
|
VAT id on the shipping side. Captured for B2B shipping documents. |
postcode - String!
|
Postcode on the shipping side. |
city - String!
|
City on the shipping side. |
state - String
|
State / region on the shipping side. |
countryId - Int
|
Country id on the shipping side. |
zoneId - Int
|
Zone id on the shipping side. |
comments - String
|
Delivery instructions captured at address creation. |
billingStreetAddress - String
|
Alternate billing-side street address. Null means billing uses the shipping side. |
billingFirstname - String
|
Alternate billing first name. |
billingLastname - String
|
Alternate billing last name. |
billingPostcode - String
|
Alternate billing postcode. |
billingCity - String
|
Alternate billing city. |
billingCountryId - String
|
Alternate billing country id (string-typed on this surface, vs. shipping's int). |
billingCompany - String
|
Alternate billing company name. |
billingVatid - String
|
Alternate billing VAT id. |
billingZoneId - String
|
Alternate billing zone id. |
billingState - String
|
Alternate billing state / region. |
billingOperatorId - Int
|
E-invoice operator id (Finnish Verkkolasku operator). Used for routing electronic invoices through an operator. |
billingInvoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI). Paired with billingOperatorId for e-invoice delivery. |
billingReference - String
|
Free-form reference / PO number printed on the invoice. |
billingReferenceRequired - Boolean
|
Whether the storefront enforces a non-empty reference at checkout for this address. |
Example
{
"id": 4,
"gender": "xyz789",
"company": "xyz789",
"firstname": "abc123",
"lastname": "abc123",
"streetAddress": "xyz789",
"vatid": "xyz789",
"postcode": "abc123",
"city": "xyz789",
"state": "xyz789",
"countryId": 987,
"zoneId": 987,
"comments": "abc123",
"billingStreetAddress": "abc123",
"billingFirstname": "xyz789",
"billingLastname": "xyz789",
"billingPostcode": "abc123",
"billingCity": "xyz789",
"billingCountryId": "xyz789",
"billingCompany": "xyz789",
"billingVatid": "xyz789",
"billingZoneId": "abc123",
"billingState": "xyz789",
"billingOperatorId": 987,
"billingInvoiceAddress": "abc123",
"billingReference": "xyz789",
"billingReferenceRequired": false
}
AddressBook
Description
An address-book entry belonging to a customer. Holds the shipping address in the entry_* columns plus an optional alternate billing address in the billing_* columns of the same row — a customer who ships to one address but invoices to another (common for B2B accounts) keeps both halves together here.
When the billing_* fields are null/empty, billing falls back to the shipping side. For a customer's standalone list of billing-only addresses (multiple invoice recipients without a paired shipping address), see billingAddresses, which reads from a separate billing_address_book table.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the address-book entry (address_book_id). |
customerId - Int!
|
Customer this address belongs to. |
gender - String
|
Salutation / gender code for the recipient (e.g. 'm', 'f'). Tenant-defined; many tenants leave this null. |
company - String
|
Company name on the shipping side. Set when the address is a business delivery. |
firstname - String!
|
Recipient first name on the shipping side. |
lastname - String!
|
Recipient last name on the shipping side. |
streetAddress - String!
|
Street address line on the shipping side. |
vatid - String
|
VAT / business id on the shipping side. Captured for B2B shipping documents. |
postcode - String!
|
Postal code on the shipping side. |
city - String!
|
City on the shipping side. |
state - String
|
State / region on the shipping side. Used in countries that need it (e.g. US, AU). |
countryId - Int!
|
Country id on the shipping side. Resolves against the countries query. |
zoneId - Int!
|
Zone id on the shipping side. Resolves against the country's zones table. |
comments - String
|
Free-form delivery instructions captured at address creation. |
billingStreetAddress - String
|
Alternate billing-side street address. Null means billing uses the shipping side. |
billingFirstname - String
|
Alternate billing first name. Null means billing uses the shipping side. |
billingLastname - String
|
Alternate billing last name. |
billingPostcode - String
|
Alternate billing postcode. |
billingCity - String
|
Alternate billing city. |
billingCountryId - String
|
Alternate billing country id (string-typed in this surface, vs. shipping which is int). |
billingCompany - String
|
Alternate billing company name. |
billingVatid - String
|
Alternate billing VAT / business id. |
billingZoneId - String
|
Alternate billing zone id. |
billingState - String
|
Alternate billing state / region. |
billingOperatorId - Int
|
E-invoice operator id (Finnish OVT / Verkkolasku operator). Used when invoices are routed via an e-invoicing operator. |
billingInvoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI). Used together with billingOperatorId for e-invoice routing. |
billingReference - String
|
Free-form reference / PO number to print on the invoice (e.g. 'PO #1234'). |
billingReferenceRequired - Boolean
|
Whether the tenant flags this address as requiring a reference at checkout. true = the storefront enforces a non-empty reference before letting the order through. |
Example
{
"id": 4,
"customerId": 123,
"gender": "abc123",
"company": "abc123",
"firstname": "xyz789",
"lastname": "xyz789",
"streetAddress": "xyz789",
"vatid": "xyz789",
"postcode": "xyz789",
"city": "abc123",
"state": "abc123",
"countryId": 987,
"zoneId": 987,
"comments": "xyz789",
"billingStreetAddress": "abc123",
"billingFirstname": "abc123",
"billingLastname": "xyz789",
"billingPostcode": "abc123",
"billingCity": "xyz789",
"billingCountryId": "abc123",
"billingCompany": "xyz789",
"billingVatid": "abc123",
"billingZoneId": "xyz789",
"billingState": "xyz789",
"billingOperatorId": 123,
"billingInvoiceAddress": "abc123",
"billingReference": "abc123",
"billingReferenceRequired": false
}
AddressFormat
Description
A country-specific address-rendering template. Different countries print postal addresses in different orders (e.g. 'CITY POSTCODE' vs 'POSTCODE CITY', whether the state goes on its own line, where the company name sits relative to the recipient name). Each Country.addressFormatId points to one of these templates, and the storefront / admin / order documents render addresses by substituting recipient values into the template.
The template uses placeholders for the address fields (recipient name, street, postcode, city, state, country); the formatter consumes them when rendering an AddressBook / BillingAddress / order-shipping snapshot.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the format (address_format_id). |
addressFormat - String!
|
Long-form template used to render multi-line postal addresses (the form printed on shipping labels and order documents). |
addressSummary - String!
|
Short-form template used to render single-line address summaries (the form shown in lists, order tables, and dropdowns). |
Example
{
"id": "4",
"addressFormat": "abc123",
"addressSummary": "xyz789"
}
AdminNotification
Description
An admin-facing error notification. The platform writes a row whenever a background job, integration sync, or critical pipeline raises an error worth surfacing to operators (failed ERP sync, payment-gateway timeout, cron job exception, etc.). The admin dashboard renders the un-cleared rows in an inbox so on-duty operators can investigate and dismiss them once handled.
emailErrorSent records whether the platform also dispatched the notification email; errorCleared records whether an operator has acknowledged it. The two flags can move independently — an entry may be emailed but never cleared, cleared without emailing, etc.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the notification (notification_id). |
errorText - String!
|
Free-form error description written by the producing module. Typically a one-line summary plus the exception message. |
createdAt - String!
|
Timestamp the notification was raised. |
emailErrorSent - Boolean!
|
Whether the platform has dispatched the notification email to operators. |
errorCleared - Boolean!
|
Whether an operator has acknowledged / dismissed the notification. |
Example
{
"id": "4",
"errorText": "xyz789",
"createdAt": "xyz789",
"emailErrorSent": true,
"errorCleared": false
}
AdminTrackingCreate
Description
An audit row recording that an admin created (or otherwise mutated) a product. The platform writes one entry per admin-driven product change so the admin product editor's history view, the 'created by …' badge on a product's detail page, and any compliance reporting can attribute the change to a real user.
Distinct from productPriceHistory — this surface tracks the lifecycle events of a product entity (creation, edits, etc.), while productPriceHistory tracks just price changes with their old/new values. Distinct from actionRecorderEntries — this surface is product-specific and write-tracked at the model layer, while actionRecorder is a general-purpose audit log.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the tracking entry. |
productId - Int!
|
Product the entry is about. |
userId - Int
|
Id of the admin who performed the action. Null for system-generated entries (e.g. ERP sync writes). |
userName - String
|
Username of the admin, captured at write time so the row stays readable if the admin is later deleted. |
action - String
|
Action performed on the product. Examples seen in production:
|
dateAdded - String!
|
Timestamp the action was recorded. |
Example
{
"id": "4",
"productId": 123,
"userId": 987,
"userName": "abc123",
"action": "abc123",
"dateAdded": "xyz789"
}
Administrator
Description
An admin user — someone with login access to aicc-admin. Holds the account's identity (username, email), authentication settings (2FA), and the RBAC scope that decides which admin pages and modules they can open and whether they're allowed to write or only to read.
superadmin trumps the per-module grantAccess list — superadmins see every module regardless. writePermission is checked at the module level to gate save / delete actions independently of read access. For per-action audit trails of what an admin actually did with these permissions, see actionRecorderEntries.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the administrator. |
userName - String!
|
Login username. |
email - String
|
Email used for password resets and operator notifications. |
twoFactor - Boolean
|
Whether 2FA (TOTP) is enabled. When true and the secret column is set, login requires a 6-digit code from an authenticator app on top of username + password. |
superadmin - Boolean
|
Whether the admin is a super-administrator. Superadmins bypass the grantAccess RBAC list and can also manage other admin accounts. |
writePermission - Boolean
|
Whether the admin can perform write operations (create / update / delete). When false, the account is read-only across whichever modules they can open. |
grantAccess - String
|
RBAC list of admin modules the user can access. Stored as a semicolon-delimited string of module ids. Example value: 'module_orders;module_customers;module_products' grants access to the orders, customers, and products admin pages. Ignored for superadmins (they see every module). The module id list is defined by aicc-admin and varies by tenant. |
Example
{
"id": "4",
"userName": "xyz789",
"email": "xyz789",
"twoFactor": true,
"superadmin": false,
"writePermission": false,
"grantAccess": "xyz789"
}
ApiProcessJob
Description
A job queued for an outbound third-party API call — typically an ERP / PIM / marketplace synchronisation push (Netvisor / Lemonsoft / Akeneo / shipping-carrier APIs). The platform writes a row here whenever it needs to dispatch a request to an external system, and a worker drains the queue and replays each job against its target. Successful jobs leave error null; failed jobs capture the error for retry / inspection.
Use this surface to inspect the queue from admin tooling and oncall runbooks ('what's stuck?'), to reconcile against external system status, and to filter to specific failure modes via the status argument.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the queued job. |
jobId - String
|
Worker-side job id when the worker assigns one. Null until the worker picks the row up. |
api - String!
|
Identifier of the target third-party API (e.g. 'netvisor', 'lemonsoft', 'akeneo', 'tisma'). |
endpoint - String!
|
API endpoint or path the job will invoke (e.g. '/customer.nv', '/products'). |
method - String
|
HTTP method to use (typically 'POST' or 'PUT'). Null for non-HTTP integrations. |
data - JSON!
|
Request payload to send, as JSON. The worker serializes this to the wire format the target API expects. |
createdAt - String!
|
Timestamp the job was queued. |
error - String
|
Error text from the most recent attempt; null while the job has not failed. |
status - String!
|
Computed status derived from the error column:
|
Example
{
"id": 4,
"jobId": "xyz789",
"api": "xyz789",
"endpoint": "abc123",
"method": "abc123",
"data": {},
"createdAt": "xyz789",
"error": "xyz789",
"status": "abc123"
}
Availability
Description
A stock-availability label shown on product detail and listing pages (e.g. "In Stock", "Out of Stock", custom delivery-window phrases).
Each tenant defines its own set of labels. Ids 1 and 2 are conventionally reserved for "In Stock" and "Out of Stock"; ids 3+ are tenant-defined delivery-window variants ("usually ships in 1–3 days", "special order", etc.).
Returned in one row per (id, languageId) pair so storefronts can pick the shopper's language at render time.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Stable numeric id of the availability label across all languages. |
languageId - Int!
|
Language identifier matching the languages query. Common values:
Tenants may add or remove languages — resolve dynamically via the languages query rather than hardcoding ids. |
name - String!
|
Localized label shown to shoppers in the chosen language. |
hexCode - String
|
Hex color (without leading #) used to tint the label in storefront UI. Common conventions:
May be null for legacy labels that pre-date the colored-badge UI. |
Example
{
"id": 4,
"languageId": 123,
"name": "abc123",
"hexCode": "xyz789"
}
BankPayment
Description
An incoming bank-transfer settlement matched to one order. Tenants that accept payment via invoice / bank wire reconcile their bank statement feed (typically SEPA / Finvoice for Finnish operators) into bank_payments rows so the admin's invoice tab and any ERP reconciliation report can show 'this order has been paid, on this date, in this amount'.
Distinct from the gateway-specific payment surfaces (ordersNets, ordersVivawallet) — those carry the provider-side transaction state for card / mobile-wallet payments. bankPayments is for plain bank-transfer reconciliation against incoming statement lines.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Bank transaction id (varchar primary key, captured from the bank statement feed). |
orderId - Int!
|
Order this transfer settles. |
invoicePaymentDate - String!
|
Bank-statement posting date — the date the transfer appeared on the tenant's bank statement. |
invoicePaymentValueDate - String!
|
Settlement / value date — when the funds are actually available, used for cash-flow reconciliation timing. |
amount - Float!
|
Amount received, in the tenant's default currency. |
Example
{
"id": "4",
"orderId": 123,
"invoicePaymentDate": "xyz789",
"invoicePaymentValueDate": "abc123",
"amount": 987.65
}
Banner
Description
A storefront banner — a clickable promotional image rendered in a banner zone (homepage hero, sidebar, category banner, etc.). Each banner belongs to one group, links to a landing URL, and tracks impressions and clicks for performance reporting.
Use the banners query to enumerate every banner the tenant has defined, bannersByGroup to fetch only the banners in one zone, and the Banner.historyByDate field for daily click / impression series.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the banner (banners_id). |
title - String!
|
Display title used as the banner's accessible label and admin-side identifier. |
url - String!
|
Destination URL the banner links to when clicked. |
group - String!
|
Free-form group code identifying which storefront zone the banner belongs to (e.g. 'home', 'sidebar', 'category-1'). Tenants define their own groups. |
status - Int!
|
Visibility flag stored as int. 1 = active (rendered on the storefront); 0 = inactive (hidden but kept for history). |
image - String
|
Filename of the banner image, served from the tenant's banner-image directory. Null when the banner is text-only. |
history - BannerHistory!
|
Lifetime impression and click totals for this banner. |
historyByDate - [BannerHistoryEntry!]!
|
Per-day impression and click history for this banner, newest day first. Pass startDate / endDate to bracket the chart window — the underlying query truncates banners_history_date to a date and groups rows by day, so partial days at the edge of the window count correctly. |
Example
{
"id": "4",
"title": "xyz789",
"url": "abc123",
"group": "abc123",
"status": 123,
"image": "xyz789",
"history": BannerHistory,
"historyByDate": [BannerHistoryEntry]
}
BannerHistory
Description
Lifetime impression / click totals for one banner. Aggregated across all history rows for the banner. For a per-day breakdown (e.g. to render a performance chart) see Banner.historyByDate, which buckets the same underlying banners_history rows by day.
Example
{"impressions": 987, "clicks": 123}
BannerHistoryEntry
Description
One day's aggregated impression and click counts for a single banner. The banners_history table stores per-event rows that the resolver groups by DATE(banners_history_date) and sums into these per-day buckets.
Used to drive performance charts in the admin banner editor (line / bar chart of clicks-per-day) and to power CTR reporting. For lifetime totals see Banner.history; this surface is the day-by-day breakdown.
Example
{
"bannerId": 123,
"date": "xyz789",
"impressions": 123,
"clicks": 123
}
BillingAddress
Description
A standalone billing-address entry belonging to a customer. Distinct from AddressBook — that surface holds shipping addresses with optional alternate billing fields per row, while BillingAddress is a dedicated invoice-recipient book customers can populate independently of where they ship.
Used primarily for B2B accounts that need multiple invoice recipients (e.g. an organization with several cost centres / departments billed separately) without dragging a shipping address along. The fields mirror the billing_* half of AddressBook plus the e-invoice routing fields used in Finnish / Nordic invoicing.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the billing-address entry (billing_address_id). |
customerId - Int!
|
Customer this billing address belongs to. |
company - String
|
Company name on the invoice. |
firstname - String
|
Recipient first name on the invoice. |
lastname - String
|
Recipient last name on the invoice. |
streetAddress - String
|
Street address on the invoice. |
postcode - String
|
Postal code on the invoice. |
city - String
|
City on the invoice. |
state - String
|
State / region on the invoice. |
countryId - String
|
Country id on the invoice. |
zoneId - String
|
Zone id on the invoice. |
vatid - String
|
VAT / business id printed on the invoice. Required for B2B invoices in EU jurisdictions. |
operatorId - Int
|
E-invoice operator id (Finnish Verkkolasku operator). Used for routing electronic invoices through an operator. |
invoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI). Paired with operatorId for e-invoice delivery. |
reference - String
|
Free-form reference / PO number to print on the invoice. |
referenceRequired - Boolean!
|
Whether this billing address requires a non-empty reference at checkout. The storefront enforces the flag before letting the order through. |
Example
{
"id": "4",
"customerId": 987,
"company": "abc123",
"firstname": "abc123",
"lastname": "xyz789",
"streetAddress": "xyz789",
"postcode": "abc123",
"city": "abc123",
"state": "abc123",
"countryId": "abc123",
"zoneId": "abc123",
"vatid": "abc123",
"operatorId": 123,
"invoiceAddress": "xyz789",
"reference": "xyz789",
"referenceRequired": true
}
Boolean
Description
The Boolean scalar type represents true or false.
BrowseHistory
Description
One page-view captured by the storefront's browse-history tracker. Every product, category, manufacturer, and search-result page rendered by the storefront writes a row here with the visiting session's key (so anonymous and logged-in journeys can both be reconstructed), the entity that was viewed, page-load timing, geo-IP country, and any variant filters that were active.
Used to power 'Recently viewed' on the storefront, internal-search analytics, conversion-funnel reporting, and the homepage's top-picks curation. Distinct from actionRecorderEntries — this surface tracks visitor browsing for product / merchandising analytics, while the action recorder tracks admin and auth events for security audit.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the page-view entry. |
customerId - Int
|
Customer id when the visitor was logged in. Null for anonymous visitors — the sessionKey still threads their journey across pages. |
sessionKey - String!
|
Storefront session key that ties together page views from one browser session, even before login. |
loadTimeMsec - Int!
|
Server-side page-load time in milliseconds, captured at write time. Used for performance regression tracking. |
categoryId - Int
|
Category id when the page-view was a category listing. Null when the visitor wasn't on a category page. |
productId - Int
|
Product id when the page-view was a product detail page. Null when the visitor wasn't on a product page. |
manufacturerId - Int
|
Manufacturer id when the page-view was filtered by a manufacturer. Null when no manufacturer filter was active. |
color - Int
|
Color filter active on the page (option-value id from products_options_values). 0 / null when no color filter was applied. |
size - Int
|
Size filter active on the page (option-value id from products_options_values). 0 / null when no size filter was applied. |
geoipCountry - String!
|
Two-letter geo-IP country code resolved at request time (e.g. 'FI', 'US'). Useful for regional behaviour analytics. |
ipAddress - String!
|
Visitor IP address at the time of the page view. Captured for fraud / abuse forensics. |
date - String!
|
Server timestamp of the page view. |
timestamp - Int
|
Unix timestamp of the page view (seconds since epoch). Mirrors the date field in epoch form for time-series analysis. |
topPicks - Boolean!
|
Whether this page view was rendered from the storefront's curated 'top picks' surface (homepage hero / featured area) rather than a regular browse path. Used to attribute conversions back to merchandising decisions. |
keywords - String
|
Search-keywords slot on the row. In practice usually empty / null on browse_history rows — internal-search keyword logging lives in the dedicated searched_keywords table. Kept on this surface for legacy-compat callers. |
Example
{
"id": 4,
"customerId": 123,
"sessionKey": "xyz789",
"loadTimeMsec": 123,
"categoryId": 987,
"productId": 123,
"manufacturerId": 987,
"color": 123,
"size": 123,
"geoipCountry": "abc123",
"ipAddress": "abc123",
"date": "xyz789",
"timestamp": 123,
"topPicks": false,
"keywords": "xyz789"
}
Category
Description
A node in the product category tree. Categories nest via parentId (a value of 0 indicates a top-level category) and stack into the storefront's main navigation, breadcrumbs, and faceted browsing.
Carries the visual assets (image, banner) and the structural fields (parentId, sortOrder, position) directly; localized titles, URLs, and SEO copy are returned through the descriptions field — one entry per (category, languageId) pair so the storefront can pick the shopper's language at render time.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the category. |
code - String
|
Internal code for the category, stable across languages — used by ERP / PIM mappings. |
image - String
|
Filename of the category thumbnail image, served from the tenant's category-image directory. Used in navigation tiles and category-card surfaces. |
banner - String
|
Filename of the category hero banner image, served from the tenant's category-image directory. Rendered above the product listing on the category page. |
parentId - Int
|
Id of the parent category, or 0 for top-level categories. |
sortOrder - Int
|
Display sort order within the parent category. Lower values render first in navigation and listing. |
position - Int
|
Position field used as a secondary ordering / placement hint (e.g. for featured-category slots). Tenant interpretation. |
descriptions - [CategoryDescription]
|
Localized name / URL / description / SEO rows, one per language. |
Example
{
"id": 4,
"code": "abc123",
"image": "abc123",
"banner": "xyz789",
"parentId": 123,
"sortOrder": 987,
"position": 123,
"descriptions": [CategoryDescription]
}
CategoryDescription
Description
Localized text and SEO metadata for one Category, in one language. A Category has one CategoryDescription per (category, languageId) pair — the storefront picks the row matching the shopper's active language at render time. Carries the visible name, the slug-style URL fragment, the long descriptions shown above and below the product listing, the hero-banner copy, and the SEO meta-tags emitted into the page head.
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for (resolves against the languages query). |
name - String
|
Localized category name shown in navigation, breadcrumbs, and the page header. |
url - String
|
Slug-style URL fragment used in the canonical category URL (e.g. 'living-room-lamps'). |
path - String
|
Full URL path the category resolves to (e.g. 'lighting/living-room-lamps'), composed by the storefront router. |
pathOld - String
|
Previous URL path before the most recent rename. Used to emit redirects from the old URL to the new one. |
description - String
|
Long-form description rendered below the product listing on the category page. |
descriptionTop - String
|
Optional intro copy rendered above the product listing on the category page (typically a one-paragraph teaser / SEO blurb). |
metaTitle - String
|
Localized |
metaDescription - String
|
Localized for the category page. |
featureTitle - String
|
Localized title used in featured-category surfaces (homepage tiles, navigation highlights, etc.). |
typeTitle - String
|
Localized title used in the category-type / facet listing (e.g. when the same category is rendered as a filter chip). |
bannerText - String
|
Localized hero-banner copy on the category page. |
bannerButton - String
|
Localized hero-banner CTA button label (e.g. 'Shop now'). |
bannerUrl - String
|
Hero-banner CTA destination URL when the shopper clicks the button. |
redirectStatus - Int
|
Redirect-on flag for path migrations (1 = the old slug should redirect to the new one; 0 = no redirect). Read by the router when the shopper hits pathOld. |
Example
{
"languageId": 987,
"name": "xyz789",
"url": "xyz789",
"path": "xyz789",
"pathOld": "xyz789",
"description": "xyz789",
"descriptionTop": "abc123",
"metaTitle": "xyz789",
"metaDescription": "xyz789",
"featureTitle": "abc123",
"typeTitle": "xyz789",
"bannerText": "abc123",
"bannerButton": "abc123",
"bannerUrl": "xyz789",
"redirectStatus": 987
}
Configuration
Description
One configuration setting — a key/value pair that controls platform behaviour. Each row has a stable string key (e.g. 'STORE_NAME', 'MODULE_PAYMENT_NETS_INSTALLED') that the storefront and backend code read at runtime, plus a free-form value, an admin-side display title, and a helper description.
useFunction and setFunction are PHP function names invoked by the admin UI to render the value (e.g. format a checkbox vs a free text input) and to validate / transform input on save. Settings that don't need custom rendering leave both null.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the setting (configuration_id). |
title - String
|
Display title shown next to the input in the admin configuration UI. |
key - String!
|
Stable lookup key the storefront and backend read at runtime (e.g. 'STORE_NAME', 'MAX_DISPLAY_BESTSELLERS', 'MODULE_PAYMENT_NETS_INSTALLED'). |
value - String
|
Current value, stored as a free-form string. The storefront / backend casts it to the expected type at read time. |
description - String
|
Helper text shown below the input in the admin configuration UI. |
groupId - Int
|
Id of the parent ConfigurationGroup (configuration_group_id). |
sortOrder - Int
|
Display order of the setting within its group. Lower values render first. |
lastModified - String
|
Timestamp of the most recent edit. Useful for change-tracking dashboards. |
dateAdded - String
|
Timestamp the setting was first inserted. |
useFunction - String
|
PHP function name the admin UI calls to render the input control (e.g. for checkbox vs textarea vs select). Null when the setting uses the default text input. |
setFunction - String
|
PHP function name the admin UI calls to validate / transform input on save. Null when no transformation is needed. |
group - ConfigurationGroup
|
Resolved parent group, populated when the configurations query is filtered by groupId. |
Example
{
"id": 4,
"title": "abc123",
"key": "abc123",
"value": "abc123",
"description": "abc123",
"groupId": 123,
"sortOrder": 987,
"lastModified": "abc123",
"dateAdded": "abc123",
"useFunction": "abc123",
"setFunction": "xyz789",
"group": ConfigurationGroup
}
ConfigurationGroup
Description
A logical grouping of configuration settings shown as a section in the admin's configuration UI (e.g. 'Email Options', 'Tax Options', 'Stock Settings', 'Module — Payment'). Groups exist purely to organize the admin-side rendering of the underlying key/value Configuration rows — the storefront and backend code read individual settings by key, not by group.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the group (configuration_group_id). |
title - String
|
Display title shown as the section header in the admin configuration UI (e.g. 'Email Options'). |
description - String
|
Helper text shown below the section title in the admin UI. |
sortOrder - Int
|
Display order of the group within the admin configuration UI. Lower values render first. |
configurations - [Configuration]
|
Settings that belong to this group, populated when the parent group is fetched via configurationGroupsWithSettings. The configurations field is empty when the group is reached through configurationGroups (which doesn't eagerly hydrate its children). |
Example
{
"id": "4",
"title": "abc123",
"description": "xyz789",
"sortOrder": 123,
"configurations": [Configuration]
}
Country
Description
A country supported by the tenant for shipping or billing addresses. Countries are the top-level reference data behind every address picker on the storefront and admin: registration forms, checkout shipping / billing destinations, the customer's address book, and the admin order builder all read from this surface.
Each country carries the format-template id used to render its addresses (Country.addressFormatId resolves against addressFormats), the default currency a shopper from that country sees on first visit, and optional duty fields used for cross-border tax / customs calculation.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the country. |
name - String!
|
Localized country name shown in country dropdowns (e.g. 'Finland', 'United States'). |
iso2 - String!
|
Two-letter ISO 3166-1 alpha-2 country code (e.g. 'FI', 'US'). Used for storefront locale resolution and most external integrations. |
iso3 - String!
|
Three-letter ISO 3166-1 alpha-3 country code (e.g. 'FIN', 'USA'). Used by some shipping carriers and tax services. |
dutyRate - Float
|
Default customs-duty rate applied to imports into this country, as a percentage. Used by the cross-border price calculator; informational on countries the tenant doesn't ship to. |
dutyLimit - Float
|
De minimis threshold — order value below which no duty applies, in the tenant's default currency. Null when not configured. |
addressFormatId - Int
|
Id of the AddressFormat used to render addresses in this country (street order, postcode placement, state line, etc.). Resolves against the addressFormats query. |
defaultCurrencyId - Int
|
Id of the default Currency a shopper from this country sees on first visit, before they explicitly switch. Resolves against the currencies query. |
Example
{
"id": "4",
"name": "xyz789",
"iso2": "abc123",
"iso3": "abc123",
"dutyRate": 123.45,
"dutyLimit": 987.65,
"addressFormatId": 987,
"defaultCurrencyId": 987
}
CreateCustomerInput
Description
Input for createCustomer — registers a new customer with a password. Fields not marked required can be omitted; the storefront / admin capture the rest at checkout or via the address book later.
Fields
| Input Field | Description |
|---|---|
gender - String
|
Salutation / gender code (e.g. 'm', 'f'). Optional. |
firstname - String
|
First name. |
lastname - String
|
Last name. |
emailAddress - String!
|
Email address. Must be unique across registered (non-temporary) customers in the tenant. |
password - String!
|
Plaintext password — the resolver bcrypts it before storing. Capped at 128 characters. |
telephone - String
|
Telephone number. |
newsletter - Boolean
|
Newsletter opt-in flag. true subscribes the customer to the newsletter list. |
company - String
|
Company name. Set for B2B accounts. |
streetAddress - String
|
Street address line for the initial address-book entry. |
vatid - String
|
VAT / business id. Captured for B2B accounts. |
postcode - String
|
Postal code for the initial address-book entry. |
city - String
|
City for the initial address-book entry. |
state - String
|
State / region for the initial address-book entry. |
countryId - Int
|
Country id (resolves against the countries query). |
zoneId - Int
|
Zone id within the country. |
comments - String
|
Free-form delivery instructions captured at registration. |
Example
{
"gender": "xyz789",
"firstname": "xyz789",
"lastname": "xyz789",
"emailAddress": "xyz789",
"password": "xyz789",
"telephone": "abc123",
"newsletter": true,
"company": "xyz789",
"streetAddress": "abc123",
"vatid": "xyz789",
"postcode": "abc123",
"city": "abc123",
"state": "abc123",
"countryId": 987,
"zoneId": 987,
"comments": "abc123"
}
CreateGuestCustomerInput
Description
Input for createGuestCustomer — provisions a guest account for one-time checkout. No password is required (the platform generates a random one internally so the row can still satisfy the auth schema). Guest emails are not unique across the tenant — multiple guest checkouts can share the same email, and a guest email can also coexist with a registered customer using the same address.
Fields
| Input Field | Description |
|---|---|
gender - String
|
|
firstname - String
|
|
lastname - String
|
|
emailAddress - String!
|
Email address. Not enforced unique for guests. |
telephone - String
|
|
newsletter - Boolean
|
|
company - String
|
|
streetAddress - String
|
|
vatid - String
|
|
postcode - String
|
|
city - String
|
|
state - String
|
|
countryId - Int
|
|
zoneId - Int
|
|
comments - String
|
Example
{
"gender": "abc123",
"firstname": "abc123",
"lastname": "abc123",
"emailAddress": "abc123",
"telephone": "abc123",
"newsletter": false,
"company": "xyz789",
"streetAddress": "abc123",
"vatid": "xyz789",
"postcode": "abc123",
"city": "abc123",
"state": "abc123",
"countryId": 987,
"zoneId": 987,
"comments": "xyz789"
}
CreateOrderInput
Description
Input for createOrder. Use deliveryAddressId / billingAddressId to reference the customer's saved AddressBook entries (resolved at call time and snapshotted onto the order), or pass deliveryAddress / billingAddress as inline OrderPartyInput when the order is for an ad-hoc address that shouldn't land in the customer's saved book.
Fields
| Input Field | Description |
|---|---|
customerId - Int!
|
Placing customer id. Required. |
deliveryAddressId - Int
|
Saved AddressBook id to use as the delivery address. Mutually exclusive with deliveryAddress. |
billingAddressId - Int
|
Saved AddressBook id to use as the billing address. Mutually exclusive with billingAddress. |
customer - OrderPartyInput
|
Customer-side party snapshot. Optional — falls back to the customer record. |
deliveryAddress - OrderPartyInput
|
Inline delivery party. Mutually exclusive with deliveryAddressId. |
billingAddress - OrderPartyInput
|
Inline billing party. Mutually exclusive with billingAddressId. |
status - Int
|
Initial status id. Defaults to 1 (Received). Default = 1 |
statusComment - String
|
Operator comment recorded on the initial status-history entry. |
currency - String
|
ISO 4217 currency code. Defaults to 'EUR'. Default = "EUR" |
currencyValue - Float
|
Exchange rate against the tenant's primary currency. Defaults to 1 (when currency matches the primary). Default = 1 |
paymentMethod - String!
|
Display label for the chosen payment method as shown to the shopper at checkout (e.g. 'Verkkopankki', 'Pay by paypal'). Required and non-empty. |
paymentCode - String!
|
Code identifying the chosen payment module. Required. Must match one of the entries in the tenant's MODULE_PAYMENT_INSTALLED configuration value (a ';'-separated list of currently-installed payment modules such as 'Cod', 'NetsBank', 'VivawalletCreditcard'). Free-form values and codes from removed/renamed modules are rejected — the createOrder mutation fails loud and the error message lists the modules currently available for the connected tenant. |
paymentApiId - String
|
Internal id passed to the chosen payment module's API for reconciliation. |
paymentField - String
|
Free-form payment field captured at checkout (module-specific extra payload). |
paymentInput - JSON
|
Module-specific payment input payload as captured at checkout (JSON-encoded). |
shippingMethod - String!
|
Display label for the chosen shipping method as shown to the shopper at checkout (e.g. 'Posti - Noutopiste'). Required. |
shippingApiId - String
|
Internal id passed to the chosen shipping module's API for label generation and tracking. |
shippingCode - String!
|
Code identifying the chosen shipping module. Required. Must match one of the entries in the tenant's MODULE_SHIPPING_INSTALLED configuration value (a ';'-separated list such as 'Flat', 'Matkahuolto', 'Smartpost'). Free-form values are rejected. |
shippingCost - Float
|
Shipping cost to charge on the order, in the order's currency. Defaults to 0. Default = 0 |
warehouseCode - String
|
Warehouse code identifying which warehouse the order ships from when the tenant runs multi-warehouse fulfilment. Resolves against the warehouses query. |
items - [CreateOrderItemInput!]
|
Line items to create on the order. |
Example
{
"customerId": 987,
"deliveryAddressId": 123,
"billingAddressId": 123,
"customer": OrderPartyInput,
"deliveryAddress": OrderPartyInput,
"billingAddress": OrderPartyInput,
"status": 123,
"statusComment": "xyz789",
"currency": "xyz789",
"currencyValue": 123.45,
"paymentMethod": "xyz789",
"paymentCode": "xyz789",
"paymentApiId": "abc123",
"paymentField": "xyz789",
"paymentInput": {},
"shippingMethod": "abc123",
"shippingApiId": "xyz789",
"shippingCode": "abc123",
"shippingCost": 123.45,
"warehouseCode": "abc123",
"items": [CreateOrderItemInput]
}
CreateOrderItemInput
Description
One line on a createOrder call. Most fields mirror the OrderItem read shape; the resolver writes the captured snapshot into orders_products at the moment of order creation, so later catalog edits don't change the line.
Fields
| Input Field | Description |
|---|---|
productId - Int
|
Product id from the catalog. Null for free-form / fee / refund lines. |
sku - String
|
Optional SKU captured at order time. |
productModel - String
|
Product model number captured at order time. |
productEan - String
|
EAN / barcode captured at order time. |
productName - String!
|
Display name to write on the receipt and admin order detail. |
price - Float!
|
Unit price actually charged, in the order's currency. |
originalPrice - Float
|
Catalog price at the time of order, before any per-customer / coupon adjustments. Useful for computing realised discount per line. |
tax - Float
|
Tax rate applied to this line as a percentage (e.g. 24.0 = 24% VAT). |
quantity - Int!
|
Quantity ordered. |
stockVariants - String
|
Comma- or JSON-encoded snapshot of the variant stock-id selection. |
lineType - String
|
Line type ('item' | 'refund' | tenant-defined). Defaults to 'item'. Default = "item" |
comment - String
|
Free-form line comment (gift message, configuration notes). Default = "" |
customOptions - JSON
|
Module-specific custom-options payload (JSON-encoded). |
variants - [CreateOrderItemVariantInput!]
|
Configurable-option choices selected on this line. |
Example
{
"productId": 987,
"sku": "xyz789",
"productModel": "xyz789",
"productEan": "xyz789",
"productName": "xyz789",
"price": 987.65,
"originalPrice": 123.45,
"tax": 987.65,
"quantity": 123,
"stockVariants": "xyz789",
"lineType": "abc123",
"comment": "abc123",
"customOptions": {},
"variants": [CreateOrderItemVariantInput]
}
CreateOrderItemVariantInput
Description
One configurable-option choice on a CreateOrderItemInput line. Multiple variants stack on the same line, each contributing a price delta interpreted via pricePrefix. Mirrors the OrderItemVariant read shape.
Fields
| Input Field | Description |
|---|---|
optionId - Int!
|
Product-option id this choice is for (matches a row in the catalog options table). |
optionName - String!
|
Display label of the option as shown to the shopper (e.g. 'Size'). |
optionValue - String!
|
Selected value as shown to the shopper (e.g. 'XL'). |
price - Float
|
Price delta this choice contributes, interpreted via pricePrefix. Defaults to 0. Default = 0 |
pricePrefix - String
|
How the price delta is applied: '+' (additive, default) or '' (replacement). Default = "+" |
Example
{
"optionId": 123,
"optionName": "xyz789",
"optionValue": "xyz789",
"price": 123.45,
"pricePrefix": "xyz789"
}
CreateProductCustomOptionInput
Fields
| Input Field | Description |
|---|---|
productId - Int!
|
Product to attach this option override to. |
productsOptionsId - Int!
|
Id of the parent ProductOption being overridden. |
required - Boolean
|
Whether the option is required at checkout. Defaults to false. |
position - Int
|
Display position within the product's option list. |
type - String
|
Input rendering type (see ProductCustomOption.type for example values). |
Example
{
"productId": 123,
"productsOptionsId": 123,
"required": true,
"position": 987,
"type": "abc123"
}
CreateQuoteInput
Fields
| Input Field | Description |
|---|---|
customerId - Int
|
Requesting customer id. Optional — leave null for anonymous quotes captured via sessionId. |
sessionId - String
|
Anonymous browser session id when no customer is logged in. |
ipAddress - String
|
Requester IP address (forensics). |
statusId - Int
|
Initial status id. Defaults to the tenant's 'Open' status when omitted. |
shipmentMethod - String
|
Display label for the requested shipping method. |
shipmentCode - String
|
Code identifying the requested shipping module. |
shipmentPrice - Float
|
Quoted shipping cost. |
warehouseId - Int
|
Preferred warehouse id for stock pre-allocation. |
items - [QuoteProductInput!]!
|
Line items to create on the quote. Required (at least one). |
Example
{
"customerId": 123,
"sessionId": "abc123",
"ipAddress": "abc123",
"statusId": 123,
"shipmentMethod": "xyz789",
"shipmentCode": "abc123",
"shipmentPrice": 123.45,
"warehouseId": 123,
"items": [QuoteProductInput]
}
Currency
Description
A currency the storefront supports for display and order placement. Tenants enable currencies they want shoppers to be able to switch between (e.g. EUR + SEK + USD), and one currency is configured as the primary in the platform settings — that's the currency used for stock prices, order totals stored in DB, and accounting reports.
All non-primary currencies carry an exchange-rate value that's refreshed by a backend job; the storefront multiplies primary-currency prices by this rate at render time when the shopper picks a non-primary currency. Display formatting (currency symbol, where it sits relative to the number) lives in symbolLeft / symbolRight.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the currency. |
title - String
|
Display name of the currency (e.g. 'Euro', 'US Dollar'). Used in the storefront's currency switcher. |
code - String
|
ISO 4217 three-letter currency code (e.g. 'EUR', 'USD', 'GBP'). |
symbolLeft - String
|
Symbol rendered before the amount when formatting prices (e.g. '$' for USD). Empty when the currency uses a right-side symbol. |
symbolRight - String
|
Symbol rendered after the amount when formatting prices (e.g. ' €' for EUR in some locales). Empty when the currency uses a left-side symbol. |
value - Float
|
Exchange rate against the tenant's primary currency. Multiply a primary-currency amount by this value to convert it into this currency at the rate captured at lastUpdated. |
lastUpdated - String
|
Timestamp of the last exchange-rate refresh. The platform's FX-rate sync job updates this when it pulls fresh rates. |
Example
{
"id": "4",
"title": "xyz789",
"code": "xyz789",
"symbolLeft": "abc123",
"symbolRight": "xyz789",
"value": 987.65,
"lastUpdated": "xyz789"
}
Customer
Description
A customer of the tenant — registered shopper, B2B account, or guest one-time-checkout record. The same row holds individual and B2B customers (distinguished via the type field), and guest checkouts reuse the table with temporaryCustomer set so the storefront can later upgrade them to registered accounts.
Carries identity (email, name, telephone), behaviour flags (newsletter, freeShipping threshold, payment / shipping blocks), pointers to the customer's saved addresses (addresses field, default ids), the activity-stats sidecar (info field), and ERP-facing ids (apiId, apiBillingId). For login / failure counters see CustomerInfo; for per-customer pricing see customerPrice / customersPrices; for group-based pricing see customerGroups.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the customer. |
gender - String
|
Salutation / gender code (e.g. 'm', 'f'). Free-form, tenant-defined. |
firstname - String
|
First name. |
lastname - String
|
Last name. |
emailAddress - String
|
Login email. Unique across registered customers in the tenant; guest customers (temporaryCustomer = true) may share email addresses with each other and with registered accounts. |
defaultAddressId - Int
|
Pointer to the customer's default address-book entry — the address the storefront pre-selects at checkout. |
defaultDeliveryAddressId - Int
|
Pointer to the address-book entry used as the default delivery destination. May differ from defaultAddressId when the customer ships to a different address than they bill to. |
telephone - String
|
Telephone number. |
newsletter - Boolean
|
Newsletter subscription state. true = opted in. |
freeShipping - Float
|
Free-shipping order-value threshold. Orders over this value (in the tenant's default currency) ship free; 0 = no per-customer override (the global rule applies). Per-customer free shipping; not a percentage discount. |
admin - Int
|
Whether this customer record is also an admin user. Stored as int — 0 = regular customer, non-zero = admin (mostly legacy / ERP-staff records). |
type - Int
|
Customer category. Example values:
|
group - String
|
Customer-group memberships. Stored as a JSON-encoded array of group_id strings (e.g. '["1","5"]'). Empty array means the customer is in no groups. Group definitions live in the customer_groups table — resolve human-readable descriptions, discount type, and customer-type / B2B gating via the customerGroups query. The customerPrice resolver consults this list when choosing the lowest applicable group price for a product. |
approved - Boolean
|
true once the customer has confirmed their email and the account is enabled for purchasing. Used for double-opt-in and B2B account moderation flows. |
undeliveredOrders - Int
|
Counter of orders that failed delivery (returned to sender, undeliverable address, etc.). Useful as a fraud / address-quality signal. |
blockPayments - String
|
Comma-separated list of payment-module ids the customer is barred from using at checkout (e.g. 'invoice,banktransfer'). Empty / null means no restrictions. Set by admins on accounts with payment risk. |
blockShipments - String
|
Comma-separated list of shipping-module ids the customer is barred from using at checkout. Empty / null means no restrictions. |
temporaryCustomer - Boolean
|
true when this row is a guest-checkout / placeholder record rather than a registered account. The underlying column stores a Unix timestamp of when the guest record was created (so admin tooling can sweep stale guests); this field is the truthy/falsy projection of that timestamp. |
emailSent - Boolean
|
Whether the welcome / confirmation email has been dispatched to the customer. |
apiId - String
|
External (ERP / PIM) identifier for the customer record, captured when the customer is mirrored from a third-party system. |
apiBillingId - Int
|
External identifier for the customer's billing entity in the ERP. Distinct from apiId — large customers can have one billing record covering multiple shipping accounts. |
grantWhatsapp - Boolean
|
Whether the customer has consented to receive WhatsApp notifications (order updates, abandoned-cart reminders). |
billingOperatorId - Int
|
E-invoice operator id captured on the customer record itself (a customer-level default that propagates onto billing addresses). |
billingInvoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI) captured on the customer record itself. |
billingReference - String
|
Customer-level invoice reference / PO number default. |
billingReferenceRequired - Boolean
|
Whether the customer's invoices require a non-empty reference at checkout. |
info - CustomerInfo
|
Activity-stats sidecar (last login, login counters, account creation date, etc.). Backed by the customers_info table — see CustomerInfo for field-level docs. |
addresses - [Address]
|
Address-book entries for this customer, hydrated alongside the customer record. For an independent paginated view see addressBookEntries. |
Example
{
"id": 4,
"gender": "xyz789",
"firstname": "xyz789",
"lastname": "xyz789",
"emailAddress": "xyz789",
"defaultAddressId": 123,
"defaultDeliveryAddressId": 123,
"telephone": "xyz789",
"newsletter": true,
"freeShipping": 987.65,
"admin": 123,
"type": 987,
"group": "abc123",
"approved": false,
"undeliveredOrders": 987,
"blockPayments": "abc123",
"blockShipments": "abc123",
"temporaryCustomer": true,
"emailSent": false,
"apiId": "xyz789",
"apiBillingId": 987,
"grantWhatsapp": false,
"billingOperatorId": 123,
"billingInvoiceAddress": "abc123",
"billingReference": "xyz789",
"billingReferenceRequired": false,
"info": CustomerInfo,
"addresses": [Address]
}
CustomerBlacklistEntry
Description
A blacklist entry pinning one customer to a moderation status — typically 'blocked from purchasing' for chargeback fraud, abusive returns, or unpaid invoices. Multiple rows per customer can stack history (each new status is a fresh row, the latest wins), and the free-form reason field is kept for audit so operators can explain why a block was added later.
Distinct from Customer.blockPayments / blockShipments — those are per-method bans (this customer can't pay with X / ship via Y) while CustomerBlacklist is the binary 'stop this customer from buying at all' switch. Distinct from CustomerProductInclusion — that limits which products a customer can see, while this surface gates whether they can transact in the first place.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the blacklist entry. |
customerId - Int!
|
Customer the entry applies to. |
status - Int!
|
Blacklist status code. Tenant-defined; typically 1 = active block, 0 = lifted / inactive. Multiple statuses stack across rows so operators can review history. |
reason - String!
|
Free-form admin note explaining why the entry was added. Captured for audit. |
lastModified - String
|
Timestamp the entry was last edited (the resolver orders newest-first by this column). |
Example
{
"id": 4,
"customerId": 123,
"status": 123,
"reason": "abc123",
"lastModified": "xyz789"
}
CustomerFavorite
Description
A favorited product on a customer's wishlist. Backed by the customers_favorites table — one row per (customer, product) pair. Powers the storefront's 'Heart this product' / 'Save for later' / 'My wishlist' surface, the saved-favorites widget on the customer account page, and the back-in-stock notification audience for any restock alerts a tenant runs.
Distinct from customers_basket — favorites are a long-lived product list ('I want this someday'), while customers_basket is the active cart in flight to checkout.
Example
{
"id": "4",
"customersId": 123,
"productsId": 123
}
CustomerGroup
Description
A pricing / discount scheme applied to a slice of customers — a B2B tier, a wholesale partner channel, a loyalty group, etc. Customers belong to zero or more groups (via Customer.group, JSON-array of group ids), and the storefront / pricing engine layers the group's discount, per-product price-list rules, and dynamic-discount tiers on top of each shopper's regular price.
Carries the headline-level configuration (discount amount + type, B2B / consumer gating via customerType, validity window) plus the two sub-collections that hang off it: priceList (per-product overrides) and dynamicDiscounts (manufacturer / category-scoped extras).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the customer group (groups_id). |
description - String
|
Display description of the group, shown to admins (e.g. 'Wholesale tier 1', 'Loyalty members'). |
discountAmount - Float
|
Discount amount, interpreted via discountType (currency or percent depending on type). |
discountType - String
|
How discountAmount is applied. Example values:
|
dateStart - String
|
Inclusive lower bound on when the group's discount is active. Null = no lower bound. |
dateEnd - String
|
Inclusive upper bound on when the group's discount is active. Null = no upper bound. |
minOrder - Float
|
Minimum order value the basket must reach before the group's discount applies. 0 = no threshold. |
minOrderType - String
|
How minOrder is interpreted. Example values:
|
customerType - String
|
Customer-type gate. The customerGroups resolver also reads the request's X-Customer-Type header and only returns groups whose customerType matches 'all' or the header value. Example values:
|
discountedProducts - Int
|
Count of products that have a CustomerGroupPriceRule against this group. A precomputed convenience for the admin's group editor — no need to count rule rows separately. |
groupsType - String
|
Group-shape classifier — how the group's discount is structured. Example values:
|
dynamicDiscounts - [CustomerGroupDynamicDiscount]
|
Dynamic-discount tiers attached to the group. Empty when the group doesn't run dynamic discounts. |
priceList - [CustomerGroupPriceRule]
|
Per-product price overrides for the group. Empty when the group doesn't run a price list. |
Example
{
"id": "4",
"description": "abc123",
"discountAmount": 987.65,
"discountType": "abc123",
"dateStart": "xyz789",
"dateEnd": "abc123",
"minOrder": 123.45,
"minOrderType": "abc123",
"customerType": "abc123",
"discountedProducts": 123,
"groupsType": "xyz789",
"dynamicDiscounts": [CustomerGroupDynamicDiscount],
"priceList": [CustomerGroupPriceRule]
}
CustomerGroupDynamicDiscount
Description
One dynamic-discount tier inside a customer group. Dynamic discounts apply at the basket / catalogue level on top of the group's base discount, gated by manufacturer / category / date window — letting tenants run group-scoped promotions like 'Members get an extra 10 € off Brand X this month' without rewriting the group's main discount.
Distinct from CustomerGroupPriceRule — that surface fixes a specific product's price for the group, while dynamic discounts apply across whole product slices defined by manufacturer / category.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the dynamic-discount entry. |
groupId - String
|
Id of the parent customer group this discount applies to. |
amount - Float
|
Discount amount, in the tenant's default currency (not a percentage). |
dateStart - String
|
Inclusive lower bound on when the discount is active. Null = no lower bound. |
dateEnd - String
|
Inclusive upper bound on when the discount is active. Null = no upper bound. |
manufacturer - String
|
Manufacturer code / id this discount is scoped to. Null = applies across all manufacturers. |
category - String
|
Category code / id this discount is scoped to. Null = applies across all categories. |
sort - Int
|
Display sort order when the admin UI lists multiple dynamic-discount rows on a group. |
Example
{
"id": 4,
"groupId": "xyz789",
"amount": 987.65,
"dateStart": "abc123",
"dateEnd": "abc123",
"manufacturer": "abc123",
"category": "abc123",
"sort": 987
}
CustomerGroupPriceRule
Description
One product-level price override inside a customer group. Replaces the product's regular price with rule_price for members of the group when the rule is active (validFrom / validTo bracket). Used to run wholesale / contract pricing where individual products carry hand-set prices for a group, not a percentage off the regular price.
For variant-level overrides, productStockId points at one variant in products_stock; null means the override applies to the product as a whole. For percentage / formula-based group discounts see CustomerGroup.discountAmount + discountType; for cross-group lookup see customerGroupPriceList.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the price rule. |
groupId - String
|
Id of the parent customer group this rule applies to. |
productId - Int
|
Product the rule overrides the price of. |
productStockId - Int
|
Variant (products_stock_id) the rule scopes to. Null = applies to the product as a whole, regardless of variant. |
price - Float
|
Replacement price for the product / variant, in the tenant's default currency. Replaces the product's regular price for members of the group. |
validFrom - String
|
Inclusive lower bound on when the rule is active. Null = no lower bound. |
validTo - String
|
Inclusive upper bound on when the rule is active. Null = no upper bound. |
customerGroup - CustomerGroup
|
Resolved parent customer group, fetched on demand when the field is selected. Lets one round-trip pull a price-rule plus the group it belongs to (description, discount type, validity window). |
product - Product
|
Resolved product the rule applies to, fetched on demand when the field is selected. Returns the product's name / model / image / base price for surface display alongside the rule. |
Example
{
"id": 4,
"groupId": "abc123",
"productId": 987,
"productStockId": 123,
"price": 987.65,
"validFrom": "abc123",
"validTo": "xyz789",
"customerGroup": CustomerGroup,
"product": Product
}
CustomerHistoryEntry
Description
An audit-log entry recording one field-level change to a customer record (or to one of its address-book / customer-info side-tables). The customers_history table is generic enough to capture edits across multiple source tables — sourceTable identifies which table the row originated from, fieldName / oldValue / newValue capture the diff, and the userId / userName columns attribute the edit to the admin who made it.
Used by the admin's customer detail view's history tab, by GDPR / data-subject-access reports, and by any after-the-fact investigation ('who changed this customer's email last week?'). For the broader cross-module audit log see actionRecorderEntries; for product-level edits see adminTrackingCreate; this surface is the customer-record-specific change log.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the history entry. |
customerId - Int!
|
Customer the change was made on. |
addressBookId - Int
|
Address-book row id when the change was on an address row. Null when the change was on the customer record itself or on a non-address side-table. |
userId - Int!
|
Id of the admin who made the change. |
userName - String!
|
Username of the admin, captured at write time so the row stays readable if the admin is later deleted. |
sourceTable - String!
|
Source table the changed row belongs to. Example values seen in code:
|
fieldName - String!
|
Column name within sourceTable that changed (e.g. 'customers_email_address', 'entry_postcode'). |
oldValue - String
|
Value before the change. Null when the field was previously empty. |
newValue - String
|
Value after the change. Null when the field was cleared. |
page - String
|
Admin-page path that made the change (e.g. '/admin/customers/edit'). Useful for tracing which UI flow caused the edit. |
dateAdded - String!
|
Timestamp the change was recorded. |
Example
{
"id": "4",
"customerId": 987,
"addressBookId": 123,
"userId": 987,
"userName": "xyz789",
"sourceTable": "abc123",
"fieldName": "xyz789",
"oldValue": "abc123",
"newValue": "abc123",
"page": "xyz789",
"dateAdded": "abc123"
}
CustomerInfo
Description
Per-customer login and lifecycle counters tracked outside the main customers row. The customers_info table holds slow-changing meta about a customer account — when they last logged in, how many times, how many failed attempts, when the account was created and last edited, plus optional marketing-source attribution and notification preferences.
Used by the admin's customer detail view to surface 'Last login' and 'Account age' badges, by security tooling that watches failed-login counters, and by any onboarding / re-engagement automation that needs to know how stale an account is. For a customer's full profile + addresses see the customer query; this surface is the activity-stats side car.
Fields
| Field Name | Description |
|---|---|
dateOfLastLogon - String
|
Timestamp of the customer's most recent successful login. Null for accounts that have never logged in (e.g. admin-created records). |
numberOfLogons - Int
|
Total successful logins by this customer over the lifetime of the account. |
numberOfFailedLogins - Int
|
Total failed-login attempts since the last successful login. Used by anti-brute-force tooling — typically reset on successful auth. |
dateOfLastLoginFail - String
|
Timestamp of the most recent failed-login attempt for this account. Null when no failed attempts have been recorded. |
dateAccountCreated - String
|
Timestamp the account was created. |
dateAccountLastModified - String
|
Timestamp the account was last edited (profile update, password change, address change). |
sourceId - Int
|
Marketing-source attribution id captured at registration — referrer / campaign id when the tenant runs source tracking. Null when the tenant doesn't track sources or the source was unknown. |
globalProductNotifications - Int
|
Whether the customer has opted in to global product notifications (back-in-stock alerts, restock notices, etc.). Stored as int (1=on, 0=off). |
Example
{
"dateOfLastLogon": "xyz789",
"numberOfLogons": 123,
"numberOfFailedLogins": 987,
"dateOfLastLoginFail": "abc123",
"dateAccountCreated": "xyz789",
"dateAccountLastModified": "abc123",
"sourceId": 123,
"globalProductNotifications": 123
}
CustomerPrice
CustomerProductInclusion
Description
An allowlist row binding one product to one customer. When a customer has any inclusion rows the catalog flips into 'private' mode for them — they can only see and order the products explicitly listed here, not the rest of the tenant's catalog. Used to run B2B private catalogs, named-account contract assortments, and confidential pre-release windows.
Empty inclusions means the customer sees the standard catalog (no restriction). The check is per-customer, not per-customer-group — for group-level visibility rules see the customer-group / channel surfaces.
Example
{"id": 4, "customerId": 123, "productId": 987}
CustomerProductInclusionInput
CustomersApiCustomer
Description
An ERP-mirrored snapshot of one customer record. The customers_api table caches the customer master data the tenant's ERP owns — Netvisor / Lemonsoft / Tehden / SAP / Tisma depending on the tenant — so the storefront and admin can reference contract-side identifiers, payment terms, credit limits, sales codes, and discount-group assignments without round-tripping to the ERP for every read.
The Finnish-language column names (asiakaskoodi = customer code, alennusryhma = discount group, ytunnus = business id) reflect the Finnish-ERP origin of the schema; the table is read-only from the GraphQL surface — the writer is an async ERP-side sync job that pushes updates into this cache as the source-of-truth ERP changes.
For the platform-side customer record (logins, addresses, orders, group membership), see Customer / customers. customersApi is the ERP-shaped counterpart, joined on the asiakaskoodi key.
Fields
| Field Name | Description |
|---|---|
asiakaskoodi - String!
|
ERP-side primary customer code (Finnish 'asiakaskoodi'). The stable join key into the platform-side Customer.apiId. |
name - String
|
Primary recipient name as stored in the ERP. |
secondaryName - String
|
Secondary name line — typically a contact person, department, or 'attention to' line in the ERP. |
addressLine1 - String
|
First street-address line (ERP shipping/main address). |
addressLine2 - String
|
Second street-address line. |
addressLine3 - String
|
Third street-address line — typically postcode + city in the ERP convention. |
deliveryName1 - String
|
First delivery-address line — separate from the main address when ERP tracks ship-to and bill-to as different parties. |
deliveryName2 - String
|
Second delivery-address line. |
deliveryName3 - String
|
Third delivery-address line. |
billingCustomerId - Int
|
ERP id of the billing customer when this record is a delivery sub-account that bills to a parent customer. |
paymentTerm - String
|
ERP-defined payment-term code (e.g. 'NET14', 'NET30'). Drives invoice due-date calculation. |
customerGroup - String
|
ERP customer-group code (e.g. wholesale tier, regional segment). Used by the storefront pricing engine when mirrored into platform-side customer groups. |
chain - String
|
ERP chain / parent-group code when the customer belongs to a chain account. |
salesCode - String
|
ERP-side sales-code / sales-rep id (the salesperson responsible for the account). |
creditLimit - String
|
Credit limit set in the ERP, in the customer's currency. Stored as a string because the ERP may format it (e.g. '10000.00'). |
deliveryBlock - String
|
ERP delivery-block code. When set, the ERP has flagged this customer as not-to-be-delivered (e.g. for outstanding invoices). |
email - String
|
ERP-side primary email. |
website - String
|
ERP-side website / URL. |
phone - String
|
ERP-side phone number. |
fax - String
|
ERP-side fax number (legacy field; rarely populated on modern accounts). |
deliveryMethod - String
|
ERP delivery-method code (e.g. 'pickup', 'parcel', 'truck'). Maps to a shipping module on the storefront. |
discountGroup - String
|
ERP discount-group code ('alennusryhma'). The pricing engine looks up the discount percentage by this code. |
discountPercent - Float
|
Discount percentage from the ERP for this customer (the customer-level baseline, before group / contract overrides). |
secondaryDiscountPercent - Float
|
Secondary discount percentage. ERPs commonly use this for stacking a category-level or campaign-level discount on top of the primary discount. |
languageCode - String
|
ERP-side language code (e.g. 'fi', 'sv', 'en'). Used to localize ERP-generated documents (invoices, packing slips). |
comment1 - String
|
First free-form ERP comment field. Tenant-defined notes. |
comment2 - String
|
Second free-form ERP comment field. |
contactPerson - String
|
Primary contact-person name on the customer record. |
contactPersonId - Int
|
Primary contact-person id (ERP-side reference into a contacts table). |
lastLoginAt - String
|
Timestamp of the customer's most recent storefront login, mirrored back into the ERP cache. |
vatLiability - String
|
VAT-liability code from the ERP (e.g. 'standard', 'reverse-charge', 'exempt'). Drives tax behaviour on invoices. |
currency - String
|
ERP-side default currency code for the customer (ISO 4217). |
modifiedAt - String
|
Timestamp of the most recent ERP-side edit to the record. |
businessId - String
|
Business id (Finnish 'ytunnus' / VAT number). Used for B2B invoicing and EU VAT validation. |
billingAddress - String
|
Default invoice address line stored on the ERP record. |
intermediaryService - String
|
E-invoice intermediary / operator code ('valityspalvelu' in Finnish e-invoicing). Names the operator routing the customer's e-invoices. |
netvisorKey - Int
|
Netvisor-side customer key (Finnish ERP integration). Used to look up the customer in Netvisor's API; 0 / null for customers not mirrored from Netvisor. |
Example
{
"asiakaskoodi": "abc123",
"name": "abc123",
"secondaryName": "xyz789",
"addressLine1": "abc123",
"addressLine2": "abc123",
"addressLine3": "xyz789",
"deliveryName1": "xyz789",
"deliveryName2": "abc123",
"deliveryName3": "abc123",
"billingCustomerId": 987,
"paymentTerm": "abc123",
"customerGroup": "abc123",
"chain": "xyz789",
"salesCode": "xyz789",
"creditLimit": "abc123",
"deliveryBlock": "xyz789",
"email": "abc123",
"website": "abc123",
"phone": "abc123",
"fax": "abc123",
"deliveryMethod": "abc123",
"discountGroup": "xyz789",
"discountPercent": 987.65,
"secondaryDiscountPercent": 987.65,
"languageCode": "xyz789",
"comment1": "abc123",
"comment2": "xyz789",
"contactPerson": "xyz789",
"contactPersonId": 123,
"lastLoginAt": "xyz789",
"vatLiability": "xyz789",
"currency": "abc123",
"modifiedAt": "xyz789",
"businessId": "xyz789",
"billingAddress": "xyz789",
"intermediaryService": "abc123",
"netvisorKey": 987
}
CustomersBasketItem
Description
One line item in a customer's persistent (server-side) basket. Unlike the volatile session basket, customers_basket rows survive logout and device switch — they're the storefront's 'we saved your cart' surface, the basket the abandoned-basket reminder emails are built on, and the starting point when a logged-in customer adds the same product again.
A line carries the product, the chosen variant + option values (variants / productOptions), any free-form custom-option text inputs (customOptions), and an explicit price snapshot (specialPrice) when the storefront wants to lock in a promotional price. Bundle support is via bundleId + includes for parent / child line linking.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the basket line (customers_basket_id). |
cartId - String!
|
Cart key. Lets one customer hold multiple parallel baskets (saved-for-later, B2B quote draft, etc.) keyed by this opaque id. |
customersId - Int!
|
Customer id this basket line belongs to. |
itemId - String
|
Free-form item identifier captured at add-to-cart time. Used by some integrations to match the line back to an external system. |
productId - Int
|
Product id added to the basket. Null for bundle child rows that point at the parent via bundleId instead. |
variants - String
|
Variant identifier for the line — matches the comma-separated option-value-id format used in ProductStock.variant (e.g. '11_22' = option 11 value 22). Null when the product has no variants. |
productOptions - String
|
Configurable-option choices captured at add-to-cart, encoded the same way OrderItemVariant rows persist them on a finalized order. |
comment - String
|
Free-form line comment from the shopper (e.g. gift-message, delivery instructions for this line specifically). |
customOptions - String
|
Custom-option text inputs captured at add-to-cart (the free-text counterpart to productOptions, e.g. engraving text, monogram initials). |
quantity - Int!
|
Quantity ordered on this line. |
specialPrice - Float
|
Price snapshot to lock the line to, in the tenant's default currency. Null = use the live product price at checkout. Set when the storefront wants to honour a promotional price even if the catalog price changes before checkout. |
bundleId - String
|
Bundle parent id for child rows. Null = this line is either a standalone product or the bundle parent itself. |
includes - String
|
Bundle-children references when this row is a bundle parent (free-form encoding identifying the included products / lines). |
dateAdded - String
|
Timestamp the line was added to the basket. Used to age out stale baskets. |
emailSent - Int
|
Abandoned-basket reminder counter. Tracks how many reminder emails the line has triggered so far. |
emailLast - String
|
Timestamp of the most recent abandoned-basket reminder email sent for the line. |
variableImage - String
|
Variant-specific image filename to render on the basket page (e.g. when the customer picked a colour variant). |
allowSubstitute - Boolean!
|
Whether the customer is OK with the warehouse shipping a substitute item if this product is out of stock at pick time. Captured for B2B / wholesale flows where missing stock can be swapped for an equivalent. |
Example
{
"id": "4",
"cartId": "xyz789",
"customersId": 123,
"itemId": "abc123",
"productId": 123,
"variants": "abc123",
"productOptions": "xyz789",
"comment": "abc123",
"customOptions": "xyz789",
"quantity": 987,
"specialPrice": 123.45,
"bundleId": "xyz789",
"includes": "abc123",
"dateAdded": "abc123",
"emailSent": 123,
"emailLast": "xyz789",
"variableImage": "abc123",
"allowSubstitute": true
}
CustomersBraintreeToken
Description
A saved card kept in Braintree's vault for one customer. The platform stores only the Braintree-side payment-method-token plus a few display-friendly bits (card type, masked number, expiry) — the actual PAN never lives on platform infrastructure. At checkout the storefront references the token to charge against the saved card without re-collecting card details (PCI scope reduction).
One customer can have multiple saved cards (e.g. corporate + personal, or expired + replacement). The 'currently default' card isn't an explicit column on this surface — applications typically pick the most-recent dateAdded as the default, or read the default off Braintree's customer record directly.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the token entry. |
customersId - Int!
|
Customer the saved card belongs to. |
braintreeToken - String!
|
Braintree payment-method-token (vault id). Pass this to Braintree at charge time to bill the saved card. |
cardType - String!
|
Card brand (e.g. 'Visa', 'MasterCard', 'Amex'). Returned by Braintree at vault time and cached here for display. |
numberFiltered - String!
|
Masked card number for display (e.g. '--****-1234'). The full PAN is never stored locally — only the masked form. |
expiryDate - String!
|
Card expiry, in the format Braintree returns (typically 'MM/YYYY'). |
dateAdded - String!
|
Timestamp the card was added to the vault. Used as a tiebreaker when picking a 'most recent' default. |
Example
{
"id": "4",
"customersId": 123,
"braintreeToken": "xyz789",
"cardType": "xyz789",
"numberFiltered": "xyz789",
"expiryDate": "abc123",
"dateAdded": "xyz789"
}
DeliveryAddress
Description
A delivery-address entry belonging to a customer, stored in the modern delivery_address_book table. Used by tenants who've migrated to the newer split-address schema where shipping (delivery) and billing live in separate dedicated tables — distinct from AddressBook, which holds shipping with optional alternate-billing fields in one row, and from BillingAddress, which holds standalone invoice recipients.
Rows can carry a legacyAddressBookId pointing back to the original address_book row this delivery entry was migrated from; pass includeLegacy=true on the query to side-load the original AddressBook (with its billing fields) alongside the modern delivery row in the same response — useful while the migration is in flight.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the delivery-address entry (delivery_address_id). |
customerId - Int!
|
Customer this delivery address belongs to. |
gender - String
|
Salutation / gender code on the recipient. |
company - String
|
Company name on the recipient. Set when the address is a business delivery. |
firstname - String!
|
Recipient first name. |
lastname - String!
|
Recipient last name. |
streetAddress - String!
|
Street address line. |
vatid - String
|
VAT / business id captured for B2B shipping documents. |
postcode - String!
|
Postal code. |
city - String!
|
City. |
state - String
|
State / region. Used in countries that need it (US, AU, etc.). |
countryId - Int!
|
Country id (resolves against the countries query). |
zoneId - Int!
|
Zone id within the country. |
comments - String
|
Free-form delivery instructions captured at address creation. |
legacyAddressBookId - Int
|
Pointer to the legacy address_book row this delivery entry was migrated from. Null when the row was created directly in the modern delivery_address_book. |
legacyAddress - AddressBook
|
Resolved legacy AddressBook (with billing fields), populated only when the query is called with includeLegacy=true and legacyAddressBookId is set. Useful while the dual-write migration is still in flight. |
Example
{
"id": 4,
"customerId": 123,
"gender": "abc123",
"company": "abc123",
"firstname": "abc123",
"lastname": "xyz789",
"streetAddress": "abc123",
"vatid": "xyz789",
"postcode": "xyz789",
"city": "xyz789",
"state": "abc123",
"countryId": 987,
"zoneId": 987,
"comments": "xyz789",
"legacyAddressBookId": 123,
"legacyAddress": AddressBook
}
DiscountCoupon
Description
A discount coupon definition — the rule that says 'enter code XYZ at checkout to get N off, applicable when …'. Coupons can be unrestricted (apply to any basket) or scoped to specific products, categories, customers, manufacturers, shipping methods, or geo-zones via the applicability arrays (categories, products, customers, manufacturers, shippingMethods, zones) — each populated from a dedicated discount_coupons_to_* join table.
The orders[] array on this type doubles as the redemption history — it contains the order ids the coupon has actually been applied to. For per-order lookup of which coupons were applied see discountCouponsToOrders / Order.discountCoupons; for per-customer attach/revoke flows see attachDiscountCouponToCustomer / removeDiscountCouponFromCustomer mutations.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Coupon id (a row in the discount_coupons table). Strings on the wire — most tenants use human-readable codes like 'WELCOME10' rather than numeric ids. |
description - String!
|
Admin-facing description (e.g. 'Welcome 10% off'). Not shown to shoppers. |
amount - Float!
|
Discount value, interpreted via discountType. |
discountType - String!
|
How amount is applied. Example values:
|
dateStart - String
|
Inclusive lower bound on when the coupon is redeemable. Null = no lower bound. |
dateEnd - String
|
Inclusive upper bound on when the coupon is redeemable. Null = no upper bound. |
maxUse - Int!
|
Maximum total redemptions across all customers. 0 = unlimited. |
minOrder - Float!
|
Minimum order threshold for the coupon to apply, interpreted via minOrderType. |
minOrderType - String
|
How minOrder is interpreted. Example values:
|
numberAvailable - Int!
|
Remaining redemptions allowed across all customers. Decremented each time the coupon is applied to an order; reaches 0 when the coupon is exhausted (subject to maxUse). 0 / null when unbounded. |
customerType - String!
|
Customer-eligibility filter. Example values:
|
discountedProducts - Int
|
Cached count of products the coupon currently applies to (rolled up from the products / categories / manufacturers join tables). Convenience for admin UI; recomputed when applicability changes. |
discountedProductsOld - Int
|
Cached count of products the coupon previously applied to before the most recent applicability edit. Used by the admin to show 'previous vs current' diffs when editing a coupon. |
allowedProducts - String
|
Free-form whitelist of additional product ids (typically comma-separated) the coupon applies to even if the categories / products join tables don't list them. Null when no extra whitelist is set. |
categories - [Int!]
|
Category ids the coupon is restricted to (from discount_coupons_to_categories). Empty array means 'no category restriction'. |
products - [Int!]
|
Product ids the coupon is restricted to (from discount_coupons_to_products). Empty array means 'no per-product restriction'. |
customers - [Int!]
|
Customer ids the coupon is restricted to (from discount_coupons_to_customers) — the per-customer issued-coupon allowlist. Empty array means 'any eligible customer can use it'. |
orders - [Int!]
|
Order ids the coupon has been redeemed against (from discount_coupons_to_orders). Doubles as the redemption history. |
manufacturers - [Int!]
|
Manufacturer ids the coupon is restricted to (from discount_coupons_to_manufacturers). Empty array means 'no manufacturer restriction'. |
shippingMethods - [String!]
|
Shipping-method codes the coupon is restricted to (from discount_coupons_to_shipping). Empty array means 'no shipping-method restriction'. |
zones - [Int!]
|
Geo-zone ids the coupon is restricted to (from discount_coupons_to_zones). Empty array means 'no geo restriction'. |
Example
{
"id": 4,
"description": "xyz789",
"amount": 123.45,
"discountType": "xyz789",
"dateStart": "xyz789",
"dateEnd": "abc123",
"maxUse": 987,
"minOrder": 987.65,
"minOrderType": "abc123",
"numberAvailable": 987,
"customerType": "xyz789",
"discountedProducts": 987,
"discountedProductsOld": 987,
"allowedProducts": "abc123",
"categories": [987],
"products": [987],
"customers": [987],
"orders": [987],
"manufacturers": [123],
"shippingMethods": ["abc123"],
"zones": [123]
}
DiscountCouponCustomerLink
Description
A per-customer issuance link — one row in discount_coupons_to_customers binding one coupon to one customer. When a coupon's customers list is non-empty, only the listed customers can redeem it (private / VIP / named-account coupons). Empty list = anyone eligible by the coupon's other rules can redeem.
Same join surface that's exposed as DiscountCoupon.customers[] (the read view from the coupon side). Use the mutations here to attach a coupon to a customer (idempotent via ON DUPLICATE KEY) or detach it.
Example
{"couponCode": 4, "customerId": 4}
DiscountCouponCustomerLinkInput
DiscountCouponOrderLink
Description
One redemption-history entry — a row in discount_coupons_to_orders recording that a specific coupon was applied to a specific order at checkout. Same join table that's exposed as DiscountCoupon.orders[] (the from-coupon side) and as Order.discountCoupons (the from-order side); this surface is the standalone link-row view, useful for cross-cutting queries that want the join with both endpoints resolvable in one round-trip.
The link is created at checkout when the customer applies a coupon successfully, and is read at order display, refund / return flows, and coupon-performance reporting. Removing a coupon from an order after the fact requires deleting this link row plus reversing the numberAvailable counter on the parent DiscountCoupon — there's no built-in mutation for that here.
Fields
| Field Name | Description |
|---|---|
couponCode - ID!
|
Coupon id that was applied (matches DiscountCoupon.id). |
orderId - ID!
|
Order id the coupon was applied to. |
coupon - DiscountCoupon
|
Resolved coupon, fetched on demand when the field is selected. Returns the full DiscountCoupon with its applicability arrays. |
order - Order
|
Resolved order, fetched on demand when the field is selected. Returns a slim Order shape (customer, status, totals, payment / shipping method). |
Example
{
"couponCode": 4,
"orderId": "4",
"coupon": DiscountCoupon,
"order": Order
}
Domain
Description
One storefront-domain configuration row. Tenants run multi-domain setups where each domain is bound to a language (e.g. shop.example.fi for Finnish, shop.example.se for Swedish, shop.example.com for English) — this surface holds the per-domain wiring that ties one hostname to its language id, hreflang, default flag icon, and the full set of marketing-pixel ids the storefront should render in the page head.
Carries:
- language wiring: languageId, code, hreflang, cctld, flag, sortOrder
- WordPress companion-blog link: wpDomain
- per-domain AI assistant config: openaiChatInstructions / openaiVectorStoreId / openaiChatAssistantId
- marketing-pixel ids: Google / Adwords / Meta / TikTok / Microsoft Ads / Pinterest / MS Clarity / Hotjar
Only domains with status = 1 are returned by the resolver. The marketing-pixel and AI fields are tenant-configured per domain so one storefront's analytics / chat assistant can differ between language variants.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the domain entry. |
languageId - Int!
|
Storefront language id this domain serves (resolves against the languages query). |
code - String!
|
Short language code (e.g. 'fi', 'sv', 'en'). Also the value compared by the domains(locale:) query argument. |
hreflang - String!
|
Hreflang attribute emitted in tags (e.g. 'fi-FI', 'en-GB'). Used by search engines to map language variants of the same content. |
domain - String!
|
Full domain name the storefront serves on (e.g. 'shop.example.fi'). |
cctld - String!
|
Country-code top-level domain extracted from the domain (e.g. '.fi', '.se'). Used for storefront-side display and country detection. |
flag - String!
|
Filename of the flag icon shown in the language switcher (served from the tenant's flag-image directory). |
sortOrder - Int
|
Display order of the domain in the language switcher. Lower values render first. |
googlePixel - String
|
Google Analytics measurement id (e.g. 'G-XXXXXXXX'). Rendered into the storefront's analytics tag. |
googleApiSecret - String
|
Google Analytics Measurement Protocol API secret. Used for server-side event posting. |
adwordsPixel - String
|
Google Ads conversion-tracking id. |
adwordsPhone - String
|
Google Ads conversion label for phone-call conversions. |
adwordsPurchase - String
|
Google Ads conversion label for purchase conversions. |
adwordsContact - String
|
Google Ads conversion label for contact-form conversions. |
adwordsQuote - String
|
Google Ads conversion label for quote-request conversions. |
metaPixel - String
|
Meta (Facebook) Pixel id. |
metaApiSecret - String
|
Meta Conversions API access token, paired with metaPixel for server-side event posting. |
tiktokPixel - String
|
TikTok Pixel id. |
tiktokApiSecret - String
|
TikTok Events API access token. |
msAdsPixel - String
|
Microsoft Ads (Bing) UET tag id. |
msAdsPhone - String
|
Microsoft Ads goal id for phone-call conversions. |
msAdsContact - String
|
Microsoft Ads goal id for contact-form conversions. |
msAdsPurchase - String
|
Microsoft Ads goal id for purchase conversions. |
msAdsQuote - String
|
Microsoft Ads goal id for quote-request conversions. |
pinterestPixel - String
|
Pinterest Tag id. |
msClarityPixel - String
|
Microsoft Clarity project id (session-replay analytics). |
hotjarPixel - String
|
Hotjar site id. |
wpDomain - String
|
Hostname of the WordPress companion site bound to this domain (e.g. blog / news subdomain). Null when the domain has no WP companion. |
openaiChatInstructions - String
|
System-prompt / instructions for the per-domain OpenAI chat assistant rendered on the storefront. Tenants tune this to set the assistant's tone and storefront-specific context. |
openaiVectorStoreId - String
|
OpenAI vector-store id holding the domain-specific knowledge corpus the assistant retrieves from. |
openaiChatAssistantId - String
|
OpenAI assistant id bound to this domain (for the storefront chat widget). |
Example
{
"id": 4,
"languageId": 987,
"code": "abc123",
"hreflang": "xyz789",
"domain": "xyz789",
"cctld": "xyz789",
"flag": "xyz789",
"sortOrder": 123,
"googlePixel": "xyz789",
"googleApiSecret": "abc123",
"adwordsPixel": "xyz789",
"adwordsPhone": "abc123",
"adwordsPurchase": "abc123",
"adwordsContact": "abc123",
"adwordsQuote": "xyz789",
"metaPixel": "xyz789",
"metaApiSecret": "xyz789",
"tiktokPixel": "xyz789",
"tiktokApiSecret": "xyz789",
"msAdsPixel": "abc123",
"msAdsPhone": "xyz789",
"msAdsContact": "xyz789",
"msAdsPurchase": "abc123",
"msAdsQuote": "abc123",
"pinterestPixel": "abc123",
"msClarityPixel": "xyz789",
"hotjarPixel": "xyz789",
"wpDomain": "abc123",
"openaiChatInstructions": "abc123",
"openaiVectorStoreId": "abc123",
"openaiChatAssistantId": "xyz789"
}
FaqCategory
Description
A grouping of FAQ questions — the top level of the help-center tree. Each FaqCategory carries display assets (icon, image), visibility / SEO flags, sort order, and a localized FaqCategoryDescription per language. The questions field is hydrated when the parent faqCategories query is called with the appropriate filters (visibleOnly / includeHiddenQuestions / sortByOrder shape what it contains).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the category. |
icon - String
|
Filename of the category icon (small inline glyph). |
image - String
|
Filename of the category hero image. |
visibility - Int
|
Visibility flag. 1 = visible on the storefront; 0 = hidden. |
googleIndex - Int
|
Search-engine indexability flag for the category landing page. 1 = indexable, 0 = noindex. |
sortOrder - Int
|
Display sort order. Lower values render first. |
descriptions - [FaqCategoryDescription]
|
Localized name / URL / description / SEO rows, one per language. |
questions - [FaqQuestion]
|
Questions belonging to this category, hydrated from the faq_to_category bridge. Ordered by question sortOrder when sortByOrder is true on the query, otherwise by id. |
Example
{
"id": 4,
"icon": "xyz789",
"image": "abc123",
"visibility": 123,
"googleIndex": 987,
"sortOrder": 987,
"descriptions": [FaqCategoryDescription],
"questions": [FaqQuestion]
}
FaqCategoryDescription
Description
Localized text and SEO metadata for one FAQ category, in one language. Each FaqCategory has one FaqCategoryDescription per (category, languageId) pair — the storefront picks the row matching the active language at render time. Carries the visible name, the slug-style URL fragment, the long category description, and the SEO meta-tags emitted into the FAQ landing page head.
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for (resolves against the languages query). |
name - String
|
Localized category name shown in the FAQ navigation and page header. |
url - String
|
Slug-style URL fragment for the category landing page. |
description - String
|
Long-form category description shown above the question list. |
metaTitle - String
|
Localized |
metaDescription - String
|
Localized for the category landing page. |
Example
{
"languageId": 123,
"name": "xyz789",
"url": "abc123",
"description": "xyz789",
"metaTitle": "xyz789",
"metaDescription": "abc123"
}
FaqQuestion
Description
One FAQ entry — a question with one or more localized answers. Lives under one or more FaqCategory parents (the categories array makes the question-to-category relationship many-to-many via the faq_to_category bridge), and can optionally surface as its own SEO landing page (when enableUrl = 1, the question's slug from FaqQuestionDescription.url becomes routable).
Used to render the storefront's help center, accordion-style FAQ blocks on product / category pages, and AI-assistant grounding (the same content frequently feeds the chat widget's vector store, see Domain.openaiVectorStoreId).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the question. |
image - String
|
Optional illustration filename, served from the tenant's FAQ-image directory. |
sortOrder - Int
|
Display sort order within each parent category. Lower values render first. |
visibility - Int
|
Visibility flag. 1 = visible on the storefront; 0 = hidden (kept for editing without going live). |
googleIndex - Int
|
Search-engine indexability flag for the per-question landing page. 1 = indexable, 0 = noindex. |
enableUrl - Int
|
Whether the question gets its own SEO landing page at the slug captured in FaqQuestionDescription.url. 1 = enabled, 0 = the question only renders inside category pages. |
categories - [Int]
|
Parent category ids — many-to-many. One question can live under multiple FAQ categories. |
descriptions - [FaqQuestionDescription]
|
Localized question / answer rows, one per language. |
Example
{
"id": "4",
"image": "xyz789",
"sortOrder": 123,
"visibility": 123,
"googleIndex": 123,
"enableUrl": 123,
"categories": [123],
"descriptions": [FaqQuestionDescription]
}
FaqQuestionDescription
Description
Localized text and SEO metadata for one FAQ question, in one language. Each FaqQuestion has one FaqQuestionDescription per (question, languageId) pair. Carries the question itself, the long answer, an optional shortAnswer used in collapsed / preview surfaces, the per-question slug, and SEO meta-tags emitted when the question gets its own landing page (gated by FaqQuestion.enableUrl).
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for. |
question - String
|
The question text shown to shoppers. |
answer - String
|
Long-form answer body. Typically rich text. |
shortAnswer - String
|
Short answer used in collapsed / accordion surfaces and in card previews. |
url - String
|
Slug-style URL fragment for the per-question landing page (used when enableUrl = 1). Looked up by the faqQuestion(slug:) query. |
metaTitle - String
|
Localized |
metaDescription - String
|
Localized for the per-question landing page. |
Example
{
"languageId": 123,
"question": "abc123",
"answer": "abc123",
"shortAnswer": "abc123",
"url": "abc123",
"metaTitle": "abc123",
"metaDescription": "abc123"
}
Float
Description
The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.
Example
123.45
ID
Description
The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.
Example
"4"
Int
Description
The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
Example
123
JSON
Example
{}
Language
Description
A language enabled for the tenant. Drives the languages dropdown on the storefront / admin, every per-language description row across the schema (CategoryDescription, FaqQuestionDescription, OrderStatus, etc.), and the localized labels emitted in transactional emails and receipts. The platform's core canonical ids — 1=English, 5=Swedish, 6=Finnish, 9=Spanish, 14=Italian — are shared across tenants; tenants may add more by inserting rows here and creating matching *_description rows for each localized table.
Every typedef in the schema that references a languageId resolves it against this table. Always resolve dynamically rather than hardcoding — the canonical id list isn't enforced at the DB level and tenants can extend it.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the language (language_id). Used as the languageId in every per-language description row across the schema. |
code - String!
|
ISO 639-1 short code (e.g. 'fi', 'sv', 'en'). The code shoppers see in the URL when language is encoded in the path. |
name - String!
|
Display name of the language in the language's own form (e.g. 'Suomi' for Finnish). |
metadata - LanguageMetadata
|
Storefront i18n metadata: flag icon filename and language-bundle directory. |
Example
{
"id": "4",
"code": "abc123",
"name": "xyz789",
"metadata": LanguageMetadata
}
LanguageMetadata
Description
Storefront-side i18n metadata for one language. The image and directory fields come from the legacy oscommerce-derived language bundle layout — image holds the flag-icon filename rendered in the language switcher, while directory names the bundle folder containing the language's PHP translation files (e.g. 'finnish', 'english').
Fields
| Field Name | Description |
|---|---|
image - String
|
Filename of the flag icon used in the language switcher, served from the tenant's flag-icon directory. |
directory - String
|
Name of the language-bundle directory (oscommerce-style i18n folder, e.g. 'finnish', 'english'). Used by the legacy admin to load the localized PHP translations. |
Example
{
"image": "abc123",
"directory": "xyz789"
}
Manufacturer
Description
A brand or manufacturer associated with one or more products in the catalog. Drives the storefront's brand index, the brand-filter facet on category pages, the per-brand landing page, and any brand-scoped pricing rules (special discounts applied at the brand level).
Carries three image slots for different rendering surfaces (hero, brand-page banner, listing thumbnail), per-brand commerce flags (status visibility, homepage feature, country-of-sale scope), and one ManufacturerInfo row per language for the localized body copy.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the manufacturer (manufacturers_id). |
name - String
|
Brand display name shown in navigation, breadcrumbs, and the brand-page header. |
code - String
|
Internal code or short identifier for the brand. Stable across languages — used by ERP / PIM mappings and for routing rules. |
image - String
|
Filename of the brand hero image (the large brand logo / hero shown on the brand landing page). Served from the tenant's manufacturer-image directory. |
brandPageImage - String
|
Filename of the brand-page banner image — wider hero / banner slot rendered above the product listing on the brand landing page. |
listingImage - String
|
Filename of the listing thumbnail used in search results, brand-grid tiles, and category-side brand chips. |
sortOrder - Int
|
Display sort order across the brand index. Lower values render first. |
status - Int
|
Visibility flag. 1 = brand is active and visible on the storefront; 0 = hidden (kept for editing without going live). |
dateAdded - String
|
Timestamp the brand record was created. |
lastModified - String
|
Timestamp of the most recent edit to the brand record. |
fitValue - String
|
Brand-specific size / fit hint shown on product detail pages (e.g. 'runs small', 'true to size'). Free-form short text. |
specialDiscount - Int
|
Brand-level percentage discount applied across the brand's products at checkout (a tinyint flag / value). 0 means no brand-level discount. |
cmsDescription - Int
|
Flag indicating the description is sourced from a CMS instead of the inline ManufacturerInfo body. 1 = use CMS, 0 = use inline. |
countryApprovedProduct - String
|
Comma-separated country codes where the brand is approved for sale. Empty / null means no country restriction. |
displayFrontpage - Int
|
Whether the brand is featured on the storefront homepage. 1 = featured (rendered in the homepage brand carousel / spotlight), 0 = not featured. |
infos - [ManufacturerInfo]
|
Localized description / click-tracking rows, one per language. |
Example
{
"id": "4",
"name": "abc123",
"code": "xyz789",
"image": "abc123",
"brandPageImage": "xyz789",
"listingImage": "abc123",
"sortOrder": 987,
"status": 987,
"dateAdded": "xyz789",
"lastModified": "xyz789",
"fitValue": "abc123",
"specialDiscount": 123,
"cmsDescription": 123,
"countryApprovedProduct": "abc123",
"displayFrontpage": 987,
"infos": [ManufacturerInfo]
}
ManufacturerInfo
Description
Localized text and click-tracking metadata for one Manufacturer, in one language. Carries the long brand body and the intro / preamble copy that render on the brand landing page, plus a counter of how many times the brand's external URL has been clicked from the storefront and the timestamp of the most recent click.
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for (resolves against the languages query). |
urlClicked - Int
|
Counter of clicks on the brand's external URL from the storefront. Used for brand-engagement reporting. |
dateLastClick - String
|
Timestamp of the most recent external-URL click. Null when the brand's URL has never been clicked. |
description - String
|
Long-form brand description body (rich text). Rendered below the intro on the brand landing page. |
descriptionTop - String
|
Intro / preamble copy rendered above the long description on the brand landing page (typically a one-paragraph teaser / SEO blurb). |
Example
{
"languageId": 987,
"urlClicked": 987,
"dateLastClick": "xyz789",
"description": "xyz789",
"descriptionTop": "xyz789"
}
Order
Description
A purchase placed by a customer — the central record in the order pipeline. Captures everything snapshotted at checkout time: who placed the order (customer / customerId / customerName / customerEmail), where it ships and bills (deliveryAddress / billingAddress), the chosen payment and shipping methods (paymentMethod / paymentCode / shippingMethod / shippingCode + their module-specific fields), the current status, the discount applied at the order level, and the fulfilment metadata that gets populated as the order moves through pick-and-pack and dispatch (deliveryQuantity / weight / dimensions, shippingLocation*, trackingCode / trackingLink).
Read-only on this type. To create an order use createOrder; to record status transitions use addOrdersStatusHistory; to add / edit / remove line items use the addOrdersProduct / updateOrdersProduct / removeOrdersProduct mutations. Line items hang off Order.items (mirroring the orderItems query); totals breakdown off Order.totals (mirroring orderTotals); coupons applied at checkout off Order.discountCoupons; and provider-specific payment notifications off Order.bankPayments / vivawalletPayments / netsNotifications depending on the payment module used.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the order (orders_id). |
customerId - Int
|
Id of the placing customer. Null for orders placed by a customer record that's since been deleted. |
customerName - String!
|
Display name of the placing customer at order time (typically firstname + lastname). Snapshotted so the order stays readable if the customer record is later renamed. |
customerEmail - String!
|
Email of the placing customer at order time. Snapshotted so transactional emails can still be re-sent even if the customer's account email later changes. |
customer - OrderParty
|
Customer-side party snapshot (the placing party). Same shape as deliveryAddress / billingAddress for symmetric rendering. |
deliveryAddress - OrderParty
|
Delivery (ship-to) party snapshot at order time. Drives the shipping label. |
billingAddress - OrderParty
|
Billing (invoice) party snapshot at order time. Drives the invoice header. |
status - Int!
|
Numeric status id. Common values across tenants:
Tenants may extend this set with custom statuses (e.g. payment-provider intermediate states, test orders). Always resolve dynamically via the orderStatuses query rather than hardcoding ids. |
datePurchased - String
|
ISO timestamp of when the order was placed. |
lastModified - String
|
ISO timestamp of the most recent edit to the order. Touched by status transitions, line edits, and totals recomputation. |
currency - String
|
ISO 4217 currency code the order was placed in. |
currencyValue - Float
|
Exchange rate (vs the tenant's primary currency) captured at order time. Used to convert the order's foreign-currency totals back into the primary currency for accounting reports. |
paymentMethod - String
|
Display label of the chosen payment method as shown to the shopper at checkout (e.g. 'Verkkopankki', 'Postiennakko - 4.90 EUR'). Localized — varies per tenant and language. |
paymentCode - String
|
Code identifying the payment module behind the order. Range seen in production includes module names ('NetsBank', 'Cod', 'NetsCreditcard'), Finnish identifiers ('Lasku', 'Nouto'), snake_case keys ('paylane_paypal'), and historical codes from modules since removed ('WalleyInvoice', 'PaylaneCard', 'BraintreeCard'). For new orders it must match the tenant's MODULE_PAYMENT_INSTALLED list; older orders may carry codes that are no longer in the active list. Use this for routing, reconciliation, and reports. |
shippingMethod - String
|
Display label of the chosen shipping method as shown to the shopper at checkout (e.g. 'Posti - Noutopiste'). Localized; may include a price suffix. |
shippingCode - String
|
Code identifying the shipping module behind the order. Range seen in production includes module-pair forms ('flat_flat', 'matkahuolto_matkahuolto'), bare module names ('Smartpost', 'Flat'), and historical codes. For new orders it must match the tenant's MODULE_SHIPPING_INSTALLED list. |
shippingCost - Float
|
Shipping cost charged on the order, in the order's currency. May be 0 when the order qualified for free shipping (via Customer.freeShipping threshold, a coupon, or a customer-group rule). |
deliveryQuantity - Int
|
Number of physical packages the order ships in (defaults to 1). |
deliveryWeight - Float
|
Total package weight in kilograms (decimal, 4-digit precision). |
deliveryLength - Float
|
Package length in centimetres. |
deliveryWidth - Float
|
Package width in centimetres. |
deliveryHeight - Float
|
Package height in centimetres. |
deliveryComments - String
|
Free-form delivery notes captured at checkout (e.g. 'leave at front door', 'call before arrival'). |
shippingLocationId - String
|
Pickup-point identifier when the chosen shipping method is a parcel locker / pickup-point service. Empty/0 for home delivery. |
shippingLocationName - String
|
Display name of the chosen pickup point (e.g. 'R-kioski Kamppi'). |
shippingLocationStreetAddress - String
|
|
shippingLocationPostcode - String
|
|
shippingLocationCity - String
|
|
paymentApiId - String
|
Internal id passed to the chosen payment module's API for reconciliation. |
paymentProvider - String
|
Payment provider key. Coarser grouping than paymentCode (e.g. 'nets', 'vivawallet'). |
paymentField - String
|
Free-form payment field captured at checkout (module-specific extra payload). |
paymentInput - String
|
Module-specific payment input payload as captured at checkout. |
paymentTermId - String
|
Payment-term identifier when the order uses an invoice with terms (e.g. '14 NETTO'). |
shippingApiId - String
|
Internal id passed to the chosen shipping module's API for label generation and tracking. |
shippingApiTermId - String
|
Term identifier within the shipping module (e.g. selected service tier). |
shippingCostCentreId - String
|
Cost-centre id used for accounting allocation of shipping costs. |
shippingContractId - String
|
Carrier-contract identifier used to negotiate shipping rates. |
shippingContractCourier - String
|
Carrier name on the contract (Posti, DHL, Schenker, etc.). |
warehouseCode - String
|
Warehouse code identifying which warehouse the order ships from when the tenant runs multi-warehouse fulfilment. Resolves against the warehouses query. |
discountType - String
|
How discountAmount is applied at the order level. Same enum as on coupons and customer groups: 'fixed', 'percent', or 'shipping'. Defaults to 'fixed'. |
discountAmount - Float
|
Order-level discount value, interpreted according to discountType. |
trackingCode - String
|
Carrier tracking code. Populated once the order has been shipped. |
trackingLink - String
|
Full tracking URL the customer can click to follow the parcel. May embed the tracking code in the path. |
customerNotifiedFlag - Int
|
True (1) once the order-confirmation email has been queued/sent to the customer; 0 means not sent. |
trollyLocker - Float
|
Trolley-locker workflow flag (warehouse pick-and-pack staging). 0 = not picked, non-zero = picked / staged. DECIMAL(2,1) in the DB. |
transactionId - String
|
Payment-provider transaction id (the id the bank/PSP returned). Used for reconciliation against statements. |
ipAddress - String
|
IP address the order was placed from (used for fraud / risk scoring). |
ipIsp - String
|
ISP or geo-org of the placing IP (when resolved). |
pdfFiles - String
|
Newline-separated list of attached PDF filenames (invoice, packing slip, return label, etc.) stored in the tenant's order-document directory. |
returnReason - String
|
Customer-supplied reason text when the order was returned. Null when the order was not returned. |
referralId - String
|
Marketing / referral attribution token captured at checkout (UTM tag, click id, etc.). |
ordersApiId - String
|
External ERP / marketplace order id, when this order originated from or was synced to an external system. |
apiSent - Int
|
Outbound-API send status: 0 = not yet exported to the ERP, 1 = exported successfully, larger values are tenant-specific intermediate states. |
emailSent - Int
|
Order-creation push-status flag: 1 = order-confirmation email has been emitted; 0 = not yet. |
apiMessage - String
|
Last error / status message from the ERP push (null on success). |
apiMessageDate - String
|
ISO timestamp of the apiMessage. |
apiOrderStatusMessage - String
|
Last error / status message from the ERP order-status push. |
apiOrderStatusMessageDate - String
|
ISO timestamp of the apiOrderStatusMessage. |
ordersPackingRulesJson - String
|
Resolved packing rules (JSON-encoded) applied when the order was picked. Null when no per-order packing rules were attached. |
discountCoupons - [DiscountCoupon]
|
Coupons that were applied to this order at checkout. Empty when no coupon was used. Resolves via the discount_coupons_to_orders join table. |
items - [OrderItem!]!
|
All purchased lines on this order, including their selected variants. Equivalent to the orderItems query but resolves in the same round-trip when you're already fetching the Order. |
totals - [OrderTotal!]!
|
Totals breakdown for this order, optionally filtered to one class. Equivalent to the orderTotals query but resolves in the same round-trip. |
Arguments
|
|
bankPayments - [BankPayment!]!
|
Bank-transfer settlements applied to this order. Empty when the order was paid by another method (card, wallet) or hasn't been paid yet. |
vivawalletPayments - [OrderVivawalletPayment!]!
|
Vivawallet payment records linked to this order. Empty for orders paid via other providers (Nets, Cod, invoice). |
Example
{
"id": 4,
"customerId": 123,
"customerName": "xyz789",
"customerEmail": "xyz789",
"customer": OrderParty,
"deliveryAddress": OrderParty,
"billingAddress": OrderParty,
"status": 987,
"datePurchased": "abc123",
"lastModified": "xyz789",
"currency": "xyz789",
"currencyValue": 987.65,
"paymentMethod": "xyz789",
"paymentCode": "abc123",
"shippingMethod": "abc123",
"shippingCode": "xyz789",
"shippingCost": 123.45,
"deliveryQuantity": 123,
"deliveryWeight": 987.65,
"deliveryLength": 987.65,
"deliveryWidth": 123.45,
"deliveryHeight": 987.65,
"deliveryComments": "abc123",
"shippingLocationId": "xyz789",
"shippingLocationName": "xyz789",
"shippingLocationStreetAddress": "xyz789",
"shippingLocationPostcode": "xyz789",
"shippingLocationCity": "abc123",
"paymentApiId": "abc123",
"paymentProvider": "abc123",
"paymentField": "abc123",
"paymentInput": "xyz789",
"paymentTermId": "abc123",
"shippingApiId": "xyz789",
"shippingApiTermId": "xyz789",
"shippingCostCentreId": "xyz789",
"shippingContractId": "xyz789",
"shippingContractCourier": "abc123",
"warehouseCode": "abc123",
"discountType": "xyz789",
"discountAmount": 987.65,
"trackingCode": "abc123",
"trackingLink": "abc123",
"customerNotifiedFlag": 987,
"trollyLocker": 123.45,
"transactionId": "abc123",
"ipAddress": "xyz789",
"ipIsp": "abc123",
"pdfFiles": "abc123",
"returnReason": "abc123",
"referralId": "abc123",
"ordersApiId": "xyz789",
"apiSent": 987,
"emailSent": 123,
"apiMessage": "abc123",
"apiMessageDate": "xyz789",
"apiOrderStatusMessage": "abc123",
"apiOrderStatusMessageDate": "abc123",
"ordersPackingRulesJson": "abc123",
"discountCoupons": [DiscountCoupon],
"items": [OrderItem],
"totals": [OrderTotal],
"bankPayments": [BankPayment],
"vivawalletPayments": [OrderVivawalletPayment]
}
OrderHistoryEntry
Description
An audit-log entry recording a single change to an order or one of its child rows (line items, totals, status history, notifications). Captured automatically by the admin panel and selected automation flows whenever order data is modified after the order is placed — typically a staff edit, a refund, or a re-trigger.
Use this for compliance audits, order-detail change logs, and the "history" view on the admin order page. The log is append-only at the application layer; combined with orderStatusHistory (status transitions only), it provides the complete order-modification trail.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the audit entry. |
orderId - Int!
|
Order whose row was changed. |
entityType - String!
|
Source table the change happened in. Example values seen in production:
|
entityId - Int
|
Row id within the entity table when the change targets a specific row (line id, totals row id, etc.). Null for header-level changes on orders itself. |
columnName - String!
|
Database column name that changed (e.g. 'orders_status', 'products_quantity', 'shipping_method'). |
oldValue - String
|
Previous value as stored in the column, serialized to string. Null when the row was newly created or the field was previously null. |
newValue - String
|
New value as stored in the column, serialized to string. Null when the field was cleared. |
actionType - String!
|
Kind of change. Example values seen in production:
|
userId - Int
|
Administrator user id who made the change. Null for automated / system-triggered changes. |
userName - String
|
Administrator user name (denormalised at write time for stability). |
page - String
|
Admin panel route the change was made from (helps trace whether it came from a list page, detail page, or bulk action). |
createdAt - String!
|
ISO timestamp of when the change was recorded. |
Example
{
"id": "4",
"orderId": 987,
"entityType": "abc123",
"entityId": 123,
"columnName": "abc123",
"oldValue": "abc123",
"newValue": "xyz789",
"actionType": "xyz789",
"userId": 123,
"userName": "xyz789",
"page": "abc123",
"createdAt": "abc123"
}
OrderItem
Description
A purchased line on an order — the snapshot of one product (or shipping / fee / comment line) as it appeared in the cart at the moment of checkout. Includes the per-line price, tax, configurable variant selections, and warehouse pick-and-pack state that gets populated as the order moves through fulfilment.
Read-only on this type. To modify lines on an existing order use the addOrdersProduct / updateOrdersProduct / removeOrdersProduct mutations, which write to the same underlying orders_products row but expose a write-shaped contract via the OrdersProduct type.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the order line (orders_products_id). |
orderId - Int!
|
Order this line belongs to. |
productId - Int
|
Product id from the catalog. Null for lines that don't reference a catalog product (free-form refund / fee lines). |
productModel - String
|
Product SKU / model identifier captured at order time. |
productEan - String
|
EAN / barcode captured at order time. |
productName - String!
|
Display name shown on the receipt and admin order detail. |
quantity - Int!
|
Quantity ordered. |
quantityReturned - Int!
|
Quantity already returned (for refunds / partial returns). 0 on a fresh order. |
price - Float!
|
Unit price actually charged, in the order's currency. |
originalPrice - Float!
|
Catalog price at the time of order (before any per-customer or coupon adjustments). Useful for computing realised discount per line. |
tax - Float!
|
Tax rate applied to this line as a percentage (e.g. 24.0 = 24% VAT). |
stockVariants - String
|
Comma- or JSON-encoded snapshot of the variant stock-id selection (e.g. for size/colour SKUs). |
lineType - String
|
Line type. Example values seen in production:
Tenants may extend with custom types ('shipping', 'fee', 'comment'). |
comment - String
|
Free-form comment captured at checkout (gift message, configuration notes, etc.). |
customOptions - JSON
|
Module-specific custom-options payload (JSON-encoded). Set when the product has configurable options the shopper filled out at checkout. |
productCategories - String
|
Snapshot of the product's category memberships at order time (comma-separated category ids). |
productWeight - Float
|
Per-line product weight in kilograms (used for shipping calculation when line-level weights matter). |
productLocation - String
|
Per-line warehouse location code captured at order time (e.g. shelf identifier). |
variableImage - String
|
Filename of a per-line custom image uploaded by the shopper (for personalised / printed products). Null when the line carries no custom image. |
allowSubstitute - Int!
|
True (1) if the customer accepted product substitution for this line: warehouse may ship a similar product when the requested variant is unavailable. 0 = strict matching. |
confirmFlag - Int!
|
True (1) if a confirmation step was applied to this line during pick-and-pack (warehouse confirmed the SKU + quantity). 0 = unconfirmed. |
confirmProductsQuantity - Int!
|
Confirmed quantity captured during pick-and-pack. May differ from the ordered quantity when shortages or substitutions occurred. |
autoComment - Int!
|
True (1) if the line was added by an automatic process (auto-bundle expansion, accessory rule, etc.) rather than by the shopper. 0 = manually added. |
variants - [OrderItemVariant!]!
|
Configurable variants selected on this line. Empty array for products without options or when the order line is a fee / refund / comment row. |
Example
{
"id": 4,
"orderId": 987,
"productId": 123,
"productModel": "abc123",
"productEan": "xyz789",
"productName": "abc123",
"quantity": 123,
"quantityReturned": 987,
"price": 123.45,
"originalPrice": 987.65,
"tax": 123.45,
"stockVariants": "abc123",
"lineType": "abc123",
"comment": "abc123",
"customOptions": {},
"productCategories": "abc123",
"productWeight": 987.65,
"productLocation": "abc123",
"variableImage": "abc123",
"allowSubstitute": 123,
"confirmFlag": 123,
"confirmProductsQuantity": 123,
"autoComment": 123,
"variants": [OrderItemVariant]
}
OrderItemVariant
Description
A configurable-product option selected on one order line — for example a size/colour pair on a t-shirt, or a personalisation field on a gift. Variants stack: a single OrderItem can carry many OrderItemVariants, each contributing an additive or replacement price delta to the line total via pricePrefix. Captured as a snapshot at order time, so later changes to the underlying product option definition do not retroactively rewrite already-placed orders.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the variant selection. |
orderProductId - Int!
|
Order line (OrderItem) this variant selection belongs to. |
optionId - Int!
|
Product option id (matches a row in the catalog options table). |
optionName - String!
|
Display label of the option as shown to the shopper at checkout (e.g. 'Size', 'Engraving'). |
optionValue - String!
|
Selected value as shown to the shopper (e.g. 'XL', 'Happy Birthday Anna'). |
price - Float!
|
Price delta this variant contributes to the line, interpreted via pricePrefix. |
pricePrefix - String
|
How the price delta is applied to the line:
Tenants may define additional prefixes; treat unrecognised values as additive by default. |
Example
{
"id": 4,
"orderProductId": 987,
"optionId": 987,
"optionName": "abc123",
"optionValue": "abc123",
"price": 987.65,
"pricePrefix": "xyz789"
}
OrderNetsNotification
Description
A payment notification from the Nets payment service for one order. Captured by the storefront's webhook handler (or the admin's manual reconcile flow) for every callback Nets sends — authorization callbacks, settlement notifications, refunds, and error events.
The table is keyed by ordersPaytrailId (a Nets-provided session id that pre-dates the rename from Paytrail to Nets), with notificationId distinguishing successive callbacks for the same session. Use this type for reconciliation against Nets settlement reports and for diagnosing failed payments. Available only on tenants whose payment integration is Nets; other tenants will not have rows for these fields.
Fields
| Field Name | Description |
|---|---|
ordersPaytrailId - Int!
|
Nets-side session/order id (legacy 'paytrail' name retained for backwards compatibility). Primary key on the orders_nets table. |
customersId - Int!
|
Customer the originating order belongs to (denormalised from orders.customers_id). |
notificationId - Int!
|
Sequence number distinguishing successive notifications for the same ordersPaytrailId (e.g. 1 = authorization, 2 = settlement, 3 = refund). |
sessionId - String
|
Browser session id captured at checkout. Useful for correlating with storefront analytics. |
transactionId - String
|
Nets transaction id returned by the provider. Used for reconciliation against Nets reports. |
stamp - String
|
Provider-side stamp/timestamp value captured from the webhook payload. |
reference - String
|
Provider-side reference token (Nets-supplied) for this notification, used for reconciliation against settlement reports. |
amount - Float
|
Amount this notification covers, in the smallest currency unit (e.g. cents). May be the full order amount, a partial refund, or zero for status-only callbacks. |
error - String
|
Error code or message from the provider when this notification represents a failed event. Null for successful events. |
Example
{
"ordersPaytrailId": 987,
"customersId": 123,
"notificationId": 987,
"sessionId": "xyz789",
"transactionId": "xyz789",
"stamp": "abc123",
"reference": "xyz789",
"amount": 123.45,
"error": "abc123"
}
OrderParty
Description
A party on an order — the customer, delivery recipient, or billing entity. Captured as a snapshot at the moment of purchase: later edits to the customer's saved AddressBook / BillingAddress entries do not retroactively change finalised orders. Each Order has three of these (customer / deliveryAddress / billingAddress) so the same base shape carries the placing-customer info, where to ship, and where to invoice.
Fields
| Field Name | Description |
|---|---|
name - String!
|
Recipient name (formatted firstname + lastname or the company contact name) at order time. |
company - String
|
Company name on the party. Set for B2B parties; null on personal-shopper deliveries. |
vatId - String
|
VAT / business id on the party. Captured for B2B documents. |
streetAddress - String!
|
Street address line at order time. |
city - String!
|
City at order time. |
postcode - String!
|
Postal code at order time. |
state - String
|
State / region at order time. Used in countries that need it (US, AU, etc.). |
country - String!
|
Country name (resolved from the country id at order time and snapshotted as a string). |
telephone - String
|
Telephone number at order time. |
emailAddress - String
|
Email address at order time. May differ from the placing customer's current email if they update their account later. |
addressFormatId - Int
|
AddressFormat id at order time — drives the rendering template used for shipping labels and invoice addresses (resolves against the addressFormats query). |
invoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI). Set for parties using e-invoice routing; null for paper / email invoicing. |
operatorId - Int
|
E-invoice operator id (Finnish Verkkolasku operator). Paired with invoiceAddress for e-invoice delivery. |
reference - String
|
Free-form invoice reference / PO number captured at checkout. |
Example
{
"name": "abc123",
"company": "xyz789",
"vatId": "abc123",
"streetAddress": "xyz789",
"city": "xyz789",
"postcode": "abc123",
"state": "abc123",
"country": "abc123",
"telephone": "abc123",
"emailAddress": "xyz789",
"addressFormatId": 987,
"invoiceAddress": "xyz789",
"operatorId": 123,
"reference": "abc123"
}
OrderPartyInput
Description
Input for one party (customer / delivery / billing) when creating an order. Either passed in full to capture a fresh address snapshot, or omitted in favour of the deliveryAddressId / billingAddressId pointers on CreateOrderInput which load the saved AddressBook entry.
Fields
| Input Field | Description |
|---|---|
name - String
|
Recipient name (firstname + lastname or company contact). |
company - String
|
Company name. Set for B2B parties. |
vatId - String
|
VAT / business id. |
streetAddress - String
|
Street address line. |
city - String
|
City. |
postcode - String
|
Postal code. |
state - String
|
State / region. |
countryId - Int
|
Country id (resolves against the countries query). |
countryCode - String
|
Two-letter country code, alternative to countryId. The resolver normalises this to a country id. |
telephone - String
|
Telephone number. |
emailAddress - String
|
Email address. |
addressFormatId - Int
|
AddressFormat id used for rendering. Resolves against addressFormats. |
invoiceAddress - String
|
E-invoice address (Finnish OVT-tunnus / EDI). |
operatorId - Int
|
E-invoice operator id (Finnish Verkkolasku operator). |
reference - String
|
Free-form invoice reference / PO number. |
Example
{
"name": "xyz789",
"company": "abc123",
"vatId": "abc123",
"streetAddress": "abc123",
"city": "xyz789",
"postcode": "xyz789",
"state": "xyz789",
"countryId": 987,
"countryCode": "xyz789",
"telephone": "xyz789",
"emailAddress": "xyz789",
"addressFormatId": 123,
"invoiceAddress": "xyz789",
"operatorId": 123,
"reference": "xyz789"
}
OrderStatus
Description
A status label for orders, defined per tenant and per language. Returned in one row per (id, languageId) pair so storefronts and admin panels can render the status in the operator's chosen language.
Tenants typically share a common core set of ids (1=Received, 2=Packing, 3=Shipped, etc. — see Order.status for the cross-tenant default list) and add custom statuses on top for payment-provider intermediate states or workflow-specific stages. Always resolve Order.status via this query rather than hardcoding ids.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Stable numeric status id, used in Order.status and OrderStatusHistory.statusId. |
languageId - Int!
|
Language the localized name is in (1=English, 5=Swedish, 6=Finnish, 9=Spanish, 14=Italian; tenants may extend). |
code - String
|
Internal code for the status (e.g. 'received', 'shipped', 'awaiting_payment'). Null for legacy entries that pre-date the code column. |
name - String!
|
Localized display label shown to operators and (for some tenants) to customers in transactional emails. |
apiFlag - Int!
|
If non-zero, this status triggers ERP / order-management API push when set on an order. 0 = local-only status. |
apiId - String
|
External-system identifier when the status is mirrored in an ERP (Lemonsoft / Netvisor / Tehden status code). |
colorCode - String
|
Hex color (without leading #) used to tint the status badge in admin UI. Null = default neutral color. |
Example
{
"id": 4,
"languageId": 987,
"code": "xyz789",
"name": "abc123",
"apiFlag": 987,
"apiId": "xyz789",
"colorCode": "abc123"
}
OrderStatusHistory
Description
A status-transition entry on an order's timeline — one row per status change captured as the order progresses (Received → Packing → Shipped → Delivered, plus any backwards transitions for cancellations or returns). Each row records the new status id, an optional staff comment, and whether the customer was notified.
Read-only on this type. To record a new transition (and optionally emit a notification to the customer) use the addOrdersStatusHistory mutation, which writes to the same underlying table.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the status-transition entry. |
orderId - Int!
|
Order this status transition belongs to. |
statusId - Int!
|
Numeric status id moved to. Resolve to a localized name via the orderStatuses query. |
statusName - String
|
Localized status name as it was at the time of the transition (denormalised for stability when status names are later renamed). |
dateAdded - String!
|
ISO timestamp of when the transition was recorded. |
customerNotified - Int
|
Whether a notification email was sent to the customer for this transition. Example values:
|
comments - String
|
Free-form staff comment attached to the transition (e.g. 'Awaiting carrier pickup', 'Refunded — damaged on arrival'). |
Example
{
"id": "4",
"orderId": 987,
"statusId": 987,
"statusName": "abc123",
"dateAdded": "xyz789",
"customerNotified": 987,
"comments": "xyz789"
}
OrderTotal
Description
A single line on the order's totals breakdown — the rendered "totals block" at the bottom of an invoice or order detail (Subtotal, Tax, Shipping, Coupon discount, Grand total). Each row represents one contribution to the final order amount, sorted by sortOrder, and carries the formatted display text the storefront / receipt renders verbatim.
Mutations don't write to OrderTotal directly: totals are recomputed by the order pipeline whenever the underlying lines or coupons change. Use this type for read-only reporting and rendering.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the totals entry (orders_total_id). |
orderId - Int!
|
Order this totals row belongs to. |
title - String!
|
Display label shown next to the value (e.g. 'Subtotal', 'Tax 24%', 'Shipping'). |
text - String!
|
Pre-formatted display value rendered next to the title (e.g. '€ 49.90', 'Free'). Includes currency symbol and locale formatting. |
value - Float!
|
Numeric amount in the order's currency. Sum of all rows of class 'Total' equals the order's final amount. |
valueUnreturned - Float!
|
Numeric amount excluding any returned/refunded portion. Equals value when the order has not been partially returned. |
taxRate - Float
|
Tax rate (percentage) applied to compute taxAmount, when this row represents a taxed total. Null for tax-free totals (e.g. shipping discounts). |
taxAmount - Float
|
Tax portion of value, in the order's currency. Null when the row is itself a tax line. |
class - String!
|
Total category. Example values seen in production:
Tenants may extend with additional 'ot_*' modules. |
sortOrder - Int!
|
Display sort order. Lower values render first; the totals block typically goes Subtotal → Tax → Shipping → Discount → Total. |
Example
{
"id": "4",
"orderId": 987,
"title": "xyz789",
"text": "abc123",
"value": 123.45,
"valueUnreturned": 123.45,
"taxRate": 987.65,
"taxAmount": 987.65,
"class": "abc123",
"sortOrder": 987
}
OrderVivawalletPayment
Description
A payment record from the Viva Wallet (Vivawallet) payment service for one order. Captured when the shopper completes payment through any of the Vivawallet-hosted methods (cards, Klarna, PayPal, Apple Pay, Google Pay) and returned for reconciliation against Vivawallet's merchant reports.
Available only on tenants whose payment integration is Vivawallet. The paymentMethod string indicates which Vivawallet sub-method was used; transactionUuid is the cross-system identifier for chargeback and refund flows.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the payment record. |
orderId - Int!
|
Order this payment belongs to. |
customerId - Int!
|
Customer who placed the order (denormalised from orders.customers_id). |
paymentMethod - String!
|
Which Vivawallet sub-method was used. Example values seen in production:
Both CamelCase and snake_case variants appear in production — historical drift across module versions. Treat them as equivalent when matching by sub-method. |
notificationId - Int!
|
Sequence number distinguishing successive notifications for the same order (1 = initial, higher = retries / refunds). |
orderCode - String
|
Vivawallet 'orderCode' identifying the payment session at the provider. Used for cross-referencing with Vivawallet's merchant portal. |
transactionUuid - String
|
Vivawallet transaction UUID. Stable cross-system identifier — use this for chargeback handling and refund APIs. |
sessionId - String
|
Browser session id captured at checkout. Useful for correlating with storefront analytics. |
Example
{
"id": 4,
"orderId": 123,
"customerId": 987,
"paymentMethod": "abc123",
"notificationId": 987,
"orderCode": "xyz789",
"transactionUuid": "xyz789",
"sessionId": "abc123"
}
OrdersNetsNotificationInput
Description
Input shape for upsertOrdersNetsNotification — every field that Nets supplies on a callback can be persisted here.
Fields
| Input Field | Description |
|---|---|
ordersPaytrailId - Int!
|
Nets-side session/order id (primary key). |
customersId - Int!
|
Customer the originating order belongs to. |
notificationId - Int!
|
Sequence number for successive notifications on the same session. |
sessionId - String
|
Browser session id captured at checkout. |
transactionId - String
|
Nets transaction id returned by the provider. |
stamp - String
|
Provider-side stamp value from the webhook. |
reference - String
|
Provider-side reference token captured from the Nets webhook payload. |
amount - Float
|
Amount in the smallest currency unit. |
error - String
|
Error code/message; pass null on successful events. |
Example
{
"ordersPaytrailId": 123,
"customersId": 987,
"notificationId": 123,
"sessionId": "xyz789",
"transactionId": "xyz789",
"stamp": "xyz789",
"reference": "abc123",
"amount": 987.65,
"error": "xyz789"
}
OrdersProduct
Description
Write-shaped representation of an order line, returned by the addOrdersProduct / updateOrdersProduct mutations. Maps to the same underlying orders_products row that OrderItem reads from, but excludes the nested variants list (manage variants separately via the addOrdersProductsVariant / updateOrdersProductsVariant / removeOrdersProductsVariant mutations).
Use OrderItem for read flows; use OrdersProduct + the matching mutations when modifying lines on an already-placed order from the admin panel or an integration.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the line (orders_products_id). |
orderId - Int!
|
Order this line belongs to. |
productId - Int
|
Catalog product id this line references. Null for free-form lines. |
productModel - String
|
Product SKU / model identifier captured at order time. Snapshotted from products.products_model so the order stays stable when the catalog is later edited. |
productEan - String
|
EAN / barcode captured at order time. |
productName - String!
|
Display name shown on the receipt and admin order detail. Snapshotted at order time. |
price - Float!
|
Unit price actually charged, in the order's currency. |
originalPrice - Float!
|
Catalog price at the time of order, before per-customer or coupon adjustments. |
tax - Float!
|
Tax rate applied to this line as a percentage (e.g. 24.0 = 24% VAT). |
quantity - Int!
|
Quantity ordered on this line. |
quantityReturned - Int!
|
Quantity already returned. 0 on a fresh line. |
stockVariants - String
|
Comma- or JSON-encoded snapshot of the variant stock-id selection. |
lineType - String
|
Line type. Example values: 'item' (default), 'refund'. |
comment - String!
|
Free-form comment captured at checkout (gift message, configuration notes). |
customOptions - JSON
|
Module-specific custom-options payload (JSON-encoded) for configurable products. |
Example
{
"id": "4",
"orderId": 123,
"productId": 123,
"productModel": "abc123",
"productEan": "abc123",
"productName": "xyz789",
"price": 123.45,
"originalPrice": 123.45,
"tax": 987.65,
"quantity": 123,
"quantityReturned": 987,
"stockVariants": "abc123",
"lineType": "abc123",
"comment": "abc123",
"customOptions": {}
}
OrdersProductsVariant
Description
A configurable-product option selected on an order line, returned by the addOrdersProductsVariant / updateOrdersProductsVariant mutations. Stored on a separate table (orders_products_variants) from the line itself so a single line can carry many variant selections.
Read-side: this same data is exposed through OrderItem.variants on the read query path. Use the mutations here when you need to add, modify, or remove option selections on an already-placed order from the admin panel or an integration.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the variant selection. |
orderId - Int!
|
Order the variant belongs to (denormalised for filtering). |
orderProductId - Int!
|
Order line (OrderItem / OrdersProduct) this variant selection belongs to. |
optionId - Int!
|
Product option id (matches a row in the catalog options table). |
optionName - String!
|
Display label of the option as shown to the shopper at checkout (e.g. 'Size', 'Engraving'). |
optionValue - String!
|
Selected value as shown to the shopper (e.g. 'XL', 'Happy Birthday Anna'). |
price - Float!
|
Price delta this variant contributes to the line, interpreted via pricePrefix. |
pricePrefix - String
|
How the price delta is applied. Example values:
|
Example
{
"id": 4,
"orderId": 123,
"orderProductId": 123,
"optionId": 123,
"optionName": "xyz789",
"optionValue": "xyz789",
"price": 987.65,
"pricePrefix": "abc123"
}
OrdersStatusHistoryEntry
Description
Write-side representation of a status-transition entry, returned by the addOrdersStatusHistory mutation. Maps to the same underlying orders_status_history row that OrderStatusHistory reads from, with a trimmed shape (no statusName lookup — the read query enriches it).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the inserted transition. |
orderId - Int!
|
Order the transition belongs to. |
statusId - Int!
|
Numeric status id moved to. |
dateAdded - String!
|
ISO timestamp of when the transition was recorded. |
customerNotified - Int
|
Whether a customer notification email was emitted for this transition (0 = not notified, 1 = notified). |
comments - String
|
Staff comment attached to the transition. |
Example
{
"id": "4",
"orderId": 123,
"statusId": 987,
"dateAdded": "xyz789",
"customerNotified": 123,
"comments": "xyz789"
}
OrdersStatusHistoryInput
Description
Input shape for addOrdersStatusHistory. orderId + statusId are required; the optional flags control side effects (customer notification and order-header status update).
Fields
| Input Field | Description |
|---|---|
orderId - Int!
|
Order to record the transition on. |
statusId - Int!
|
New status id (must exist in orderStatuses for the connected tenant). |
comments - String
|
Free-form staff comment to attach to the transition. |
notifyCustomer - Boolean
|
If true, send a notification email to the customer about this status change. Default: false. |
updateOrderStatus - Boolean
|
If true, also update the order header's current status (orders.orders_status) to this statusId. If false, the transition is recorded for audit but the order's current status is unchanged. Default: true. |
Example
{
"orderId": 987,
"statusId": 123,
"comments": "abc123",
"notifyCustomer": false,
"updateOrderStatus": true
}
Product
Description
A product available for sale in the catalog. This type is intentionally thin — it carries the headline fields used to render product cards and the basic detail header (id, name, model, image, price, descriptions, material). Richer product surfaces hang off other queries:
- Configurable options + values: productAttributes
- Variant-level stock + per-variant pricing: productStock
- Per-warehouse stock split: warehouseStock
- Price history: productPriceHistory
- Group-based price overrides: customerGroupPriceList
- Per-customer pricing: customerPrice
- Volume / step pricing: productVolumeAddonPrices, productVolumeDiscounts
- Image gallery (variant-aware): productExtraImages
- PDFs / CAD / lighting profiles / non-image media: productsMedia
- Category memberships: productsToCategories
- Per-product custom-option overrides: productsCustomOptions
The Product.description and shortDescription fields come from a per-language products_description row picked by the languageId argument on the product query. The products listing query returns rows in the tenant's primary language only.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the product (products_id). Used as the productId in every related product surface listed above. |
name - String!
|
Display name shown to shoppers — falls back to the product model when the localized name is empty. |
model - String
|
Manufacturer / vendor SKU or model identifier. Stable across languages and used as the join key into ERP / PIM systems. |
image - String
|
Filename of the main product image, served from the tenant's product-image directory. For the variant-aware image gallery use productExtraImages; for non-image media use productsMedia. |
price - Float!
|
Catalog base price in the tenant's default currency, exclusive of VAT. Per-customer / per-group / volume-tier prices may override this at checkout — see customerPrice / customerGroupPriceList / productVolumeAddonPrices. |
description - String
|
Long-form HTML description rendered on the product detail page. Comes from products_description for the requested languageId. |
shortDescription - String
|
Plain-text short-description used in product cards, listings, and meta descriptions. Comes from products_description for the requested languageId. |
material - String
|
Material / composition string (e.g. 'cotton 80%, polyester 20%'). Comes from products_description for the requested languageId; null when the tenant doesn't capture material per product. |
Example
{
"id": "4",
"name": "xyz789",
"model": "abc123",
"image": "abc123",
"price": 123.45,
"description": "abc123",
"shortDescription": "abc123",
"material": "abc123"
}
ProductCategoryLink
Description
A many-to-many link row tying one product to one category. The catalog navigation, breadcrumbs, and category landing pages all rely on this pivot table — a product lives in multiple categories at once (a lamp can be in 'Living room', 'Floor lamps', and 'Sale'), and each category lists every product linked to it.
This is a thin pivot — id-only — but the resolver hydrates the related Product and Category objects when included in the selection set, so the caller can fetch link rows + their endpoints in a single round-trip.
Example
{
"productId": 4,
"categoryId": "4",
"product": Product,
"category": Category
}
ProductCustomOption
Description
A product-specific override of a shared ProductOption. Where ProductOption defines the option globally (with its values, sort, and labels), ProductCustomOption attaches that option to one product and lets the tenant tweak per-product behaviour: whether it's required at checkout, the display position relative to other options on this product, and the input rendering type (radio / select / checkbox / textarea / etc.).
This table is currently empty across production tenants — mutations are wired but no rows exist yet. The parent products_options system (rendered via productAttributes) carries the live configuration today; expect this surface to gain rows as tenants migrate to per-product option overrides.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the product-custom-option link (products_custom_options_id). |
productId - Int!
|
Product this option override applies to. |
productsOptionsId - Int!
|
Id of the parent ProductOption (products_options) being overridden. |
required - Boolean!
|
Whether the shopper must pick a value for this option before adding the product to the basket. |
position - Int!
|
Display position of this option within the product's option list. Lower values render first. |
type - String!
|
Input rendering type for this option on this product. Defaults to 'radio'. Example values (from the oscommerce-derived custom-options model used by aicc-admin/pub/custom_options.php):
|
Example
{
"id": 4,
"productId": 123,
"productsOptionsId": 123,
"required": true,
"position": 987,
"type": "xyz789"
}
ProductExtraImage
Description
An additional image attached to a product, beyond the main image stored on the Product type. Used to render the gallery / carousel on product detail pages: alternate angles, in-use shots, packaging, lifestyle photography.
Optionally variant-specific via optionId — e.g. a colour variant can have its own gallery, so the storefront swaps images when the shopper picks a different colour. For non-image attachments (PDFs, CAD files, videos) see productsMedia, which is a broader media-attachment surface with an explicit type and category.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the extra-image entry (products_extra_image_id). |
code - String
|
Free-form code captured at upload time, used by tenants for sorting / matching against ERP image references. Null when the tenant doesn't use codes. |
url - String
|
Filename or relative URL of the image, served from the tenant's product-image directory. |
sort - Int
|
Display sort order within the product's gallery. Lower values render first. |
optionId - Int
|
Variant option-value id this image is tied to (matches a row in products_options_values). When set, the storefront shows this image only when the shopper has that variant selected. 0 = applies to all variants. |
description - String
|
Localized caption / alt text for the image. |
Example
{
"id": 4,
"code": "xyz789",
"url": "xyz789",
"sort": 123,
"optionId": 123,
"description": "xyz789"
}
ProductMedia
Description
A media attachment on a product — PDF datasheets, CAD files, lighting profiles, additional documents, video links, anything beyond the main image and gallery. Each file has a type indicating its format and an optional category for storefront grouping.
For image-specific gallery shots tied to product detail pages or variants, prefer productExtraImages — it has variant-awareness via optionId. ProductMedia is the broader catch-all surface used by the storefront's "Documents & downloads" section and by the Akeneo / PIM sync pipelines (see ProductMediaSyncer.php).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the media entry (products_media_id). |
productId - ID
|
Product this media belongs to. |
categoryId - Int
|
Id of the parent ProductMediaCategory, or null for uncategorised media. |
file - String
|
Filename of the attachment, served from the tenant's product-media directory. |
sortOrder - Int
|
Display sort order within the parent category. |
type - String
|
File-type label. Production has both CamelCase and lowercase variants (historical drift). Example values seen across tenants:
The full whitelist (with file-extension prefixes) lives in ProductMediaSyncer.php in aicc-mvc. |
size - String
|
Human-readable size label (e.g. '2.4 MB'). Pre-formatted at upload time. |
description - String
|
Localized description / caption shown alongside the file in the storefront. |
category - ProductMediaCategory
|
Resolved parent category, included when includeCategory=true on the query. |
Example
{
"id": "4",
"productId": "4",
"categoryId": 987,
"file": "xyz789",
"sortOrder": 123,
"type": "abc123",
"size": "xyz789",
"description": "abc123",
"category": ProductMediaCategory
}
ProductMediaCategory
Description
A grouping label for product media files — for example 'manuals', 'datasheets', 'IES', 'PDF'. Tenants define their own categories; there's no global enum. Categories show up as section headers when the storefront renders the product attachments block.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the category. |
code - String
|
Tenant-defined free-form code (e.g. 'manuals', 'IES', 'responsibility'). Used internally for grouping and ERP matching. |
sortOrder - Int
|
Display sort order of the category itself within the product's media block. |
name - String
|
Localized human-readable category name shown to shoppers. |
Example
{
"id": 4,
"code": "abc123",
"sortOrder": 123,
"name": "abc123"
}
ProductOption
Description
A configurable option attached to a product — for example "Size" with values XL/L/M/S, "Engraving" with a free-text value, or "Material" with a price- affecting choice. ProductOption represents the option itself; the ProductOptionValue list holds the choices the shopper can pick.
Options drive the variant selector on product detail pages and seed OrderItemVariant rows when the shopper checks out. The same configurable- option model also feeds quotes (QuoteProduct.variant) and per-line customisations on saved baskets.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the option (products_options_id). |
name - String
|
Localized display label of the option (e.g. 'Size', 'Material', 'Engraving'). |
code - String
|
Internal code for the option, stable across languages — useful for routing rules and ERP mappings. |
description - String
|
Localized helper text shown beneath the option in the product page UI. |
sort - Int
|
Display sort order. Lower values render first in the variant selector. |
values - [ProductOptionValue]
|
The selectable values for this option. Empty for free-form options where the shopper types a value at checkout. |
Example
{
"id": 4,
"name": "xyz789",
"code": "xyz789",
"description": "xyz789",
"sort": 987,
"values": [ProductOptionValue]
}
ProductOptionValue
Description
One selectable value of a ProductOption — for example 'XL' under 'Size', or 'Engraving up to 12 chars' under 'Personalisation'. Carries an optional price delta that's applied at the line level when the shopper picks this value (see also OrderItemVariant.price + pricePrefix for the persisted form).
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the option value (products_options_values_id). |
name - String
|
Localized label shown to shoppers (e.g. 'XL', 'Stainless steel'). |
code - String
|
Internal code for the value, stable across languages. |
specification - String
|
Free-form spec text shown alongside the value (e.g. dimensions, technical detail). |
weight - Float
|
Weight delta added to the product's base weight when this value is chosen, in kilograms. Used in shipping calculation. |
sort - Int
|
Display sort order within the parent option. |
hex - String
|
Hex color (without leading #) for swatch UI. Null when the value isn't a color. |
priceDelta - Float
|
Price delta this value contributes when chosen, in the tenant's default currency. Interpreted via pricePrefix. |
pricePrefix - String
|
How priceDelta is applied. Example values:
Mirrors OrderItemVariant.pricePrefix for the persisted form. |
apiId - String
|
External-system identifier for the value when the option is mirrored in an ERP / PIM. |
Example
{
"id": "4",
"name": "abc123",
"code": "xyz789",
"specification": "abc123",
"weight": 987.65,
"sort": 123,
"hex": "abc123",
"priceDelta": 987.65,
"pricePrefix": "abc123",
"apiId": "abc123"
}
ProductPriceHistory
Description
A snapshot of one price change for a product. Every time a product's price is updated — at the product level or for a specific variant — a row is written here capturing the new price, the timestamp, and the user who made the change. The table is append-only and serves as the audit trail behind the admin's pricing reports and any 'price last changed by …' display.
For the live current price see ProductStock.price (per-variant) and the product-level price on Product. For volume / step-discount ladders that layer on top of the live price see productVolumeAddonPrices and productVolumeDiscounts.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the history entry. |
productId - ID!
|
Product whose price changed. |
stockId - ID!
|
Variant (products_stock) whose price changed. 0 means a product-level price change rather than a per-variant change. |
price - Float!
|
New price recorded by this change, in the tenant's default currency. |
date - String!
|
Timestamp of the price change. ISO-8601 string. |
userName - String!
|
Username of the admin who applied the change. Useful for audit / accountability reports. |
Example
{
"id": 4,
"productId": 4,
"stockId": 4,
"price": 987.65,
"date": "abc123",
"userName": "abc123"
}
ProductStock
Description
A stock-keeping row for one variant of a product. Products that come in multiple variants (size, color, configuration) have one ProductStock row per variant, each with its own SKU, barcode, price, on-hand quantity, and warehouse shelf location.
ProductStock holds the totals across all warehouses for a given variant. When a tenant runs multi-warehouse inventory, the per-warehouse split lives in WarehouseStock — sum WarehouseStock.quantity across warehouses for one product to reconcile against ProductStock.quantity. Price changes are audited via productPriceHistory.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the stock entry (products_stock_id). |
productId - ID!
|
Product this variant belongs to. |
variant - String
|
Variant identifier — typically a comma-separated list of option-value ids that uniquely identify the variant within the product (e.g. '11_22' = option 11 value 22). |
quantity - Int!
|
On-hand quantity for this variant, summed across all warehouses. |
price - Float!
|
Current selling price for this variant in the tenant's default currency. |
priceOriginal - Float!
|
Reference / list price before any current promotion. Used to compute discount badges in the storefront. |
shelf - String
|
Warehouse shelf location code captured for pick-and-pack staff (e.g. 'A1-03'). Null when the tenant doesn't track shelves. |
Example
{
"id": 4,
"productId": 4,
"variant": "abc123",
"quantity": 987,
"price": 987.65,
"priceOriginal": 987.65,
"shelf": "abc123"
}
ProductVolumeAddonPriceTier
Description
One step in a per-product step-pricing ladder. Tenants define thresholds ('buy 10 → €5.50, buy 50 → €4.90') so the storefront and quoting engine can swap in the lower unit price once the basket reaches the minimum quantity. Distinct from ProductVolumeDiscountTier — that surface applies a percentage discount keyed off customer group / customer type, while this surface replaces the unit price outright on a per-product basis.
Example
{"minimumQuantity": 987, "unitPrice": 987.65}
ProductVolumeDiscountTier
Description
One tier in a group-based volume-discount ladder. The discount is expressed as a percentage off the regular price and is gated by customer group, customer type (B2B vs B2C vs all), or a specific customer id — letting tenants run wholesale ladders, contract pricing, and named-customer deals through the same surface.
Fields
| Field Name | Description |
|---|---|
minimumQuantity - Int!
|
Quantity threshold the basket must reach for this discount to apply. |
discountPercentage - Float!
|
Discount percentage applied off the regular price once the threshold is met. |
customerGroupId - String
|
Customer-group code this tier is restricted to. Null when not group-gated. |
customerId - Int
|
Customer id this tier is restricted to. 0 (or null) means any customer. |
customerType - String
|
Customer-type gate for this tier. Example values (from the products_volume_discount_groups.customer_type enum):
|
Example
{
"minimumQuantity": 987,
"discountPercentage": 987.65,
"customerGroupId": "xyz789",
"customerId": 123,
"customerType": "xyz789"
}
Quote
Description
A quote — a B2B request-for-pricing record created by a customer or on their behalf by a sales rep. Quotes progress through their own status lifecycle (Open → Proposal sent → Accepted → Ordered, or Cancelled / Expired, see quoteStatuses), can be tied to a customer account or held under an anonymous sessionId, and aggregate one or more QuoteProduct line items.
Carries the negotiation state (statusId, dates, reminder / follow-up cadence flags), the order-level discount applied to the quote (discountType + discountAmount), preferred shipping (shipmentMethod / shipmentCode / shipmentPrice), preferred warehouse (warehouseId for stock pre-allocation), and the cc field for follow-up email recipients.
Once a customer accepts a quote, the quote-to-order conversion flow spawns a new Order with the QuoteProduct lines mapped onto OrderItem rows. For attachments see quoteFiles; for the status timeline see quoteStatusHistory; for status definitions see quoteStatuses.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the quote. |
customerId - Int
|
Id of the requesting customer. Null for anonymous quotes (filled in via sessionId until the requester logs in / registers). |
sessionId - String
|
Anonymous browser session identifier when the quote is created without a customer account. Lets the storefront thread the quote across page views before login. |
ipAddress - String
|
IP address of the requester captured at quote creation. Useful for fraud / abuse forensics. |
statusId - Int
|
Numeric status id of the quote. Common values across tenants:
Tenants may extend this set. Always resolve dynamically via the quoteStatuses query. |
dateAdded - String
|
Timestamp the quote was created. |
dateModified - String
|
Timestamp of the most recent edit to the quote. |
dateReminder - String
|
Timestamp the auto-reminder system is scheduled to dispatch a reminder email at. Paired with sendReminder. |
dateFollowUp - String
|
Timestamp the auto-reminder system is scheduled to dispatch a follow-up email at. Paired with sendFollowUp. |
sendReminder - String
|
Whether the auto-reminder system should send the dateReminder email. Stored as a flag string (e.g. '1' / '0'). |
sendFollowUp - String
|
Whether the auto-reminder system should send the dateFollowUp email. Stored as a flag string (e.g. '1' / '0'). |
discountType - String
|
How the discountAmount is interpreted. Same enum as on coupons and customer groups. Example values:
Defaults to 'fixed' on new quotes. |
discountAmount - Float
|
Discount value to apply at the quote level, interpreted via discountType. |
comment - String
|
Free-form comment captured at quote creation (customer's brief or sales-rep notes). |
cc - String
|
Comma-separated list of CC email addresses to copy on quote-related notifications (proposal email, reminders, follow-ups). |
shipmentMethod - String
|
Display label for the requested shipping method (e.g. 'Posti - Noutopiste'). Mirrors the shape on Order.shippingMethod. |
shipmentCode - String
|
Code identifying the requested shipping module. Mirrors Order.shippingCode. |
shipmentPrice - Float
|
Quoted shipping cost in the tenant's default currency. |
warehouseId - Int
|
Preferred warehouse id for stock pre-allocation when the quote is later converted to an order. Resolves against the warehouses query. |
items - [QuoteProduct!]!
|
Line items on the quote. |
Example
{
"id": "4",
"customerId": 987,
"sessionId": "xyz789",
"ipAddress": "xyz789",
"statusId": 123,
"dateAdded": "abc123",
"dateModified": "abc123",
"dateReminder": "xyz789",
"dateFollowUp": "xyz789",
"sendReminder": "xyz789",
"sendFollowUp": "abc123",
"discountType": "abc123",
"discountAmount": 123.45,
"comment": "xyz789",
"cc": "xyz789",
"shipmentMethod": "xyz789",
"shipmentCode": "xyz789",
"shipmentPrice": 123.45,
"warehouseId": 987,
"items": [QuoteProduct]
}
QuoteFile
Description
An attachment on a quote. Either a customer-supplied document (specification, drawing, brief) uploaded when the quote is requested, or a seller-generated PDF (the proposal sent back to the customer) attached as the quote progresses. Stored as a filename pointer — the actual file lives in the tenant's quote-files directory.
Example
{
"id": "4",
"quoteId": 987,
"file": "xyz789"
}
QuoteGroup
Description
A localized quote-group label — the categorisation a customer or operator picks when creating a quote (e.g. 'Wholesale', 'B2B project', 'Sample request', 'Construction tender'). Each group has one row per language, so the storefront's quote form can render the group dropdown in the shopper's chosen language.
Tenants define their own group set; the values are not enforced as an enum at the GraphQL layer. Used for routing — quotes in some groups go to specific sales reps or trigger different reminder cadences than others.
Example
{
"id": "4",
"languageId": 987,
"name": "abc123"
}
QuoteNotificationFlagsInput
Description
Optional notification-cadence flags applied alongside a status transition. The reminder / follow-up flags on the parent Quote control whether the auto-reminder system will email the customer if the quote sits in its current status — recording a transition is a natural moment to flip those flags (e.g. enable follow-up emails when the quote moves to 'Proposal sent').
Example
{"sendReminder": true, "sendFollowUp": true}
QuoteProduct
Description
A line item on a quote — references a product, an optional variant, quantity, and any per-line pricing overrides. Mirrors the shape of an OrderItem but for the pre-order quote flow: prices may be tentative (discountedPrice override), variant selections may still be in flux, and the line carries a productGroup marker for combined-discount rules across grouped lines.
Captured per quote — when a quote is later converted to an order, the resolver translates these QuoteProduct rows into OrderItem + OrderItemVariant rows on the new order.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the quote line. |
quoteId - ID!
|
Quote this line belongs to. |
productId - Int!
|
Product id from the catalog. |
variant - String!
|
Variant identifier — typically a comma-separated list of option-value ids (matches the format used in ProductStock.variant). Empty string when the product has no variants. |
quantity - Int!
|
Quantity quoted on this line. |
discountedPrice - Float
|
Per-line negotiated price override. Null means use the product's catalog price. |
productGroup - Int
|
Bundle / pricing-rule grouping marker. 0 means ungrouped (default for most lines). Non-zero values group multiple lines together so combined-discount rules and kit-style packaging can be evaluated across the group as a unit. |
comment - String
|
Free-form per-line comment from the customer or sales rep (configuration notes, customisation requests). |
customOptions - String
|
JSON-encoded free-text custom-option inputs (the counterpart to product-options choices, e.g. engraving text, monogram initials). |
bundleId - Int
|
Bundle parent id when the line is a child of a configured product bundle. 0 means a standalone line. |
Example
{
"id": "4",
"quoteId": 4,
"productId": 123,
"variant": "xyz789",
"quantity": 123,
"discountedPrice": 987.65,
"productGroup": 123,
"comment": "xyz789",
"customOptions": "abc123",
"bundleId": 123
}
QuoteProductInput
Fields
| Input Field | Description |
|---|---|
productId - Int!
|
Product id from the catalog. |
variant - String!
|
Variant identifier — comma-separated option-value ids (matches ProductStock.variant). Empty string when the product has no variants. |
quantity - Int
|
Quantity to quote. Defaults to 1. Default = 1 |
discountedPrice - Float
|
Per-line negotiated price override. Null = use the catalog price. |
productGroup - Int
|
Bundle / pricing-rule grouping marker. Defaults to 0 (ungrouped). Default = 0 |
comment - String
|
Free-form per-line comment. Default = "" |
customOptions - String
|
JSON-encoded custom-option inputs. |
bundleId - Int
|
Bundle parent id. Defaults to 0 (standalone line). Default = 0 |
Example
{
"productId": 987,
"variant": "xyz789",
"quantity": 987,
"discountedPrice": 123.45,
"productGroup": 123,
"comment": "abc123",
"customOptions": "xyz789",
"bundleId": 987
}
QuoteStatus
Description
A localized quote-status label. Mirrors the order-status pattern but for B2B quotes — quotes move through their own lifecycle (Open → Proposal sent → Accepted → Ordered, or Cancelled / Expired) and the storefront / admin renders the current status using the localized name returned here.
The platform's canonical status ids — 1 Open, 2 Accepted, 3 Cancelled, 4 Ordered, 5 Proposal sent, 50 Pending approval — are shared across tenants by default; tenants can extend with custom workflow stages. Each status has a stable internal code (e.g. 'open', 'accepted') in addition to the localized display name.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Stable numeric status id, used in Quote.statusId and QuoteStatusEntry.statusId. |
languageId - Int!
|
Language id this row is for. |
name - String!
|
Localized display label shown to operators and customers (e.g. 'Open', 'Hyväksytty', 'Avbruten'). |
code - String!
|
Stable internal code for the status, language-independent (e.g. 'open', 'accepted', 'cancelled', 'ordered'). Use this for routing rules and integrations rather than matching on numeric id or localized name. |
Example
{
"id": 4,
"languageId": 987,
"name": "xyz789",
"code": "abc123"
}
QuoteStatusEntry
Description
A status-transition entry on a quote's timeline — one row per status change captured as the quote progresses. Mirrors OrderStatusHistory but for quotes. Read-only on this type; record new transitions via the addQuoteStatusHistory mutation, which writes to the same underlying table.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the timeline entry. |
quoteId - Int!
|
Quote this transition belongs to. |
statusId - Int!
|
Numeric status id moved to. Resolve to a localized name via the quoteStatuses query. |
statusName - String
|
Localized status name as it was at the time of the transition (denormalised for stability when status names are later renamed). |
dateAdded - String!
|
ISO timestamp of when the transition was recorded. |
customerNotified - Int
|
Whether a notification email was sent to the customer for this transition. Example values:
|
comments - String
|
Free-form operator comment attached to the transition (e.g. 'Awaiting customer signature'). |
Example
{
"id": "4",
"quoteId": 123,
"statusId": 987,
"statusName": "abc123",
"dateAdded": "abc123",
"customerNotified": 123,
"comments": "xyz789"
}
RemoveCustomerFavoriteInput
Description
Input for deleteFavorite. At least one of id, customersId, or productsId must be provided — the resolver builds an AND filter from the supplied fields and deletes the matching rows. Pass id to remove one specific favorite; pass (customersId, productsId) to remove a customer's favorite of a specific product; pass just customersId to clear the customer's wishlist; pass just productsId to remove every customer's favorite of one product.
Example
{"id": 4, "customersId": 123, "productsId": 123}
Review
Description
A customer review of a product, with optional vendor reply via ReviewDetail.answer. Reviews progress through a moderation lifecycle (statusId / statusCode) before they're published — typical states are pending → approved (visible) or rejected (hidden). Verified-buyer flagging is automatic: the platform sets verifiedBuyer = true when the reviewer's customer id is found on a previous order for the same product.
Used to render product detail page review widgets, the per-product review carousels in product cards, and the admin moderation queue. Aggregate scores (count of approved reviews + average rating) are exposed via reviewSummaries.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the review. |
productId - ID!
|
Product the review is about. |
customerId - Int
|
Reviewer's customer id. Null for guest / unauthenticated reviews. |
nickname - String
|
Public display name shown alongside the review (the reviewer's chosen handle). |
country - String
|
Reviewer's country at submission time (typically a 2-letter ISO code). Used for region-aware moderation and aggregate filtering. |
isRecommended - Boolean
|
Whether the reviewer would recommend the product to others. Optional star-recommendation flag captured alongside the rating. |
verifiedBuyer - Boolean
|
Whether the reviewer is a verified purchaser. Auto-set when the reviewer's customer id is found on a previous order for the product. |
count - Int
|
Tenant-defined counter on the review row. Semantics vary across tenants — most commonly 'helpful votes' in production, but treated as opaque by core code. |
statusId - Int
|
Numeric moderation status. Resolve to a stable string code via statusCode; the platform's canonical lifecycle is pending → approved → rejected. |
statusCode - String
|
Stable internal moderation status code (e.g. 'pending', 'approved', 'rejected'). Use this for routing rules rather than statusId, which may collide across tenants. |
dates - ReviewDates
|
Submission / vendor-reply / order-date timestamps. |
details - [ReviewDetail]
|
Localized title / body / answer rows, one per language. |
Example
{
"id": "4",
"productId": 4,
"customerId": 123,
"nickname": "abc123",
"country": "abc123",
"isRecommended": false,
"verifiedBuyer": false,
"count": 123,
"statusId": 987,
"statusCode": "xyz789",
"dates": ReviewDates,
"details": [ReviewDetail]
}
ReviewDates
Description
Date metadata for a Review. Captured at submission, optionally at vendor-reply time, and a snapshot of the order date when the review is tied to a verified purchase. Returned as a nested object so the three timestamps can be hydrated together without flattening into the parent Review type.
Example
{
"createdAt": "xyz789",
"orderDate": "xyz789",
"answerDate": "abc123"
}
ReviewDetail
Description
Localized text for one Review, in one language. A review can have multiple ReviewDetail rows (one per language) when the storefront supports translated review bodies; carries the localized title, the body text, and the optional vendor reply.
Fields
| Field Name | Description |
|---|---|
languageId - Int
|
Language id this row is for (resolves against the languages query). Null on tenants that don't localize reviews. |
title - String
|
Review headline shown above the body. |
detail - String
|
Long-form review body (rich or plain text depending on the tenant's input field). |
answer - String
|
Vendor reply published below the customer's body. Null when the vendor hasn't responded. |
Example
{
"languageId": 123,
"title": "xyz789",
"detail": "xyz789",
"answer": "xyz789"
}
ReviewSummary
Description
Aggregate review metrics for one product. Recomputed by the review pipeline whenever a review's moderation state flips into / out of 'approved' so the storefront can render review counts and average star ratings without scanning all reviews on every page render.
Example
{"productId": 4, "reviewsCount": 123, "ratingSummary": 123}
Service
Description
A static-content page in the storefront's CMS layer — typically About Us, Shipping & Returns, FAQ, Terms, Contact, or any tenant-defined informational page. Each page lives under one ServiceCategory (categoryId) and carries per-page visual / behaviour fields plus a ServiceDescription per language for the localized copy.
Per-page custom CSS (css) and external script / stylesheet hooks (externalJs / externalCss) let tenants customize individual page layouts without touching the storefront theme — useful for marketing landing pages with bespoke visual treatments. The googleFeed flag controls whether the page surfaces in the Google Merchant feed; the displayFooter flag controls whether it appears in the storefront's footer link block.
Distinct from the catalog product / category surfaces — services hold static content (information pages, policies), not buyable goods. For category-tree navigation see serviceCategories.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the service / page. |
categoryId - Int
|
Id of the parent ServiceCategory. |
image - String
|
Filename of the page hero / illustration image, served from the tenant's service-image directory. |
sortOrder - Int
|
Display sort order within the parent category. Lower values render first. |
displayFooter - Int
|
Whether the page appears in the storefront footer link block. 1 = visible in footer, 0 = not in footer. |
googleFeed - Int
|
Whether the page is included in the Google Merchant feed. 1 = include, 0 = exclude. |
css - String
|
Per-page custom CSS injected into the rendered page. Used to tweak layout for one page without changing the global theme. |
externalJs - String
|
External JavaScript URL to load on this page (e.g. a third-party widget script). |
externalCss - String
|
External stylesheet URL to load on this page. |
svgIcon - String
|
Inline SVG markup for the page icon. Stored as SVG source — the storefront drops it directly into the page. |
descriptions - [ServiceDescription]
|
Localized name / URL / body / meta rows, one per language. |
category - ServiceCategory
|
Resolved parent ServiceCategory, hydrated alongside the service in the same response. |
Example
{
"id": "4",
"categoryId": 987,
"image": "xyz789",
"sortOrder": 987,
"displayFooter": 987,
"googleFeed": 123,
"css": "abc123",
"externalJs": "abc123",
"externalCss": "xyz789",
"svgIcon": "xyz789",
"descriptions": [ServiceDescription],
"category": ServiceCategory
}
ServiceCategory
Description
A grouping of static-content service pages — the top level of the storefront's CMS layer. Holds About-us / Help / Terms / Contact-style pages organized into a navigation tree (parentId nests categories under each other), with display flags for inclusion in the storefront footer and per-language description rows for the localized copy.
Distinct from category (the product-catalog category tree) — service categories are CMS pages, while categories group products. For the individual service / page records living under each category, see the services query.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the service category. |
parentId - Int
|
Id of the parent category, or 0 for top-level categories. |
sortOrder - Int
|
Display sort order within the parent category. Lower values render first. |
displayFooter - Int
|
Whether the category appears in the storefront footer navigation. 1 = visible in the footer, 0 = navigation-only (not in footer). |
svgIcon - String
|
Inline SVG markup for the category icon. Stored as the SVG source rather than a filename — the storefront drops it directly into the page. |
descriptions - [ServiceCategoryDescription]
|
Localized name / URL / body rows, one per language. |
children - [ServiceCategory]
|
Child categories nested under this one. Empty for leaf categories. |
Example
{
"id": "4",
"parentId": 987,
"sortOrder": 123,
"displayFooter": 987,
"svgIcon": "abc123",
"descriptions": [ServiceCategoryDescription],
"children": [ServiceCategory]
}
ServiceCategoryDescription
Description
Localized text and SEO metadata for one ServiceCategory, in one language. Each category has one ServiceCategoryDescription per (category, languageId) pair — the storefront picks the row matching the active language at render time.
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for (resolves against the languages query). |
name - String
|
Localized category name shown in navigation, breadcrumbs, and the page header. |
url - String
|
Slug-style URL fragment for the category landing page. |
html - String
|
Long-form rich-text body rendered on the category landing page. |
Example
{
"languageId": 123,
"name": "abc123",
"url": "abc123",
"html": "xyz789"
}
ServiceDescription
Description
Localized text and SEO metadata for one Service page, in one language. Each Service has one ServiceDescription per (service, languageId) pair — the storefront picks the row matching the active language at render time. Carries the visible name, slug-style URL, the rich-text body rendered on the page, and the meta-tags emitted into the page head.
Fields
| Field Name | Description |
|---|---|
languageId - Int!
|
Language id this row is for (resolves against the languages query). |
name - String
|
Localized service / page name shown in navigation and the page header. |
url - String
|
Slug-style URL fragment for the page (e.g. 'shipping-and-returns'). |
html - String
|
Long-form rich-text body rendered on the page. Typically HTML; tenants who run a separate CMS may keep this empty and render from the CMS instead. |
metaTitle - String
|
Localized |
metaDescription - String
|
Localized for the page. |
Example
{
"languageId": 123,
"name": "xyz789",
"url": "xyz789",
"html": "abc123",
"metaTitle": "xyz789",
"metaDescription": "xyz789"
}
String
Description
The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
Example
"xyz789"
UpdateOrdersProductInput
Description
Input shape for partially updating an existing order line via updateOrdersProduct. All fields are optional — only the provided fields are written. Used for admin post-order corrections (price adjustment, quantity fix, attach a custom comment).
Fields
| Input Field | Description |
|---|---|
orderId - ID
|
Move the line to a different order id (rare; used for split / merge operations). |
productId - Int
|
Update the catalog product id reference. |
productModel - String
|
Update the product model snapshot. |
productEan - String
|
Update the EAN snapshot. |
productName - String
|
Update the display name shown on the receipt. |
price - Float
|
Update the unit price charged. |
originalPrice - Float
|
Update the catalog reference price. |
tax - Float
|
Update the tax rate. |
quantity - Int
|
Update the quantity ordered. |
stockVariants - String
|
Update the variant stock-id snapshot. |
lineType - String
|
Update the line type. |
comment - String
|
Update the line comment. |
customOptions - JSON
|
Update the custom-options payload. |
Example
{
"orderId": "4",
"productId": 987,
"productModel": "abc123",
"productEan": "xyz789",
"productName": "xyz789",
"price": 987.65,
"originalPrice": 123.45,
"tax": 123.45,
"quantity": 123,
"stockVariants": "abc123",
"lineType": "xyz789",
"comment": "xyz789",
"customOptions": {}
}
UpdateOrdersProductsVariantInput
Description
Input shape for partially updating an existing variant selection. All fields are optional — only provided fields are written. Used for admin post-order corrections (e.g. fixing a typo in the captured option name, or adjusting a price delta after the fact).
Fields
| Input Field | Description |
|---|---|
orderId - ID
|
Move the variant to a different order (rare; used in split / merge flows). |
orderProductId - ID
|
Move the variant to a different order line. |
optionId - Int
|
Update the catalog option id reference. |
optionName - String
|
Update the option display label captured at order time. |
optionValue - String
|
Update the selected value captured at order time. |
price - Float
|
Update the price delta this variant contributes. |
pricePrefix - String
|
Update how the price delta is applied ('+' additive or '' replacement). |
Example
{
"orderId": 4,
"orderProductId": "4",
"optionId": 123,
"optionName": "abc123",
"optionValue": "xyz789",
"price": 123.45,
"pricePrefix": "abc123"
}
UpdateProductCustomOptionInput
Fields
| Input Field | Description |
|---|---|
productId - Int
|
Move the override to a different product. |
productsOptionsId - Int
|
Point the override at a different ProductOption. |
required - Boolean
|
Toggle whether the option is required at checkout. |
position - Int
|
New display position within the product's option list. |
type - String
|
New input rendering type (see ProductCustomOption.type for example values). |
Example
{
"productId": 987,
"productsOptionsId": 123,
"required": true,
"position": 987,
"type": "abc123"
}
Warehouse
Description
A physical (or 3PL / virtual) warehouse the tenant ships from. Drives multi-warehouse fulfilment routing (which warehouse picks an order), per-warehouse stock split (WarehouseStock holds the per-warehouse on-hand quantities), and the storefront's 'check stock at your local store' surface.
A tenant on single-warehouse fulfilment will typically have one row here (often code 'MAIN'); multi-warehouse setups use the visible flag to control which warehouses appear in shopper-facing surfaces vs. back-office-only locations. Each warehouse exposes a paginated stock view via Warehouse.stock — same data as the warehouseStock query reachable via this side of the join.
Fields
| Field Name | Description |
|---|---|
id - ID!
|
Database row id of the warehouse. |
name - String
|
Display name of the warehouse (e.g. 'Helsinki Main', 'Stockholm Hub'). |
code - String
|
Internal short code (e.g. 'MAIN', 'WH1', 'SE-HUB'). Used by Order.warehouseCode and as the join key into ERP / WMS systems. |
phone - String
|
Contact phone for the warehouse — captured for storefront display on the 'Find a store' surface and for B2B contact flows. |
email - String
|
Contact email for the warehouse. |
visible - Boolean!
|
Whether the warehouse should appear in shopper-facing surfaces (the 'check stock' picker, store-locator). false = back-office-only (e.g. a 3PL hub the storefront shouldn't expose by name). |
stock - [WarehouseStock]
|
Per-warehouse stock for one product (or every product when productId is omitted). Resolves the warehouseStock data filtered to this warehouse — same rows the warehouseStock query returns when called with a warehouseId filter. |
Arguments
|
|
Example
{
"id": 4,
"name": "abc123",
"code": "xyz789",
"phone": "xyz789",
"email": "abc123",
"visible": true,
"stock": [WarehouseStock]
}
WarehouseStock
Description
Per-warehouse on-hand quantity for one product. When a tenant runs multi-warehouse fulfilment (e.g. a main warehouse plus regional satellites or a 3PL), the product's total inventory in ProductStock is split across warehouses here — one row per (warehouse, product) pair, holding only that warehouse's slice.
ProductStock holds the variant-level totals across all warehouses; WarehouseStock holds the warehouse-level split per product. Sum WarehouseStock.quantity for a product across warehouses to reconcile against ProductStock.quantity. Used by the picking / dispatch flow to pick the right warehouse, by the storefront's 'in stock at your nearest store' display, and by ERP / WMS reconciliation reports.
Example
{"id": 4, "warehouseId": 123, "productId": 987, "quantity": 987}