Your partner’s invoice and your CDRs disagree

4 min read

Your partner's invoice and your CDRs disagree — blog cover

The supplier PDF is 570 EUR above Last Calls for the same month. Finance wants to pay or to withhold. Pair their call file with yours before either.

Averon Networks (4 May 2026) writes that wholesale settlement fights fail on how minutes become money, not on the headline rate. Heksagon describes the same grind: extract CDRs, compare destination totals, find missing or mismatched calls, then exchange evidence. MOR and M4 run that comparison under BILLING → CDR → Disputes. Use it after they sent a CDR file. For why one answered call can bill two durations, see Your minutes and theirs will not match.

Cause 1: you compared invoice totals, not call rows

You summed Last Calls. They summed an invoice grouped by destination. The two figures disagree, and the argument stays on the invoice total.

ASTPP’s 2026 billing note (3 June 2026) lists CDRs that never billed, and reseller invoices that do not match usage. A total cannot tell you which of those you have.

You hold a PDF (or XLSX) and a report total. You do not hold their CDR CSV for that period. Ask for Source, Destination, Start Time, Disposition, Billsec, and Price. Column order does not matter. Use eight decimal places on price. About 500 rows gives the pairing enough calls to find a clock shift.

On MOR, map that layout once under Billing → CDR → Import → Templates. Then open BILLING → CDR → Disputes, pick direction (user or provider), the period, trailing source and destination digits, their currency, billsec tolerance in seconds, and price tolerance in currency. M4 uses the same menu. Direction there is Originator or Terminator, and the user list is connection points.

Cause 2: the file does not pair

You imported the CSV and most rows landed on code 90 (not matched) or code 00 (not compared).

The tool pairs source and destination, then looks at start-time differences. If one difference covers more than half of the compared CDRs, that difference becomes the time shift for the run. Other pairs stay unmatched. On M4, a pair has to land inside one second of that shifted start. MOR also has Compare by Calls calculated Answer Time when their file keys off answer, not invite.

Sort the summary to 90. If the same destination appears on both sides with a fixed offset (one hour, or a timezone), change the period or the answer-time option and run again. If non-answered rows fill the file, turn on Check only ANSWERED Calls. You see those other rows as 00 and they drop out of the match.

With a few dozen calls, MOR cannot elect a stable time shift. Bring closer to 500.

Code 99 is a broken row: empty source, empty destination, or a disposition the import cannot read. Fix the CSV. Do not argue the month on 99.

Cause 3: answered on one side only

Code 40 is answered in your CDRs and not answered in theirs. Code 42 is the reverse: they billed a connect you show as failed, busy, or no answer.

Send that row first. A destination total hides it.

Open the detailed report, filter 42, pick one source–destination–start. Check your hangup. If they show ANSWERED and a short billsec, and you show no conversation, treat it as a connect you did not see. False answer supervision is one reason billed duration can start without a real answer. Clustered short 42s on one terminator are that conversation. A single 42 can also be a clock that put the answer on the next invoice.

Cause 4: the same call appears twice

Code 70 is a duplicate in your set. Code 72 is a duplicate in their file. The match attributes are the same ones as an exact match: numbers, times, billsec, price, disposition.

One invite, two billed rows on their CSV. Ask them to drop the extra row before you talk about rates. If the duplicate is yours, find the export or the CDR write that doubled it. CDR export files on the server is the copy you send back, not a second billing engine.

Cause 5: the pair exists and the money differs

Codes 10 (exact) and 21–23 (inside the tolerances you set) are not a fight. Codes 31–33 sit outside those tolerances.

  • 31: billsec matches, price does not.
  • 32: price matches, billsec does not.
  • 33: both sit outside tolerance.

31 is a rate row, a currency, or an origin split. Origin-based rating is the case where prefix 356 has two prices and the A-number picks the row. 32 and 33 are duration rules: increment, whole-second round-up, grace. Those live in the minutes article. Stop at the code here. You cannot diagnose 32 from the invoice PDF.

Set billsec tolerance to the step you accepted in the contract (1 second, 6 seconds, or 60). Then 22 means the file behaved as written. Tolerance 0 turns a one-second round-up into 32.

What to do before you pay

  1. Get their CDR CSV for the invoice window. Save the column map as an import template for that partner.
  2. Open BILLING → CDR → Disputes. Set direction, period, trailing digits, currency, billsec tolerance, and price tolerance. Save those options as a dispute template if you reuse them.
  3. Import, wait for the background task. You cannot edit a dispute while it runs. You cannot edit it after it completes. Deleting it removes the imported CDRs.
  4. Read the summary in this order: 90 and 99, then 40 and 42, then 70 and 72, then 31–33. Send the detailed rows for the codes that hold the money, not the PDF delta.
  5. If 32 or 33 dominate after pairing, open the minutes article and check increment, grace, and the rate that was live at start time.

MOR does not ingest their invoice PDF. There is no partner portal that opens a dispute from the XLSX they emailed finance. The input is a CDR CSV.

How MOR and M4 run the comparison

From MOR X10, BILLING → CDR → Disputes imports their file and tags each pair. M4 has the same codes. M4 also expects answer_time and end_time on the calls table, and the CSV can carry Answer Time and End Time as extra columns.

Code What you send the partner
10, 21–23 Inside the rules you set. Leave it.
31 Same seconds, different money. Rate or origin.
32 Same money, different seconds. Duration rule.
40 / 42 Answered on one side only.
70 / 72 Duplicate row.
90 / 99 Did not pair, or the row is broken. Fix the file.

On M4, originator and terminator replace user and provider. The report shows local vs external calls, billsec, price, and the delta.

FAQ

Can I dispute from the invoice PDF alone?

No. The comparison needs their CDR rows. Ask for the six columns above. A destination-grouped invoice is the symptom, not the evidence.

Do I need 500 calls every time?

The pairing uses a majority time shift. A handful of rows will not elect one. Use a day with traffic, or the full period if the partner’s file is small.

Is code 42 always FAS?

No. 42 means they marked ANSWERED and you did not. FAS is one explanation when short connects cluster on a route. A timezone cut can also park the answer on their file and the failure on yours.

Run one file before you wire the settlement

Pick the partner whose invoice is furthest from Last Calls. Import their CSV, read 42 and 90 before 31. Pay the rows that matched. Hold the rows the report named.

Open BILLING → CDR → Disputes on the MOR online demo (admin web interface only; it does not place live calls). The billing feature list sits on VoIP billing software.


Pair their CSV before you pay

Open BILLING → CDR → Disputes, import the partner file, and send the mismatch rows. The minutes article covers increment and grace after the codes.

Contact us

Leave a Reply

Your email address will not be published. Required fields are marked *