> ## 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` and `productMarketId` — Omnium stores each product language as a separate document. Set these to avoid duplicate product rows.
    * (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",
          "productMarketId": "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)
