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.

Request
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 },
    ...
  ]
}
Response
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.

DistributorOctober 2026Search ⌘K3A
Prime Medical Distributors
DIST-NYC-01
Provisional
Oct 2026
Net value, in your scope
$4,550,000
Oct 2026, your territories only
Units sold
9,860
Signed net of returns
Match rate
91%
3,742 of 4,112 rows matched an outlet
Mapped outlets
412
64 SKU crosswalk rows
BatchPeriodTypeStatus
b7f3c21e2026-10salesreceived
61d2aa902026-10stockprojected
f09e44b32026-09salesprojected
2c7b8e152026-09salesrejected
d4a1937c2026-08salesprojected
3 ways in
API push, upload API and email
Never zero
Unreadable rows set aside with a reason
Kept
The original file, exactly as received

Three ways in, all checked the same way.

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.

For files, the upload API issues a signed link for one sales or stock CSV. The link expires after 15 minutes and the server decides where the file is stored, so a caller can never write over another file. Distributors without an integration can email their CSV from a registered sender address.

Checked against the distributor's own format.

Each distributor has a mapping that names its columns and date formats. Rows are read with that mapping, numbers in local formats such as "1,234.50" or "(500)" are understood, and dates are parsed by the format you set, never guessed.

A row that cannot be read is set aside with a reason code instead of being loaded as a zero. A batch for a closed period is refused whole.

You can always see where a number came from.

Every batch is stamped with the distributor, the file type, the mapping it ran under and who or what sent it. The file is kept exactly as received, and the cleaned version is written next to it before anything reaches your reports.

Batches appear on the distributor's page in the console with their period, type and status, so "did the file arrive" has an answer.

Questions people ask.

How do distributors send us data?
Three ways: their system pushes rows with an API key, a file goes through the signed upload API, or someone emails a CSV from a registered address. Every route runs the same checks.
What happens to a bad row?
It is set aside with a reason, such as a missing required field, a value that is not a number, or a date that does not match the configured format. It never loads as a zero, and the data quality workbench shows the reasons.
Can one distributor's key send data for another?
A key pinned to a distributor writes that distributor's data and nothing else. A request naming a different one is refused, and the account always comes from the key, never from the request.
Is the original file kept?
Yes. The file is kept exactly as received, alongside the cleaned rows, so any figure can be traced back to its source.

Email 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 more

Data quality workbench

Match rate, rejected rows by reason and duplicate outlets for each distributor, on one screen, linked straight to the match queue.

Read more

Net 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 more

See it on your own team.

Tell us your fleet and we will size a proposal. Complete roll-out may take up to 4 months, counted from signed requirements and first payment.