Reports

Review sales, purchasing, pipeline, and customer receivables intelligence with key and user access checked at request time.

Reports are for aggregate commercial, accounts receivable, and opportunity views. Use them when a workflow needs a rollup, dashboard, comparison table, collections view, or pipeline summary rather than individual record detail.

Endpoints

EndpointUse it for
GET /reportsList report keys, parameters, dimensions, measures, required scope, and whether this key can run each report.
GET /reports/{reportKey}Run one allowed report with documented parameters and offset pagination.

Report routes require reports:read plus the acting user's live ShelfCycle permissions. GET /me also reports effectiveCapabilities.reports.available so clients can check available report keys before showing report actions.

Discover reports

Call the catalog before running a report. The catalog is the best source for labels, accepted parameters, dimensions, measures, and per-key availability.

curl "$SHELFCYCLE_API_BASE_URL/reports" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Revenue dashboard"
{
  "data": {
    "reports": [
      {
        "key": "sales-summary",
        "title": "Sales summary",
        "description": "Sales rollups by customer, product, salesperson, supplier, or month.",
        "params": [
          { "name": "groupBy", "required": true, "description": "One or two dimensions." },
          { "name": "startDate", "required": true, "description": "YYYY-MM-DD in the org timezone." },
          { "name": "endDate", "required": true, "description": "YYYY-MM-DD in the org timezone." },
          { "name": "comparisonStartDate", "required": false, "description": "Start of an optional comparison window." },
          { "name": "comparisonEndDate", "required": false, "description": "End of an optional comparison window." }
        ],
        "dimensions": ["customer", "productFamily", "productCode", "salesPerson", "supplier", "month"],
        "measures": ["salesCents", "productCostCents", "orderCostsCents", "totalCostCents", "gpCents", "gpPct"],
        "requiredScope": "reports:read",
        "allowedForThisKey": true
      }
    ]
  }
}

If allowedForThisKey is false, do not run that report with the same key.

Run a report

curl "$SHELFCYCLE_API_BASE_URL/reports/sales-summary?groupBy=customer&startDate=2026-04-01&endDate=2026-06-30&comparisonStartDate=2026-01-01&comparisonEndDate=2026-03-31&dateField=invoiceDate&sortBy=salesDelta&sortDirection=desc&limit=50" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Revenue dashboard"

Report responses include report metadata, normalized params, basis notes, rows, complete filtered-population totals, and pagination metadata. Sales, purchasing, open-order, and pipeline rows use grouping fields such as groupId, bucketKey, and groupName; two-level groupings also include group2Id, group2Key, and group2Name. AR aging rows use customer and transaction-currency fields described below.

Money values in sales, purchasing, open-order, AR aging, and Customer AR Intelligence reports are cents-as-string. Sales, purchasing, open-order, settlement behavior, and credit exposure use the organization's base currency. AR aging keeps each transaction currency in a separate lane. Invoice charge totals use the organization's base currency while each supporting row also names its transaction currency. Pipeline estimates use exact decimal strings paired with the organization's estimate currency. Keep all amounts as integer strings or decimal-safe values in your application.

Compare two periods

Add comparisonStartDate and comparisonEndDate together to compare the primary window with another bounded period. The windows can be adjacent, overlapping, equal in length, or different in length. Each window can span up to 366 days, with up to 732 combined days.

When comparison dates are present, sales and purchase rows include:

  • comparison measures for the comparison window
  • deltas calculated as primary minus comparison
  • comparisonClassification with new, lost, or retained activity

Use comparisonClassification to focus on groups active only in the primary period, only in the comparison period, or in both. Classification follows recorded activity, so zero-dollar and credit activity are not mistaken for inactivity.

Sorting happens across the complete filtered population before limit and offset are applied. Sales summaries can sort by sales, gross profit, comparison values, or their changes. Purchase summaries can sort by spend, comparison spend, or spend change. Use sortDirection=desc for the largest increases and sortDirection=asc for the largest declines.

data.totals covers the filtered population before pagination. meta.rankingComplete confirms that ranking considered that population, while meta.rowsCoverFullPopulation tells you whether the returned rows contain the complete filtered result. This lets a workflow make a top-ranked claim without treating one page as a complete list.

Review accounts receivable aging

Use ar-aging to see who currently owes money, how much is open, and how overdue the invoices are. The report groups receivables by customer and transaction currency, then keeps totals and rankings within each currency so every comparison stays meaningful.

curl "$SHELFCYCLE_API_BASE_URL/reports/ar-aging?transactionCurrencyCode=USD&sortBy=pastDueInvoiceCents&sortDirection=desc&limit=50" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Collections priority view"

Each row includes:

  • invoice balances that are current, 1-30, 31-60, 61-90, more than 90 days overdue, or missing a due date;
  • gross open invoice balance, unapplied credits, and net receivables;
  • gross past-due invoice balance and count;
  • open and unknown-due invoice counts; and
  • the oldest due date and the oldest number of days past due.

Selected fields from one response:

{
  "data": {
    "basis": {
      "dateBasis": "current-org-calendar-day",
      "timezone": "America/New_York",
      "asOfDate": "2026-08-07",
      "currencyMode": "transaction-currency-subledger-ar",
      "generatedAt": "2026-08-07T14:00:00.000Z",
      "notes": []
    },
    "rows": [
      {
        "customerId": "00000000-0000-4000-8000-000000000101",
        "customerName": "Northstar Chemical",
        "transactionCurrencyCode": "USD",
        "currentCents": "125000",
        "days1To30Cents": "250000",
        "days31To60Cents": "0",
        "days61To90Cents": "75000",
        "days90PlusCents": "50000",
        "unknownCents": "0",
        "openInvoiceCents": "500000",
        "unappliedCreditCents": "-40000",
        "netCents": "460000",
        "pastDueInvoiceCents": "375000",
        "openInvoiceCount": 6,
        "pastDueInvoiceCount": 4,
        "unknownDueInvoiceCount": 0,
        "oldestDueDate": "2026-04-20",
        "oldestDaysPastDue": 109
      }
    ],
    "totals": {
      "scope": "filtered-population-before-pagination",
      "byTransactionCurrency": [
        {
          "transactionCurrencyCode": "USD",
          "openInvoiceCents": "500000",
          "unappliedCreditCents": "-40000",
          "netCents": "460000",
          "pastDueInvoiceCents": "375000",
          "openInvoiceCount": 6,
          "pastDueInvoiceCount": 4,
          "unknownDueInvoiceCount": 0
        }
      ]
    }
  }
}

Invoice aging and unapplied credits stay distinct. unappliedCreditCents is negative, and openInvoiceCents + unappliedCreditCents = netCents. pastDueInvoiceCents is the gross past-due invoice amount, so open credits do not hide collections exposure. The six invoice buckets sum to openInvoiceCents, and the four overdue buckets sum to pastDueInvoiceCents.

The report uses the organization's current calendar day. An invoice due today remains current; the more-than-90-day bucket begins at 91 days past due. An invoice without a due date appears in unknownCents and increments unknownDueInvoiceCount.

Use customerId to focus on one customer and transactionCurrencyCode to focus on one three-letter currency code. Sort with netCents, pastDueInvoiceCents, days90PlusCents, or oldestDaysPastDue; sortDirection defaults to desc. The default ranking is netCents descending. Currency lanes remain separate, and totals.byTransactionCurrency covers the complete filtered population before pagination.

Measure invoice settlement behavior

Use customer-invoice-settlement-behavior to understand how paid customer invoices reached final settlement over a selected period. The response combines the overall pace and due-date performance with invoice-level evidence.

curl "$SHELFCYCLE_API_BASE_URL/reports/customer-invoice-settlement-behavior?customerId=00000000-0000-4000-8000-000000000101&from=2026-01-01&to=2026-06-30&limit=25" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Customer payment review"

The totals include:

  • settled invoice count and amount in the organization's base currency;
  • weighted average days to final settlement;
  • weighted average and median days against the due date; and
  • on-time results by invoice count and base-currency amount.

Each evidence row names the customer, invoice, invoice and due days, final-settlement day, timing values, transaction amount, base amount, and the recorded source for the settlement date. basis.historyState, the effective date window, and meta.coverage give the context needed to present those measures confidently.

Use the phrase "final settlement" in customer-facing views so the displayed measure keeps its precise business meaning. Add customerId for one account or omit it for an organization-wide view.

Prioritize customer credit exposure

Use customer-credit-exposure for a current view of posted receivables and uninvoiced commitments by customer. The default ranking places the largest total exposure first across the complete matching customer population.

curl "$SHELFCYCLE_API_BASE_URL/reports/customer-credit-exposure?sortBy=totalExposure&sortDirection=desc&limit=50" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Credit exposure review"

Each row keeps the exposure equation visible:

gross open invoices + open credits = net posted exposure
net posted exposure + committed uninvoiced value = total exposure

Rows include commitments split across confirmed, shipped, and delivered orders, plus credit-limit state, available credit, utilization, overage, and factual attention flags when those values apply. totals covers the complete matching population, while flagSummaries provides customer counts and exposure totals for each factual attention state.

Use sortBy with totalExposure, overage, utilization, postedExposure, committedExposure, or customerName. Use flags to focus a worklist on states such as over_limit, within_posted_over_with_commitments, or shipped_or_delivered_unbilled. Multiple flags are comma-separated and match any selected state. Add customerId for one exact customer.

Analyze customer invoice charges

Use customer-invoice-charges to total posted invoice charges and matching credits for a selected date window. Search by a configured cost category, familiar description, or ledger account wording.

curl "$SHELFCYCLE_API_BASE_URL/reports/customer-invoice-charges?from=2026-01-01&to=2026-06-30&query=tariff&limit=25" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Customer charge review"

The report returns gross charges, matching credits, and net charges in the organization's base currency. Supporting rows identify the customer, document number, posted day, description, account, category, match reason, transaction currency and amount, and base amount. A row's kind distinguishes an invoice_charge from a matched_credit.

Provide costCategoryId, query, or both. Add customerId for one account. Use the response's exact matched rows when explaining the total so finance, billing, and account teams can review the same charge history together.

Review the opportunity pipeline

Use pipeline-summary to review opportunity volume, entered estimates, ownership, and outcomes across the complete visible pipeline. Group by status, assignedTo, or aspect, where aspect separates customer- and supplier-linked opportunities.

curl "$SHELFCYCLE_API_BASE_URL/reports/pipeline-summary?groupBy=assignedTo&status=LEAD,IN_PROGRESS&limit=50" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Pipeline review"

Each row includes the opportunity count, exact sum of entered estimated values, estimate currency, count without an entered value, won and lost counts, and the oldest open creation time. data.totals covers the complete filtered opportunity population before pagination.

{
  "data": {
    "basis": {
      "dateBasis": "opportunity-created-at",
      "timezone": "America/New_York",
      "currencyMode": "single-org-base-estimate",
      "currencyCode": "USD",
      "generatedAt": "2026-08-08T14:00:00.000Z",
      "notes": []
    },
    "rows": [
      {
        "groupId": "00000000-0000-4000-8000-000000000201",
        "bucketKey": "00000000-0000-4000-8000-000000000201",
        "groupName": "Jordan Buyer",
        "opportunityCount": 12,
        "estimatedValueTotal": "185000.00",
        "currencyCode": "USD",
        "noValueCount": 2,
        "wonCount": 3,
        "lostCount": 1,
        "oldestOpenCreatedAt": "2026-05-12T15:30:00.000Z"
      }
    ],
    "totals": {
      "scope": "filtered-opportunity-population-before-pagination",
      "opportunityCount": 24,
      "estimatedValueTotal": "342500.00",
      "currencyCode": "USD",
      "noValueCount": 4,
      "wonCount": 6,
      "lostCount": 2
    }
  }
}

Use status to select one or more lifecycle stages, aspect for customer or supplier activity, assignedToId for one or more owners, and createdFrom with createdTo for an ISO timestamp window. Opportunities without estimates remain in the opportunity count and are called out in noValueCount.

Available reports

Report keyWhat it returns
sales-summarySales, cost, gross profit, and gross profit percent by one or two dimensions: customer, product family, product code, salesperson, supplier, or month.
purchase-summaryMaterial purchase-order spend by supplier, product code, or product family.
open-sales-ordersCurrent open sales-order value by status or customer.
ar-agingCurrent accounts receivable by customer and transaction currency, with invoice aging, unapplied credits, net balances, and past-due facts.
pipeline-summaryOpportunity counts, entered estimate totals, missing-value counts, outcomes, and oldest open dates by status, owner, or customer and supplier activity.
customer-invoice-settlement-behaviorFinal-settlement pace and due-date timing for paid customer invoices, with invoice-level evidence and coverage context.
customer-credit-exposureCurrent posted receivables, uninvoiced commitments, total exposure, credit-limit context, and factual attention states by customer.
customer-invoice-chargesMatched posted invoice charges and credits by customer, date, category, description, and ledger account.

Parameter notes

sales-summary reflects recovered pass-through charges in its fulfillment-cost and margin measures. orderCostsCents is the fulfillment cost allocated to the group after mapped charge recovery, and totalCostCents combines it with productCostCents. gpCents is salesCents less totalCostCents. Groups made up only of charges retain their additive cents fields, including salesCents, orderCostsCents, totalCostCents, and gpCents, while gpPct is null because those groups do not have a meaningful percentage base. These measures follow the same current mappings used in ShelfCycle's Sales Performance view.

sales-summary accepts startDate and endDate in YYYY-MM-DD format and dateField as invoiceDate, shipDate, or orderDate. It supports one or two grouping dimensions. For period comparisons, use customer, product family, product code, salesperson, or supplier dimensions. Month remains available for single-period rollups.

purchase-summary uses purchase-order created dates and supports supplier, product-code, or product-family comparisons. Its spend is material purchase-order item amount only. It excludes landed costs, standalone purchase-order cost rows, AP cash payments, quantity, and unit-cost measures.

open-sales-orders uses current sales orders in confirmed and shipped states. includeDraft=true adds draft orders. It returns open sell value only, without cost or margin.

ar-aging accepts optional customerId, transactionCurrencyCode, sortBy, and sortDirection filters. It uses the organization's current calendar day and returns population-wide totals for each transaction currency before pagination.

pipeline-summary accepts groupBy as status, assignedTo, or aspect, plus optional status, aspect, assignedToId, createdFrom, and createdTo filters. Its totals cover every visible opportunity in the filtered population before pagination.

customer-invoice-settlement-behavior requires from and to, accepts optional customerId, and returns up to 25 evidence rows by default. limit can be from 1 to 100.

customer-credit-exposure accepts optional customerId, sortBy, sortDirection, and comma-separated flags. It returns up to 100 customer rows by default, with a maximum of 500. Sorting and flag summaries cover the full filtered population before the row limit is applied.

customer-invoice-charges requires from and to, plus costCategoryId, query, or both. It accepts optional customerId and returns up to 25 evidence rows by default. limit can be from 1 to 100.

Sales, purchasing, open-order, AR aging, and pipeline reports paginate with limit and offset. Customer AR Intelligence reports use limit for bounded customer or evidence rows. Finder and reference-directory routes use their own documented pagination.

Guardrail

Reports are read-only rollups. Use detail endpoints for selected records, not reports, when a workflow needs record-specific fields, notes, documents, or write readiness.