CNR Lookup | API Reference Guide | CourtMesh
    Skip to main content

    CNR lookup

    Fetch a case by its 16 character CNR, the identifier eCourts assigns to every case. For a CNR we do not hold, one parameter pulls it live from eCourts. To be told when a CNR changes, add it to a watchlist.

    CNR endpoints
    One lookup, one exact-match search field, a flat price.
    GET

    /cases/by-cnr/:cnr

    1 credit

    Returns the case record for a CNR. The record is the same one GET /cases/:id returns.

    Path and query parameters

    FieldTypeRequiredNotes
    cnrpath stringYesThe CNR in any common spelling. It is normalised before use. Responses always echo the canonical 16 character form.
    fetchbooleanNoDefault false. When true and the CNR is not in the corpus, a live fetch from eCourts is started and the response is pending. The call that starts the fetch returns pending and is free; the poll that returns the record is the one 1 credit charge, and a fetch eCourts cannot satisfy is free. If eCourts had nothing for the CNR in the last 24 hours it is not asked again: the call answers 404 CASE_NOT_FOUND straight away. Counted against the same daily live fetch cap as POST /request-timeline with refresh:true. Not available on the Free tier (403 LIVE_FETCH_NOT_ALLOWED); a Supreme Court CNR we do not hold cannot be fetched live and is 404 at once.

    data.status

    FieldTypeRequiredNotes
    foundHTTP 200Nocase holds the full record, in the same shape GET /cases/:id returns, including caseStatus, caseStage, nextHearingDate, lastListedOn and orderCount. 1 credit.
    pendingHTTP 202NoA live fetch is running, started by this call with fetch=true or already in flight. requestId is set. requestId is opaque: poll the same URL, GET /get-timeline does not know it. Costs nothing; the poll that returns the record is the 1 credit charge.
    not_foundHTTP 404NoNot in the corpus and fetch was false, or eCourts has no such case (also the answer for 24 hours afterwards, without a new fetch), a Supreme Court CNR we do not hold, or a case taken down at a party's request. Code CASE_NOT_FOUND, with cnr and status: not_found added to the error body. Costs nothing.
    curl https://research.courtmesh.ai/api/v1/prod/cases/by-cnr/DLHC010084212021 \
      -H "X-API-Key: cm-YOUR_KEY_HERE"
    
    # A CNR we do not hold yet: fetch it live from eCourts
    curl "https://research.courtmesh.ai/api/v1/prod/cases/by-cnr/DLHC010084212021?fetch=true" \
      -H "X-API-Key: cm-YOUR_KEY_HERE"

    CNR normalisation

    The input is trimmed and uppercased, and spaces, hyphens, slashes, dots and a leading CNR, CNR: or CNR NO are removed. A valid CNR is then exactly 16 characters: 4 letters followed by 12 digits (the six character establishment code of some district courts may include digits after the first two letters). Anything else is refused with HTTP 400 and code INVALID_CNR. The four letters name the state and the district, or the High Court and its bench; the next two digits are the court establishment, then a six digit filing number and the four digit year of filing.

    The Node and Python clients apply the same normalisation before sending, and the server is the authority. Supreme Court CNRs start with SCIN. A CNR is a High Court CNR when its prefix is one of the known High Court prefixes (for example DLHC, PHHC, HCBM, HCMA or WBCHCO) or when characters three and four are HC; everything else is a District Court.

    POST

    /search/cases

    1 credit

    POST /search/cases takes an optional cnr field. When present it is normalised and matched exactly, with no fuzzy text matching, and query becomes optional. It returns the one matching case as an ordinary search hit, or an empty list, not the full record: the progress fields and orderCount are only on GET /cases/by-cnr/:cnr. Use it when you want a list shaped result instead of a single record. Every search result also carries a cnr field where the court published one.

    curl -X POST https://research.courtmesh.ai/api/v1/prod/search/cases \
      -H "X-API-Key: cm-YOUR_KEY_HERE" \
      -H "Content-Type: application/json" \
      -d '{ "cnr": "DLHC010084212021" }'
    
    # cnr is an exact match, no fuzzy text matching. query becomes optional when
    # cnr is present and is ignored. The result is one ordinary search hit.

    Pricing

    • A lookup that returns a record: 1 credit, ₹0.10 on Pay As You Go.
    • not_found and a poll of a pending lookup: free.
    • fetch=true for a CNR we do not hold: the call that starts the fetch is free (it returns pending); the poll that returns the record is the one 1 credit charge. A fetch eCourts cannot satisfy is free.

    See the pricing page for every endpoint.

    SDKs

    import { CourtMeshClient } from '@courtmesh/sdk';
    
    const client = new CourtMeshClient({ apiKey: process.env.COURTMESH_API_KEY });
    
    // The CNR is normalised client side too, so a pasted "DLHC-0100842-2021" works
    const res = await client.getCaseByCnr('DLHC010084212021', { fetch: true });
    
    if (res.data.status === 'found') {
      console.log(res.data.case.nextHearingDate);
    } else if (res.data.status === 'pending') {
      // A live fetch is running: call again in a few seconds
    }
    from courtmesh import CourtMesh
    
    client = CourtMesh(api_key="cm-YOUR_KEY_HERE")
    
    res = client.get_case_by_cnr("DLHC010084212021", fetch=True)
    
    if res.data["status"] == "found":
        print(res.data["case"]["nextHearingDate"])
    elif res.data["status"] == "pending":
        pass  # a live fetch is running: call again in a few seconds