> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dema.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Omnium OMS

> Integrate Omnium's order management system to sync orders, returns, products, inventory, and inbound deliveries into our platform.

export const HistoricalDataNote = () => <Tip>
    <strong>Historical data recommendation</strong> — For accurate forecasting, marketing-mix modeling, and cohort analytics, we recommend providing data going back to at least two years. Our default start date for data ingestion is <strong>January 1, 2023</strong>. The more historical data available, the better our ML models perform.
  </Tip>;

### Supported data types

<CardGroup cols={3}>
  <Card title="Orders" icon="file-invoice-dollar">
    Online and in-store orders, including tax-inclusive prices, shipments, and vouchers
  </Card>

  <Card title="Returns" icon="rotate-left">
    Return orders with line-level quantities and reasons
  </Card>

  <Card title="Products" icon="tags">
    Product catalog with variants, categories, brand, and imagery
  </Card>

  <Card title="Product inventory" icon="boxes-stacked">
    Per-warehouse stock levels and cost of goods sold
  </Card>

  <Card title="In-delivery" icon="truck">
    Outstanding purchase order quantities per line
  </Card>
</CardGroup>

## Prerequisites

<HistoricalDataNote />

* An Omnium tenant on `api.omnium.no` (production) or `apitest.omnium.no` (test).
* An **Omnium API user** created inside the Omnium admin GUI under **Configuration > Authorization > API Users**. Use the `test.omnium.no` admin GUI for test tenants and `admin.omnium.no` for production.
* Read roles assigned to that API user for the data types you want to sync: `OrderRead`, `ProductRead`, `InventoryRead`, and `PurchaseOrderRead`. A freshly created API user has no roles — the token exchange still succeeds, but every read endpoint returns `403` with an empty body until roles are granted. Roles take effect on the next issued token; no secret rotation is needed.

<Note>
  The Omnium admin GUI signs in through Azure AD (Microsoft Entra). An Azure AD email and password that works for the portal is **not** an API credential and returns `401` from `/api/Token`. Only credentials for a provisioned API user work.
</Note>

## Step-by-step integration guide

<Steps>
  <Step title="Create an Omnium API user">
    1. Sign in to your Omnium admin GUI (`test.omnium.no` for test tenants, `admin.omnium.no` for production).
    2. Go to **Configuration > Authorization > API Users** and create a new API user.
    3. Assign the read roles your integration needs: `OrderRead`, `ProductRead`, `InventoryRead`, and `PurchaseOrderRead`.
    4. Copy the generated `clientId` and `clientSecret`. Store them securely.
  </Step>

  <Step title="Collect your tenant details">
    Gather the following before sharing credentials:

    * `clientId` and `clientSecret` for the API user you just created.
    * `apiEndpoint` — the base URL for your tenant. Defaults to `https://api.omnium.no`; use `https://apitest.omnium.no` for the test environment.
    * Your **warehouse-code mapping** — a list mapping each Omnium `warehouseCode` (used on inventory records, order shipments, and returns) to a readable warehouse name.
    * The tenant's **order statuses** and **order types**. In Omnium, `status` and `orderType` on an order are free text configured per tenant, so we need the values your tenant actually uses.
    * (Optional, multi-language tenants) `productLanguage` — Omnium stores each product language as a separate document. Set this to avoid duplicate product rows.
    * (Optional) `productMarketIds` — a list of Omnium market IDs to import products from. If you leave it unset, Dema finds all active Omnium markets and imports products from each one, removing duplicates by product ID. Set it to limit the import to the listed markets.
    * (Optional) `orderMarketIds` — a list of Omnium market IDs to import orders from. If you leave it unset, orders from all markets are imported. Use it to split one Omnium tenant's markets across separate storefront integrations.
    * (Optional) `warehouseCodes` — restrict inventory extraction to specific warehouses.
  </Step>

  <Step title="Submit your credentials">
    Package the details as shown and send them to your Customer Success Manager.

    ```json Omnium example theme={null}
    {
      "auth": {
        "clientId": "your-api-user-client-id",
        "clientSecret": "your-api-user-client-secret",
        "apiEndpoint": "https://api.omnium.no"
      },
      "config": {
        "extractorParameters": {
          "productLanguage": "en",
          "productMarketIds": ["SE"],
          "orderMarketIds": ["SE"],
          "warehouseCodes": ["MAIN", "STORE-01"]
        },
        "warehouseMap": {
          "MAIN": "Main warehouse",
          "STORE-01": "Flagship store"
        },
        "statusMap": {
          "AwaitingPayment": "PENDING",
          "OnHold": "PENDING"
        },
        "offlineOrderTypes": ["Pos"]
      }
    }
    ```

    <Note>Send credentials through a secure channel as recommended by the Customer Success team.</Note>
  </Step>
</Steps>

## Order status and order type mapping

Omnium orders carry two tenant-configurable free-text fields that must be mapped so downstream reporting is accurate.

### `statusMap`

Order `status` is free text constrained by each tenant's order settings, not a fixed enum. Our connector already handles the common values (`New`, `InProgress`, `Shipped`, `Completed`, `Cancelled`, `PartiallyReturned`, `Returned`). Anything else maps to `UNKNOWN` — and an `UNKNOWN` order still counts as a sale in reporting (only `CANCELLED` is excluded).

During onboarding, list every status configured in the tenant's Omnium order settings. Any value outside the built-in set goes into `statusMap` so it is routed to the correct DEMA `OrderStatus` (for example `AwaitingPayment` → `PENDING`, `OnHold` → `PENDING`).

### `offlineOrderTypes`

Order `orderType` is also tenant-configurable free text. Types listed in `offlineOrderTypes` map to order type `OFFLINE`; everything else defaults to `ONLINE`. The default is `["Pos"]`. If your tenant uses different values for in-store orders (for example `Store`, `Retail`), list them here.

## Cost of goods sold (COGS)

COGS is sourced from the **product inventory** feed, not from order lines.

Omnium's order-line `cost` is enriched from product data, so it carries no information the inventory feed doesn't have. Including it would let an unpopulated or zero order-line cost silently override the inventory COGS and report full margin on that line. Our order transformer drops the order-line cost, and margin is computed from `cost`, `costCurrency`, and `costTotal` on each `Inventory/Search` record.

Make sure inventory `cost` is populated for the SKUs and warehouses you care about — an unpopulated cost leaves margin to fall back on other configured cost sources.

## Warehouse, shipment, and delivery address

Order lines take their `warehouse`, `shipmentId`, `shipmentStatus`, and `shippingProvider` from the shipment inside `orderForm.shipments[]` that carries the line (matched on `lineItemId`). A line that no shipment has picked up yet has none of these fields set.

The order has no shipping address of its own — the delivery address lives on each shipment. The connector reads `country`, `zipCode`, and `city` from the first shipment's address, falling back to the billing address.

The warehouse code on each shipment is resolved through `warehouseMap` (see above), which is also applied to inventory rows and return lines.

## Data synchronization process

After the integration is set up, our platform will:

1. **Initial data load**: Perform a full sync of historical orders, returns, products, inventory, and inbound deliveries.
2. **Ongoing synchronization**: Poll Omnium daily. Orders are fetched twice per period — once by `createdFrom`/`createdTo` and once by `modifiedFrom`/`modifiedTo` — and deduplicated, so both new orders and changes to older ones are picked up.

## Troubleshooting and support

* **`401` from `/api/Token`** — the credential is an Azure AD user, not a provisioned Omnium API user. Create one in the admin GUI under **Configuration > Authorization > API Users**.
* **`403` with an empty body on a read endpoint** — the API user is missing the read role for that data type. Assign the role in the admin GUI; a new token issued after the change carries the new permissions.
* **An order status maps to `UNKNOWN`** — the tenant is using a status value outside the built-in set. Add it to `statusMap`.

If you encounter any other issues, reach out to our support team for assistance.

## Additional resources

* [Omnium documentation](https://docs.omnium.no/docs)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.