---
title: "Compose a multi-subject comparison report"
method: POST
path: "/api/locus-report-compose"
tags: ["data", "search", "real-estate", "property", "property-research", "due-diligence", "public-records", "x402", "comparison", "compose", "multi-subject", "buyer", "agent-workflow", "x402", "category:reports"]
---

# Compose a multi-subject comparison report

`POST /api/locus-report-compose`

## Request

- Base URL: `https://api.locus.report`
- URL: `https://api.locus.report/api/locus-report-compose`
- Auth: API key in header `PAYMENT-SIGNATURE`

Compare two or three homes from caller-supplied allowlisted free and paid results. Returns cited HTML and JSON plus optional share proof, without new research or provider calls. No winner, valuation, or recommendation. Charge-free when evidence is too thin. npx @velinussage/locus-agent-skill add.

## Request body

- object
  - `question` string, required
  - `subjects` object[], required
    - `id` string, required
    - `address` string, required
  - `results` union[], required
    - union
      - object
        - `source` 'caller_supplied', required
        - `result` unknown, required
        - `tool` 'locus_place_facts', required
        - `subjectId` string, required
      - object
        - `source` 'caller_supplied', required
        - `result` unknown, required
        - `tool` 'locus_parcel_lookup', required
        - `subjectId` string, required
      - object
        - `tool` 'locus-three-property-buyer-comparison', required
        - `source` 'caller_supplied', required
        - `result` unknown, required

## Response `200`

Successful paid artifact, or a free pre-charge diagnostic when the request is outside current coverage.

- union
  - object
    - `kind` 'report_compose', required
    - `generatedAt` string, required
    - `question` string, required
    - `subjects` object[], required
      - `id` string, required
      - `address` string, required
    - `dimensions` object[], required
      - `id` string, required
      - `label` string, required
      - `shared` boolean: True only when every subject reported the same single value.
      - `openQuestion` string
      - `cells` object[], required
        - `subjectId` string, required
        - `status` 'present' | 'missing' | 'contradictory' | 'source_unavailable' | 'not_covered', required: present = one cited value; contradictory = cited sources disagree and every reported value is listed.
        - `value` string
        - `provenance` object
          - `sourceName` string, required
          - `sourceUrl` string
          - `fetchedAt` string
          - `recordId` string
          - `callerSupplied` boolean, required
        - `caveat` string
        - `conflictValues` string[]
        - `conflictEvidence` object[]
          - `value` string, required
          - `provenance` object, required
            - `sourceName` string, required
            - `sourceUrl` string
            - `fetchedAt` string
            - `recordId` string
            - `callerSupplied` boolean, required
    - `sourceChecks` object[], required
      - `id` string, required
      - `label` string, required
      - `subjectId` string, required
      - `status` 'same_reported_value' | 'different_reported_values' | 'insufficient_evidence', required
      - `note` string, required
      - `reported` object[], required
        - `label` string, required
        - `value` string, required
        - `provenance` object, required
          - `sourceName` string, required
          - `sourceUrl` string
          - `fetchedAt` string
          - `recordId` string
          - `callerSupplied` boolean, required
    - `openQuestions` string[], required
    - `missingEvidence` string[], required
    - `contradictions` string[], required
    - `limitations` string[], required
    - `sourcePolicies` object[], required
      - `sourceName` string, required
      - `policyUrl` string, required
      - `paidResponse` string, required
      - `cache` string, required
      - `downstreamRedistribution` string, required
      - `publicPinning` string, required
      - `attributionText` string
    - `callerSuppliedTools` string[], required
    - `reportId` string, required
    - `reportExpiresAt` string, required
    - `skillContinuation` object
      - `skillId` string, required
      - `version` string, required
      - `url` string, required
      - `reason` string, required
    - `charged` true, required
    - `shareAccessProof` string
    - `artifacts` object, required
      - `json` object, required
        - `url` string, required
        - `sha256` string, required
        - `cid` string
      - `html` object, required
        - `url` string, required
        - `sha256` string, required
        - `cid` string
    - `idempotent` boolean
  - object
    - `kind` 'report_compose_diagnostic', required
    - `charged` false, required
    - `status` 'invalid_input' | 'insufficient_evidence' | 'disabled' | 'persistence_unavailable' | 'share_unavailable', required
    - `message` string, required
    - `componentStatus` object[]
      - `component` string, required
      - `subjectId` string
      - `status` string, required
      - `detail` string
    - `rule` string
    - `thresholds` object
      - `minComparableDimensions` number, required
      - `minSubjectsPerDimension` number, required
      - `everySubjectNeedsCitedFact` boolean, required
    - `refusalDetail` object
      - `reason` 'use_policy' | 'subject_binding' | 'no_overlapping_dimension' | 'subject_without_cited_fact', required
      - `rule` string, required
      - `thresholds` object, required
        - `minComparableDimensions` number, required
        - `minSubjectsPerDimension` number, required
        - `everySubjectNeedsCitedFact` boolean, required
      - `dimensions` object[], required
        - `id` string, required
        - `label` string, required
        - `citedSubjectCount` number, required
        - `subjects` object[], required
          - `subjectId` string, required
          - `status` string, required
          - `citedEvidence` boolean, required
          - `note` string, required
      - `subjectsWithoutCitedFact` string[], required
      - `policyErrors` object[], required
        - `subjectId` string, required
        - `tool` string, required
        - `field` string, required
        - `problem` string, required

## Other responses

- `400`: Invalid request body.
- `402`: Payment Required. For x402 v2, repeat the identical request with a valid PAYMENT-SIGNATURE header (legacy X-PAYMENT is accepted for compatibility). MPP is disabled for this lifecycle-bound tool.

---

[API](https://skmtc.dev/locus/apis/locus-api.md) · [All operations](https://skmtc.dev/locus/apis/locus-api/llms.txt) · [OpenAPI document](https://skmtc.dev/locus/apis/locus-api/revisions/ba7786b74adb?raw)
