Base URL
LocalApiPort setting in the agent’s appsettings.json (default 5555). Leave it at the
default: the tray app’s fallback connection and the web app’s Local Service tab always use port 5555. See the
configuration reference.
The API uses plain HTTP. It is served by the Windows service, so it is available only while the service is running.
Access and security
- Localhost only. The agent listens on the loopback addresses only (
127.0.0.1and::1). Other computers on your network cannot connect to it, and it needs no firewall rule. A request that names any host other thanlocalhostor a loopback address is refused with403 Forbidden. - One required header. Every request to a route under
/apimust carry the headerX-Omnilinker-Local: 1. Without it, the agent answers403 Forbiddenwith an empty body./healthdoes not check the header; sending it there does no harm. - Browsers: Omnilinker only. A web page cannot add that header without asking the agent first (a CORS
preflight). The agent agrees only for Omnilinker’s own address,
https://omnilinker.pl, and its subdomains, over HTTPS. That is how the web app’s Local Service tab, open in a browser on the agent computer, reads the API. Requests from any other website are refused with403. - No authentication. Programs on the computer, such as the tray app, PowerShell or
curl, send the header and need no API key, password or token.
Conventions
- Request and response bodies are JSON. Property names are camelCase.
- Times are in UTC, in ISO 8601 format, for example
2026-09-27T08:15:02.1234567Z. - Enumerations are returned as numbers, not names. The tables on this page list the values.
- Control routes return
400 Bad Requestwith a command response when the agent refuses the command. 403 Forbiddenwith an empty body means the request was refused before it reached the agent: theX-Omnilinker-Localheader is missing, the host is notlocalhost, or a browser sent it from another website.- The examples use PowerShell. In Windows PowerShell 5.1,
curlis an alias forInvoke-WebRequest. Typecurl.exeto use curl.
Routes
No other routes exist.
Health
GET /health
Runs the agent’s health checks and returns the overall result as plain text:Healthy, Degraded or Unhealthy.
The HTTP status is 200 OK for Healthy and Degraded, and 503 Service Unavailable for Unhealthy.
/health returns Unhealthy until the agent has connected to the ERP database, for example right after the service
starts or before the setup wizard has run. Use /api/sync/health to
check only that the service is running.
GET /api/sync/health
Returns200 OK whenever the API is answering. It does not check the ERP or Omnilinker.
string
Always
healthy.string
The agent’s current time, UTC.
Status
GET /api/sync/status
Returns the agent’s full status. The tray app’s status window and the web app’s Local Service tab show the same data.integer
The agent’s state.
boolean
Whether the agent’s last request to Omnilinker succeeded.
boolean
Whether the agent is connected to the ERP database.
string | null
When the last sync cycle finished successfully.
string | null
When the next cycle is expected, if known.
integer
Errors since the last successful cycle.
string | null
The last error message, for example
Waiting for cloud configuration.string | null
Why a cycle is delayed, for example
Product polling delayed (HashCheck in progress).integer[]
Fixes the tray app offers for the last error.
1 test ERP connection, 2 test cloud connection, 3 check
settings, 4 retry now, 5 view logs, 6 check network, 7 contact support, 8 view details, 9 skip item.object
Events in the agent’s outbox, with
pending, sent, failed and retrying. The same numbers as
/api/sync/outbox/stats.object
Outbox counts per entity type, keyed by type name (for example
Product, Brand, PriceLevel, Price,
Warehouse, Stock). Each value has total, synced, pending and failed. Only events still in the local
outbox are counted: sent events are removed after 24 hours (1 hour during the initial sync).string
The agent’s version.
boolean
Not used: always
false. The agent updates itself, but does not report a
waiting update here.string | null
Not used: always
null.object | null
The same object as
/api/sync/hash/status.object | null
While a hash check runs:
productsChecked, totalProducts, brandsChecked, totalBrands, elapsed,
estimatedTimeRemaining and itemsPerSecond.object | null
currentPending, healthLevel (0 normal, fewer than 50 pending; 1 elevated, 50 to 199; 2 backlogged, 200
or more), trend (0 steady, 1 growing, 2 draining), trendItemsPerMinute and trendDescription.object[]
Operations running now, such as polling or publishing, with their item counts and progress.
object[]
The most recently completed operations, with
completedAt, itemCount, duration, success and
errorMessage.object
Health of four components:
erpConnection, cloudApi, database and credentials. Each has a level (0
healthy, 1 warning, 2 critical), a message and the time of the last check. overallHealth is the worst of the
four, and issueCount counts those that are not healthy.currentOperations, recentActivity and systemHealth also carry display fields used by the
tray app. Do not rely on their exact shape; it can change between agent versions.
GET /api/sync/config
Returns a few facts about the agent. It does not return its settings or credentials.string
The agent’s version.
boolean
Whether syncing is paused.
string
The agent’s state as a name, for example
Idle (unlike /api/sync/status, which returns a number).Control
These routes take no parameters and no request body.Command response
Every control route, andPOST /api/sync/hash/trigger, returns this object:
boolean
Whether the agent accepted the command.
string
What happened, or why the command was refused.
POST /api/sync/now
Asks the agent to look for changes now.POST /api/sync/trigger does exactly the same.
The request is picked up at the agent’s next polling cycle, within PollingIntervalSeconds (60 seconds by default).
With hash scan change detection it starts a hash check.
POST /api/sync/pause
Pauses syncing. The agent stops detecting new changes until you resume. Always returns200 with Sync paused.
- Events already in the outbox are still sent to Omnilinker while the agent is paused.
- A pause is not kept when the service restarts.
POST /api/sync/resume
Resumes syncing. Always returns200 with Sync resumed.
Logs
GET /api/sync/logs
Returns the newest entries of the agent’s own sync log, newest first. These are the entries the tray app’s log viewer shows. They are not the Omnilinker sync log entries described in Monitoring, and not the service’s log files.integer
default:"50"
How many entries to return. At most 500; larger values return 500.
string
Minimum level:
Debug, Info, Warning, Error or Critical (or 0 to 4). Returns entries at this level and
above.string
Only entries of this category, for example
ErpPolling, HashCheck or ChangeConsumption. Exact match.string
Only entries for this entity type. Exact match.
integer
The entry’s ID.
string
When the entry was written.
integer
0 Debug, 1 Info, 2 Warning, 3 Error, 4 Critical.string
The message.
string | null
Extra details, if any.
string | null
The component that wrote the entry.
string | null
The entity type concerned, if any.
string | null
The entity concerned, if any.
string | null
The exception, for errors.
Outbox
GET /api/sync/outbox/stats
The agent queues every change in a local outbox and sends it to Omnilinker in batches. This route counts the events in the outbox by state.integer
Waiting to be sent, including events that failed an attempt and will be tried again.
integer
Sent successfully and not yet cleaned up. Sent events are removed after 24 hours (1 hour during the initial sync).
integer
Failed on every attempt (
MaxRetryAttempts, 5 by default). The agent does not send these again.integer
Being sent right now. Despite the name, this is not a count of events waiting for a retry: those are in
pending.pending count that keeps growing means the agent cannot send to Omnilinker. See
Troubleshooting.
Hash check
A hash check compares the ERP data with what the agent last sent, to find changes. It is how the agent detects changes with hash scan change detection. See Wapro.GET /api/sync/hash/status
boolean
Whether hash checks are enabled in the connection’s sync configuration. With WFM_INT change tracking, a weekly
reconciliation check always runs and this is
true.boolean
Whether a hash check is running now.
boolean
Whether hash checks are paused on their own (from the tray app).
string | null
When the last hash check finished.
string | null
When the next one is due.
integer
Products compared in the last check.
lastProductsChanged, lastBrandsChecked and lastBrandsChanged work the
same way.integer
Products in the hash store.
totalStoredBrandHashes is the same for brands.string | null
The last hash check error.
GET /api/sync/hash/stats
integer
Products in the hash store.
integer
Brands in the hash store.
string | null
When the store was last updated by a hash check.
POST /api/sync/hash/trigger
Starts a hash check now, without waiting for its interval.Named pipe
The tray app talks to the service mainly over a Windows named pipe,OmnilinkerErpSync, and falls back to this HTTP
API when the service does not answer on the pipe. The pipe is an internal interface between the two parts of the
agent, not a public API: its commands can change between agent versions. Use the HTTP routes on this page for
scripts and monitoring.
- Who can connect: SYSTEM, administrators, and people signed in to the computer, at the console or over Remote Desktop.
- What they can do: anyone connected can read the status, logs and settings. Commands that change the agent,
its ERP database or its credentials, or that pause it, need a member of Omnilinker ERP Sync Operators or an
administrator whose tray app runs elevated. Others get the error “Only an administrator of this PC can do that.”
(code
Pipe:NotAllowed). See Who can change the agent. - Which service: the tray app talks only to the Windows service. It does not trust another program that opens a pipe with the same name.