Handle Service Compare To

​

CRM-9667 phase 2 — Δ and Impact for one page of the Services table.

The service-grain counterpart to /compare and /companies/compare. Same shape and same timeframe vocabulary, and the same reason for being a separate endpoint rather than an extension of POST /filter: these values are computed per request from two points in time, and that router sorts and filters over real columns on the queried model.

Eight metrics — ARR, CARR, MRR, CMRR and their _local twins. No ACV or TCV: both are contract-span figures with no per-service reading that sums back to the contract's.

Unlike the other two grains, the current side is computed rather than read: per-service ARR and CARR are stored nowhere, so they are derived through the same code path the snapshot writer uses. That is what keeps a service's Δ and the figure beside it on the same row from disagreeing.

A service deleted between the page load and this call is reported in notFoundRevenueItemIds rather than omitted, following the company grain — silently dropping them makes a page of deleted services indistinguishable from a page where nothing moved.

Body·

required
application/json

A Compare to request for one page of the Services table.

Row ids come from the caller for the reason the other two grains' requests do: the comparison is a companion to the table's own paginated read, not a replacement for it. The client already holds the page and asks only for the movement on those rows, which keeps this out of the shared /filter router — that one filters and sorts over real columns, and these values are computed per request from two points in time.

  • Comparison timeframe. MTD, QTD and YTD follow the account's fiscal calendar; last30Days and last12Months are counted back from today.

    values
    last30Daysmtdqtdytdlast12Monthscustom
  • Revenue item IDs to compare, normally the current page. Capped so one request cannot fan out across a whole tenant.

  • Start date, required when period is 'custom' and ignored otherwise

Responses

  • application/json
  • application/json
Request Example for post/services/compare
curl https://crm.dreamhub.ai/api/v1/contracts/services/compare \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "revenueItemIds": [
    ""
  ],
  "period": "last30Days",
  "customStart": ""
}'
{
  "period": "string",
  "periodStart": "2026-10-07T22:43:40.394Z",
  "services": [
    {
      "revenueItemId": "string",
      "existed": true,
      "previousCapturedAt": "2026-10-07T22:43:40.394Z",
      "previousSource": "string",
      "currency": "string",
      "previousCurrency": "string",
      "contractHasFinancialOverride": false,
      "metrics": {
        "additionalProperty": {
          "previous": 1,
          "current": 1,
          "delta": 1,
          "impact": "new"
        }
      }
    }
  ],
  "notFoundRevenueItemIds": [
    "string"
  ]
}