API Reference
Technical guide to the Campaign public REST API — create, update, search, and manage campaign lifecycles programmatically via the Omnium API.
Overview
The Campaign API lets external systems manage campaigns programmatically. Use it to integrate campaign management with your ERP, build custom campaign dashboards, or automate campaign workflows from external systems.
All endpoints are available at https://apitest.omnium.no/api/Campaigns (test) and your production API host under the same path.
What you can do
- Create and update campaigns with markets, stores, tags, and custom properties
- Give a campaign its campaign code (
externalIds) and the same campaign in an earlier year (previousCampaignId) - Read a campaign's status timeline and milestones
- Search and filter campaigns by date range, status, market, and more
- Transition campaigns through their lifecycle (Planning → Active → Completed → Archived)
- Retrieve promotion IDs linked to a campaign (promotions are linked with
campaignIdon the Promotions API) - Delete campaigns (with automatic promotion unlinking)
What the Campaign API does not do
Campaign API manages the campaign container itself. To manage the promotions within a campaign, use the Promotions API: a promotion joins a campaign through its campaignId. To set SKU-level pricing, use the Price Lists API: a price list is planned under the campaign of the promotion it belongs to. The relationship looks like this:
Authentication and Authorization
All Campaign endpoints require a valid JWT Bearer token. Include it in the Authorization header:
Obtain a token via POST /api/Token. See Authentication for details.
Access Levels
| Operation | Required Role | Description |
|---|---|---|
| Read (GET, Search) | PromotionRead | View campaigns and linked promotions |
| Write (POST, PUT, PATCH, DELETE) | PromotionAdmin | Create, update, delete, and change status |
Campaign Model
The API returns campaigns using the OmniumCampaign model.
| Property | Type | Description |
|---|---|---|
Id | string | Unique campaign identifier (GUID). Auto-generated on create if not provided. |
Name | string | Campaign display name. Required. |
Description | string | Optional internal description. |
Tags | string[] | Labels for categorization and filtering (e.g., ["seasonal", "clearance"]). |
StartDate | datetime | When the campaign begins. Required. |
EndDate | datetime | When the campaign ends. Must be after StartDate. Required. |
Status | string | Lifecycle status: the name of one of the campaign statuses configured for your environment. Without configured statuses: Planning, Active, Completed, or Archived. |
Markets | string[] | Market IDs where the campaign applies (e.g., ["NOR", "SWE"]). |
Stores | string[] | Store IDs where the campaign targets. Empty means all stores. |
PlanningNotes | string | Internal notes for the planning phase. |
CreatedDate | datetime? | When the campaign was created. Read-only (set by server). |
UpdatedDate | datetime? | When the campaign was last updated. Read-only (set by server). |
Properties | OmniumPropertyItem[] | Custom key-value pairs for extensibility. |
Errors | OmniumEntityError[] | Validation or processing errors. Read-only (set by server). |
InternalComments | OmniumComment[] | Internal comments on the campaign. Read-only. |
ExternalIds | OmniumExternalId[] | Identifiers of the campaign in other systems, one per provider. The first one is shown as the campaign code in Omnium. |
PreviousCampaignId | string | The same campaign in an earlier year. The follow-up uses its actual sales as the campaign's last year. |
Milestones | OmniumCampaignMilestone[] | Read-only. The campaign's deadlines that are not statuses, one per milestone type configured for your environment. |
StatusSteps | OmniumCampaignStatusStep[] | Read-only. The campaign's status timeline, one step per configured status, in status order. |
OmniumExternalId
| Property | Type | Description |
|---|---|---|
ProviderName | string | The system the id belongs to, such as Erp |
Id | string | The campaign's id in that system |
OmniumCampaignMilestone
| Property | Type | Description |
|---|---|---|
Key | string | Key of the milestone type. PlanningStart is the day planning opens. |
Name | string | Display name of the milestone |
Date | datetime? | The deadline. null when the campaign has no start date to count it from. |
IsCompleted | bool | The milestone has been marked as done |
IsManuallySet | bool | A user set the date. A date set by hand stays when the start date moves; the others move with it. |
OmniumCampaignStatusStep
| Property | Type | Description |
|---|---|---|
Name | string | Name of the status |
Order | int | Position of the status in the configured sequence |
Date | datetime? | The planned date before the campaign enters the status; the date it entered it after |
IsActivated | bool | The campaign has entered the status |
Milestones and status steps are edited in the Omnium UI. The API returns them but does not set them; a create or update fills and moves them from the campaign's start date as described under Update a Campaign, and a status change through Update Campaign Status activates and dates the step of the new status.
Campaign statuses
The statuses a campaign can have are configured per environment, under Configuration → Settings → Orders → Promotion → Campaign Statuses (see Campaign Settings). Each status has a name, an order and its available next steps. An environment that configures none uses the four default statuses:
| Status | Available next steps |
|---|---|
Planning | Active |
Active | Completed, Planning |
Completed | Archived |
Archived | (none) |
Wherever the API takes a status (Status on create and update, status on the status change, Statuses in the search), it is the status name, compared case-sensitively. A name that is not configured answers 400 Bad Request with the configured names, for example "Invalid status. Valid values: Planning, Locked, Active, Completed, Archived" in an environment that adds a Locked status.
OmniumPropertyItem
| Property | Type | Description |
|---|---|---|
Key | string | Property name |
Value | string | Property value |
KeyGroup | string | Optional grouping key |
ValueType | string | Optional type hint (e.g., "string", "number", "boolean") |
Endpoints
Get a Campaign
Returns a single campaign by ID.
Response: 200 OK with OmniumCampaign body, or 404 Not Found.
Example:
Search Campaigns
Search and filter campaigns with pagination. This is the primary way to list campaigns — there is no GET /api/Campaigns list endpoint.
Request body: OmniumCampaignSearchRequest
| Property | Type | Default | Description |
|---|---|---|---|
SearchText | string | — | Free-text search across name, description, tags, and ID. Supports fuzzy matching. |
StartFrom | datetime? | — | Campaigns that start on or after this date |
StartTo | datetime? | — | Campaigns that start on or before this date |
EndFrom | datetime? | — | Campaigns that end on or after this date |
EndTo | datetime? | — | Campaigns that end on or before this date |
Statuses | string[] | — | Filter by statuses. Empty means all. Values: the configured campaign status names, by default Planning, Active, Completed, Archived |
MarketIds | string[] | — | Filter by market IDs |
StoreIds | string[] | — | Filter by store IDs |
Tags | string[] | — | Filter by tags |
CampaignIds | string[] | — | Filter by specific campaign IDs |
Page | int | 1 | Page number (1-based) |
Take | int | 20 | Results per page. Max 200. |
SortOrder | string | StartDateDesc | Sort order (see table below) |
ExcludeArchived | bool | true | Exclude archived campaigns from results |
Sort options:
| Value | Description |
|---|---|
StartDateDesc | Newest start date first (default) |
StartDateAsc | Oldest start date first |
EndDateDesc | Newest end date first |
EndDateAsc | Oldest end date first |
NameAsc | Alphabetical A-Z |
NameDesc | Alphabetical Z-A |
CreatedAsc | Oldest created first |
CreatedDesc | Newest created first |
Pagination limits: Take cannot exceed 200. Take × Page cannot exceed 10,000. For larger datasets, use narrower filters.
Response: 200 OK with OmniumSearchResult<OmniumCampaign>:
Example — Find all active campaigns in the Norwegian market:
Example — Find campaigns running during a specific week:
To find campaigns that overlap with a date range, combine StartTo and EndFrom. This returns campaigns where StartDate <= endOfRange AND EndDate >= startOfRange:
Example — Full-text search with tag filter:
Create a Campaign
Creates a new campaign. Returns the created campaign with server-set fields (Id, CreatedDate, Status).
Request body: OmniumCampaignRequest
| Property | Type | Required | Description |
|---|---|---|---|
Id | string | No | Custom ID. A GUID is generated if omitted. |
Name | string | Yes | Campaign display name |
Description | string | No | Internal description |
Tags | string[] | No | Categorization labels |
StartDate | datetime | Yes | Campaign start date |
EndDate | datetime | Yes | Campaign end date (must be after StartDate) |
Status | string | No | Initial status: one of the configured campaign statuses. Defaults to the first configured status (Planning by default) if omitted. |
Markets | string[] | No | Market IDs |
Stores | string[] | No | Store IDs |
PlanningNotes | string | No | Internal planning notes |
Properties | OmniumPropertyItem[] | No | Custom key-value pairs |
ExternalIds | OmniumExternalId[] | No | Identifiers of the campaign in other systems, one per provider. The first one is the campaign code. |
PreviousCampaignId | string | No | The same campaign in an earlier year. Must be another existing campaign. |
Response: 201 Created with the full OmniumCampaign body.
Validation rules:
Namemust not be emptyEndDatemust be afterStartDateStatus(if provided) must be the name of a configured campaign status, case-sensitivePreviousCampaignId(if provided) must be an existing campaign other than this one
Example — Create a basic campaign:
Example — Create with custom properties:
Properties let you attach arbitrary metadata to campaigns. Use them for ERP references, budget tracking, or any custom data:
Update a Campaign
Replaces an existing campaign with the provided data. This is a full replacement — all fields in the request body overwrite the existing values. Fields you omit will be cleared, except server-managed fields like CreatedDate and the fields listed under Important behavior below.
Request body: Same as Create (OmniumCampaignRequest).
Response: 200 OK with updated OmniumCampaign, or 404 Not Found.
Important behavior:
- The
Idin the URL takes precedence over anyIdin the request body CreatedDateis preserved from the original campaign- If
Statusis omitted or empty, the existing status is preserved - A
Statusmust be a configured campaign status or the one already stored. It is saved as given: the update does not check the transition rules, activate the status step or run the status workflow. Use Update Campaign Status to move a campaign to its next status - Server-managed fields (such as
CreatedDate,Errors) are preserved ExternalIdsandPreviousCampaignIdare often set in the Omnium UI, so they are preserved when the request leaves them out (null). An empty list ("externalIds": []) removes the external ids, and an empty string ("previousCampaignId": "") removes the previous campaignPreviousCampaignIdmust be an existing campaign other than the one you update; the one already stored is accepted as it is- The campaign's status step dates and milestones are preserved. When you change
startDate, milestone dates that nobody has set by hand move by the same number of days, and so do default status step dates that are neither set by hand nor activated. Later status steps without a date get their default date. Every update of a campaign with a start date also adds the milestones of milestone types configured since
Example — Update campaign dates and add a store filter:
Since PUT is a full replacement, include all fields you want to keep. For example, if the campaign had
Tagsand you omitTagsin the PUT request, the tags will be cleared.ExternalIdsandPreviousCampaignIdare the exception: leave them out to keep them.
Delete a Campaign
Permanently deletes a campaign. All promotions linked to the campaign are automatically unlinked (but not deleted).
Response: 204 No Content on success, or 404 Not Found.
Example:
Deletion is permanent. Campaign performance data is also removed. Linked promotions continue to function independently after being unlinked.
Update Campaign Status
Moves a campaign to a new lifecycle status, the same way a status change on the campaign page does. This is the way to change status: the move is checked against the configured transitions, the status step of the new status is activated and dated, and the workflow steps configured for the new status run (for example notification emails or SMS messages).
Request body:
| Property | Type | Required | Description |
|---|---|---|---|
status | string | Yes | Name of the target status: one of the configured campaign statuses, case-sensitive, that is an available next step of the campaign's current status |
Response: 200 OK with the updated OmniumCampaign, 404 Not Found, or 400 Bad Request:
| When | Message |
|---|---|
status is missing | "Status is required" |
status is not a configured status | "Invalid status. Valid values: Planning, Active, Completed, Archived" (the configured names) |
The current status does not list status as an available next step | "Invalid status transition from 'Planning' to 'Completed'. Allowed next statuses: Active." |
| The current status has no next steps | "Invalid status transition from 'Archived' to 'Active'. A campaign in 'Archived' cannot change status." |
Status transition rules:
A campaign can move only to a status that its current status lists as an available next step. A status with no available next steps configured at all can move to any configured status. With the default statuses:
An environment with a locked status typically moves Planning → Locked → Active, so a Planning campaign must be locked before it can go live:
The AutoTransitionCampaignsScheduledTask scheduled task makes the same moves on the dates of the status steps, so you only need this endpoint for moves you want to make before or without those dates.
What happens on status change:
When you change a campaign's status, the workflow steps configured for the new status run, for example sending notification emails or SMS messages to relevant stakeholders. A workflow step that fails is logged and does not undo the status change.
Example — Activate a campaign:
Example — Complete a campaign after its end date:
Get Linked Promotions
Returns the IDs of all promotions linked to a campaign. Use these IDs with the Promotions API to retrieve full promotion details.
Response: 200 OK with string[], or 404 Not Found.
Example:
To link a promotion to the campaign, or move or remove it, set
campaignIdon the promotion withPOST /api/PromotionsorPATCH /api/Promotions. See Build a campaign with promotions and price lists.
Common Integration Patterns
Build a campaign with promotions and price lists
A campaign's Planning tab lists the items of the price lists that belong to the campaign's promotions. To build a planned campaign through the API, create the campaign, then the promotions with campaignId, then their price lists with promotionId, then the items:
Step 1: Create the campaign, with its campaign code and last year's campaign:
Step 2: Create a price list promotion in the campaign. campaignId must be an existing campaign:
Step 3: Create the promotion's price list. promotionId puts it under the campaign; campaignId records the campaign on the price list too:
Step 4: Add the items with their campaign prices and planning figures:
AddPriceListItems and PatchPriceListItems accept the same item fields, including the store cost fields storeCostPrice, storeCostDiscount, storeCostDiscountPercent and storeCostPriceAdditionPercent.
Linking a promotion with campaignId works as adding it on the campaign page: the campaign's start and end dates are recalculated from the dates of its promotions, and so are those of the campaign the promotion leaves. On the promotion and price list endpoints, campaignId left out (null) keeps the stored campaign, and an empty string removes it.
Move or remove a promotion: send only the campaign in a patch. A patch that changes nothing but the campaign does not save the promotion itself, so its prices are not rebuilt:
ERP Campaign Sync
A typical ERP integration creates campaigns in Omnium to match campaign plans from the ERP, then tracks performance back:
Step 1: ERP creates the campaign via POST /api/Campaigns with the ERP campaign number as its campaign code in ExternalIds:
Step 2: Merchandising team links promotions and sets targets in the Omnium UI, or the ERP creates the promotions with campaignId as shown above.
Step 3: ERP activates the campaign via PATCH /api/Campaigns/{id}/status.
Step 4: ERP periodically searches for active campaigns to pull status updates:
Custom Dashboard
Build a campaign calendar or dashboard by searching for campaigns across a date range:
This returns all campaigns that overlap with the year 2026, sorted chronologically.
Automated Lifecycle Management
Use the status endpoint to automate campaign transitions based on business rules:
- Activate on start date: A scheduled job searches for
Planningcampaigns whereStartDatehas passed, then callsPATCH /statuswithActive - Complete on end date: Search for
Activecampaigns whereEndDatehas passed, then transition toCompleted - Archive after review period: Search for
Completedcampaigns older than 90 days, then archive
Error Handling
All endpoints follow a consistent error pattern:
| Status Code | Meaning | When |
|---|---|---|
200 OK | Success | GET, PUT, PATCH |
201 Created | Resource created | POST (create) |
204 No Content | Deleted successfully | DELETE |
400 Bad Request | Validation error | Missing Name, a Status that is not configured, a status change the current status does not allow, EndDate before StartDate, unknown PreviousCampaignId or the campaign itself, pagination limits exceeded |
404 Not Found | Campaign not found | GET, PUT, PATCH, DELETE with non-existent ID |
401 Unauthorized | Missing or invalid token | Any endpoint |
403 Forbidden | Insufficient permissions | Write operations without PromotionAdmin role |
500 Internal Server Error | Server error | Unexpected failures |
400 errors return a descriptive message in the response body:
Endpoint Summary
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/Campaigns/{id} | Read | Get a single campaign |
POST | /api/Campaigns/Search | Read | Search with filters and pagination |
POST | /api/Campaigns | Admin | Create a new campaign |
PUT | /api/Campaigns/{id} | Admin | Full update of an existing campaign |
DELETE | /api/Campaigns/{id} | Admin | Delete a campaign |
PATCH | /api/Campaigns/{id}/status | Admin | Change campaign status |
GET | /api/Campaigns/{id}/promotions | Read | Get linked promotion IDs |