# Fake Case Citation Checker - Verify AI Legal Briefs (`that_red_bird/legal-citation-verifier`) Actor

Catch AI-invented case law before you file. Paste a brief: every case citation is extracted and marked verified, name mismatch, not found or bad reporter, with a source link. Works with no token; add a free CourtListener token for wider coverage. Research aid, not legal advice.

- **URL**: https://apify.com/that_red_bird/legal-citation-verifier.md
- **Developed by:** [mohamed alaya](https://apify.com/that_red_bird) (community)
- **Categories:** AI, Business, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Fake Case Citation Checker - Verify AI Legal Briefs

Paste a brief and get every case citation back marked **verified**, **name mismatch**, **not found** or **invalid reporter**, with a link to the real case.
Built for law firms, court clerks and legal-AI teams after the string of sanctions for filings that cited cases an AI invented. It checks two things most tools skip: that the citation exists, and that the case name written next to it is the case that actually sits there.

Works with **no token**. Adding a free CourtListener token widens coverage.

### Input examples

**1. Paste a brief (no token needed)**

```json
{ "text": "See Roe v. Wade, 410 U.S. 113 (1973); Varghese v. China Southern Airlines Co., 925 F.3d 1339 (11th Cir. 2019)." }
```

**2. With a free CourtListener token, and only the problems**

```json
{ "text": "...your brief...", "courtListenerToken": "YOUR_TOKEN", "onlyProblems": true }
```

**3. A plain list of citations**

```json
{ "citations": ["Miranda v. Arizona, 384 U.S. 436 (1966)", "Smith v. Jones, 410 U.S. 113 (1973)"] }
```

Run with no input for a demo brief that mixes real, mismatched and invented citations.

### How verification works

| Mode | Used when | Source | Coverage |
|---|---|---|---|
| Token | You supply a CourtListener token | CourtListener citation-lookup API v4 | Federal and state courts incl. recent decisions. Rate limit: about 60 citations a minute, handled for you. |
| No token | Default | Harvard Caselaw Access Project volume files, then CourtListener anonymous search | Every volume the Caselaw Access Project holds (federal and state reporters, mostly published through the 2010s and early 2020s). Newer volumes fall back to CourtListener search. |

Every row says which source answered and how confident it is. In **no-token mode**:

- `high` confidence means the reporter volume is in the Caselaw Access Project and the answer is definitive: a case begins on that page or none does.
- `medium` confidence means only CourtListener search was available; a "not found" is a prompt to check, not proof.
- `UNVERIFIED` means no free source covers that citation (Westlaw or Lexis numbers, some neutral citations, very recent volumes). These rows are never charged.

To get a CourtListener token: create a free account at courtlistener.com, open Profile, then Developer Tools. Your token is used only during your run and is marked secret in the form.

### Output

One row per distinct citation plus one `brief-report` row per document.

| Field | Meaning |
|---|---|
| `status` | `VERIFIED`, `NAME_MISMATCH`, `NOT_FOUND`, `AMBIGUOUS`, `INVALID_REPORTER` or `UNVERIFIED` |
| `confidence`, `source` | How sure, and which source answered |
| `caseNameAsCited` | Parties as written in your text |
| `matchedCaseName`, `matchedDate`, `matchedCourt`, `matchedCitations`, `matchedUrl` | The real case found at that citation |
| `explanation` | Plain-English reason |
| `flags` | For example `YEAR_DIFFERS (cited 2019, decided 2018)` |
| `riskLevel` (report row) | `HIGH`, `REVIEW`, `LOW` or `NONE`, plus counts and `problemCitations` |

Sample rows:

```json
{ "type": "citation", "citation": "925 F.3d 1339", "caseNameAsCited": "Varghese v. China Southern Airlines Co.", "status": "NOT_FOUND", "confidence": "high", "source": "case.law-static",
  "explanation": "No case exists at 925 F.3d 1339. Volume 925 of F.3d is in the Caselaw Access Project (...) and no case begins on page 1339." }
{ "type": "citation", "citation": "410 U.S. 113", "caseNameAsCited": "Smith v. Jones", "status": "NAME_MISMATCH", "matchedCaseName": "Roe v. Wade", "matchedDate": "1973-01-22",
  "explanation": "410 U.S. 113 is a real citation, but it is Roe v. Wade (1973), not \"Smith v. Jones\". Neither party name matches." }
```

### Use it with

- **A legal-AI drafting pipeline:** run this Actor on the draft before it leaves your system and block on `riskLevel: HIGH`.
- **Court or clerk intake:** feed filed briefs (as text) through it and queue the flagged citations for a person.

### FAQ

**Does VERIFIED mean the case supports the proposition?** No. It means the citation points at a real case and the party names match. Whether the case says what the brief claims is for a lawyer to read.

**Which citations are extracted?** Full case citations in the usual reporter format (U.S., F.3d, F. Supp., S. Ct., state reporters and so on), using an eyecite-style extractor. Short forms (Id., supra), statutes and regulations are skipped.

**Why was a real case marked NAME_MISMATCH?** Party names are compared with abbreviation-tolerant matching, but unusual styling of a case name can still miss. Read the explanation and the matched case before you rely on it.

**PDFs?** Paste the text; PDF files are not read.

### Honest limits

- This is a research aid, not legal advice. Confirm every flagged citation in an official reporter.
- No free source holds every state and recent decision. In no-token mode newer volumes can only be checked through CourtListener search at medium confidence.
- Westlaw and Lexis citation numbers cannot be looked up for free and come back `UNVERIFIED`.

### Price

Pay per event: **$0.003 per citation checked** (`citation-checked`, charged when you get a definite answer, not for `UNVERIFIED`) and **$0.01 per brief report** (`brief-report`). A brief with 40 citations costs about **$0.13**.

# Actor input Schema

## `text` (type: `string`):

Paste the full text of a brief, memo, motion or AI-written answer. Every case citation in it (for example '410 U.S. 113') is extracted and checked together with the case name written next to it. Leave all inputs empty to run a built-in demo.

## `citations` (type: `array`):

Alternative to pasting a brief: one citation per line, ideally with the case name, for example 'Roe v. Wade, 410 U.S. 113 (1973)'.

## `documentUrls` (type: `array`):

Optional. Public URLs of text or HTML pages that contain the brief. Each one is checked and reported separately. PDF files are not read; paste their text instead.

## `courtListenerToken` (type: `string`):

Optional free token from courtlistener.com (Profile > Developer Tools > API token). With it, citations are checked through CourtListener's official citation-lookup API, which covers more courts and recent cases. Without it the Actor uses the Harvard Caselaw Access Project volume files and CourtListener's anonymous search, which cover fewer recent cases. The token is used only for your run and never stored.

## `onlyProblems` (type: `boolean`):

Output only rows that are NOT_FOUND, NAME_MISMATCH, AMBIGUOUS, INVALID_REPORTER or UNVERIFIED, plus the brief report. Verified citations are then not output and not charged.

## `maxCitations` (type: `integer`):

Upper bound on how many distinct citations are checked in one run (hard limit 1000). With a CourtListener token, about 55 citations are checked per minute because of its rate limit.

## Actor input object example

```json
{
  "text": "",
  "citations": [],
  "documentUrls": [],
  "onlyProblems": false,
  "maxCitations": 300
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `downloadCsv` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `count` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "text": "",
    "citations": [],
    "documentUrls": [],
    "onlyProblems": false,
    "maxCitations": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("that_red_bird/legal-citation-verifier").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "text": "",
    "citations": [],
    "documentUrls": [],
    "onlyProblems": False,
    "maxCitations": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("that_red_bird/legal-citation-verifier").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "text": "",
  "citations": [],
  "documentUrls": [],
  "onlyProblems": false,
  "maxCitations": 300
}' |
apify call that_red_bird/legal-citation-verifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,that_red_bird/legal-citation-verifier"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ExHVbKaUKkWpEn8iD/builds/5YQEpvtdNlSV8hlOp/openapi.json
