The truth about what actually sold.
Distributor data arrives messy, with inconsistent outlet names, fragmented SKU codes and files in every shape. Dexor turns it into territory-level truth your whole organization can defend, without ever losing the original.
Get distributor sell-out in without retyping it.
Distributors send sell-out and stock by API push, the upload API or email. Every file is checked, stamped with where it came from, and kept as received.
A distributor's system can push rows as JSON to the ingest endpoint with an API key. The key decides the account, and a key pinned to one distributor can only write that distributor's data, whatever the request says.
POST /v1/ingest/sales
x-api-key: ••••••••••••3f9a
content-type: application/json
{
"distributorId": "DIST-NYC-01",
"data": [
{ "invoiceDate": "21/10/2026", "outletName": "Hudson Medical Pharmacy",
"sku": "CRD-10", "qty": 36, "netValue": 16200 },
...
]
} 202 Accepted
{
"message": "Accepted",
"uploadId": "b7f3c21e-41d0-4c8a-9e62-0f5d1a7e2b90"
} The account and distributor come from the key itself. A key pinned to one distributor cannot write for another.
POST /v1/sales/uploads/presign
authorization: Bearer ••••
{
"distributorId": "DIST-NYC-01",
"fileType": "stock"
} 200 OK
{
"url": "https://…",
"fields": {
"key": "raw/…/DIST-NYC-01/61d2aa90….csv",
"Content-Type": "text/csv",
"x-amz-meta-distributorid": "DIST-NYC-01",
"x-amz-meta-filetype": "stock",
…
}
} A signed upload slot for one CSV that expires in 15 minutes. The server sets the file key, so the caller never chooses where the file lands.
| Batch | Period | Type | Status |
|---|---|---|---|
| b7f3c21e | 2026-10 | sales | received |
| 61d2aa90 | 2026-10 | stock | projected |
| f09e44b3 | 2026-09 | sales | projected |
| 2c7b8e15 | 2026-09 | sales | rejected |
| d4a1937c | 2026-08 | sales | projected |
Unmatched rows never enter a territory rollup, so they are missing from every figure above.
Distributor codes mapped to a catalog product. An unmapped code sells but cannot be attributed to a product.
Outlets under this distributor's partition that resolve to a territory.
Clear unmatched outlets in a few keystrokes.
A two-pane review queue for outlet names that did not match on ingest. Approve a candidate, override the territory, or reject, from the keyboard.
Pick a distributor and the queue lists every distinct unmatched name with its best score and how often it appeared in the latest batch. Select one to see its ranked candidates, each with a score and the territory it would assign.
Choose the correct territory, override with a known one, or reject (leave unmatched).
Choose the correct territory, override with a known one, or reject (leave unmatched).
Choose the correct territory, override with a known one, or reject (leave unmatched).
Choose the correct territory, override with a known one, or reject (leave unmatched).
Fix a mapping and restate the history.
After a match is approved, restate a past month so its unmatched lines land in the right territory. The original source data is never rewritten.
A match queue decision fixes every file that arrives after it. Lines that came in before it keep their missing territory, so last month's figures do not move under anyone's feet.
POST /v1/sales/reproject
{
"distributorId": "DIST-NYC-01",
"period": "2026-09",
"territoryId": "TERR-NYC-01",
"normalizedNameKey": "al shifa med store"
} 201 Created
{
"distributorId": "DIST-NYC-01",
"period": "2026-09",
"territoryId": "TERR-NYC-01",
"reprojected": 214,
"chunks": 3
} Running it again restates nothing new: the lines are already stamped, so the result is reprojected 0.
POST /v1/sales/reproject
{
"distributorId": "DIST-NYC-01",
"period": "2026-07",
"territoryId": "TERR-NYC-01",
"normalizedNameKey": "al shifa med store"
} 409 Conflict
{
"error": "period is closed",
"detail": {
"period": "2026-07",
"hint": "reopen the period to restate it"
}
} A manager or admin restates a period through the API.
Net sell-out by distributor, territory and SKU.
Secondary sales net of returns, per distributor and territory, with a SKU breakdown. Figures still landing are marked provisional, never shown short.
Rollups are computed when you open them, straight from the ingested invoice lines, so they always reflect the latest data. Returns carry a negative sign and net out, and the breakdown ranks your top SKUs by net value.
| Batch | Period | Type | Status |
|---|---|---|---|
| b7f3c21e | 2026-10 | sales | received |
| 61d2aa90 | 2026-10 | stock | projected |
| f09e44b3 | 2026-09 | sales | projected |
| 2c7b8e15 | 2026-09 | sales | rejected |
| d4a1937c | 2026-08 | sales | projected |
Unmatched rows never enter a territory rollup, so they are missing from every figure above.
Distributor codes mapped to a catalog product. An unmapped code sells but cannot be attributed to a product.
Outlets under this distributor's partition that resolve to a territory.
See why rows fail, then fix the cause.
Match rate, rejected rows by reason and duplicate outlets for each distributor, on one screen, linked straight to the match queue.
How much of it matched? The match rate shows lines resolved to a territory out of lines accepted, for a period. Why were rows refused? The rejection breakdown counts each batch's rejected rows by reason: a missing required field, a value that is not a number, or a date that does not fit the format.
3,742 matched of 4,112 accepted
Names that collapse to one keyMatch queue
Hudson Medical Pharmacy, HUDSON MEDICAL PHARMACY, Hudson Medical-Pharmacy
Main Street Pharmacy (Midtown), Main Street Pharmacy Midtown
Liberty Drugs, Liberty Drugs.
Know how many days of stock sit in the channel.
Closing stock at each distributor, days of cover against the last 30 days of sales, and SKUs with a batch close to expiry.
Pick a distributor and a date. For each SKU, Dexor takes the latest stock reading on or before that date for each batch and adds the batches together. It never adds readings across dates.
| SKU | Closing qty | Days of cover | Expiry |
|---|---|---|---|
| CRD-10 | 4,320 | 18 d | No |
| GLX-500 | 6,100 | 41 d | No |
| ZMX-250 | 1,180 | 9 d | Near expiry |
| CRD-20 | 2,040 | 26 d | No |
| LPR-20 | 960 | n/a | Near expiry |
| ZMX-500 | 540 | n/a | No |
See your share of the market that actually sold.
Your share, market growth and evolution index against the realised market, nationally, by city or by territory, with a monthly or moving annual view.
Pick a scope: national, a city, or one of your own territories by the name you use. Dexor shows the size of the realised market there, your share of it, how fast the market grew, and your evolution index, marked "Outgrowing" or "Under-indexing".
The market line breaks at any month locked for confidentiality. No suppressed figure is ever plotted.
Every feature in sell-out intelligence.
Each one has its own page.
Distributor data ingest
Distributors send sell-out and stock by API push, the upload API or email. Every file is checked, stamped with where it came from, and kept as received.
Read moreEmail ingest
Registered distributor senders email a CSV to Dexor. Unknown or spoofed senders are dropped, and every file is checked line by line before import.
Read moreOutlet and SKU matching
Distributor outlet names and SKU codes are matched to your masters. Clean matches land in a territory; uncertain ones wait for a person.
Read moreMatch queue
A two-pane review queue for outlet names that did not match on ingest. Approve a candidate, override the territory, or reject, from the keyboard.
Read moreRestatement
After a match is approved, restate a past month so its unmatched lines land in the right territory. The original source data is never rewritten.
Read moreNet sales rollups
Secondary sales net of returns, per distributor and territory, with a SKU breakdown. Figures still landing are marked provisional, never shown short.
Read moreData quality workbench
Match rate, rejected rows by reason and duplicate outlets for each distributor, on one screen, linked straight to the match queue.
Read moreChannel stock
Closing stock at each distributor, days of cover against the last 30 days of sales, and SKUs with a batch close to expiry.
Read moreMarket intelligence
Your share, market growth and evolution index against the realised market, nationally, by city or by territory, with a monthly or moving annual view.
Read moreMarket map
Every territory you manage on a map, coloured by addressable share or sales value, with a drill from nation to province, city and territory.
Read moreDoctor and chemist links
Tag the chemists that serve a doctor, map each chemist to a distributor outlet, and see the sell-out invoiced to those chemists, clearly labelled.
Read moreDirectory
Searchable lists of the doctors, chemists, distributors and SKUs your team works with, each opening to a detail page with its activity and sales.
Read moreTargets and forecasting
Join reconciled sell-out to per-SKU targets for precise attainment and a forward-looking quarter verdict.
Targets and forecastingPlatform and admin
Distributor, outlet, and SKU-crosswalk masters, seat governance, and a tamper-evident audit trail.
Platform and admin