# Third Party Litigation Report API

Source: https://caseprimus.ai/docs/litigation-report-api

## API To Generate A Third Party Litigation Report On Any Company In India

The **Third Party Litigation Report API** compiles a company's court-case history into one report. CasePrimus.ai finds the company's cases by name, fetches each case's details live from its own court, and gives every case a kind of litigation and a risk level with the reasons behind it. Built for third-party due diligence, vendor onboarding, lending and M&A, it turns a company name into a report your team can act on.

The report carries the company's overall litigation level and a reputation score on a 0 to 1000 scale, the same scale as the watchlist, with breakdowns by kind of litigation, court, state and filing year. You start a report, follow its progress, then list and filter its cases, or read a single case with its orders, parties and acts.

> **Built on certified infrastructure.** CasePrimus.ai is operated by Pegadroid IQ Solutions Private Limited, the legal entity behind Attestr's products, which holds ISO/IEC 27001:2022 certification. Data is hosted in India (AWS Mumbai, ap-south-1) and every connection is encrypted in transit.

## Key capabilities

- **A whole company in one report.** Cases are found by the company's name, and each case's details are fetched live from its own court.
- **A kind of litigation for every case.** Every case is categorised, for example `CRIMINAL_CHEQUE_BOUNCE` or `INSOLVENCY_RECOVERY`, so you can filter on it.
- **A risk level, with the reasons.** Each case gets a risk level and the reasons behind it. The company gets an overall litigation level and a reputation score from 0 to 1000.
- **Basic or Advanced depth.** A Basic report reads each court's own record. An Advanced report also reads the most recent order on every case.
- **How closely each case matched.** Each case is tagged by whether it was filed where the company is: by name alone, by name and state, or by name, state and district. It is an indication, not a verification.
- **Filter, sort and page the cases.** Narrow the case list by kind of litigation, risk level, status, court, state and match, and sort by risk or by filing date.
- **Breakdowns at a glance.** Figures by kind of litigation, court, state and filing year, the pending cases that weigh most, and how much of the record could be read.
- **Identifiers sharpen the reading.** A CIN, PAN, GSTIN or address you give is used only to recognise the company in the results. Identifiers and addresses are never sent to a court data source.

## How it works

1. **Start a report.** Post the company's name, and the `tier`, to `POST /litigation-reports`. The call returns straight away with the report in `QUEUED`, and the report is prepared in the background.
2. **Follow its progress.** Poll `GET /litigation-reports/{reportId}`. The status moves from `QUEUED` through `DISCOVERING` and `ENRICHING` to `COMPLETE`. A Basic report takes up to 6 hours, longer for a company with a great many cases.
3. **Read the figures and the cases.** Once the report is `COMPLETE`, it carries the totals, the litigation level and the reputation score. List and filter its cases, or read one case in full.

## API definition

### Start a Third Party Litigation Report

Starts a Third Party Litigation Report on a company. CasePrimus finds the company's court cases by name, fetches each case's details live from its own court, gives every case a kind of litigation and a risk level with the reasons behind it, and tags it by how closely it matched the company: by name alone, by name and state, or by name, state and district. `tier` chooses how deep the report goes and defaults to BASIC. A Basic report reads each court's own record of the case: the parties, the acts and sections, the stage and the dates. It opens no document, so nothing in it reflects what an order decided. An Advanced report also reads one document per case, the most recent order the court lists, and gives each case that order's summary, which way it went for the company, and `orderRead.identity`: whether the order's identifiers and addresses confirm the case is this company's. Identifiers and addresses you send are used only to recognise the company in the results; they are never sent to a court data source. The call returns straight away with the report in QUEUED, and the report is prepared in the background. A Basic report takes up to 6 hours, longer for a company with a great many cases. Poll the report to follow its progress. Up to 3 reports are prepared at once for an account; a fourth is refused with 429 until one finishes. Requires case.write.

**Request URL**

`POST https://api.caseprimus.ai/api/caseprimus/v1/litigation-reports`

**Request headers**

| Type | Name | Value | Optional |
| --- | --- | --- | --- |
| String | `Content-Type` | `application/json` | Required |
| String | `X-CasePrimus-Api-Key` | Your API key | Required |

**Input parameters**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Required | The company's name as it would appear in a court record. 2 to 255 characters |
| `tier` | enum | Optional | How deep the report goes. BASIC reads each court's own record and opens no document. ADVANCED also reads the most recent order on every case - exactly one document per case - and gives each case that order's summary, which way it went, and whether the order's identifiers and addresses confirm the case is this company's. Omitting it keeps a report Basic. One of: BASIC, ADVANCED |
| `nameVariations` | array of string | Optional | Other spellings the courts may have used. |
| `autoNameVariations` | boolean | Optional | Let CasePrimus derive the variations instead of listing them. |
| `identifiers` | any | Optional | CIN, PAN, GSTIN or UDYAM - a list of up to 12, or one comma-separated string. Never sent to a court data source; used only to recognise the company in the results (a CIN gives its state of registration). |
| `addresses` | array of object | Optional | Where the company sits, so a case can be compared with it. Never sent to a court data source. |
| `addresses[].label` | string or null | Optional | up to 60 characters |
| `addresses[].line` | string or null | Optional | up to 400 characters |
| `addresses[].city` | string or null | Optional | up to 100 characters |
| `addresses[].district` | string or null | Optional | up to 100 characters |
| `addresses[].state` | string or null | Optional | up to 100 characters |
| `addresses[].pincode` | string or null | Optional |  |
| `partyType` | enum | Optional | Which side to look for the company on. Both by default. One of: PETITIONER, RESPONDENT, BOTH |
| `criteria` | object | Optional |  |
| `criteria.caseStatus` | enum | Optional | One of: ALL, PENDING, DISPOSED |
| `criteria.fromYear` | integer or null | Optional | Not later than this year. minimum 1950 |
| `criteria.toYear` | integer or null | Optional | minimum 1950 |
| `criteria.maxPages` | integer | Optional | Pages of 100 cases to read. 1 to 50 |
| `criteria.courtTypes` | array of enum | Optional | Search only these courts. SC the Supreme Court, HC the High Courts, DC the District Courts, OTHER everything else - the consumer commissions, NCLT, NCLAT, CESTAT, ITAT, DRT, DRAT, GSTAT, NGT, SAT, APTEL and any court that cannot be placed. Omit it to search every court. It narrows the SEARCH, not the finished report: a report restricted to the High Courts never looks anywhere else, so it finishes sooner and maxPages covers more of what you asked for. One of: SC, HC, DC, OTHER |

**Sample request**

```bash
BASE="https://api.caseprimus.ai/api/caseprimus/v1"

curl -X POST "$BASE/litigation-reports" \
  -H "X-CasePrimus-Api-Key: $CASEPRIMUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Logistics Private Limited",
    "nameVariations": [
      "Acme Logistics Pvt Ltd"
    ],
    "identifiers": [
      {
        "type": "CIN",
        "value": "U63090MH2012PTC123456"
      }
    ],
    "addresses": [
      {
        "label": "Registered office",
        "line": "14 Marine Lines",
        "city": "Mumbai",
        "district": "Mumbai City",
        "state": "Maharashtra",
        "pincode": "400020"
      }
    ],
    "partyType": "BOTH",
    "criteria": {
      "caseStatus": "ALL",
      "fromYear": 2015,
      "maxPages": 10
    }
  }'
```

**Responses**

- `202`: The report was accepted and is being prepared.
- `400`: The request is not valid (`VALIDATION_ERROR`, 60000).
- `403`: Caller lacks case.write, or the plan does not include this product (`PRODUCT_NOT_IN_PLAN`, 61470).
- `429`: Too many reports are already being prepared for this account (`LITIGATION_REPORT_TOO_MANY_RUNNING`, 61477).
- `503`: Reports cannot be started right now and nothing was created (`LITIGATION_REPORT_UNAVAILABLE`, 61480).

**Response fields (HTTP 202)**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reportId` | string |  |  |
| `name` | string |  | The company the report is about |
| `tier` | enum |  | How deeply the cases were read. BASIC uses the court's own case record and opens no order documents. ADVANCED reads the latest order of each case and ADVANCED_PLUS reads every order; neither is available yet. One of: BASIC, ADVANCED, ADVANCED_PLUS |
| `status` | enum |  | Where the report has got to. DISCOVERING is finding the cases, ENRICHING is fetching each case from its court and scoring it. The internal FINALIZING step, when the figures are computed, is reported as ENRICHING - it is not a step a customer waits on separately. One of: QUEUED, DISCOVERING, ENRICHING, COMPLETE, FAILED |
| `disclaimer` | object |  | The caveats that travel with every form of the report - this response, the dashboard, the CSV, the JSON and the PDF all show these same words. `coverage`, `notCovered` and `readingLimits` say what the search reaches, what it does not, and how an order that is a scan or is in a regional language is read; the PDF prints all three in full. |
| `disclaimer.summary` | string |  |  |
| `disclaimer.points` | array of string |  |  |
| `disclaimer.coverage` | array of object |  | Every forum searched for this company, grouped. |
| `disclaimer.notCovered` | array of string |  | What a report of this kind cannot show - FIRs that have not reached a court, private arbitration, regulatory action that is not litigation, and the rest. |
| `disclaimer.readingLimits` | array of string |  | How an order is read on an Advanced report, and where that can go wrong. The model reads the court's PDF directly and transcribes and translates as it reads - there is no separate OCR or translation step - so a faint scan, a handwritten order or an unusual script can be read wrongly, and the summary will still read fluently. |
| `disclaimer.tierNote` | string or null |  | The one sentence that differs by tier - whether this report opens any order at all. |
| `input` | object |  | What the report was asked for, as it was understood. `identifiers[].derived` is what each identifier told us - a CIN gives a state code - and is all that an identifier is used for. |
| `input.name` | string |  |  |
| `input.nameVariations` | array of string |  |  |
| `input.partyType` | enum |  | One of: PETITIONER, RESPONDENT, BOTH |
| `input.identifiers` | array of object |  |  |
| `input.addresses` | array of object |  |  |
| `input.criteria` | object |  |  |
| `progress` | object |  | How many cases have been found and how far each has got. The counts add up to `discovered` once nothing is waiting. |
| `progress.discovered` | integer |  | Cases found for the company. |
| `progress.waiting` | integer |  | Found |
| `progress.fetched` | integer |  |  |
| `progress.notFound` | integer |  | The court has no case for the reference. |
| `progress.unavailable` | integer |  | The case carries nothing that court can be asked with. |
| `progress.failed` | integer |  |  |
| `warnings` | array of string |  | Anything that limits how the figures should be read - cases that could not be fetched, a page limit that was reached. |
| `summary` | object or null |  | The report's figures. Null until the report is COMPLETE. |
| `summary.computedAt` | integer (int64) |  |  |
| `summary.scoringVersion` | integer or null |  | Which version of the risk-scoring rules produced these figures. Reports computed before carry the same number under the old name `rubricVersion`; this response always uses `scoringVersion`. |
| `summary.totals` | object |  |  |
| `summary.level` | object |  | The company's litigation level, set by the most serious thing pending against it - not by an average. |
| `summary.reputationScore` | object or null |  | The company's reputation score, 0-1000, where HIGHER IS BETTER - the same scale and direction as the watchlist's entity score. It is BANDED by the litigation level above, so the two can never disagree: the band says how serious the worst pending matter is, and the position inside the band says how much of the case load is like it. |
| `summary.byCategory` | array of object |  |  |
| `summary.byCourtType` | array of object |  |  |
| `summary.byState` | array of object |  | Up to 25 states, busiest first. |
| `summary.byFilingYear` | array of object |  |  |
| `summary.bySide` | array of object |  | Which side of the case the company was on. |
| `summary.byLocationTag` | array of object |  | How closely each case matched the company. Always all three tags, including the ones with no cases. |
| `summary.outcomes` | object (free-form) |  | How the finished cases ended, counted by outcome. |
| `summary.topPending` | array of object |  | The ten pending cases with the highest risk scores. |
| `summary.coverage` | object |  | How much of the record could actually be read - the honest limit on every figure above. |
| `failureReason` | string or null |  | Set only when `status` is FAILED. |
| `createdAt` | integer (int64) |  |  |
| `startedAt` | integer (int64) or null |  |  |
| `finishedAt` | integer (int64) or null |  |  |
| `expiresAt` | integer (int64) |  | When the report's cases are deleted - 30 days after it was started. The report and its figures are kept. |
| `caseDataExpired` | boolean |  | True once `expiresAt` has passed |

**Example response (202)**

```json
{
  "reportId": "CPLR0exampledemo0002",
  "status": "QUEUED",
  "tier": "ADVANCED",
  "name": "Acme Logistics Private Limited"
}
```

### Get a litigation report

Returns one report. While it is being prepared, `progress` says where it has got to. Once it is COMPLETE it carries the full figures: the totals, the company's litigation level and reputation score, the breakdowns by kind of litigation, court, state and filing year, the pending cases that weigh most, and how much of the record could be read. Requires case.read.

**Request URL**

`GET https://api.caseprimus.ai/api/caseprimus/v1/litigation-reports/{reportId}`

**Request headers**

| Type | Name | Value | Optional |
| --- | --- | --- | --- |
| String | `X-CasePrimus-Api-Key` | Your API key | Required |

**Parameters**

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `reportId` | path | Required | The report's id, as returned when it was started. |

**Sample request**

```bash
BASE="https://api.caseprimus.ai/api/caseprimus/v1"

curl "$BASE/litigation-reports/LITIGATION_REPORT_ID" \
  -H "X-CasePrimus-Api-Key: $CASEPRIMUS_API_KEY"
```

**Responses**

- `200`: The report.
- `403`: Caller lacks case.read, or the plan does not include this product (61470).
- `404`: No such report for this account (`LITIGATION_REPORT_NOT_FOUND`, 61475).

**Response fields (HTTP 200)**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `reportId` | string |  |  |
| `name` | string |  | The company the report is about |
| `tier` | enum |  | How deeply the cases were read. BASIC uses the court's own case record and opens no order documents. ADVANCED reads the latest order of each case and ADVANCED_PLUS reads every order; neither is available yet. One of: BASIC, ADVANCED, ADVANCED_PLUS |
| `status` | enum |  | Where the report has got to. DISCOVERING is finding the cases, ENRICHING is fetching each case from its court and scoring it. The internal FINALIZING step, when the figures are computed, is reported as ENRICHING - it is not a step a customer waits on separately. One of: QUEUED, DISCOVERING, ENRICHING, COMPLETE, FAILED |
| `disclaimer` | object |  | The caveats that travel with every form of the report - this response, the dashboard, the CSV, the JSON and the PDF all show these same words. `coverage`, `notCovered` and `readingLimits` say what the search reaches, what it does not, and how an order that is a scan or is in a regional language is read; the PDF prints all three in full. |
| `disclaimer.summary` | string |  |  |
| `disclaimer.points` | array of string |  |  |
| `disclaimer.coverage` | array of object |  | Every forum searched for this company, grouped. |
| `disclaimer.notCovered` | array of string |  | What a report of this kind cannot show - FIRs that have not reached a court, private arbitration, regulatory action that is not litigation, and the rest. |
| `disclaimer.readingLimits` | array of string |  | How an order is read on an Advanced report, and where that can go wrong. The model reads the court's PDF directly and transcribes and translates as it reads - there is no separate OCR or translation step - so a faint scan, a handwritten order or an unusual script can be read wrongly, and the summary will still read fluently. |
| `disclaimer.tierNote` | string or null |  | The one sentence that differs by tier - whether this report opens any order at all. |
| `input` | object |  | What the report was asked for, as it was understood. `identifiers[].derived` is what each identifier told us - a CIN gives a state code - and is all that an identifier is used for. |
| `input.name` | string |  |  |
| `input.nameVariations` | array of string |  |  |
| `input.partyType` | enum |  | One of: PETITIONER, RESPONDENT, BOTH |
| `input.identifiers` | array of object |  |  |
| `input.addresses` | array of object |  |  |
| `input.criteria` | object |  |  |
| `progress` | object |  | How many cases have been found and how far each has got. The counts add up to `discovered` once nothing is waiting. |
| `progress.discovered` | integer |  | Cases found for the company. |
| `progress.waiting` | integer |  | Found |
| `progress.fetched` | integer |  |  |
| `progress.notFound` | integer |  | The court has no case for the reference. |
| `progress.unavailable` | integer |  | The case carries nothing that court can be asked with. |
| `progress.failed` | integer |  |  |
| `warnings` | array of string |  | Anything that limits how the figures should be read - cases that could not be fetched, a page limit that was reached. |
| `summary` | object or null |  | The report's figures. Null until the report is COMPLETE. |
| `summary.computedAt` | integer (int64) |  |  |
| `summary.scoringVersion` | integer or null |  | Which version of the risk-scoring rules produced these figures. Reports computed before carry the same number under the old name `rubricVersion`; this response always uses `scoringVersion`. |
| `summary.totals` | object |  |  |
| `summary.level` | object |  | The company's litigation level, set by the most serious thing pending against it - not by an average. |
| `summary.reputationScore` | object or null |  | The company's reputation score, 0-1000, where HIGHER IS BETTER - the same scale and direction as the watchlist's entity score. It is BANDED by the litigation level above, so the two can never disagree: the band says how serious the worst pending matter is, and the position inside the band says how much of the case load is like it. |
| `summary.byCategory` | array of object |  |  |
| `summary.byCourtType` | array of object |  |  |
| `summary.byState` | array of object |  | Up to 25 states, busiest first. |
| `summary.byFilingYear` | array of object |  |  |
| `summary.bySide` | array of object |  | Which side of the case the company was on. |
| `summary.byLocationTag` | array of object |  | How closely each case matched the company. Always all three tags, including the ones with no cases. |
| `summary.outcomes` | object (free-form) |  | How the finished cases ended, counted by outcome. |
| `summary.topPending` | array of object |  | The ten pending cases with the highest risk scores. |
| `summary.coverage` | object |  | How much of the record could actually be read - the honest limit on every figure above. |
| `failureReason` | string or null |  | Set only when `status` is FAILED. |
| `createdAt` | integer (int64) |  |  |
| `startedAt` | integer (int64) or null |  |  |
| `finishedAt` | integer (int64) or null |  |  |
| `expiresAt` | integer (int64) |  | When the report's cases are deleted - 30 days after it was started. The report and its figures are kept. |
| `caseDataExpired` | boolean |  | True once `expiresAt` has passed |

**Example response (200)**

```json
{
  "reportId": "CPLR0exampledemo0001",
  "name": "Acme Logistics Private Limited",
  "tier": "BASIC",
  "status": "COMPLETE",
  "disclaimer": {
    "summary": "Public court records, compiled for information. Not legal advice, not a verification of the company, and the risk levels are indicative only.",
    "points": [
      "This report is compiled from public court records. It is information, not legal advice, and not a verification of the company.",
      "Cases are found by matching the company name and the spellings you gave. A case may belong to a different company of a similar name, and a case filed under a name we were not given will be missing. Where a case is only a name match the report says so.",
      "The risk level and the score are INDICATIVE: they come from the kind of case, where it stands, and - on an Advanced report - what the one order it read appeared to say. They are not a finding about the case or the company.",
      "Acts and sections are explained from a reference list for general information only. It has not been verified by a lawyer, and the statute itself is the authority.",
      "Court records change daily and some courts publish late or incompletely. Each report states how many of its cases it could fetch from the court and which it could not.",
      "Decisions about a company should not rest on this report alone."
    ]
  },
  "input": {
    "name": "Acme Logistics Private Limited",
    "nameVariations": [
      "Acme Logistics Pvt Ltd"
    ],
    "partyType": "BOTH",
    "identifiers": [
      {
        "type": "CIN",
        "value": "U63090MH2012PTC123456",
        "derived": {
          "stateCode": "MH"
        }
      }
    ],
    "addresses": [
      {
        "label": "Registered office",
        "city": "Mumbai",
        "district": "Mumbai City",
        "state": "Maharashtra",
        "pincode": "400020",
        "stateCode": "MH"
      }
    ],
    "criteria": {
      "caseStatus": "ALL",
      "fromYear": 2015,
      "toYear": null,
      "maxPages": 10
    }
  },
  "progress": {
    "discovered": 312,
    "waiting": 0,
    "fetched": 296,
    "notFound": 2,
    "unavailable": 11,
    "failed": 3
  },
  "warnings": [
    "11 cases could not be fetched from their court and are scored from the search record alone."
  ],
  "summary": {
    "computedAt": 1757397000000,
    "scoringVersion": 5,
    "totals": {
      "cases": 312,
      "pending": 118,
      "disposed": 194,
      "filedLast12Months": 41,
      "hearingsNext90Days": 37,
      "oldestPendingYear": 2009
    },
    "level": {
      "company": "MODERATE",
      "reason": "9 pending cases are high risk, out of 118",
      "pendingVeryHigh": 0,
      "pendingHigh": 9,
      "pendingModerate": 43,
      "pendingMedium": 43,
      "byLevel": {
        "VERY_HIGH": 0,
        "HIGH": 14,
        "MODERATE": 61,
        "LOW": 190,
        "MINIMAL": 47
      }
    },
    "reputationScore": {
      "value": 486,
      "scale": 1000,
      "higherIsBetter": true,
      "band": "MODERATE",
      "version": 4,
      "deductions": [
        {
          "key": "HIGH_SHARE",
          "points": 41,
          "label": "9 of the 118 pending cases are high risk"
        },
        {
          "key": "ADVERSE_OUTCOMES",
          "points": 22,
          "label": "22 of the 194 finished cases went against the company"
        }
      ],
      "basedOn": {
        "cases": 312,
        "pending": 118,
        "disposed": 194,
        "pendingVeryHigh": 0,
        "pendingHigh": 9,
        "pendingMedium": 43,
        "adverse": 22
      }
    },
    "byCategory": [
      {
        "key": "CRIMINAL_CHEQUE_BOUNCE",
        "label": "Cheque bounce (criminal)",
        "count": 96,
        "pending": 44,
        "high": 9,
        "medium": 31
      },
      {
        "key": "COMMERCIAL_CONTRACT",
        "label": "Commercial and contract",
        "count": 61,
        "pending": 29,
        "high": 2,
        "medium": 14
      }
    ],
    "byCourtType": [
      {
        "key": "DC",
        "label": "District courts",
        "count": 243
      },
      {
        "key": "HC",
        "label": "High Courts",
        "count": 58
      }
    ],
    "byState": [
      {
        "key": "Maharashtra",
        "label": "Maharashtra",
        "count": 171
      },
      {
        "key": "Gujarat",
        "label": "Gujarat",
        "count": 44
      }
    ],
    "byFilingYear": [
      {
        "year": 2023,
        "count": 52
      },
      {
        "year": 2024,
        "count": 38
      }
    ],
    "bySide": [
      {
        "key": "RESPONDENT",
        "count": 204
      },
      {
        "key": "PETITIONER",
        "count": 108
      }
    ],
    "byLocationTag": [
      {
        "key": "NAME_STATE_DISTRICT",
        "label": "Name, state and district",
        "count": 139
      },
      {
        "key": "NAME_STATE",
        "label": "Name and state",
        "count": 73
      },
      {
        "key": "NAME_ONLY",
        "label": "Name only",
        "count": 100
      }
    ],
    "outcomes": {
      "AGAINST_COMPANY": 22,
      "IN_FAVOUR": 61,
      "NEUTRAL": 111,
      "NOT_APPLICABLE": 118
    },
    "topPending": [
      {
        "caseRef": "cr_9a0b1c2d3e4f5061",
        "caseNumber": "CP(IB)/412/MB/2023",
        "court": "NCLT, Mumbai",
        "category": "INSOLVENCY_RECOVERY",
        "level": "VERY_HIGH",
        "score": 94,
        "filingYear": 2023
      },
      {
        "caseRef": "cr_51ff1354f54a87d5",
        "caseNumber": "CC/1182/2021",
        "court": "District Court, Mumbai City",
        "category": "CRIMINAL_CHEQUE_BOUNCE",
        "level": "HIGH",
        "score": 80,
        "filingYear": 2021
      }
    ],
    "coverage": {
      "casesWithLiveDetails": 296,
      "casesNotFoundAtCourt": 2,
      "casesFailed": 3,
      "casesWaiting": 0,
      "casesWithState": 301,
      "unavailable": [
        {
          "reason": "NO_IDENTIFIER",
          "count": 11
        }
      ],
      "yearRange": {
        "from": 2009,
        "to": 2026
      }
    }
  },
  "failureReason": null,
  "createdAt": 1757390000000,
  "startedAt": 1757390010000,
  "finishedAt": 1757397000000,
  "expiresAt": 1759982000000,
  "caseDataExpired": false
}
```

### List the cases in a report

Returns the report's cases, filtered, sorted and paged. Every case carries its court record, the kind of litigation, a risk level with the reasons behind it, how closely it matched the company, and whether its details could be fetched from the court. Each case also carries `orderIds`, the ids of its orders on the court's record (empty where the details were never fetched or the court lists no order). The orders themselves, the parties as the court recorded them, the judges and the acts explained come only when one case is read. `orderRead` is on every case and always carries a `status`, so a Basic report (NOT_APPLICABLE), a case where the court published no document (NO_ORDER, NO_DOCUMENT) and a document that could not be read (FAILED) can be told apart. On an Advanced report every case carries a summary, and `summaryBasis` says what it rests on: ORDER means the court's own document was read; RECORD means no document could be, so the summary is written from the court's index entry (parties, acts, stage and dates) and it never carries a `riskSignal`. A case that was read also carries `riskSignal`, which way the order went for the company, and `identity`, whether the order's identifiers and addresses confirm the case is this company's: CONFIRMED, CONFLICTS or NOT_FOUND. A match is evidence; the absence of one is not disproof. Cases are deleted 30 days after the report is started. The report and its figures remain, and reading the cases after that is refused with 410. Requires case.read.

**Request URL**

`GET https://api.caseprimus.ai/api/caseprimus/v1/litigation-reports/{reportId}/cases`

**Request headers**

| Type | Name | Value | Optional |
| --- | --- | --- | --- |
| String | `X-CasePrimus-Api-Key` | Your API key | Required |

**Parameters**

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `reportId` | path | Required |  |
| `category` | query | Optional | Kinds of litigation to include, e.g. CRIMINAL_CHEQUE_BOUNCE, INSOLVENCY_RECOVERY. |
| `level` | query | Optional | Risk levels to include. MEDIUM is accepted as the former name of MODERATE, so a filter written against the earlier three-level vocabulary keeps working. |
| `status` | query | Optional |  |
| `courtType` | query | Optional | e.g. DC, HC, SC, NCLT, CESTAT. |
| `state` | query | Optional |  |
| `tag` | query | Optional | How closely the case matched the company - by name alone, by name and state, or by name, state and district. |
| `details` | query | Optional | Whether the court's own details could be fetched for the case. |
| `identity` | query | Optional | What the order said about whether the case is this company's. Only an Advanced report has this; on a Basic report it matches nothing rather than erroring, so a saved filter does not break when a company is re-run at the other tier. |
| `signal` | query | Optional | Which way the most recent order went for the company. Advanced only, on the same terms as `identity`. |
| `q` | query | Optional | Free text - a case number, a party, a court. |
| `sort` | query | Optional | `order_adverse` and `order_favourable` sort by what the most recent order said, worst or best first, with risk as the second key. A case where no order was read always sorts last, whichever direction is asked for - sorting by what an order said should not promote cases where nothing was said. Accepted on a Basic report, where every case ranks equal and risk decides, so a saved view does not break when the same company is re-run at the other tier. |
| `skip` | query | Optional |  |
| `limit` | query | Optional |  |

**Sample request**

```bash
BASE="https://api.caseprimus.ai/api/caseprimus/v1"

curl "$BASE/litigation-reports/LITIGATION_REPORT_ID/cases" \
  -H "X-CasePrimus-Api-Key: $CASEPRIMUS_API_KEY"
```

**Responses**

- `200`: A page of the report's cases.
- `400`: The query is not valid (60000).
- `403`: Caller lacks case.read, or the plan does not include this product (61470).
- `404`: No such report for this account (61475).
- `410`: The report's case data has expired, 30 days after the report was started (`LITIGATION_REPORT_EXPIRED`, 61478).

**Response fields (HTTP 200)**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `total` | integer |  | How many cases match the filter, before paging. |
| `skip` | integer |  |  |
| `limit` | integer |  |  |
| `cases` | array of object |  |  |
| `cases[].caseRef` | string |  | The case's reference within this report. |
| `cases[].caseNumber` | string or null |  | The case number, or whichever of the registration, filing or CNR number the court gave instead. |
| `cases[].cnrNumber` | string or null |  |  |
| `cases[].court` | string or null |  |  |
| `cases[].courtType` | string |  | e.g. DC, HC, SC, NCLT, CESTAT. |
| `cases[].state` | string or null |  |  |
| `cases[].district` | string or null |  |  |
| `cases[].caseType` | string or null |  |  |
| `cases[].caseCategory` | string or null |  |  |
| `cases[].status` | enum |  | One of: PENDING, DISPOSED |
| `cases[].caseStatus` | string or null |  | The court's own words for where the case stands. |
| `cases[].caseStage` | string or null |  |  |
| `cases[].filingDate` | string or null |  |  |
| `cases[].filingYear` | integer or null |  |  |
| `cases[].registrationDate` | string or null |  |  |
| `cases[].decisionDate` | string or null |  |  |
| `cases[].nextHearingDate` | string or null |  |  |
| `cases[].natureOfDisposal` | string or null |  |  |
| `cases[].petitioners` | array of string |  |  |
| `cases[].respondents` | array of string |  |  |
| `cases[].matchedParty` | string or null |  | The party on the record that matched the company. |
| `cases[].companySide` | enum or null |  | One of: PETITIONER, RESPONDENT, BOTH |
| `cases[].acts` | array of string |  | The acts and sections as the court wrote them. |
| `cases[].counts` | object |  |  |
| `cases[].courtCategory` | string or null |  | The court's own category for the dispute, in the court's own coding, e.g. "14.02 Cheque Dishonour ( 1182 )". |
| `cases[].courtSubCategory` | string or null |  |  |
| `cases[].courtSubSubCategory` | string or null |  |  |
| `cases[].courtRegistrationNumber` | string or null |  | The number the court registered the case under, from the court's own record. `caseNumber` above is whichever identifying number the search result carried, which is not always this one - a case is frequently registered under a different number from the one it was filed under, and reconciling a report against a court's site needs both. |
| `cases[].courtFilingNumber` | string or null |  | The number the case was filed under |
| `cases[].previousHearingDate` | string or null |  | The last hearing the court held |
| `cases[].orderIds` | array of string |  | The ids of this case's orders on the court's record, in the order the court lists them. Computed from the order itself, so an id here is the same id a fresh lookup of the case returns - which is how an order named in a report is matched to the order a download can be asked for; the endpoint's own description gives the sequence. Present on the list and on the single case alike. Empty where the court's details could not be fetched or the court lists no order, and short of `counts.orders` on a case fetched before whose stored orders have no ids until it is fetched again. An id names an order on the court's RECORD, which is not the same as a document existing: several courts list orders they published nothing for. The orders' own numbers, dates and types are on the single-case response and in the JSON export, not here. |
| `cases[].category` | string |  | The kind of litigation, e.g. CRIMINAL_CHEQUE_BOUNCE, INSOLVENCY_RECOVERY. |
| `cases[].categoryLabel` | string |  |  |
| `cases[].risk` | object |  | What this case means on its own. The level and the score come from the kind of case, the company's side, how it stands and what the statute behind it allows - not from reading any order. |
| `cases[].orderRead` | object |  | What was read for this case, and what it said. Always present and always carrying a `status`, so a reader can tell "this is a Basic report" (`NOT_APPLICABLE`) from "the court published no document" (`NO_ORDER`, `NO_DOCUMENT`) and from "we could not read it" (`FAILED`). |
| `cases[].locationMatch` | object |  | How closely the case matched the company - whether it was filed where the company is registered or has an address. An indication, not a verification. |
| `cases[].details` | object |  | Whether the court's own record could be fetched for this case, and why not where it could not. |

**Example response (200)**

```json
{
  "total": 312,
  "skip": 0,
  "limit": 25,
  "cases": [
    {
      "caseRef": "cr_51ff1354f54a87d5",
      "caseNumber": "CC/1182/2021",
      "cnrNumber": "MHCC010123452021",
      "court": "District Court, Mumbai City",
      "courtType": "DC",
      "state": "Maharashtra",
      "district": "Mumbai City",
      "caseType": "Complaint Case",
      "caseCategory": null,
      "status": "PENDING",
      "caseStatus": "Case Pending",
      "caseStage": "Evidence",
      "filingDate": "2021-03-14",
      "filingYear": 2021,
      "registrationDate": "2021-03-20",
      "decisionDate": null,
      "nextHearingDate": "2026-11-18",
      "natureOfDisposal": null,
      "petitioners": [
        "Suraj Packaging LLP"
      ],
      "respondents": [
        "Acme Logistics Private Limited"
      ],
      "matchedParty": "Acme Logistics Private Limited",
      "companySide": "RESPONDENT",
      "acts": [
        "Negotiable Instruments Act 1881 | Section 138"
      ],
      "counts": {
        "orders": 4,
        "hearings": 11
      },
      "orderIds": [
        "af2538a37a645f61a09c177924d3ecb5",
        "6e96db2dfa0d699908f8d5fed84af3ae",
        "1b7c93e2d5084a61b0f3c7d9a24e8f50",
        "c40e8b1f6a2d47c9815be03f9d7a261c"
      ],
      "category": "CRIMINAL_CHEQUE_BOUNCE",
      "categoryLabel": "Cheque bounce (criminal)",
      "risk": {
        "level": "HIGH",
        "score": 80,
        "outcome": "NOT_APPLICABLE",
        "basis": "LIVE",
        "reasons": [
          "Cheque bounce (criminal) matter",
          "The company is on the defending side",
          "Still pending",
          "Negotiable Instruments Act, 1881 s. 138 - moderate severity, exposure proportionate to the amount involved"
        ]
      },
      "orderRead": {
        "status": "NOT_APPLICABLE",
        "summary": null,
        "riskSignal": null,
        "order": null,
        "identity": null,
        "reason": null
      },
      "locationMatch": {
        "tag": "NAME_STATE_DISTRICT",
        "label": "Name, state and district",
        "caseState": "MH",
        "caseDistrict": "MUMBAI CITY"
      },
      "details": {
        "status": "FETCHED",
        "label": "Fetched from the court",
        "reason": null,
        "fetchedAt": 1757396000000
      }
    }
  ]
}
```

### Get one case from a report

Returns one case with everything the list carries, and in addition each of its orders in full (number, date and type beside the id), the parties as the court recorded them, what the acts and sections on the record mean, the judges and the court establishment, and the identifier needed to look the case up live. Requires case.read.

**Request URL**

`GET https://api.caseprimus.ai/api/caseprimus/v1/litigation-reports/{reportId}/cases/{caseRef}`

**Request headers**

| Type | Name | Value | Optional |
| --- | --- | --- | --- |
| String | `X-CasePrimus-Api-Key` | Your API key | Required |

**Parameters**

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `reportId` | path | Required |  |
| `caseRef` | path | Required | The case's reference within this report, as the case list returns it. |

**Sample request**

```bash
BASE="https://api.caseprimus.ai/api/caseprimus/v1"

curl "$BASE/litigation-reports/LITIGATION_REPORT_ID/cases/CASE_ID" \
  -H "X-CasePrimus-Api-Key: $CASEPRIMUS_API_KEY"
```

**Responses**

- `200`: The case.
- `403`: Caller lacks case.read, or the plan does not include this product (61470).
- `404`: No such report, or no such case in it (61475).
- `410`: The report's case data has expired, 30 days after the report was started (61478).

**Response fields (HTTP 200)**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `caseRef` | string |  | The case's reference within this report. |
| `caseNumber` | string or null |  | The case number, or whichever of the registration, filing or CNR number the court gave instead. |
| `cnrNumber` | string or null |  |  |
| `court` | string or null |  |  |
| `courtType` | string |  | e.g. DC, HC, SC, NCLT, CESTAT. |
| `state` | string or null |  |  |
| `district` | string or null |  |  |
| `caseType` | string or null |  |  |
| `caseCategory` | string or null |  |  |
| `status` | enum |  | One of: PENDING, DISPOSED |
| `caseStatus` | string or null |  | The court's own words for where the case stands. |
| `caseStage` | string or null |  |  |
| `filingDate` | string or null |  |  |
| `filingYear` | integer or null |  |  |
| `registrationDate` | string or null |  |  |
| `decisionDate` | string or null |  |  |
| `nextHearingDate` | string or null |  |  |
| `natureOfDisposal` | string or null |  |  |
| `petitioners` | array of string |  |  |
| `respondents` | array of string |  |  |
| `matchedParty` | string or null |  | The party on the record that matched the company. |
| `companySide` | enum or null |  | One of: PETITIONER, RESPONDENT, BOTH |
| `acts` | array of string |  | The acts and sections as the court wrote them. |
| `counts` | object |  |  |
| `counts.orders` | integer or null |  |  |
| `counts.hearings` | integer or null |  |  |
| `counts.objections` | integer or null |  | How many objections the court has recorded on the case - a case with one outstanding is a case that has not moved for a reason. |
| `counts.documents` | integer or null |  | How many filed documents the court lists. |
| `counts.applications` | integer or null |  | How many interlocutory applications the court lists. |
| `courtCategory` | string or null |  | The court's own category for the dispute, in the court's own coding, e.g. "14.02 Cheque Dishonour ( 1182 )". |
| `courtSubCategory` | string or null |  |  |
| `courtSubSubCategory` | string or null |  |  |
| `courtRegistrationNumber` | string or null |  | The number the court registered the case under, from the court's own record. `caseNumber` above is whichever identifying number the search result carried, which is not always this one - a case is frequently registered under a different number from the one it was filed under, and reconciling a report against a court's site needs both. |
| `courtFilingNumber` | string or null |  | The number the case was filed under |
| `previousHearingDate` | string or null |  | The last hearing the court held |
| `orderIds` | array of string |  | The ids of this case's orders on the court's record, in the order the court lists them. Computed from the order itself, so an id here is the same id a fresh lookup of the case returns - which is how an order named in a report is matched to the order a download can be asked for; the endpoint's own description gives the sequence. Present on the list and on the single case alike. Empty where the court's details could not be fetched or the court lists no order, and short of `counts.orders` on a case fetched before whose stored orders have no ids until it is fetched again. An id names an order on the court's RECORD, which is not the same as a document existing: several courts list orders they published nothing for. The orders' own numbers, dates and types are on the single-case response and in the JSON export, not here. |
| `category` | string |  | The kind of litigation, e.g. CRIMINAL_CHEQUE_BOUNCE, INSOLVENCY_RECOVERY. |
| `categoryLabel` | string |  |  |
| `risk` | object |  | What this case means on its own. The level and the score come from the kind of case, the company's side, how it stands and what the statute behind it allows - not from reading any order. |
| `risk.level` | enum |  | One of: VERY_HIGH, HIGH, MODERATE, LOW, MINIMAL |
| `risk.score` | integer or null |  | Higher is worse, for ordering cases within a report. The company's own score runs the other way - see `reputationScore`. Null on a watchlist case's `analysis`: a monitored case's level comes from the watchlist itself, and publishing the rubric's competing number beside it would put two scores for one case on one screen. Always present on a litigation report's own cases. 0 to 100 |
| `risk.outcome` | string |  | How a finished case ended. NOT_APPLICABLE while it is pending. |
| `risk.basis` | enum |  | Whether the court's own details were read, or only the search record. One of: LIVE, SEARCH |
| `risk.reasons` | array of string |  | Everything that moved the score, in plain words. A severity read from the statute rather than reviewed by hand says so. |
| `orderRead` | object |  | What was read for this case, and what it said. Always present and always carrying a `status`, so a reader can tell "this is a Basic report" (`NOT_APPLICABLE`) from "the court published no document" (`NO_ORDER`, `NO_DOCUMENT`) and from "we could not read it" (`FAILED`). |
| `orderRead.status` | enum |  | One of: NOT_APPLICABLE, READ, NO_ORDER, NO_DOCUMENT, FAILED |
| `orderRead.summary` | string or null |  | What the order decided, in a sentence or two. On an Advanced report every case carries one; read `summaryBasis` before quoting it. |
| `orderRead.summaryBasis` | enum or null |  | `ORDER` - the court's own document was read, so this is what a judge wrote. `RECORD` - no document could be read, so the summary is written from the court's index entry: its parties, acts, stage and dates. A `RECORD` summary never carries a `riskSignal`. One of: ORDER, RECORD |
| `orderRead.riskSignal` | enum or null |  | Which way the order went for the company. Null on a Basic report, and on any case summarised from the record rather than from a document. One of: ADVERSE, UNFAVOURABLE, NEUTRAL, FAVOURABLE |
| `orderRead.amount` | object or null |  | The sum the order states, with the court's own wording of it beside the number so a reader can check it rather than take it. Null where the order states none - the court's case record carries no amount field at all, so this exists only on an Advanced report. |
| `orderRead.order` | object or null |  | Which order was read. Null where none was. |
| `orderRead.identity` | object or null |  | Whether the order's own identifiers and addresses confirm the case belongs to this company. Null where no order was read. |
| `orderRead.reason` | string or null |  | Why nothing was read, where nothing was. |
| `orderRead.documentAvailable` | boolean |  | Whether the order this report read can be opened. Ask for a link by case; the storage key itself is never published. |
| `locationMatch` | object |  | How closely the case matched the company - whether it was filed where the company is registered or has an address. An indication, not a verification. |
| `locationMatch.tag` | enum |  | One of: NAME_ONLY, NAME_STATE, NAME_STATE_DISTRICT |
| `locationMatch.label` | string |  |  |
| `locationMatch.caseState` | string or null |  |  |
| `locationMatch.caseDistrict` | string or null |  |  |
| `details` | object |  | Whether the court's own record could be fetched for this case, and why not where it could not. |
| `details.status` | enum |  | One of: PENDING, RUNNING, FETCHED, NOT_FOUND, UNAVAILABLE, FAILED |
| `details.label` | string |  |  |
| `details.reason` | string or null |  |  |
| `details.fetchedAt` | integer (int64) or null |  |  |
| `lookupIdentifier` | object (free-form) or null |  | What to send to Live Case Lookup or an order download for this case. Null where the case carries nothing that court can be asked with, or where its only identifier is an internal one. Single-case response only. |
| `actsExplained` | object or null |  | What the acts and sections on this case's record mean. Single-case response only. A section the catalogue does not hold is simply absent; nothing is guessed. |
| `actsExplained.entries` | array of object |  | One entry per provision recognised on the record, most serious first. |
| `actsExplained.disclaimer` | string |  | Shown with the entries, never separately - they are general information about what a section covers, not advice. |
| `actsExplained.reviewed` | boolean |  | Whether a lawyer has checked the severities and descriptions. |
| `judges` | string or null |  | The bench as the court prints it, in one string - names, section and bench run together and pipe-separated, e.g. "HON'BLE MR. JUSTICE SANJEEV NARULA \| Original side \| High Court of Delhi". Not a list: the courts do not publish one, and splitting this reliably is not possible. Null where the court's details could not be fetched or it named nobody. |
| `courtEstablishment` | string or null |  |  |
| `firstHearingDate` | string or null |  |  |
| `liveParties` | object or null |  | The parties as the court recorded them, with addresses where it gave them. Null where the court's details could not be fetched. |
| `liveParties.petitioners` | array of object |  |  |
| `liveParties.respondents` | array of object |  |  |
| `readOrderId` | string or null |  | The id of the order this report READ, which is the one order that downloads free - an Advanced report already fetched and stored that document in order to read it, so handing it back is not a fetch and is not charged. Every other order on the case is a fresh court fetch and is. Null on a Basic report, which reads no order at all, and null where the court gave a link rather than a document we could store, because fetching that one costs as much as any other. Single-case response only: matching it needs the orders' numbers and dates, which the list does not carry. |
| `courtRecord` | object (free-form) or null |  | THE COURT'S OWN RECORD OF THIS CASE, WHOLE - every field the court returned, in the court's own field names, exactly as Live Case Lookup returns them. The fields above are this report's reading of that record and are the ones to build on; this is here so that reading one case of a report never requires paying for a Live Case Lookup of the same case to see what the court actually said.  A High Court case carries 41 fields and a district one more, varying by court type, which is why nothing here is enumerated: among them `objections` (why the case has not moved), `category`/`subCategory`/`subSubCategory` (what the court itself calls the dispute), `caseHistory` (every hearing, with its purpose and judge), `documents` and `interlocutoryApplicationDetails` (the filings), `fir` (the police record), `linkedCases`, `transfers` and `earlierCourts` (where else the matter has been), `coram`, `bench`, `judicial`, `shortOrder`, `petitionersText`/`respondentsText` (the parties as one block of the court's own text, advocates included), `registrationNumber`, `filingNumber`, `cnrNumber`, and the court type's own additions - `assessmentYear` at ITAT, `impugnType`/`impugnNumber`/`impugnDate` at the appellate tribunals.  NOT IN IT - the orders, which are the `orders` array above: each of those carries the stable `orderId` the download endpoints take, and the court's own order does not.  NULL for a case fetched before. The court's answer was not stored then and is not backfilled, because recovering it means asking the court again - a paid lookup per case. Null here means "not kept for this case", never "the court said little".  ALWAYS NULL inside a watchlist case's `analysis`, and deliberately: that case publishes the very same record as its own `fullDetails`, one level up in the same response, so repeating it here would send it twice. |
| `orders` | array of object |  | The orders on the court's record, each with its number, date and type beside its `orderId`. Single-case response only, and in the JSON export. The ids alone are on every case of the list too, as `orderIds` - that is all the order-download endpoints need. |
| `orders[].orderId` | string |  |  |
| `orders[].number` | string or null |  |  |
| `orders[].date` | string or null |  |  |
| `orders[].type` | string or null |  |  |
| `orders[].judge` | string or null |  | The judge the court names on the order. |
| `orders[].result` | string or null |  | What the order did, where the court states it on the order itself - "Dismissed", "Allowed". Tribunals publish this; most courts do not, and leave it null. |

**Example response (200)**

```json
{
  "caseRef": "cr_51ff1354f54a87d5",
  "caseNumber": "CC/1182/2021",
  "cnrNumber": "MHCC010123452021",
  "court": "District Court, Mumbai City",
  "courtType": "DC",
  "state": "Maharashtra",
  "district": "Mumbai City",
  "caseType": "Complaint Case",
  "status": "PENDING",
  "caseStatus": "Case Pending",
  "caseStage": "Evidence",
  "filingDate": "2021-03-14",
  "filingYear": 2021,
  "nextHearingDate": "2026-11-18",
  "petitioners": [
    "Suraj Packaging LLP"
  ],
  "respondents": [
    "Acme Logistics Private Limited"
  ],
  "matchedParty": "Acme Logistics Private Limited",
  "companySide": "RESPONDENT",
  "acts": [
    "Negotiable Instruments Act 1881 | Section 138"
  ],
  "counts": {
    "orders": 4,
    "hearings": 11,
    "objections": 1,
    "documents": 3,
    "applications": null
  },
  "courtCategory": "14.02 Cheque Dishonour ( 1182 )",
  "courtSubCategory": null,
  "courtSubSubCategory": null,
  "courtRegistrationNumber": "CC/1182/2021",
  "courtFilingNumber": "CC/1182/2021",
  "previousHearingDate": "2026-09-02",
  "orderIds": [
    "af2538a37a645f61a09c177924d3ecb5",
    "6e96db2dfa0d699908f8d5fed84af3ae",
    "1b7c93e2d5084a61b0f3c7d9a24e8f50",
    "c40e8b1f6a2d47c9815be03f9d7a261c"
  ],
  "category": "CRIMINAL_CHEQUE_BOUNCE",
  "categoryLabel": "Cheque bounce (criminal)",
  "risk": {
    "level": "HIGH",
    "score": 80,
    "outcome": "NOT_APPLICABLE",
    "basis": "LIVE",
    "reasons": [
      "Cheque bounce (criminal) matter",
      "The company is on the defending side",
      "Still pending"
    ]
  },
  "locationMatch": {
    "tag": "NAME_STATE_DISTRICT",
    "label": "Name, state and district",
    "caseState": "MH",
    "caseDistrict": "MUMBAI CITY"
  },
  "details": {
    "status": "FETCHED",
    "label": "Fetched from the court",
    "reason": null,
    "fetchedAt": 1757396000000
  },
  "lookupIdentifier": {
    "courtType": "DC",
    "cnr": "MHCC010123452021"
  },
  "courtEstablishment": "Metropolitan Magistrate Court, Girgaon",
  "firstHearingDate": "2021-04-26",
  "judges": "H. K. Deshpande | Metropolitan Magistrate | District Court, Mumbai City",
  "actsExplained": {
    "entries": [
      {
        "key": "NI_138",
        "act": "NI",
        "actName": "Negotiable Instruments Act, 1881",
        "section": "138",
        "title": "Dishonour of a cheque for insufficiency of funds",
        "description": "A cheque returned unpaid for want of funds or because it exceeds the arrangement. The complaint must follow a demand notice within 30 days of the return, and the drawer gets 15 days to pay. Punishable with up to two years, or a fine up to twice the cheque amount, or both. Very common and, on its own, usually a debt dispute rather than a mark of criminality.",
        "severity": "MODERATE",
        "cognizable": false,
        "bailable": true,
        "commercial": true,
        "jurisdiction": "CENTRAL",
        "officialTitle": "Dishonour of cheque for insufficiency, etc., of funds in the account.",
        "officialSource": "https://indiacode.gov.in/handle/123456789/535883",
        "verifiedAt": "2026-10-17",
        "alsoKnownAs": null
      },
      {
        "key": "OFFICIAL|Maharashtra Stamp Act, 1958|59",
        "act": "INDIA_CODE",
        "actName": "Maharashtra Stamp Act, 1958",
        "section": "59",
        "title": "Penalty for executing an instrument not duly stamped",
        "description": "Executing, or signing otherwise than as a witness, an instrument on which the proper duty has not been paid.",
        "severity": "MINOR",
        "severityBasis": "MAX_PUNISHMENT",
        "punishment": "Imprisonment up to 6 months, or a fine up to five thousand rupees, or both",
        "exposure": {
          "band": "UNDER_1_LAKH",
          "label": "up to Rs 5,000",
          "maximumRupees": 5000,
          "multiplier": null
        },
        "cognizable": null,
        "bailable": null,
        "commercial": false,
        "jurisdiction": "Maharashtra",
        "officialTitle": "Penalty for executing an instrument not duly stamped",
        "officialSource": "https://indiacode.gov.in",
        "verifiedAt": null,
        "alsoKnownAs": null
      }
    ],
    "disclaimer": "General information about what a section covers, not legal advice.",
    "reviewed": false
  },
  "liveParties": {
    "petitioners": [
      {
        "name": "Suraj Packaging LLP",
        "address": "22 Industrial Estate, Mumbai"
      }
    ],
    "respondents": [
      {
        "name": "Acme Logistics Private Limited",
        "address": "14 Marine Lines, Mumbai 400020"
      }
    ]
  },
  "readOrderId": "6e96db2dfa0d699908f8d5fed84af3ae",
  "orders": [
    {
      "orderId": "af2538a37a645f61a09c177924d3ecb5",
      "number": "2",
      "date": "06-08-2020",
      "type": "Order",
      "judge": "PRL. CIVIL JUDGE And JMFC",
      "result": null
    },
    {
      "orderId": "6e96db2dfa0d699908f8d5fed84af3ae",
      "number": "3",
      "date": "18-08-2020",
      "type": "Judgment",
      "judge": "PRL. CIVIL JUDGE And JMFC",
      "result": null
    }
  ],
  "courtRecord": {
    "caseType": "Complaint Case",
    "filingNumber": "CC/1182/2021",
    "filingDate": "14-03-2021",
    "filingYear": "2021",
    "registrationNumber": "CC/1182/2021",
    "registrationDate": "19-03-2021",
    "cnrNumber": "MHCC010123452021",
    "state": "Maharashtra",
    "district": "Mumbai City",
    "courtName": "District Court, Mumbai City",
    "courtNumberAndJudge": "12-Metropolitan Magistrate",
    "courtEstablishment": "Metropolitan Magistrate Court, Girgaon",
    "firstHearingDate": "26-04-2021",
    "nextHearingDate": "18-11-2026",
    "previousHearingDate": "02-09-2026",
    "caseStage": "Evidence",
    "decisionDate": null,
    "natureOfDisposal": null,
    "caseStatus": "Case Pending",
    "coram": null,
    "judicial": null,
    "causeListName": null,
    "bench": null,
    "shortOrder": null,
    "category": "14.02 Cheque Dishonour ( 1182 )",
    "subCategory": null,
    "subSubCategory": null,
    "petitioners": [
      {
        "petitionerName": "Suraj Packaging LLP",
        "petitionerCounsel": "R. N. Deshmukh"
      }
    ],
    "petitionersText": "1) Suraj Packaging LLP      Advocate- R. N. Deshmukh",
    "respondents": [
      {
        "respondentName": "Acme Logistics Private Limited",
        "respondentCounsel": "M. S. Iyer"
      }
    ],
    "respondentsText": "1) Acme Logistics Private Limited      Advocate- M. S. Iyer",
    "acts": [
      {
        "act": "Negotiable Instruments Act 1881",
        "sections": "138"
      }
    ],
    "caseHistory": [
      {
        "reg": "CC/1182/2021",
        "causeListType": null,
        "judge": "PRL. CIVIL JUDGE And JMFC",
        "purpose": "EVIDENCE",
        "nextHearingDate": "18-11-2026",
        "businessDate": "02-09-2026"
      }
    ],
    "interlocutoryApplicationDetails": null,
    "objections": [
      {
        "number": "1",
        "objection": "All Objections are Complied"
      }
    ],
    "fir": null,
    "earlierCourts": null,
    "documents": [
      {
        "docNumber": "1",
        "docName": "COMPLAINT",
        "advocate": "R. N. Deshmukh",
        "filedOn": "14-03-2021"
      },
      {
        "docNumber": "2",
        "docName": "AFFIDAVIT",
        "advocate": "R. N. Deshmukh",
        "filedOn": "14-03-2021"
      },
      {
        "docNumber": "3",
        "docName": "VAKALATNAMA",
        "advocate": "M. S. Iyer",
        "filedOn": "19-04-2021"
      }
    ],
    "linkedCases": null,
    "transfers": []
  }
}
```

## Basic and Advanced reports

`tier` chooses how deep a report goes. It defaults to `BASIC`.

| What is read | Basic | Advanced |
| --- | --- | --- |
| The court's own record of the case: parties, acts and sections, stage and dates | Yes | Yes |
| An order document | None | The most recent order the court lists, one document per case |
| A summary of that order, and which way it went for the company | No | Yes |
| Whether the order's identifiers and addresses confirm the case is this company's | No | Yes |

> **A Basic report reads no order.** Nothing in a Basic report reflects what any order actually decided. It is built from each court's own case record.

## Report statuses

| Status | Meaning |
| --- | --- |
| QUEUED | The report was accepted and is waiting to be prepared. |
| DISCOVERING | The company's cases are being found. |
| ENRICHING | Each case is being fetched from its court and scored. |
| COMPLETE | The report is ready: the figures are in `summary` and the cases can be read. |
| FAILED | The report could not be prepared. `failureReason` says why. |

## Risk levels

Cases and filters use these risk levels. `MEDIUM` is still accepted in a filter as the former name of `MODERATE`.

| Value | Meaning |
| --- | --- |
| VERY_HIGH | Very high risk |
| HIGH | High risk |
| MODERATE | Moderate risk |
| LOW | Low risk |
| MINIMAL | Minimal risk |

## What an Advanced report adds to each case

- **A summary and its basis.** Every case on an Advanced report carries a summary, and `summaryBasis` says what it rests on. `ORDER` means the court's own document was read. `RECORD` means no document could be read, so the summary is written from the court's index entry: its parties, acts, stage and dates.
- **Which way the order went.** A case that was read carries `riskSignal`: `ADVERSE`, `UNFAVOURABLE`, `NEUTRAL` or `FAVOURABLE` for the company. A `RECORD` summary never carries one.
- **Whether the case is this company's.** `identity.status` is `CONFIRMED` when the order matches an identifier you gave, `CONFLICTS` when it names a different identifier of the same kind, and `NOT_FOUND` when it names none. A match is evidence; the absence of one is not disproof.

## Sorting the cases

| sort | Orders the cases by |
| --- | --- |
| `score_desc` | Risk score, highest first. The default. |
| `filing_desc` | Filing date, newest first. |
| `filing_asc` | Filing date, oldest first. |
| `order_adverse` | What the most recent order said, worst first (Advanced reports). |
| `order_favourable` | What the most recent order said, best first (Advanced reports). |

## How long a report's cases are kept

- **30 days.** A report's cases are deleted 30 days after the report is started. The report and its figures are kept, and `caseDataExpired` becomes `true`.
- **After that.** Reading the cases of an expired report returns `410`.
- **Limits.** Up to 3 reports are prepared at once for an account. A fourth is refused with `429` until one finishes.

## Errors

| Status | Code | Message |
| --- | --- | --- |

## Frequently asked questions

### What is a third party litigation report?

A report that compiles a company's court-case history into one document. CasePrimus.ai finds the company's cases by name, fetches each one from its court, and gives every case a kind of litigation and a risk level with the reasons behind it, plus an overall litigation level and reputation score for the company.

### How long does a report take?

Reports are prepared in the background. A Basic report takes up to 6 hours, longer for a company with a great many cases. Start the report, then poll it until its status is COMPLETE.

### What is the difference between a Basic and an Advanced report?

A Basic report reads each court's own record of the case and opens no order document. An Advanced report also reads one document per case, the most recent order, and gives each case that order's summary, which way it went for the company, and whether the order confirms the case is the company's.

### Can I download the report as a PDF or a spreadsheet?

Yes. A report can be exported as a CSV, a JSON file or a branded PDF from the dashboard.

### How long are a report's cases kept?

30 days after the report is started. The report and its figures are kept after that, but its cases are deleted and reading them returns a 410.

### How many reports can run at once?

Up to 3 reports are prepared at once for an account. A fourth is refused with a 429 until one finishes.

### How is this different from a historical search?

A historical search returns the cases found for a company, 100 per page, as they are. A litigation report goes further: it fetches each case from its court, categorises it, gives it a risk level with reasons, and summarises the company's litigation in one report.
