Cases | API Reference Guide | CourtMesh
    Skip to main content

    Cases

    Fetch one case by id: its detail, its stored AI analysis, documents related to it, and its judgment PDF.

    Case endpoints
    Everything keyed off a single case id.
    GET

    /cases/:id

    1 credit

    One case record. The :id segment accepts either the document identifier or a case number. AI analysis is deliberately excluded from this response; fetch it separately from /cases/:id/analysis and use the hasAnalysis flag to decide whether that call is worth making.

    curl https://research.courtmesh.ai/api/v1/prod/cases/507f1f77bcf86cd799439011 \
      -H "X-API-Key: cm-YOUR_KEY_HERE"
    GET

    /cases/:id/analysis

    1 credit, first read priced by generationAI

    The stored AI analysis for a case. This is a read, not a generation: it returns whatever has already been produced. If hasAnalysis comes back false, the analysis has not been generated yet and meta.note tells you to call POST /cases/:id/analyze.

    Each read costs 1 credit. The first time your organization reads a given case's analysis, that read is priced instead at the credits generating the analysis actually used, up to 400 credits. Every later read of that case by anyone in your organization is 1 credit again.

    Not available on the Free tier. Free Developer keys are refused HTTP 403 with code: "API_TIER_NOT_ALLOWED" on this read too, not only on the two endpoints that generate an analysis. There is no small monthly allowance: the Free tier gets zero AI analysis endpoints, full stop.

    curl https://research.courtmesh.ai/api/v1/prod/cases/507f1f77bcf86cd799439011/analysis \
      -H "X-API-Key: cm-YOUR_KEY_HERE"

    Analysis fields

    • summary and detailedSummary, short and long form
    • headnote, the extracted legal headnote
    • keyFacts, facts the model identified
    • issues, each with a question and the holding on it
    • courtsReasoning, the reasoning chain
    • citedCases, split into followed, distinguished, overruled and referred
    • practiceAreas, legalPrinciples and precedentValue

    These are model outputs. Treat them as a research aid and verify anything load bearing against the judgment PDF.

    GET

    /cases/:id/pdf

    5 credits

    A time limited link to the judgment PDF. The link is a presigned URL valid for one hour, and it is returned encrypted, so cache the case identifier rather than the URL. A 404 here carries a machine readable code so you can tell the two failure modes apart: CASE_NOT_FOUND when the case id itself does not resolve, and PDF_NOT_STORED when the case exists but carries no stored document, which also carries a hint pointing you at POST /request-timeline with refresh:true for High Court and District Court cases (tribunal documents cannot be fetched this way at all).

    curl https://research.courtmesh.ai/api/v1/prod/cases/507f1f77bcf86cd799439011/pdf \
      -H "X-API-Key: cm-YOUR_KEY_HERE"

    Decrypting the URL

    AES-256-CBC. The passphrase is caseId concatenated with caseNumber, both taken from the same response. The key is the SHA-256 of that passphrase, and the value is the hex initialisation vector, a colon, then the hex ciphertext.

    const crypto = require('crypto');
    
    function decryptUrl(encryptedUrl, passphrase) {
      const key = crypto.createHash('sha256').update(passphrase).digest();
    
      const parts = encryptedUrl.split(':');
      if (parts.length !== 2) throw new Error('Invalid encrypted URL format');
    
      const iv = Buffer.from(parts[0], 'hex');
      const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
      let decrypted = decipher.update(parts[1], 'hex', 'utf8');
      decrypted += decipher.final('utf8');
      return decrypted;
    }
    
    const response = await fetch(
      'https://research.courtmesh.ai/api/v1/prod/cases/507f1f77bcf86cd799439011/pdf',
      { headers: { 'X-API-Key': 'cm-YOUR_KEY_HERE' } }
    );
    const data = await response.json();
    
    // Passphrase is caseId concatenated with caseNumber, both from data.data
    const decryptionKey = data.data.caseId + data.data.caseNumber;
    console.log('PDF URL:', decryptUrl(data.data.pdfUrl, decryptionKey));