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.

Contact

AI Commerce Cloud onboarding

info@petrosoft.fi

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 type codes on ProductMedia, new module codes on ActionRecorderEntry, new tenant-defined groupsType codes on CustomerGroup).
  • 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 labels
  • quoteStatuses(languageId: …) for quote-status ids and labels
  • languages for the available language ids
  • currencies for enabled currencies
  • configurations for 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": "xyz789"}}

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": "abc123",
  "userId": 987,
  "success": true,
  "limit": 123,
  "offset": 987
}
Response
{
  "data": {
    "actionRecorderEntries": {
      "total": 123,
      "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]

Arguments
Name Description
customerId - ID! Customer to fetch addresses for.
limit - Int Maximum number of entries to return.
offset - Int Offset for pagination.

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": 987, "offset": 987}
Response
{
  "data": {
    "addressBookEntries": [
      {
        "id": 4,
        "customerId": 123,
        "gender": "abc123",
        "company": "xyz789",
        "firstname": "abc123",
        "lastname": "abc123",
        "streetAddress": "xyz789",
        "vatid": "abc123",
        "postcode": "xyz789",
        "city": "xyz789",
        "state": "xyz789",
        "countryId": 123,
        "zoneId": 123,
        "comments": "abc123",
        "billingStreetAddress": "xyz789",
        "billingFirstname": "abc123",
        "billingLastname": "abc123",
        "billingPostcode": "abc123",
        "billingCity": "xyz789",
        "billingCountryId": "abc123",
        "billingCompany": "abc123",
        "billingVatid": "abc123",
        "billingZoneId": "abc123",
        "billingState": "abc123",
        "billingOperatorId": 123,
        "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]

Arguments
Name Description
ids - [ID!] Restrict to specific format ids. Omit to return every format.
limit - Int Maximum number of formats to return.
offset - Int Offset for pagination.

Example

Query
query addressFormats(
  $ids: [ID!],
  $limit: Int,
  $offset: Int
) {
  addressFormats(
    ids: $ids,
    limit: $limit,
    offset: $offset
  ) {
    id
    addressFormat
    addressSummary
  }
}
Variables
{"ids": [4], "limit": 987, "offset": 123}
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]

Arguments
Name Description
limit - Int Maximum number of notifications to return.
offset - Int Offset for pagination.

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": "xyz789",
        "emailErrorSent": true,
        "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]

Arguments
Name Description
productId - Int Restrict to one product's history.
userId - Int Restrict to one admin's activity.
limit - Int Maximum number of entries to return.
offset - Int Offset for pagination.

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": 987, "offset": 123}
Response
{
  "data": {
    "adminTrackingCreate": [
      {
        "id": "4",
        "productId": 123,
        "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]

Arguments
Name Description
limit - Int Maximum number of administrators to return.
offset - Int Offset for pagination.

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": "abc123",
        "email": "xyz789",
        "twoFactor": false,
        "superadmin": false,
        "writePermission": false,
        "grantAccess": "abc123"
      }
    ]
  }
}

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": "xyz789",
  "jobId": "xyz789",
  "limit": 123,
  "offset": 987
}
Response
{
  "data": {
    "apiProcessQueue": [
      {
        "id": "4",
        "jobId": "abc123",
        "api": "abc123",
        "endpoint": "abc123",
        "method": "abc123",
        "data": {},
        "createdAt": "xyz789",
        "error": "abc123",
        "status": "abc123"
      }
    ]
  }
}

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": 123}
Response
{
  "data": {
    "availabilities": [
      {
        "id": "4",
        "languageId": 987,
        "name": "abc123",
        "hexCode": "abc123"
      }
    ]
  }
}

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": 987,
  "invoiceDateFrom": "abc123",
  "invoiceDateTo": "abc123",
  "valueDateFrom": "xyz789",
  "valueDateTo": "abc123",
  "limit": 987,
  "offset": 123
}
Response
{
  "data": {
    "bankPayments": [
      {
        "id": "4",
        "orderId": 987,
        "invoicePaymentDate": "abc123",
        "invoicePaymentValueDate": "abc123",
        "amount": 987.65
      }
    ]
  }
}

bannerHistory

Description

Standalone query for one banner's per-day history — equivalent to Banner.historyByDate but reachable without first loading the parent Banner. Used by the admin's stats dashboard when the calling code already knows the banner id and wants the chart in a single round-trip.

Returns day-bucketed aggregates ordered newest first. For the banner metadata (title, url, group, image) and lifetime totals, query the banners surface alongside.

Response

Returns [BannerHistoryEntry!]!

Arguments
Name Description
bannerId - Int! Banner to fetch the per-day history for.
startDate - String Inclusive lower bound on the banner-history date. ISO-8601 date.
endDate - String Inclusive upper bound on the banner-history date. ISO-8601 date.
limit - Int Maximum number of day-buckets to return.
offset - Int Offset for pagination across day-buckets.

Example

Query
query bannerHistory(
  $bannerId: Int!,
  $startDate: String,
  $endDate: String,
  $limit: Int,
  $offset: Int
) {
  bannerHistory(
    bannerId: $bannerId,
    startDate: $startDate,
    endDate: $endDate,
    limit: $limit,
    offset: $offset
  ) {
    bannerId
    date
    impressions
    clicks
  }
}
Variables
{
  "bannerId": 987,
  "startDate": "abc123",
  "endDate": "xyz789",
  "limit": 987,
  "offset": 123
}
Response
{
  "data": {
    "bannerHistory": [
      {
        "bannerId": 123,
        "date": "abc123",
        "impressions": 123,
        "clicks": 123
      }
    ]
  }
}

banners

Description

List every banner the tenant has defined, in id order. Use limit / offset to page through. For zone-scoped fetches (e.g. only the banners in the homepage hero zone) use bannersByGroup instead — it's the same surface filtered by Banner.group.

For per-day click / impression series, use the Banner.historyByDate field on each banner, or the bannerHistory query directly.

Response

Returns [Banner]

Arguments
Name Description
limit - Int Maximum number of banners to return.
offset - Int Offset for pagination.

Example

Query
query banners(
  $limit: Int,
  $offset: Int
) {
  banners(
    limit: $limit,
    offset: $offset
  ) {
    id
    title
    url
    group
    status
    image
    history {
      impressions
      clicks
    }
    historyByDate {
      bannerId
      date
      impressions
      clicks
    }
  }
}
Variables
{"limit": 987, "offset": 987}
Response
{
  "data": {
    "banners": [
      {
        "id": "4",
        "title": "xyz789",
        "url": "abc123",
        "group": "xyz789",
        "status": 123,
        "image": "xyz789",
        "history": BannerHistory,
        "historyByDate": [BannerHistoryEntry]
      }
    ]
  }
}

bannersByGroup

Description

List the banners belonging to one storefront zone. The group code is free-form and tenant-defined — common examples are 'home', 'sidebar', 'category-N'. Used by the storefront's banner renderer to populate one zone at a time.

Response

Returns [Banner]

Arguments
Name Description
group - String! Group code identifying the zone. Tenant-defined, see Banner.group for examples.
limit - Int Maximum number of banners to return.
offset - Int Offset for pagination.

Example

Query
query bannersByGroup(
  $group: String!,
  $limit: Int,
  $offset: Int
) {
  bannersByGroup(
    group: $group,
    limit: $limit,
    offset: $offset
  ) {
    id
    title
    url
    group
    status
    image
    history {
      impressions
      clicks
    }
    historyByDate {
      bannerId
      date
      impressions
      clicks
    }
  }
}
Variables
{
  "group": "xyz789",
  "limit": 987,
  "offset": 123
}
Response
{
  "data": {
    "bannersByGroup": [
      {
        "id": "4",
        "title": "xyz789",
        "url": "xyz789",
        "group": "abc123",
        "status": 987,
        "image": "abc123",
        "history": BannerHistory,
        "historyByDate": [BannerHistoryEntry]
      }
    ]
  }
}

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]

Arguments
Name Description
customerId - ID! Customer to fetch billing addresses for.
limit - Int Maximum number of addresses to return.
offset - Int Offset for pagination.

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": "abc123",
        "firstname": "xyz789",
        "lastname": "xyz789",
        "streetAddress": "abc123",
        "postcode": "xyz789",
        "city": "xyz789",
        "state": "abc123",
        "countryId": "abc123",
        "zoneId": "abc123",
        "vatid": "abc123",
        "operatorId": 987,
        "invoiceAddress": "xyz789",
        "reference": "xyz789",
        "referenceRequired": true
      }
    ]
  }
}

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": 123,
  "sessionKey": "abc123",
  "startDate": "xyz789",
  "endDate": "xyz789",
  "limit": 123,
  "offset": 987
}
Response
{
  "data": {
    "browseHistory": [
      {
        "id": 4,
        "customerId": 987,
        "sessionKey": "xyz789",
        "loadTimeMsec": 123,
        "categoryId": 987,
        "productId": 987,
        "manufacturerId": 123,
        "color": 987,
        "size": 987,
        "geoipCountry": "xyz789",
        "ipAddress": "xyz789",
        "date": "abc123",
        "timestamp": 987,
        "topPicks": true,
        "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]

Arguments
Name Description
limit - Int Maximum number of categories to return.
offset - Int Offset for pagination.

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": "xyz789",
        "image": "xyz789",
        "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

Arguments
Name Description
id - ID! Category id to fetch.
languageId - Int Language to scope CategoryDescription rows to. Omit for all languages.

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": "abc123",
      "image": "abc123",
      "banner": "xyz789",
      "parentId": 123,
      "sortOrder": 987,
      "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": 123,
        "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": "xyz789",
        "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]

Arguments
Name Description
groupId - Int Restrict to settings inside one ConfigurationGroup. Omit to span all groups.
limit - Int Maximum number of settings to return.
offset - Int Offset for pagination.

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": 987, "limit": 987, "offset": 987}
Response
{
  "data": {
    "configurations": [
      {
        "id": "4",
        "title": "abc123",
        "key": "abc123",
        "value": "abc123",
        "description": "xyz789",
        "groupId": 123,
        "sortOrder": 987,
        "lastModified": "abc123",
        "dateAdded": "xyz789",
        "useFunction": "xyz789",
        "setFunction": "abc123",
        "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]

Arguments
Name Description
limit - Int Maximum number of countries to return.
offset - Int Offset for pagination.

Example

Query
query countries(
  $limit: Int,
  $offset: Int
) {
  countries(
    limit: $limit,
    offset: $offset
  ) {
    id
    name
    iso2
    iso3
    dutyRate
    dutyLimit
    addressFormatId
    defaultCurrencyId
  }
}
Variables
{"limit": 987, "offset": 123}
Response
{
  "data": {
    "countries": [
      {
        "id": 4,
        "name": "abc123",
        "iso2": "xyz789",
        "iso3": "abc123",
        "dutyRate": 987.65,
        "dutyLimit": 987.65,
        "addressFormatId": 123,
        "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]

Arguments
Name Description
limit - Int Maximum number of currencies to return.
offset - Int Offset for pagination.

Example

Query
query currencies(
  $limit: Int,
  $offset: Int
) {
  currencies(
    limit: $limit,
    offset: $offset
  ) {
    id
    title
    code
    symbolLeft
    symbolRight
    value
    lastUpdated
  }
}
Variables
{"limit": 987, "offset": 123}
Response
{
  "data": {
    "currencies": [
      {
        "id": 4,
        "title": "abc123",
        "code": "abc123",
        "symbolLeft": "xyz789",
        "symbolRight": "xyz789",
        "value": 123.45,
        "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.

Response

Returns a Customer

Arguments
Name Description
id - ID! Customer id to fetch.

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": "abc123",
      "defaultAddressId": 123,
      "defaultDeliveryAddressId": 987,
      "telephone": "xyz789",
      "newsletter": true,
      "freeShipping": 987.65,
      "admin": 123,
      "type": 123,
      "group": "xyz789",
      "approved": false,
      "undeliveredOrders": 987,
      "blockPayments": "xyz789",
      "blockShipments": "abc123",
      "temporaryCustomer": false,
      "emailSent": true,
      "apiId": "xyz789",
      "apiBillingId": 987,
      "grantWhatsapp": false,
      "billingOperatorId": 987,
      "billingInvoiceAddress": "xyz789",
      "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": "xyz789"}
Response
{
  "data": {
    "customerByEmail": {
      "id": 4,
      "gender": "xyz789",
      "firstname": "xyz789",
      "lastname": "abc123",
      "emailAddress": "xyz789",
      "defaultAddressId": 123,
      "defaultDeliveryAddressId": 123,
      "telephone": "xyz789",
      "newsletter": false,
      "freeShipping": 987.65,
      "admin": 123,
      "type": 987,
      "group": "xyz789",
      "approved": true,
      "undeliveredOrders": 123,
      "blockPayments": "abc123",
      "blockShipments": "abc123",
      "temporaryCustomer": false,
      "emailSent": true,
      "apiId": "xyz789",
      "apiBillingId": 987,
      "grantWhatsapp": false,
      "billingOperatorId": 123,
      "billingInvoiceAddress": "abc123",
      "billingReference": "xyz789",
      "billingReferenceRequired": true,
      "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": "xyz789",
  "limit": 123,
  "offset": 123
}
Response
{
  "data": {
    "customerGroupPriceList": [
      {
        "id": "4",
        "groupId": "xyz789",
        "productId": 987,
        "productStockId": 123,
        "price": 123.45,
        "validFrom": "abc123",
        "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]

Arguments
Name Description
type - String Restrict to groups of this groupsType (e.g. 'fixed', 'dynamic', 'matrix', 'list').
activeOnly - Boolean When true, only return groups currently within their dateStart / dateEnd window (and only active dynamic-discount + price-list rows). Defaults to false.

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": "abc123", "activeOnly": false}
Response
{
  "data": {
    "customerGroups": [
      {
        "id": "4",
        "description": "abc123",
        "discountAmount": 987.65,
        "discountType": "xyz789",
        "dateStart": "abc123",
        "dateEnd": "abc123",
        "minOrder": 123.45,
        "minOrderType": "abc123",
        "customerType": "abc123",
        "discountedProducts": 123,
        "groupsType": "abc123",
        "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": 987
    }
  }
}

customerPrice

Response

Returns a CustomerPrice

Arguments
Name Description
customerId - Int!
productId - Int!
validOn - String

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": 987,
  "validOn": "xyz789"
}
Response
{
  "data": {
    "customerPrice": {
      "id": 4,
      "customerId": 123,
      "productId": 987,
      "price": 987.65,
      "currency": "xyz789",
      "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]

Arguments
Name Description
limit - Int Maximum number of customers to return.
offset - Int Offset for pagination.

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": "xyz789",
        "firstname": "xyz789",
        "lastname": "abc123",
        "emailAddress": "xyz789",
        "defaultAddressId": 123,
        "defaultDeliveryAddressId": 987,
        "telephone": "xyz789",
        "newsletter": true,
        "freeShipping": 123.45,
        "admin": 987,
        "type": 123,
        "group": "xyz789",
        "approved": false,
        "undeliveredOrders": 987,
        "blockPayments": "xyz789",
        "blockShipments": "abc123",
        "temporaryCustomer": false,
        "emailSent": true,
        "apiId": "abc123",
        "apiBillingId": 987,
        "grantWhatsapp": false,
        "billingOperatorId": 123,
        "billingInvoiceAddress": "abc123",
        "billingReference": "abc123",
        "billingReferenceRequired": false,
        "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": 123
}
Response
{
  "data": {
    "customersApi": [
      {
        "asiakaskoodi": "xyz789",
        "name": "xyz789",
        "secondaryName": "abc123",
        "addressLine1": "xyz789",
        "addressLine2": "abc123",
        "addressLine3": "abc123",
        "deliveryName1": "abc123",
        "deliveryName2": "abc123",
        "deliveryName3": "abc123",
        "billingCustomerId": 123,
        "paymentTerm": "xyz789",
        "customerGroup": "xyz789",
        "chain": "xyz789",
        "salesCode": "abc123",
        "creditLimit": "abc123",
        "deliveryBlock": "xyz789",
        "email": "abc123",
        "website": "abc123",
        "phone": "abc123",
        "fax": "xyz789",
        "deliveryMethod": "xyz789",
        "discountGroup": "xyz789",
        "discountPercent": 123.45,
        "secondaryDiscountPercent": 987.65,
        "languageCode": "abc123",
        "comment1": "abc123",
        "comment2": "abc123",
        "contactPerson": "xyz789",
        "contactPersonId": 987,
        "lastLoginAt": "abc123",
        "vatLiability": "xyz789",
        "currency": "abc123",
        "modifiedAt": "xyz789",
        "businessId": "abc123",
        "billingAddress": "abc123",
        "intermediaryService": "abc123",
        "netvisorKey": 123
      }
    ]
  }
}

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]

Arguments
Name Description
customersId - ID! Customer to fetch the saved basket for.
cartId - String Cart key, when the customer holds multiple parallel baskets. Omit to receive every basket the customer has.

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": "xyz789",
        "customersId": 123,
        "itemId": "abc123",
        "productId": 987,
        "variants": "abc123",
        "productOptions": "xyz789",
        "comment": "abc123",
        "customOptions": "abc123",
        "quantity": 123,
        "specialPrice": 987.65,
        "bundleId": "xyz789",
        "includes": "abc123",
        "dateAdded": "abc123",
        "emailSent": 987,
        "emailLast": "xyz789",
        "variableImage": "xyz789",
        "allowSubstitute": true
      }
    ]
  }
}

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!]!

Arguments
Name Description
customerId - Int Restrict to one customer's blacklist history.
status - Int Restrict to entries with this status code (e.g. 1 = active block).
limit - Int Maximum number of entries to return.
offset - Int Offset for pagination.

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": 987, "status": 123, "limit": 987, "offset": 123}
Response
{
  "data": {
    "customersBlacklist": [
      {
        "id": 4,
        "customerId": 123,
        "status": 123,
        "reason": "abc123",
        "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!]!

Arguments
Name Description
customersId - Int! Customer to fetch saved cards for.
cardType - String Restrict to one card brand (e.g. 'Visa'). Omit for all brands.
limit - Int Maximum number of saved cards to return.
offset - Int Offset for pagination.

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": 123,
  "cardType": "abc123",
  "limit": 987,
  "offset": 987
}
Response
{
  "data": {
    "customersBraintreeTokens": [
      {
        "id": 4,
        "customersId": 123,
        "braintreeToken": "xyz789",
        "cardType": "abc123",
        "numberFiltered": "abc123",
        "expiryDate": "abc123",
        "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": 123,
  "userId": 123,
  "sourceTable": "abc123",
  "limit": 123,
  "offset": 123
}
Response
{
  "data": {
    "customersHistory": [
      {
        "id": 4,
        "customerId": 123,
        "addressBookId": 123,
        "userId": 987,
        "userName": "abc123",
        "sourceTable": "abc123",
        "fieldName": "abc123",
        "oldValue": "xyz789",
        "newValue": "xyz789",
        "page": "abc123",
        "dateAdded": "xyz789"
      }
    ]
  }
}

customersPrices

Response

Returns [CustomerPrice!]!

Arguments
Name Description
customerId - Int
productId - Int
validOn - String
limit - Int
offset - Int

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": 123,
  "validOn": "abc123",
  "limit": 987,
  "offset": 987
}
Response
{
  "data": {
    "customersPrices": [
      {
        "id": 4,
        "customerId": 123,
        "productId": 987,
        "price": 123.45,
        "currency": "xyz789",
        "validFrom": "xyz789",
        "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": 123, "offset": 987, "includeLegacy": false}
Response
{
  "data": {
    "deliveryAddresses": [
      {
        "id": 4,
        "customerId": 987,
        "gender": "xyz789",
        "company": "abc123",
        "firstname": "xyz789",
        "lastname": "abc123",
        "streetAddress": "xyz789",
        "vatid": "abc123",
        "postcode": "abc123",
        "city": "abc123",
        "state": "abc123",
        "countryId": 987,
        "zoneId": 987,
        "comments": "abc123",
        "legacyAddressBookId": 123,
        "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": "xyz789",
      "dateStart": "xyz789",
      "dateEnd": "abc123",
      "maxUse": 987,
      "minOrder": 987.65,
      "minOrderType": "xyz789",
      "numberAvailable": 987,
      "customerType": "abc123",
      "discountedProducts": 123,
      "discountedProductsOld": 987,
      "allowedProducts": "abc123",
      "categories": [123],
      "products": [123],
      "customers": [123],
      "orders": [987],
      "manufacturers": [123],
      "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]

Arguments
Name Description
limit - Int Maximum number of coupons to return.
offset - Int Offset for pagination.

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": 123, "offset": 987}
Response
{
  "data": {
    "discountCoupons": [
      {
        "id": "4",
        "description": "xyz789",
        "amount": 123.45,
        "discountType": "abc123",
        "dateStart": "xyz789",
        "dateEnd": "abc123",
        "maxUse": 123,
        "minOrder": 987.65,
        "minOrderType": "abc123",
        "numberAvailable": 123,
        "customerType": "abc123",
        "discountedProducts": 123,
        "discountedProductsOld": 987,
        "allowedProducts": "xyz789",
        "categories": [987],
        "products": [123],
        "customers": [123],
        "orders": [987],
        "manufacturers": [123],
        "shippingMethods": ["abc123"],
        "zones": [987]
      }
    ]
  }
}

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]

Arguments
Name Description
orderId - ID Restrict to one order's redemption links.
couponCode - ID Restrict to one coupon's redemption history.
limit - Int Maximum number of link rows to return.
offset - Int Offset for pagination.

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": 987,
  "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]

Arguments
Name Description
locale - String Restrict to one language code (matches Domain.code, e.g. 'fi', 'sv', 'en').
limit - Int Maximum number of domains to return.
offset - Int Offset for pagination.

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": "abc123",
  "limit": 123,
  "offset": 123
}
Response
{
  "data": {
    "domains": [
      {
        "id": 4,
        "languageId": 987,
        "code": "xyz789",
        "hreflang": "xyz789",
        "domain": "xyz789",
        "cctld": "xyz789",
        "flag": "abc123",
        "sortOrder": 123,
        "googlePixel": "abc123",
        "googleApiSecret": "xyz789",
        "adwordsPixel": "abc123",
        "adwordsPhone": "xyz789",
        "adwordsPurchase": "xyz789",
        "adwordsContact": "abc123",
        "adwordsQuote": "xyz789",
        "metaPixel": "abc123",
        "metaApiSecret": "abc123",
        "tiktokPixel": "abc123",
        "tiktokApiSecret": "xyz789",
        "msAdsPixel": "xyz789",
        "msAdsPhone": "xyz789",
        "msAdsContact": "xyz789",
        "msAdsPurchase": "xyz789",
        "msAdsQuote": "xyz789",
        "pinterestPixel": "xyz789",
        "msClarityPixel": "xyz789",
        "hotjarPixel": "xyz789",
        "wpDomain": "xyz789",
        "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": 987,
  "visibleOnly": true,
  "includeHiddenQuestions": true,
  "sortByOrder": true
}
Response
{
  "data": {
    "faqCategories": [
      {
        "id": "4",
        "icon": "abc123",
        "image": "abc123",
        "visibility": 123,
        "googleIndex": 123,
        "sortOrder": 987,
        "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": "xyz789",
  "languageId": 123,
  "visibleOnly": false
}
Response
{
  "data": {
    "faqQuestion": {
      "id": "4",
      "image": "xyz789",
      "sortOrder": 987,
      "visibility": 123,
      "googleIndex": 987,
      "enableUrl": 987,
      "categories": [123],
      "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]

Arguments
Name Description
limit - Int Maximum number of languages to return.
offset - Int Offset for pagination.

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

Arguments
Name Description
id - ID! Brand id to fetch.
languageId - Int Language to scope ManufacturerInfo rows to. Omit for all languages.

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": "xyz789",
      "code": "xyz789",
      "image": "abc123",
      "brandPageImage": "xyz789",
      "listingImage": "xyz789",
      "sortOrder": 123,
      "status": 987,
      "dateAdded": "xyz789",
      "lastModified": "xyz789",
      "fitValue": "abc123",
      "specialDiscount": 123,
      "cmsDescription": 123,
      "countryApprovedProduct": "abc123",
      "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]

Arguments
Name Description
limit - Int Maximum number of brands to return.
offset - Int Offset for pagination.

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": 123, "offset": 123}
Response
{
  "data": {
    "manufacturers": [
      {
        "id": "4",
        "name": "abc123",
        "code": "abc123",
        "image": "xyz789",
        "brandPageImage": "xyz789",
        "listingImage": "xyz789",
        "sortOrder": 987,
        "status": 123,
        "dateAdded": "xyz789",
        "lastModified": "abc123",
        "fitValue": "xyz789",
        "specialDiscount": 987,
        "cmsDescription": 987,
        "countryApprovedProduct": "xyz789",
        "displayFrontpage": 987,
        "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.

Response

Returns an Order

Arguments
Name Description
id - ID! Order id to fetch.

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": 123,
      "customerName": "xyz789",
      "customerEmail": "abc123",
      "customer": OrderParty,
      "deliveryAddress": OrderParty,
      "billingAddress": OrderParty,
      "status": 123,
      "datePurchased": "xyz789",
      "lastModified": "xyz789",
      "currency": "abc123",
      "currencyValue": 123.45,
      "paymentMethod": "abc123",
      "paymentCode": "xyz789",
      "shippingMethod": "abc123",
      "shippingCode": "abc123",
      "shippingCost": 123.45,
      "deliveryQuantity": 123,
      "deliveryWeight": 123.45,
      "deliveryLength": 123.45,
      "deliveryWidth": 123.45,
      "deliveryHeight": 987.65,
      "deliveryComments": "abc123",
      "shippingLocationId": "abc123",
      "shippingLocationName": "abc123",
      "shippingLocationStreetAddress": "xyz789",
      "shippingLocationPostcode": "abc123",
      "shippingLocationCity": "xyz789",
      "paymentApiId": "abc123",
      "paymentProvider": "xyz789",
      "paymentField": "abc123",
      "paymentInput": "xyz789",
      "paymentTermId": "xyz789",
      "shippingApiId": "abc123",
      "shippingApiTermId": "xyz789",
      "shippingCostCentreId": "xyz789",
      "shippingContractId": "xyz789",
      "shippingContractCourier": "abc123",
      "warehouseCode": "abc123",
      "discountType": "abc123",
      "discountAmount": 123.45,
      "trackingCode": "xyz789",
      "trackingLink": "xyz789",
      "customerNotifiedFlag": 987,
      "trollyLocker": 123.45,
      "transactionId": "xyz789",
      "ipAddress": "abc123",
      "ipIsp": "abc123",
      "pdfFiles": "xyz789",
      "returnReason": "abc123",
      "referralId": "xyz789",
      "ordersApiId": "xyz789",
      "apiSent": 123,
      "emailSent": 123,
      "apiMessage": "abc123",
      "apiMessageDate": "xyz789",
      "apiOrderStatusMessage": "abc123",
      "apiOrderStatusMessageDate": "xyz789",
      "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": 987,
        "productId": 987,
        "productModel": "xyz789",
        "productEan": "xyz789",
        "productName": "xyz789",
        "quantity": 123,
        "quantityReturned": 123,
        "price": 987.65,
        "originalPrice": 123.45,
        "tax": 987.65,
        "stockVariants": "xyz789",
        "lineType": "abc123",
        "comment": "xyz789",
        "customOptions": {},
        "productCategories": "abc123",
        "productWeight": 987.65,
        "productLocation": "abc123",
        "variableImage": "abc123",
        "allowSubstitute": 123,
        "confirmFlag": 987,
        "confirmProductsQuantity": 987,
        "autoComment": 987,
        "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]

Arguments
Name Description
orderId - Int! Order to fetch the timeline for.
statusId - Int Filter to transitions to this single status id.
limit - Int Maximum rows to return.
offset - Int Number of rows to skip for pagination.

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": 987, "statusId": 987, "limit": 123, "offset": 123}
Response
{
  "data": {
    "orderStatusHistory": [
      {
        "id": 4,
        "orderId": 987,
        "statusId": 123,
        "statusName": "xyz789",
        "dateAdded": "xyz789",
        "customerNotified": 123,
        "comments": "xyz789"
      }
    ]
  }
}

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. Resolve via the languages query rather than hardcoding — tenants may extend the platform default set (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": 987}
Response
{
  "data": {
    "orderStatuses": [
      {
        "id": 4,
        "languageId": 123,
        "code": "abc123",
        "name": "abc123",
        "apiFlag": 123,
        "apiId": "abc123",
        "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!]!

Arguments
Name Description
orderId - ID!
class - String

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": 123,
        "title": "abc123",
        "text": "xyz789",
        "value": 123.45,
        "valueUnreturned": 987.65,
        "taxRate": 123.45,
        "taxAmount": 123.45,
        "class": "xyz789",
        "sortOrder": 987
      }
    ]
  }
}

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]

Arguments
Name Description
limit - Int Maximum number of orders to return.
offset - Int Offset for pagination.
customerId - Int Filter to one customer's orders.

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": 987, "offset": 123, "customerId": 123}
Response
{
  "data": {
    "orders": [
      {
        "id": "4",
        "customerId": 987,
        "customerName": "abc123",
        "customerEmail": "abc123",
        "customer": OrderParty,
        "deliveryAddress": OrderParty,
        "billingAddress": OrderParty,
        "status": 987,
        "datePurchased": "abc123",
        "lastModified": "abc123",
        "currency": "abc123",
        "currencyValue": 987.65,
        "paymentMethod": "xyz789",
        "paymentCode": "abc123",
        "shippingMethod": "xyz789",
        "shippingCode": "xyz789",
        "shippingCost": 987.65,
        "deliveryQuantity": 987,
        "deliveryWeight": 123.45,
        "deliveryLength": 987.65,
        "deliveryWidth": 123.45,
        "deliveryHeight": 123.45,
        "deliveryComments": "abc123",
        "shippingLocationId": "abc123",
        "shippingLocationName": "xyz789",
        "shippingLocationStreetAddress": "abc123",
        "shippingLocationPostcode": "abc123",
        "shippingLocationCity": "xyz789",
        "paymentApiId": "abc123",
        "paymentProvider": "xyz789",
        "paymentField": "abc123",
        "paymentInput": "abc123",
        "paymentTermId": "xyz789",
        "shippingApiId": "xyz789",
        "shippingApiTermId": "xyz789",
        "shippingCostCentreId": "abc123",
        "shippingContractId": "abc123",
        "shippingContractCourier": "abc123",
        "warehouseCode": "abc123",
        "discountType": "abc123",
        "discountAmount": 987.65,
        "trackingCode": "xyz789",
        "trackingLink": "abc123",
        "customerNotifiedFlag": 123,
        "trollyLocker": 123.45,
        "transactionId": "xyz789",
        "ipAddress": "xyz789",
        "ipIsp": "xyz789",
        "pdfFiles": "abc123",
        "returnReason": "abc123",
        "referralId": "abc123",
        "ordersApiId": "xyz789",
        "apiSent": 987,
        "emailSent": 987,
        "apiMessage": "abc123",
        "apiMessageDate": "abc123",
        "apiOrderStatusMessage": "abc123",
        "apiOrderStatusMessageDate": "abc123",
        "ordersPackingRulesJson": "abc123",
        "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": 987,
  "userId": 123,
  "startDate": "xyz789",
  "endDate": "abc123",
  "limit": 987,
  "offset": 987
}
Response
{
  "data": {
    "ordersHistory": [
      {
        "id": 4,
        "orderId": 123,
        "entityType": "xyz789",
        "entityId": 123,
        "columnName": "xyz789",
        "oldValue": "xyz789",
        "newValue": "xyz789",
        "actionType": "xyz789",
        "userId": 123,
        "userName": "xyz789",
        "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": 987,
  "transactionUuid": "abc123",
  "orderCode": "abc123",
  "limit": 987,
  "offset": 123
}
Response
{
  "data": {
    "ordersVivawallet": [
      {
        "id": "4",
        "orderId": 987,
        "customerId": 123,
        "paymentMethod": "abc123",
        "notificationId": 987,
        "orderCode": "xyz789",
        "transactionUuid": "abc123",
        "sessionId": "abc123"
      }
    ]
  }
}

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

Arguments
Name Description
id - ID! Product id to fetch.
languageId - Int Language to scope description rows to. Omit to get the row with the lowest language_id.

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": 987}
Response
{
  "data": {
    "product": {
      "id": "4",
      "name": "xyz789",
      "model": "abc123",
      "image": "xyz789",
      "price": 123.45,
      "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]

Arguments
Name Description
productId - ID! Product to fetch options for.
languageId - Int Language id for localized name + description (1=EN, 5=SV, 6=FI, 9=ES, 14=IT — tenants may extend; resolve dynamically via the languages query).

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": "abc123",
        "description": "xyz789",
        "sort": 123,
        "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]

Arguments
Name Description
productId - ID! Product to fetch extra images for.
languageId - Int Language id for the localized caption (1=EN, 5=SV, 6=FI, 9=ES, 14=IT — tenants may extend; resolve dynamically via the languages query).

Example

Query
query productExtraImages(
  $productId: ID!,
  $languageId: Int
) {
  productExtraImages(
    productId: $productId,
    languageId: $languageId
  ) {
    id
    code
    url
    sort
    optionId
    description
  }
}
Variables
{"productId": "4", "languageId": 987}
Response
{
  "data": {
    "productExtraImages": [
      {
        "id": "4",
        "code": "abc123",
        "url": "xyz789",
        "sort": 987,
        "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": "xyz789",
  "endDate": "abc123",
  "userName": "xyz789",
  "limit": 123,
  "offset": 123
}
Response
{
  "data": {
    "productPriceHistory": [
      {
        "id": "4",
        "productId": "4",
        "stockId": "4",
        "price": 987.65,
        "date": "xyz789",
        "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]

Arguments
Name Description
productId - ID! Product to fetch stock rows for.
variant - String Variant identifier to filter to a single SKU. Omit for all variants of the product.

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": 123,
        "price": 123.45,
        "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.

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": 123, "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": "xyz789"
      }
    ]
  }
}

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]

Arguments
Name Description
limit - Int Maximum number of products to return.
offset - Int Offset for pagination.

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": "xyz789",
        "model": "abc123",
        "image": "abc123",
        "price": 987.65,
        "description": "abc123",
        "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": 123,
  "includeCategory": true
}
Response
{
  "data": {
    "productsMedia": [
      {
        "id": 4,
        "productId": 4,
        "categoryId": 123,
        "file": "abc123",
        "sortOrder": 123,
        "type": "xyz789",
        "size": "xyz789",
        "description": "abc123",
        "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]

Arguments
Name Description
productId - ID Restrict to links for this product. Omit to span all products.
categoryId - ID Restrict to links for this category. Omit to span all categories.
limit - Int Maximum number of links to return.
offset - Int Offset for pagination.

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": 123,
  "offset": 987
}
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.

Response

Returns a Quote

Arguments
Name Description
id - ID! Quote id to fetch.

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": 123,
      "sessionId": "xyz789",
      "ipAddress": "xyz789",
      "statusId": 123,
      "dateAdded": "abc123",
      "dateModified": "xyz789",
      "dateReminder": "abc123",
      "dateFollowUp": "abc123",
      "sendReminder": "abc123",
      "sendFollowUp": "xyz789",
      "discountType": "abc123",
      "discountAmount": 123.45,
      "comment": "xyz789",
      "cc": "abc123",
      "shipmentMethod": "xyz789",
      "shipmentCode": "abc123",
      "shipmentPrice": 987.65,
      "warehouseId": 987,
      "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": 123,
        "file": "abc123"
      }
    ]
  }
}

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": 123}
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": "xyz789",
        "dateAdded": "abc123",
        "customerNotified": 987,
        "comments": "abc123"
      }
    ]
  }
}

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!]!

Arguments
Name Description
customerId - Int! Customer id to fetch quotes for.
statusId - Int Filter to quotes with this status id.
limit - Int Maximum number of quotes to return.

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": 123, "limit": 123}
Response
{
  "data": {
    "quotesByCustomer": [
      {
        "id": 4,
        "customerId": 123,
        "sessionId": "xyz789",
        "ipAddress": "xyz789",
        "statusId": 123,
        "dateAdded": "xyz789",
        "dateModified": "abc123",
        "dateReminder": "abc123",
        "dateFollowUp": "abc123",
        "sendReminder": "xyz789",
        "sendFollowUp": "abc123",
        "discountType": "abc123",
        "discountAmount": 987.65,
        "comment": "xyz789",
        "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!]!

Arguments
Name Description
sessionId - String! Session id to fetch quotes for.
statusId - Int Filter to quotes with this status id.
limit - Int Maximum number of quotes to return.

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": "abc123",
        "ipAddress": "abc123",
        "statusId": 123,
        "dateAdded": "xyz789",
        "dateModified": "abc123",
        "dateReminder": "xyz789",
        "dateFollowUp": "xyz789",
        "sendReminder": "abc123",
        "sendFollowUp": "xyz789",
        "discountType": "xyz789",
        "discountAmount": 123.45,
        "comment": "abc123",
        "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]

Arguments
Name Description
productId - ID Restrict to one product's summary.
limit - Int Maximum number of summaries to return.
offset - Int Offset for pagination.

Example

Query
query reviewSummaries(
  $productId: ID,
  $limit: Int,
  $offset: Int
) {
  reviewSummaries(
    productId: $productId,
    limit: $limit,
    offset: $offset
  ) {
    productId
    reviewsCount
    ratingSummary
  }
}
Variables
{"productId": 4, "limit": 987, "offset": 987}
Response
{
  "data": {
    "reviewSummaries": [
      {"productId": 4, "reviewsCount": 123, "ratingSummary": 987}
    ]
  }
}

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]

Arguments
Name Description
productId - ID Restrict to reviews for one product.
statusId - Int Restrict to reviews with this moderation status id.
languageId - Int Scope ReviewDetail rows to one language id.
limit - Int Maximum number of reviews to return.
offset - Int Offset for pagination.

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": 123
}
Response
{
  "data": {
    "reviews": [
      {
        "id": 4,
        "productId": "4",
        "customerId": 987,
        "nickname": "abc123",
        "country": "abc123",
        "isRecommended": false,
        "verifiedBuyer": true,
        "count": 123,
        "statusId": 987,
        "statusCode": "xyz789",
        "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": 987, "parentId": 123, "displayFooter": true}
Response
{
  "data": {
    "serviceCategories": [
      {
        "id": "4",
        "parentId": 987,
        "sortOrder": 123,
        "displayFooter": 123,
        "svgIcon": "abc123",
        "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]

Arguments
Name Description
languageId - Int! Language to fetch description rows in. Required.
categoryId - Int Restrict to pages under one ServiceCategory id.
displayFooter - Boolean When true, restrict to pages with displayFooter = 1 (footer-visible only).

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": 123, "displayFooter": false}
Response
{
  "data": {
    "services": [
      {
        "id": "4",
        "categoryId": 123,
        "image": "xyz789",
        "sortOrder": 123,
        "displayFooter": 987,
        "googleFeed": 987,
        "css": "abc123",
        "externalJs": "abc123",
        "externalCss": "xyz789",
        "svgIcon": "abc123",
        "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]

Arguments
Name Description
warehouseId - Int Restrict to one warehouse. Omit to span all warehouses.
productId - Int Restrict to one product. Omit to span all products.

Example

Query
query warehouseStock(
  $warehouseId: Int,
  $productId: Int
) {
  warehouseStock(
    warehouseId: $warehouseId,
    productId: $productId
  ) {
    id
    warehouseId
    productId
    quantity
  }
}
Variables
{"warehouseId": 987, "productId": 123}
Response
{
  "data": {
    "warehouseStock": [
      {"id": 4, "warehouseId": 123, "productId": 123, "quantity": 123}
    ]
  }
}

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]

Arguments
Name Description
limit - Int Maximum number of warehouses to return.
offset - Int Offset for pagination.

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": 123, "offset": 123}
Response
{
  "data": {
    "warehouses": [
      {
        "id": "4",
        "name": "abc123",
        "code": "xyz789",
        "phone": "abc123",
        "email": "abc123",
        "visible": true,
        "stock": [WarehouseStock]
      }
    ]
  }
}

Mutations

_empty

Response

Returns a String

Example

Query
mutation _empty {
  _empty
}
Response
{"data": {"_empty": "xyz789"}}

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": 123,
      "productModel": "abc123",
      "productEan": "abc123",
      "productName": "abc123",
      "price": 123.45,
      "originalPrice": 987.65,
      "tax": 123.45,
      "quantity": 987,
      "quantityReturned": 987,
      "stockVariants": "xyz789",
      "lineType": "xyz789",
      "comment": "xyz789",
      "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": 987,
      "optionId": 987,
      "optionName": "abc123",
      "optionValue": "abc123",
      "price": 123.45,
      "pricePrefix": "xyz789"
    }
  }
}

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": 987,
      "statusId": 987,
      "dateAdded": "abc123",
      "customerNotified": 987,
      "comments": "abc123"
    }
  }
}

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!

Arguments
Name Description
quoteId - ID! Quote id to attach the file to.
file - String! Filename of the already-uploaded attachment.

Example

Query
mutation addQuoteFile(
  $quoteId: ID!,
  $file: String!
) {
  addQuoteFile(
    quoteId: $quoteId,
    file: $file
  ) {
    id
    quoteId
    file
  }
}
Variables
{
  "quoteId": "4",
  "file": "xyz789"
}
Response
{
  "data": {
    "addQuoteFile": {
      "id": 4,
      "quoteId": 123,
      "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": 987,
      "statusId": 123,
      "statusName": "abc123",
      "dateAdded": "xyz789",
      "customerNotified": 987,
      "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": "xyz789",
      "emailAddress": "xyz789",
      "defaultAddressId": 987,
      "defaultDeliveryAddressId": 987,
      "telephone": "abc123",
      "newsletter": true,
      "freeShipping": 987.65,
      "admin": 123,
      "type": 123,
      "group": "abc123",
      "approved": false,
      "undeliveredOrders": 123,
      "blockPayments": "xyz789",
      "blockShipments": "abc123",
      "temporaryCustomer": true,
      "emailSent": true,
      "apiId": "abc123",
      "apiBillingId": 987,
      "grantWhatsapp": true,
      "billingOperatorId": 987,
      "billingInvoiceAddress": "xyz789",
      "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": 987, "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": "xyz789",
      "defaultAddressId": 123,
      "defaultDeliveryAddressId": 987,
      "telephone": "xyz789",
      "newsletter": true,
      "freeShipping": 123.45,
      "admin": 987,
      "type": 123,
      "group": "xyz789",
      "approved": false,
      "undeliveredOrders": 987,
      "blockPayments": "xyz789",
      "blockShipments": "xyz789",
      "temporaryCustomer": true,
      "emailSent": true,
      "apiId": "xyz789",
      "apiBillingId": 123,
      "grantWhatsapp": true,
      "billingOperatorId": 123,
      "billingInvoiceAddress": "abc123",
      "billingReference": "xyz789",
      "billingReferenceRequired": true,
      "info": CustomerInfo,
      "addresses": [Address]
    }
  }
}

createOrUpdateSharedBasket

Description

Upsert a line in a shared basket. Used to add a product to a collaborative basket (sales rep building a draft for a customer, team-mates co-editing a wholesale list) or to overwrite an existing line's full contents in one call. For narrow updates on quantity only, see updateSharedBasketQuantity.

Response

Returns a SharedBasketItem!

Arguments
Name Description
input - CreateSharedBasketInput! Line content to upsert.

Example

Query
mutation createOrUpdateSharedBasket($input: CreateSharedBasketInput!) {
  createOrUpdateSharedBasket(input: $input) {
    id
    sharedCartId
    customersId
    itemId
    productId
    variants
    productOptions
    comment
    customOptions
    quantity
    specialPrice
    bundleId
    includes
    dateAdded
    expiresAt
  }
}
Variables
{"input": CreateSharedBasketInput}
Response
{
  "data": {
    "createOrUpdateSharedBasket": {
      "id": "4",
      "sharedCartId": "abc123",
      "customersId": 987,
      "itemId": "abc123",
      "productId": 123,
      "variants": "abc123",
      "productOptions": "xyz789",
      "comment": "xyz789",
      "customOptions": "abc123",
      "quantity": 987,
      "specialPrice": 123.45,
      "bundleId": "abc123",
      "includes": "xyz789",
      "dateAdded": "abc123",
      "expiresAt": "xyz789"
    }
  }
}

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": 987,
      "customerName": "xyz789",
      "customerEmail": "xyz789",
      "customer": OrderParty,
      "deliveryAddress": OrderParty,
      "billingAddress": OrderParty,
      "status": 987,
      "datePurchased": "abc123",
      "lastModified": "xyz789",
      "currency": "abc123",
      "currencyValue": 123.45,
      "paymentMethod": "abc123",
      "paymentCode": "abc123",
      "shippingMethod": "abc123",
      "shippingCode": "abc123",
      "shippingCost": 123.45,
      "deliveryQuantity": 987,
      "deliveryWeight": 123.45,
      "deliveryLength": 987.65,
      "deliveryWidth": 123.45,
      "deliveryHeight": 987.65,
      "deliveryComments": "xyz789",
      "shippingLocationId": "xyz789",
      "shippingLocationName": "xyz789",
      "shippingLocationStreetAddress": "xyz789",
      "shippingLocationPostcode": "abc123",
      "shippingLocationCity": "abc123",
      "paymentApiId": "xyz789",
      "paymentProvider": "abc123",
      "paymentField": "xyz789",
      "paymentInput": "xyz789",
      "paymentTermId": "abc123",
      "shippingApiId": "abc123",
      "shippingApiTermId": "xyz789",
      "shippingCostCentreId": "abc123",
      "shippingContractId": "xyz789",
      "shippingContractCourier": "xyz789",
      "warehouseCode": "abc123",
      "discountType": "abc123",
      "discountAmount": 123.45,
      "trackingCode": "xyz789",
      "trackingLink": "abc123",
      "customerNotifiedFlag": 987,
      "trollyLocker": 123.45,
      "transactionId": "xyz789",
      "ipAddress": "abc123",
      "ipIsp": "abc123",
      "pdfFiles": "abc123",
      "returnReason": "xyz789",
      "referralId": "abc123",
      "ordersApiId": "abc123",
      "apiSent": 987,
      "emailSent": 123,
      "apiMessage": "abc123",
      "apiMessageDate": "xyz789",
      "apiOrderStatusMessage": "xyz789",
      "apiOrderStatusMessageDate": "abc123",
      "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": 987,
      "productsOptionsId": 987,
      "required": false,
      "position": 123,
      "type": "abc123"
    }
  }
}

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": 123,
      "sessionId": "abc123",
      "ipAddress": "xyz789",
      "statusId": 123,
      "dateAdded": "abc123",
      "dateModified": "xyz789",
      "dateReminder": "xyz789",
      "dateFollowUp": "xyz789",
      "sendReminder": "xyz789",
      "sendFollowUp": "xyz789",
      "discountType": "xyz789",
      "discountAmount": 987.65,
      "comment": "xyz789",
      "cc": "abc123",
      "shipmentMethod": "xyz789",
      "shipmentCode": "abc123",
      "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": true}}

expireSharedBasketItem

Description

Expire a shared-basket line — rewrite the expiresAt timestamp so subsequent requireActive=true reads start refusing. Used by admin 'Force expire' actions and by the periodic stale-basket sweeper.

Response

Returns a SharedBasketItem!

Arguments
Name Description
input - ExpireSharedBasketInput! Expiry update for one (sharedCartId, itemId) line.

Example

Query
mutation expireSharedBasketItem($input: ExpireSharedBasketInput!) {
  expireSharedBasketItem(input: $input) {
    id
    sharedCartId
    customersId
    itemId
    productId
    variants
    productOptions
    comment
    customOptions
    quantity
    specialPrice
    bundleId
    includes
    dateAdded
    expiresAt
  }
}
Variables
{"input": ExpireSharedBasketInput}
Response
{
  "data": {
    "expireSharedBasketItem": {
      "id": "4",
      "sharedCartId": "xyz789",
      "customersId": 123,
      "itemId": "xyz789",
      "productId": 987,
      "variants": "abc123",
      "productOptions": "abc123",
      "comment": "abc123",
      "customOptions": "abc123",
      "quantity": 987,
      "specialPrice": 123.45,
      "bundleId": "abc123",
      "includes": "abc123",
      "dateAdded": "abc123",
      "expiresAt": "xyz789"
    }
  }
}

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": 123}
  }
}

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.

Response

Returns a Boolean!

Arguments
Name Description
id - ID!

Example

Query
mutation removeOrdersProduct($id: ID!) {
  removeOrdersProduct(id: $id)
}
Variables
{"id": 4}
Response
{"data": {"removeOrdersProduct": true}}

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.

Response

Returns a Boolean!

Arguments
Name Description
id - ID!

Example

Query
mutation removeOrdersProductsVariant($id: ID!) {
  removeOrdersProductsVariant(id: $id)
}
Variables
{"id": "4"}
Response
{"data": {"removeOrdersProductsVariant": false}}

removeProductCustomOption

Description

Detach a custom option from a product. The underlying ProductOption is untouched; only this product's override is removed.

Response

Returns a Boolean

Arguments
Name Description
id - ID!

Example

Query
mutation removeProductCustomOption($id: ID!) {
  removeProductCustomOption(id: $id)
}
Variables
{"id": 4}
Response
{"data": {"removeProductCustomOption": false}}

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": true}}

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": 987,
      "productId": 123,
      "productModel": "xyz789",
      "productEan": "abc123",
      "productName": "abc123",
      "price": 987.65,
      "originalPrice": 987.65,
      "tax": 123.45,
      "quantity": 987,
      "quantityReturned": 987,
      "stockVariants": "xyz789",
      "lineType": "abc123",
      "comment": "xyz789",
      "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": 123,
      "orderProductId": 123,
      "optionId": 987,
      "optionName": "xyz789",
      "optionValue": "abc123",
      "price": 987.65,
      "pricePrefix": "abc123"
    }
  }
}

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": 123,
      "productsOptionsId": 987,
      "required": true,
      "position": 987,
      "type": "abc123"
    }
  }
}

updateSharedBasketQuantity

Description

Change the quantity on an existing shared-basket line. The storefront's quantity stepper calls this on every increment / decrement, so it's the hot-path mutation for shared-basket edits. Throws when the line is past expiresAt unless requireActive=false.

Response

Returns a SharedBasketItem!

Arguments
Name Description
input - UpdateSharedBasketQuantityInput! Quantity update for one (sharedCartId, itemId) line.

Example

Query
mutation updateSharedBasketQuantity($input: UpdateSharedBasketQuantityInput!) {
  updateSharedBasketQuantity(input: $input) {
    id
    sharedCartId
    customersId
    itemId
    productId
    variants
    productOptions
    comment
    customOptions
    quantity
    specialPrice
    bundleId
    includes
    dateAdded
    expiresAt
  }
}
Variables
{"input": UpdateSharedBasketQuantityInput}
Response
{
  "data": {
    "updateSharedBasketQuantity": {
      "id": 4,
      "sharedCartId": "abc123",
      "customersId": 987,
      "itemId": "abc123",
      "productId": 123,
      "variants": "xyz789",
      "productOptions": "abc123",
      "comment": "xyz789",
      "customOptions": "xyz789",
      "quantity": 987,
      "specialPrice": 987.65,
      "bundleId": "abc123",
      "includes": "abc123",
      "dateAdded": "abc123",
      "expiresAt": "abc123"
    }
  }
}

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": 123,
      "customersId": 987,
      "notificationId": 123,
      "sessionId": "abc123",
      "transactionId": "xyz789",
      "stamp": "xyz789",
      "reference": "abc123",
      "amount": 123.45,
      "error": "abc123"
    }
  }
}

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):

  • 'ar_admin_login' — admin login attempt
  • 'ar_admin_logoff' — admin logout
  • 'ar_admin_force_action' — admin-triggered force operations (e.g. cache resets) Tenants may add modules; treat as free-form code.
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": "xyz789",
  "identifier": "xyz789",
  "userAgent": "xyz789",
  "success": true,
  "dateAdded": "abc123"
}

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": 987, "entries": [ActionRecorderEntry]}

AddCustomerFavoriteInput

Fields
Input Field Description
customersId - Int! Customer to attach the favorite to.
productsId - Int! Product the customer is favoriting.
Example
{"customersId": 987, "productsId": 123}

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": 987,
  "productModel": "xyz789",
  "productEan": "xyz789",
  "productName": "abc123",
  "price": 987.65,
  "originalPrice": 987.65,
  "tax": 123.45,
  "quantity": 123,
  "stockVariants": "abc123",
  "lineType": "xyz789",
  "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": 987.65,
  "pricePrefix": "xyz789"
}

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": 123,
  "statusId": 987,
  "customerNotified": 987,
  "comments": "xyz789"
}

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": "abc123",
  "firstname": "abc123",
  "lastname": "abc123",
  "streetAddress": "xyz789",
  "vatid": "abc123",
  "postcode": "abc123",
  "city": "xyz789",
  "state": "xyz789",
  "countryId": 123,
  "zoneId": 123,
  "comments": "abc123",
  "billingStreetAddress": "xyz789",
  "billingFirstname": "xyz789",
  "billingLastname": "abc123",
  "billingPostcode": "abc123",
  "billingCity": "abc123",
  "billingCountryId": "abc123",
  "billingCompany": "xyz789",
  "billingVatid": "xyz789",
  "billingZoneId": "xyz789",
  "billingState": "xyz789",
  "billingOperatorId": 123,
  "billingInvoiceAddress": "abc123",
  "billingReference": "xyz789",
  "billingReferenceRequired": true
}

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": 987,
  "gender": "abc123",
  "company": "abc123",
  "firstname": "abc123",
  "lastname": "abc123",
  "streetAddress": "xyz789",
  "vatid": "xyz789",
  "postcode": "xyz789",
  "city": "abc123",
  "state": "xyz789",
  "countryId": 987,
  "zoneId": 123,
  "comments": "xyz789",
  "billingStreetAddress": "abc123",
  "billingFirstname": "xyz789",
  "billingLastname": "abc123",
  "billingPostcode": "abc123",
  "billingCity": "abc123",
  "billingCountryId": "abc123",
  "billingCompany": "xyz789",
  "billingVatid": "abc123",
  "billingZoneId": "xyz789",
  "billingState": "xyz789",
  "billingOperatorId": 123,
  "billingInvoiceAddress": "xyz789",
  "billingReference": "xyz789",
  "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": "xyz789",
  "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": false,
  "errorCleared": true
}

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:

  • 'create' — product was created
  • 'update' — product was edited
  • 'delete' — product was deleted Tenants may extend; treat as free-form code rather than a fixed enum.
dateAdded - String! Timestamp the action was recorded.
Example
{
  "id": 4,
  "productId": 123,
  "userId": 987,
  "userName": "abc123",
  "action": "xyz789",
  "dateAdded": "abc123"
}

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": true,
  "writePermission": true,
  "grantAccess": "abc123"
}

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:

  • 'queued': job has not failed (error is null) — pending or successfully processed
  • 'failed': last attempt produced an error
Example
{
  "id": 4,
  "jobId": "xyz789",
  "api": "abc123",
  "endpoint": "xyz789",
  "method": "xyz789",
  "data": {},
  "createdAt": "xyz789",
  "error": "abc123",
  "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. Example values:

  • 1: English
  • 5: Swedish
  • 6: Finnish
  • 9: Spanish
  • 14: Italian

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:

  • '005900' (dark green): item is available
  • 'ff0000' (red): item is unavailable or has an extended delivery window

May be null for legacy labels that pre-date the colored-badge UI.

Example
{
  "id": "4",
  "languageId": 987,
  "name": "abc123",
  "hexCode": "abc123"
}

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": 987,
  "invoicePaymentDate": "abc123",
  "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.
Arguments
startDate - String

Inclusive lower bound on the banner-history date. ISO-8601 date.

endDate - String

Inclusive upper bound on the banner-history date. ISO-8601 date.

limit - Int

Maximum number of day-buckets to return.

offset - Int

Offset for pagination across day-buckets.

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.

Fields
Field Name Description
impressions - Int! Total impressions across the banner's full history.
clicks - Int! Total clicks across the banner's full history.
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.

Fields
Field Name Description
bannerId - Int! Banner the day's stats belong to.
date - String! Date the bucket aggregates (DATE-truncated, no time component).
impressions - Int! Sum of banners_shown across the day for this banner.
clicks - Int! Sum of banners_clicked across the day for this banner.
Example
{
  "bannerId": 987,
  "date": "xyz789",
  "impressions": 987,
  "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": "xyz789",
  "vatid": "xyz789",
  "operatorId": 123,
  "invoiceAddress": "abc123",
  "reference": "xyz789",
  "referenceRequired": false
}

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": 987,
  "sessionKey": "xyz789",
  "loadTimeMsec": 123,
  "categoryId": 987,
  "productId": 123,
  "manufacturerId": 123,
  "color": 987,
  "size": 987,
  "geoipCountry": "abc123",
  "ipAddress": "abc123",
  "date": "xyz789",
  "timestamp": 123,
  "topPicks": true,
  "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": 987,
  "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 tag for the category page.</p> </root>
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": "abc123",
  "url": "xyz789",
  "path": "xyz789",
  "pathOld": "abc123",
  "description": "abc123",
  "descriptionTop": "abc123",
  "metaTitle": "xyz789",
  "metaDescription": "abc123",
  "featureTitle": "abc123",
  "typeTitle": "abc123",
  "bannerText": "abc123",
  "bannerButton": "abc123",
  "bannerUrl": "xyz789",
  "redirectStatus": 123
}

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": "xyz789",
  "value": "abc123",
  "description": "xyz789",
  "groupId": 987,
  "sortOrder": 123,
  "lastModified": "xyz789",
  "dateAdded": "abc123",
  "useFunction": "xyz789",
  "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": 987,
  "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": "xyz789",
  "iso3": "xyz789",
  "dutyRate": 987.65,
  "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).
countryCode - String Two- or three-letter country code, alternative to countryId. The resolver maps it through countries; if countryId is also provided they must match.
zoneId - Int Zone id within the country.
comments - String Free-form delivery instructions captured at registration.
Example
{
  "gender": "xyz789",
  "firstname": "xyz789",
  "lastname": "abc123",
  "emailAddress": "xyz789",
  "password": "abc123",
  "telephone": "abc123",
  "newsletter": false,
  "company": "xyz789",
  "streetAddress": "abc123",
  "vatid": "xyz789",
  "postcode": "abc123",
  "city": "xyz789",
  "state": "abc123",
  "countryId": 987,
  "countryCode": "xyz789",
  "zoneId": 123,
  "comments": "xyz789"
}

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 Country id (resolves against the countries query).
countryCode - String Two- or three-letter country code, alternative to countryId. The resolver maps it through countries; if countryId is also provided they must match.
zoneId - Int
comments - String
Example
{
  "gender": "abc123",
  "firstname": "xyz789",
  "lastname": "abc123",
  "emailAddress": "xyz789",
  "telephone": "xyz789",
  "newsletter": false,
  "company": "abc123",
  "streetAddress": "abc123",
  "vatid": "abc123",
  "postcode": "xyz789",
  "city": "xyz789",
  "state": "xyz789",
  "countryId": 123,
  "countryCode": "abc123",
  "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": 987,
  "billingAddressId": 987,
  "customer": OrderPartyInput,
  "deliveryAddress": OrderPartyInput,
  "billingAddress": OrderPartyInput,
  "status": 987,
  "statusComment": "xyz789",
  "currency": "xyz789",
  "currencyValue": 987.65,
  "paymentMethod": "xyz789",
  "paymentCode": "abc123",
  "paymentApiId": "xyz789",
  "paymentField": "xyz789",
  "paymentInput": {},
  "shippingMethod": "abc123",
  "shippingApiId": "abc123",
  "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": 123,
  "sku": "xyz789",
  "productModel": "xyz789",
  "productEan": "xyz789",
  "productName": "abc123",
  "price": 987.65,
  "originalPrice": 123.45,
  "tax": 987.65,
  "quantity": 123,
  "stockVariants": "xyz789",
  "lineType": "xyz789",
  "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": 987.65,
  "pricePrefix": "abc123"
}

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": 987,
  "productsOptionsId": 123,
  "required": true,
  "position": 123,
  "type": "xyz789"
}

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": 987,
  "sessionId": "abc123",
  "ipAddress": "xyz789",
  "statusId": 123,
  "shipmentMethod": "abc123",
  "shipmentCode": "abc123",
  "shipmentPrice": 123.45,
  "warehouseId": 987,
  "items": [QuoteProductInput]
}

CreateSharedBasketInput

Description

Input for createOrUpdateSharedBasket — upsert a line into a shared basket. When a row with the same (sharedCartId, itemId) exists, the resolver updates it; otherwise it inserts a new row. requireActive guards against edits on already-expired baskets.

Fields
Input Field Description
sharedCartId - String! Opaque shared-cart id.
itemId - String! Caller-supplied line identifier within the shared basket.
customersId - Int Customer to bind the line to. Optional — leave null for anonymous shared baskets.
productId - Int Catalog product id.
variants - String Variant identifier (comma-separated option-value ids).
productOptions - String Configurable-option choices.
comment - String Free-form per-line comment.
customOptions - String JSON-encoded custom-option text inputs.
quantity - Int! Quantity to set on the line.
specialPrice - Float Price snapshot to lock the line to.
bundleId - String Bundle parent id for child rows.
includes - String Bundle-children references when this row is a bundle parent.
expiresAt - String Timestamp the line should expire at.
requireActive - Boolean When true (default), the resolver throws if the existing line is past expiresAt. Set false to permit edits on expired baskets (e.g. an admin reviving a stale shared basket).
Example
{
  "sharedCartId": "xyz789",
  "itemId": "abc123",
  "customersId": 123,
  "productId": 987,
  "variants": "abc123",
  "productOptions": "xyz789",
  "comment": "xyz789",
  "customOptions": "abc123",
  "quantity": 123,
  "specialPrice": 123.45,
  "bundleId": "abc123",
  "includes": "xyz789",
  "expiresAt": "xyz789",
  "requireActive": false
}

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": "abc123",
  "code": "abc123",
  "symbolLeft": "xyz789",
  "symbolRight": "xyz789",
  "value": 123.45,
  "lastUpdated": "abc123"
}

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:

  • 0: temporary / anonymized customer (system-managed; placeholder for guest checkouts and soft-deleted records)
  • 1: registered individual customer (default for normal end-user accounts)
  • 2: business / B2B customer (typically has VAT id and company populated)
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": "abc123",
  "lastname": "abc123",
  "emailAddress": "abc123",
  "defaultAddressId": 123,
  "defaultDeliveryAddressId": 123,
  "telephone": "abc123",
  "newsletter": false,
  "freeShipping": 987.65,
  "admin": 123,
  "type": 987,
  "group": "abc123",
  "approved": true,
  "undeliveredOrders": 987,
  "blockPayments": "abc123",
  "blockShipments": "abc123",
  "temporaryCustomer": false,
  "emailSent": true,
  "apiId": "xyz789",
  "apiBillingId": 123,
  "grantWhatsapp": false,
  "billingOperatorId": 123,
  "billingInvoiceAddress": "xyz789",
  "billingReference": "abc123",
  "billingReferenceRequired": true,
  "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": 987,
  "status": 987,
  "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.

Fields
Field Name Description
id - ID! Database row id of the favorite entry.
customersId - Int! Customer the favorite belongs to.
productsId - Int! Product the favorite points at.
Example
{
  "id": "4",
  "customersId": 987,
  "productsId": 987
}

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:

  • 'fixed' — currency amount off the product price
  • 'percent' — percentage off the product price
  • 'shipping' — applies as a shipping subsidy / free-shipping flag
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:

  • 'price' — basket value in the tenant's default currency
  • 'quantity' — total item count in the basket
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:

  • 'all' — applies to every customer
  • 'vatid' — B2B / VAT-id-bearing customers only
  • 'regular' — consumer accounts (no VAT id) only
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:

  • 'fixed' — single discountAmount applied across the group
  • 'dynamic' — discount comes from CustomerGroupDynamicDiscount tiers
  • 'matrix' — manufacturer × category matrix of discounts
  • 'list' — per-product CustomerGroupPriceRule overrides
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": "xyz789",
  "discountAmount": 987.65,
  "discountType": "abc123",
  "dateStart": "xyz789",
  "dateEnd": "abc123",
  "minOrder": 123.45,
  "minOrderType": "xyz789",
  "customerType": "abc123",
  "discountedProducts": 987,
  "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": 123.45,
  "dateStart": "xyz789",
  "dateEnd": "xyz789",
  "manufacturer": "abc123",
  "category": "abc123",
  "sort": 123
}

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": "xyz789",
  "validTo": "abc123",
  "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:

  • 'customers' — top-level customer record
  • 'address_book' — one of the customer's saved addresses
  • 'customers_info' — activity-stats sidecar (login counters, etc.) Tenants may extend; treat as free-form code rather than a fixed enum.
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": "xyz789",
  "fieldName": "xyz789",
  "oldValue": "xyz789",
  "newValue": "xyz789",
  "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": "abc123",
  "numberOfLogons": 987,
  "numberOfFailedLogins": 987,
  "dateOfLastLoginFail": "xyz789",
  "dateAccountCreated": "abc123",
  "dateAccountLastModified": "xyz789",
  "sourceId": 123,
  "globalProductNotifications": 987
}

CustomerPrice

Fields
Field Name Description
id - ID!
customerId - Int!
productId - Int!
price - Float!
currency - String
validFrom - String
validTo - String
Example
{
  "id": "4",
  "customerId": 123,
  "productId": 123,
  "price": 987.65,
  "currency": "xyz789",
  "validFrom": "abc123",
  "validTo": "abc123"
}

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.

Fields
Field Name Description
id - ID! Database row id of the inclusion entry.
customerId - Int! Customer the inclusion applies to.
productId - Int! Product the customer is granted access to.
Example
{
  "id": "4",
  "customerId": 987,
  "productId": 123
}

CustomerProductInclusionInput

Fields
Input Field Description
customerId - Int! Customer to grant or revoke access for.
productId - Int! Product to grant or revoke access to.
Example
{"customerId": 987, "productId": 123}

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": "xyz789",
  "name": "abc123",
  "secondaryName": "abc123",
  "addressLine1": "xyz789",
  "addressLine2": "abc123",
  "addressLine3": "xyz789",
  "deliveryName1": "abc123",
  "deliveryName2": "abc123",
  "deliveryName3": "abc123",
  "billingCustomerId": 123,
  "paymentTerm": "xyz789",
  "customerGroup": "xyz789",
  "chain": "xyz789",
  "salesCode": "abc123",
  "creditLimit": "xyz789",
  "deliveryBlock": "xyz789",
  "email": "xyz789",
  "website": "xyz789",
  "phone": "xyz789",
  "fax": "xyz789",
  "deliveryMethod": "abc123",
  "discountGroup": "xyz789",
  "discountPercent": 987.65,
  "secondaryDiscountPercent": 987.65,
  "languageCode": "abc123",
  "comment1": "abc123",
  "comment2": "xyz789",
  "contactPerson": "xyz789",
  "contactPersonId": 123,
  "lastLoginAt": "xyz789",
  "vatLiability": "abc123",
  "currency": "abc123",
  "modifiedAt": "xyz789",
  "businessId": "abc123",
  "billingAddress": "abc123",
  "intermediaryService": "xyz789",
  "netvisorKey": 123
}

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": "xyz789",
  "productId": 123,
  "variants": "abc123",
  "productOptions": "abc123",
  "comment": "abc123",
  "customOptions": "xyz789",
  "quantity": 123,
  "specialPrice": 987.65,
  "bundleId": "abc123",
  "includes": "abc123",
  "dateAdded": "xyz789",
  "emailSent": 987,
  "emailLast": "abc123",
  "variableImage": "xyz789",
  "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": "abc123",
  "cardType": "abc123",
  "numberFiltered": "abc123",
  "expiryDate": "xyz789",
  "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": "xyz789",
  "lastname": "abc123",
  "streetAddress": "xyz789",
  "vatid": "abc123",
  "postcode": "abc123",
  "city": "xyz789",
  "state": "abc123",
  "countryId": 123,
  "zoneId": 123,
  "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:

  • 'fixed' — fixed currency amount off the order total
  • 'percent' — percentage off the order total
  • 'shipping' — applied as a shipping subsidy / free shipping
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:

  • 'price' — basket value in the tenant's default currency
  • 'quantity' — total item count in the basket
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:

  • 'all' — any customer can redeem
  • 'vatid' — only customers with a VAT id (B2B accounts)
  • 'regular' — only customers without a VAT id (consumer accounts)
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": "abc123",
  "dateStart": "xyz789",
  "dateEnd": "abc123",
  "maxUse": 987,
  "minOrder": 987.65,
  "minOrderType": "xyz789",
  "numberAvailable": 123,
  "customerType": "xyz789",
  "discountedProducts": 987,
  "discountedProductsOld": 123,
  "allowedProducts": "xyz789",
  "categories": [987],
  "products": [987],
  "customers": [123],
  "orders": [987],
  "manufacturers": [987],
  "shippingMethods": ["xyz789"],
  "zones": [987]
}

DiscountCouponCustomerLinkInput

Fields
Input Field Description
couponCode - ID! Coupon code to attach / detach.
customerId - ID! Customer id to attach the coupon to or detach it from.
Example
{"couponCode": 4, "customerId": 4}

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": "xyz789",
  "hreflang": "abc123",
  "domain": "abc123",
  "cctld": "xyz789",
  "flag": "xyz789",
  "sortOrder": 123,
  "googlePixel": "xyz789",
  "googleApiSecret": "abc123",
  "adwordsPixel": "xyz789",
  "adwordsPhone": "abc123",
  "adwordsPurchase": "abc123",
  "adwordsContact": "abc123",
  "adwordsQuote": "abc123",
  "metaPixel": "xyz789",
  "metaApiSecret": "abc123",
  "tiktokPixel": "abc123",
  "tiktokApiSecret": "xyz789",
  "msAdsPixel": "abc123",
  "msAdsPhone": "xyz789",
  "msAdsContact": "abc123",
  "msAdsPurchase": "abc123",
  "msAdsQuote": "xyz789",
  "pinterestPixel": "xyz789",
  "msClarityPixel": "abc123",
  "hotjarPixel": "abc123",
  "wpDomain": "xyz789",
  "openaiChatInstructions": "xyz789",
  "openaiVectorStoreId": "xyz789",
  "openaiChatAssistantId": "abc123"
}

ExpireSharedBasketInput

Description

Input for expireSharedBasketItem — rewrite the line's expiresAt to the current moment (or the supplied timestamp) so subsequent requireActive=true reads / edits start refusing. Used by 'Mark as expired' admin actions and by the auto-expiry sweeper.

Fields
Input Field Description
sharedCartId - String! Opaque shared-cart id.
itemId - String! Caller-supplied line identifier.
expiresAt - String Timestamp to set as the new expiresAt. When omitted the resolver uses 'now'.
Example
{
  "sharedCartId": "xyz789",
  "itemId": "abc123",
  "expiresAt": "abc123"
}

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": "xyz789",
  "visibility": 987,
  "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 tag for the category landing page.</p> </root>
metaDescription - String Localized for the category landing page.
Example
{
  "languageId": 123,
  "name": "xyz789",
  "url": "xyz789",
  "description": "abc123",
  "metaTitle": "xyz789",
  "metaDescription": "xyz789"
}

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": "abc123",
  "sortOrder": 987,
  "visibility": 123,
  "googleIndex": 123,
  "enableUrl": 987,
  "categories": [987],
  "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 tag for the per-question landing page.</p> </root>
metaDescription - String Localized for the per-question landing page.
Example
{
  "languageId": 123,
  "question": "abc123",
  "answer": "abc123",
  "shortAnswer": "xyz789",
  "url": "xyz789",
  "metaTitle": "xyz789",
  "metaDescription": "xyz789"
}

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": "abc123",
  "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": "xyz789",
  "code": "xyz789",
  "image": "abc123",
  "brandPageImage": "abc123",
  "listingImage": "xyz789",
  "sortOrder": 987,
  "status": 123,
  "dateAdded": "xyz789",
  "lastModified": "abc123",
  "fitValue": "abc123",
  "specialDiscount": 987,
  "cmsDescription": 123,
  "countryApprovedProduct": "xyz789",
  "displayFrontpage": 123,
  "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": 123,
  "dateLastClick": "abc123",
  "description": "abc123",
  "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. Example values across tenants (defaults; tenants extend):

  • 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 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
class - String
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": 987,
  "customerName": "abc123",
  "customerEmail": "xyz789",
  "customer": OrderParty,
  "deliveryAddress": OrderParty,
  "billingAddress": OrderParty,
  "status": 987,
  "datePurchased": "abc123",
  "lastModified": "abc123",
  "currency": "xyz789",
  "currencyValue": 123.45,
  "paymentMethod": "abc123",
  "paymentCode": "abc123",
  "shippingMethod": "xyz789",
  "shippingCode": "xyz789",
  "shippingCost": 987.65,
  "deliveryQuantity": 123,
  "deliveryWeight": 987.65,
  "deliveryLength": 987.65,
  "deliveryWidth": 987.65,
  "deliveryHeight": 987.65,
  "deliveryComments": "abc123",
  "shippingLocationId": "xyz789",
  "shippingLocationName": "xyz789",
  "shippingLocationStreetAddress": "xyz789",
  "shippingLocationPostcode": "xyz789",
  "shippingLocationCity": "abc123",
  "paymentApiId": "abc123",
  "paymentProvider": "xyz789",
  "paymentField": "abc123",
  "paymentInput": "xyz789",
  "paymentTermId": "xyz789",
  "shippingApiId": "xyz789",
  "shippingApiTermId": "xyz789",
  "shippingCostCentreId": "xyz789",
  "shippingContractId": "abc123",
  "shippingContractCourier": "abc123",
  "warehouseCode": "abc123",
  "discountType": "xyz789",
  "discountAmount": 123.45,
  "trackingCode": "abc123",
  "trackingLink": "abc123",
  "customerNotifiedFlag": 123,
  "trollyLocker": 987.65,
  "transactionId": "xyz789",
  "ipAddress": "abc123",
  "ipIsp": "abc123",
  "pdfFiles": "abc123",
  "returnReason": "abc123",
  "referralId": "abc123",
  "ordersApiId": "abc123",
  "apiSent": 123,
  "emailSent": 987,
  "apiMessage": "xyz789",
  "apiMessageDate": "abc123",
  "apiOrderStatusMessage": "abc123",
  "apiOrderStatusMessageDate": "xyz789",
  "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:

  • 'orders': field on the order header
  • 'orders_products': field on a line item
  • 'orders_total': totals breakdown adjustment
  • 'orders_status_history': status-history modification
  • 'orders_notifications': notification record
  • 'orders_products_variants': variant selection on a line
  • 'invoice_book', 'orders_actions': tenant-specific extensions
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:

  • 'update' (most common): a column on an existing row was modified
  • 'rebuild': bulk recomputation (e.g. totals re-derived from lines)
  • 'delete': row was deleted
  • 'insert': row was created
  • 'notify': a notification was emitted to the customer
  • 'action': tenant-specific custom action
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": 123,
  "entityType": "abc123",
  "entityId": 123,
  "columnName": "abc123",
  "oldValue": "abc123",
  "newValue": "xyz789",
  "actionType": "xyz789",
  "userId": 987,
  "userName": "xyz789",
  "page": "xyz789",
  "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:

  • 'item' (default): regular product line
  • 'refund': return-credit line subtracted from the order total

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": 123,
  "productId": 987,
  "productModel": "xyz789",
  "productEan": "xyz789",
  "productName": "abc123",
  "quantity": 987,
  "quantityReturned": 123,
  "price": 123.45,
  "originalPrice": 123.45,
  "tax": 987.65,
  "stockVariants": "xyz789",
  "lineType": "abc123",
  "comment": "abc123",
  "customOptions": {},
  "productCategories": "xyz789",
  "productWeight": 987.65,
  "productLocation": "xyz789",
  "variableImage": "abc123",
  "allowSubstitute": 123,
  "confirmFlag": 123,
  "confirmProductsQuantity": 987,
  "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:

  • '+' (most common): additive — added to the base product price
  • '' (empty): replacement — overrides the base price entirely

Tenants may define additional prefixes; treat unrecognised values as additive by default.

Example
{
  "id": "4",
  "orderProductId": 987,
  "optionId": 987,
  "optionName": "abc123",
  "optionValue": "xyz789",
  "price": 123.45,
  "pricePrefix": "abc123"
}

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": 123,
  "customersId": 123,
  "notificationId": 123,
  "sessionId": "xyz789",
  "transactionId": "abc123",
  "stamp": "abc123",
  "reference": "abc123",
  "amount": 987.65,
  "error": "xyz789"
}

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": "xyz789",
  "company": "abc123",
  "vatId": "xyz789",
  "streetAddress": "abc123",
  "city": "abc123",
  "postcode": "xyz789",
  "state": "xyz789",
  "country": "abc123",
  "telephone": "abc123",
  "emailAddress": "xyz789",
  "addressFormatId": 987,
  "invoiceAddress": "abc123",
  "operatorId": 987,
  "reference": "xyz789"
}

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": "abc123",
  "company": "xyz789",
  "vatId": "xyz789",
  "streetAddress": "abc123",
  "city": "abc123",
  "postcode": "abc123",
  "state": "abc123",
  "countryId": 123,
  "countryCode": "xyz789",
  "telephone": "abc123",
  "emailAddress": "xyz789",
  "addressFormatId": 123,
  "invoiceAddress": "abc123",
  "operatorId": 123,
  "reference": "abc123"
}

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": "abc123",
  "colorCode": "xyz789"
}

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:

  • 0: not notified (internal state change)
  • 1: notification email sent
comments - String Free-form staff comment attached to the transition (e.g. 'Awaiting carrier pickup', 'Refunded — damaged on arrival').
Example
{
  "id": "4",
  "orderId": 123,
  "statusId": 123,
  "statusName": "abc123",
  "dateAdded": "abc123",
  "customerNotified": 123,
  "comments": "abc123"
}

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:

  • 'Total': grand total of the order
  • 'Subtotal': line-items subtotal before fees and taxes
  • 'Tax': aggregated tax line (or one row per VAT rate)
  • 'Shipping': shipping cost line
  • 'DiscountCoupon': coupon-applied discount
  • 'Cod': cash-on-delivery surcharge
  • 'ot_klarna_fee', 'ot_collector_invoice_fee', 'ot_kreditor_fin_payment_chg': payment-provider fees
  • 'ot_3for2': 3-for-2 promotional discount
  • 'ot_custom', 'ot_custom_2': tenant-defined custom totals

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": "abc123",
  "text": "xyz789",
  "value": 987.65,
  "valueUnreturned": 987.65,
  "taxRate": 987.65,
  "taxAmount": 123.45,
  "class": "xyz789",
  "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:

  • 'VivawalletKlarna' / 'vivawallet_klarna': Klarna invoice / pay-later
  • 'VivawalletCreditcard' / 'vivawallet_creditcard': card payment
  • 'VivawalletPaypal' / 'vivawallet_paypal': PayPal
  • 'VivawalletApplepay' / 'vivawallet_applepay': Apple Pay
  • 'VivawalletGooglepay' / 'vivawallet_googlepay': Google Pay

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": "abc123",
  "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": 987,
  "sessionId": "xyz789",
  "transactionId": "xyz789",
  "stamp": "abc123",
  "reference": "xyz789",
  "amount": 123.45,
  "error": "abc123"
}

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": 987,
  "productId": 987,
  "productModel": "abc123",
  "productEan": "abc123",
  "productName": "abc123",
  "price": 123.45,
  "originalPrice": 987.65,
  "tax": 987.65,
  "quantity": 123,
  "quantityReturned": 987,
  "stockVariants": "xyz789",
  "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:

  • '+' (most common): additive — added to the base product price
  • '' (empty): replacement — overrides the base price entirely
Example
{
  "id": "4",
  "orderId": 987,
  "orderProductId": 987,
  "optionId": 123,
  "optionName": "abc123",
  "optionValue": "abc123",
  "price": 123.45,
  "pricePrefix": "xyz789"
}

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": 987,
  "statusId": 123,
  "dateAdded": "abc123",
  "customerNotified": 987,
  "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": 123,
  "statusId": 123,
  "comments": "xyz789",
  "notifyCustomer": true,
  "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": "xyz789",
  "price": 987.65,
  "description": "abc123",
  "shortDescription": "xyz789",
  "material": "xyz789"
}

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):

  • 'radio' — radio-button group (default)
  • 'select' — dropdown
  • 'checkbox' — multi-select checkboxes
  • 'text' — short free-form input
  • 'textarea' — long free-form input
  • 'date' / 'time' / 'area' — date / time / combined date+time inputs
  • 'file' — file upload
Example
{
  "id": 4,
  "productId": 123,
  "productsOptionsId": 987,
  "required": true,
  "position": 123,
  "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": 987,
  "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:

  • 'PDF' / 'pdf' — datasheets, manuals
  • 'JPG' / 'JPEG' / 'jpeg' / 'PNG' / 'GIF' / 'WEBP' / 'AVIF' / 'SVG' — images
  • 'IES' — lighting profiles (photometric data)
  • 'DOC' / 'DOCX' / 'XLS' / 'XLSX' / 'TXT' — office documents
  • 'DWG' / 'DXF' / 'DWF' — CAD files
  • 'LESS' — stylesheet partial

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": 123,
  "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": "abc123",
  "description": "xyz789",
  "sort": 123,
  "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:

  • '+' (most common): additive — added to the base product price
  • '' (empty): replacement — overrides the base price entirely

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": "abc123",
  "specification": "abc123",
  "weight": 987.65,
  "sort": 123,
  "hex": "xyz789",
  "priceDelta": 123.45,
  "pricePrefix": "xyz789",
  "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": 123.45,
  "date": "xyz789",
  "userName": "xyz789"
}

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": 123,
  "price": 987.65,
  "priceOriginal": 123.45,
  "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.

Fields
Field Name Description
minimumQuantity - Int! Quantity the basket must reach for this tier's price to apply.
unitPrice - Float! Replacement unit price once the threshold is met, in the tenant's default currency.
Example
{"minimumQuantity": 987, "unitPrice": 123.45}

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):

  • 'all' — applies to all shoppers (the only value seen in production today)
  • 'b2b' — business shoppers only
  • 'b2c' — consumer shoppers only
Example
{
  "minimumQuantity": 987,
  "discountPercentage": 987.65,
  "customerGroupId": "xyz789",
  "customerId": 987,
  "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. Example values across tenants (defaults; tenants extend):

  • 1: Open (received)
  • 2: Accepted
  • 3: Cancelled
  • 4: Ordered (converted to an order)
  • 5: Proposal sent
  • 50: Pending approval

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:

  • 'fixed' — currency amount off the quote total
  • 'percent' — percentage off
  • 'shipping' — applied as a shipping subsidy / free shipping

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": "abc123",
  "statusId": 123,
  "dateAdded": "abc123",
  "dateModified": "xyz789",
  "dateReminder": "xyz789",
  "dateFollowUp": "xyz789",
  "sendReminder": "abc123",
  "sendFollowUp": "abc123",
  "discountType": "xyz789",
  "discountAmount": 123.45,
  "comment": "abc123",
  "cc": "xyz789",
  "shipmentMethod": "abc123",
  "shipmentCode": "xyz789",
  "shipmentPrice": 123.45,
  "warehouseId": 123,
  "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.

Fields
Field Name Description
id - ID! Database row id of the attachment.
quoteId - Int! Quote this file is attached to.
file - String! Filename of the attachment, served from the tenant's quote-files directory.
Example
{"id": 4, "quoteId": 123, "file": "abc123"}

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.

Fields
Field Name Description
id - ID! Database row id of the quote group.
languageId - Int! Language id this row is for (resolves against the languages query).
name - String! Localized group label shown in the quote-group dropdown.
Example
{
  "id": "4",
  "languageId": 987,
  "name": "xyz789"
}

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').

Fields
Input Field Description
sendReminder - Boolean When set, update Quote.sendReminder. true = enable the reminder cadence; false = disable it.
sendFollowUp - Boolean When set, update Quote.sendFollowUp. true = enable the follow-up cadence; false = disable it.
Example
{"sendReminder": false, "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": 987,
  "variant": "abc123",
  "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": 123,
  "discountedPrice": 123.45,
  "productGroup": 123,
  "comment": "xyz789",
  "customOptions": "xyz789",
  "bundleId": 123
}

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": "abc123",
  "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:

  • 0: not notified (internal state change)
  • 1: notification email sent
comments - String Free-form operator comment attached to the transition (e.g. 'Awaiting customer signature').
Example
{
  "id": "4",
  "quoteId": 987,
  "statusId": 987,
  "statusName": "abc123",
  "dateAdded": "abc123",
  "customerNotified": 987,
  "comments": "abc123"
}

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.

Fields
Input Field Description
id - ID Database row id of the favorite to remove.
customersId - Int Customer scope for the removal.
productsId - Int Product scope for the removal.
Example
{
  "id": "4",
  "customersId": 123,
  "productsId": 987
}

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": 987,
  "nickname": "abc123",
  "country": "xyz789",
  "isRecommended": false,
  "verifiedBuyer": false,
  "count": 987,
  "statusId": 123,
  "statusCode": "abc123",
  "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.

Fields
Field Name Description
createdAt - String Timestamp the review was submitted.
orderDate - String Order date the review references when the reviewer is a verified buyer. Null for non-verified reviews.
answerDate - String Timestamp the vendor reply was posted. Null when there's no reply yet.
Example
{
  "createdAt": "abc123",
  "orderDate": "abc123",
  "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": "abc123"
}

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.

Fields
Field Name Description
productId - ID! Product the metrics aggregate over.
reviewsCount - Int Total count of approved reviews for this product.
ratingSummary - Int Aggregate star rating on a 1–5 scale. Stored as int; the storefront formats fractional stars from this aggregate as needed.
Example
{"productId": 4, "reviewsCount": 987, "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": "abc123",
  "sortOrder": 987,
  "displayFooter": 987,
  "googleFeed": 987,
  "css": "abc123",
  "externalJs": "abc123",
  "externalCss": "abc123",
  "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": 987,
  "name": "abc123",
  "url": "xyz789",
  "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 tag for the page.</p> </root>
metaDescription - String Localized for the page.
Example
{
  "languageId": 123,
  "name": "xyz789",
  "url": "xyz789",
  "html": "xyz789",
  "metaTitle": "abc123",
  "metaDescription": "xyz789"
}

SharedBasketItem

Description

One line item in a shared basket — a basket bound to an opaque shared_cart_id rather than a specific customer's session. Used for collaborative B2B flows: a sales rep builds a basket on behalf of a customer and sends them a link, two team-mates from the same customer organisation co-edit a wholesale draft, or a single shopper syncs their cart across devices via a shared id.

Same shape as CustomersBasketItem but keyed differently: customersId is optional (null on anonymous shared baskets), and the row carries an explicit expiresAt so the storefront can age out abandoned shared baskets. Each item is uniquely keyed by (sharedCartId, itemId) — the itemId lets the parent flow address one line of the shared basket without knowing the row id.

Fields
Field Name Description
id - ID! Database row id of the shared-basket line.
sharedCartId - String! Opaque shared-cart id linking lines that belong to the same shared basket. Lets multiple parties co-edit one basket without a shared customer id.
customersId - Int Customer attached to the basket. Null for anonymous shared baskets that haven't been claimed by a logged-in customer yet.
itemId - String Caller-supplied identifier for the line within the shared basket. Lets the parent flow reference a specific line ('apply discount to itemId X') without knowing its database row id.
productId - Int Catalog product id on the line. Null for free-form / placeholder lines.
variants - String Variant identifier — comma-separated option-value ids matching the format used in ProductStock.variant. Empty when the product has no variants.
productOptions - String Configurable-option choices (matches OrderItemVariant / ProductOption choices, encoded the same way as on customers_basket).
comment - String Free-form per-line comment (configuration notes, gift message).
customOptions - String JSON-encoded free-text custom-option inputs (engraving, monogram).
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.
bundleId - String Bundle parent id for child rows. Null = standalone line or bundle parent itself.
includes - String Bundle-children references when this row is a bundle parent.
dateAdded - String Timestamp the line was added to the shared basket.
expiresAt - String Timestamp the shared-basket line auto-expires. Past this point the storefront should refuse to load or accept edits unless requireActive=false is passed on the mutation.
Example
{
  "id": 4,
  "sharedCartId": "xyz789",
  "customersId": 123,
  "itemId": "xyz789",
  "productId": 123,
  "variants": "abc123",
  "productOptions": "xyz789",
  "comment": "xyz789",
  "customOptions": "abc123",
  "quantity": 987,
  "specialPrice": 987.65,
  "bundleId": "xyz789",
  "includes": "xyz789",
  "dateAdded": "xyz789",
  "expiresAt": "abc123"
}

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

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": "abc123",
  "price": 123.45,
  "originalPrice": 123.45,
  "tax": 987.65,
  "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": 987,
  "optionName": "abc123",
  "optionValue": "abc123",
  "price": 123.45,
  "pricePrefix": "xyz789"
}

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": "xyz789"
}

UpdateSharedBasketQuantityInput

Description

Input for updateSharedBasketQuantity — narrowly change the quantity on an existing line without touching the rest of the row. Used by the storefront's '+' / '-' quantity stepper on the shared-basket view.

Fields
Input Field Description
sharedCartId - String! Opaque shared-cart id.
itemId - String! Caller-supplied line identifier.
quantity - Int! New quantity for the line.
requireActive - Boolean When true (default), refuse to update if the line is past expiresAt.
Example
{
  "sharedCartId": "abc123",
  "itemId": "abc123",
  "quantity": 987,
  "requireActive": true
}

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
productId - Int

Restrict the response to one product. Omit to receive every product's quantity at this warehouse.

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.

Fields
Field Name Description
id - ID! Database row id of the per-warehouse stock entry.
warehouseId - Int! Warehouse this stock slice lives in.
productId - Int! Product this stock slice is for.
quantity - Int! On-hand quantity at this warehouse for this product.
Example
{
  "id": "4",
  "warehouseId": 987,
  "productId": 987,
  "quantity": 987
}