# Legifrance Jurisprudence Scraper: French Case Law API (DILA) (`dltik/legifrance-jurisprudence-scraper`) Actor

Search French case law via the official Legifrance / PISTE API: Cour de cassation, Conseil d'Etat, CAA, TA. Decision text, ECLI, articles cites, jurisprudences citees, formations, solutions. Avocats, legal-tech, litigation analytics. $8/1K.

- **URL**: https://apify.com/dltik/legifrance-jurisprudence-scraper.md
- **Developed by:** [Walid](https://apify.com/dltik) (community)
- **Categories:** Business, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Legifrance Jurisprudence Scraper — French Case Law API (DILA / PISTE)

⭐ **Bookmark this actor → [apify.com/dltik/legifrance-jurisprudence-scraper](https://apify.com/dltik/legifrance-jurisprudence-scraper)** — Apify ranks by bookmarks, so it directly drives the visibility of this scraper. **One click. No signup beyond your existing Apify account.**

> Scrape **French jurisprudence at scale via the official Legifrance / DILA API** (PISTE OAuth2). Cour de cassation, Conseil d'Etat, Cours d'appel, Tribunaux administratifs. Get **decision IDs, ECLI, full text, articles cites, jurisprudences citees, formations, dates, solutions** — structured JSON, ready to feed legal-NLP, litigation analytics, or AI-assisted research. **No HTML scraping. No fragile selectors. Official government API.**

### What makes this scraper different

| Feature | This scraper | Other legal scrapers |
|---|:---:|:---:|
| Official Legifrance DILA API (no HTML scrape) | YES | NO (HTML, fragile) |
| France coverage (Cass, CE, CAA, TA, CA) | YES | partial / Brazil / Spain |
| ECLI extraction | YES | rarely |
| `articles_cites` + `jurisprudences_citees` graph | YES | NO |
| Full decision text + titres et sommaires | YES | excerpts only |
| OAuth2 token auto-refresh | YES | n/a |
| Cost per decision | **$0.008** | $0.01-$0.05 |

### What can this scraper do?

- **Search 4M+ French decisions** indexed by the DILA Legifrance API (Cour de cassation, Conseil d'Etat, Cours d'appel, Tribunaux administratifs, Tribunal des conflits)
- **Filter by juridiction + date range + free-text query** — combinable, paginated, ~10K results/query cap
- **Direct lookup by decision ID** (`JURITEXT000048...`) — perfect for bulk-enrichment pipelines
- **Full structured output** — ECLI, articles cites, jurisprudences citees, rapprochements, titres + sommaires, full text
- **Official OAuth2 auth** — token cached, auto-refreshed on 401 (zero touch from your side)
- **Datacenter-friendly** — no anti-bot, no captcha, no proxy needed

### What data can you extract per decision?

| Field | Description |
|-------|-------------|
| `decision_id` | Legifrance JURI ID (e.g. `JURITEXT000048465147`) |
| `juridiction` | Cour de cassation, Conseil d'Etat, CA Paris... |
| `formation` | Chambre civile, sociale, commerciale, formation pleniere... |
| `date_decision` | YYYY-MM-DD |
| `numero_affaire` | Internal case number |
| `numero_pourvoi` | Pourvoi reference (Cour de cassation only) |
| `solution` | Cassation, rejet, irrecevabilite, annulation, etc. |
| `titres_et_sommaires` | Array of `{title, summary}` — official editorial titles |
| `texte_integral` | Full decision text (when `includeFullText=true`) |
| `articles_cites` | Array of `{code, article, text}` — laws cited |
| `jurisprudences_citees` | Array of `{decision_id, reference}` — case law cited |
| `rapprochements` | Related decisions cross-linked by DILA editors |
| `ecli` | European Case Law Identifier (e.g. `ECLI:FR:CCASS:2023:11.21465`) |
| `url_legifrance` | Direct Legifrance URL |
| `scraped_at` | ISO 8601 UTC |

### How to scrape French case law in 5 steps

1. **[Create a free PISTE account](https://piste.gouv.fr)** — official French government API portal
2. **Subscribe your app to the "DILA - Legifrance" API** (free tier ~2000 req/day, no card)
3. **Copy your `client_id` + `client_secret`** from PISTE -> Mes applications
4. **Open [Legifrance Jurisprudence Scraper](https://apify.com/dltik/legifrance-jurisprudence-scraper)** on Apify Store, paste keys into the input form (secret fields)
5. **Set your filters** — query (`"rupture brutale relation commerciale"`), juridictions (`["Cour de cassation"]`), date range — click Start

### How much does it cost to scrape Legifrance?

**PAY_PER_EVENT — $0.008 per decision scraped** ($8 per 1,000 decisions). Failed/empty runs not charged.

| Run size | Decisions | Apify cost | Time |
|----------|-----------|------------|------|
| Quick test | 10 | $0.08 | ~10s |
| Standard | 100 | $0.80 | ~1 min |
| Deep | 1,000 | $8.00 | ~10 min |
| Massive | 5,000 | $40 | ~1 h |

The official PISTE API is free (no payment to the French government). The Apify fee covers compute + the API client + the structured output. Set `includeFullText=false` to skip the `/consult/juri` round-trip if you only need metadata (~50% faster).

### Input parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `mode` | enum | `search` | `search` = query/filter; `lookup` = direct JURITEXT IDs |
| `query` | string | — | Free-text query across decision content |
| `decisionIds` | array | `[]` | List of `JURITEXT...` IDs (lookup mode) |
| `juridictions` | array | `[]` | e.g. `["Cour de cassation", "Conseil d'Etat"]` |
| `dateFrom` | string | — | YYYY-MM-DD inclusive |
| `dateTo` | string | today | YYYY-MM-DD inclusive |
| `sort` | enum | `PERTINENCE` | `PERTINENCE`, `DATE_DESC`, `DATE_ASC` |
| `includeFullText` | bool | `true` | Adds `/consult/juri` call per record for full text + citations |
| `maxResults` | integer | `25` | 1–5000 |
| `pisteClientId` | string (secret) | env `PISTE_CLIENT_ID` | OAuth2 client ID |
| `pisteClientSecret` | string (secret) | env `PISTE_CLIENT_SECRET` | OAuth2 client secret |
| `proxyConfig` | object | datacenter | Optional — PISTE rarely blocks |

### Output example

```json
{
  "decision_id": "JURITEXT000048465147",
  "juridiction": "Cour de cassation",
  "formation": "Chambre commerciale",
  "date_decision": "2023-11-15",
  "numero_affaire": "22-13.225",
  "numero_pourvoi": "22-13225",
  "solution": "Cassation partielle",
  "titres_et_sommaires": [
    {
      "title": "CONCURRENCE - Pratiques restrictives - Rupture brutale d'une relation commerciale etablie",
      "summary": "Le caractere brutal de la rupture s'apprecie au regard de la duree de la relation..."
    }
  ],
  "texte_integral": "LA COUR DE CASSATION, CHAMBRE COMMERCIALE, a rendu l'arret suivant... ",
  "articles_cites": [
    { "code": "Code de commerce", "article": "L442-1", "text": "Engage la responsabilite de son auteur..." }
  ],
  "jurisprudences_citees": [
    { "decision_id": "JURITEXT000046215511", "reference": "Cass. com., 21 sept. 2022, n. 20-22.587" }
  ],
  "rapprochements": [],
  "ecli": "ECLI:FR:CCASS:2023:CO00715",
  "url_legifrance": "https://www.legifrance.gouv.fr/juri/id/JURITEXT000048465147",
  "scraped_at": "2026-06-20T14:32:01Z"
}
````

### Use cases

- **Litigation analytics SaaS** — power dashboards a la Doctrine / Predictice over your own infra
- **Legal-NLP training corpus** — pull 50K Cour de cassation decisions to fine-tune a French legal LLM
- **AI legal assistant** — feed RAG pipelines (Claude, GPT) with up-to-date jurisprudence
- **Citation graph research** — exploit `articles_cites` + `jurisprudences_citees` to map influence networks
- **Cabinet d'avocats** — daily watch on new Cass / CE decisions matching practice-area filters
- **Academic legal research** — bulk download for empirical studies on judicial outcomes

### Use the actor via API

**Python:**

```python
import requests, os

run = requests.post(
    "https://api.apify.com/v2/acts/dltik~legifrance-jurisprudence-scraper/run-sync-get-dataset-items",
    headers={"Authorization": f"Bearer {os.environ['APIFY_TOKEN']}", "Content-Type": "application/json"},
    json={
        "mode": "search",
        "query": "rupture brutale relation commerciale",
        "juridictions": ["Cour de cassation"],
        "dateFrom": "2022-01-01",
        "dateTo": "2026-06-20",
        "sort": "DATE_DESC",
        "includeFullText": True,
        "maxResults": 50,
        "pisteClientId": os.environ["PISTE_CLIENT_ID"],
        "pisteClientSecret": os.environ["PISTE_CLIENT_SECRET"],
    },
    timeout=600,
).json()
print(f"Scraped {len(run)} decisions")
```

**curl:**

```bash
curl -X POST "https://api.apify.com/v2/acts/dltik~legifrance-jurisprudence-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "lookup",
    "decisionIds": ["JURITEXT000048465147"],
    "pisteClientId": "'"$PISTE_CLIENT_ID"'",
    "pisteClientSecret": "'"$PISTE_CLIENT_SECRET"'"
  }'
```

### FAQ

**Why do I need PISTE credentials?**
The official Legifrance API (DILA) is exposed via the French government API gateway PISTE (`api.piste.gouv.fr`) under OAuth2. Registration is free (no card), takes 2 minutes, and gives you ~2000 req/day on the free tier — more than enough for a daily monitoring job. We can't include shared credentials because each client\_id is rate-limited individually.

**Is this scraper legal? Is the data reusable?**
Yes. Legifrance is the official French government legal publisher, and the DILA API is published under Licence Ouverte v2.0 (Etalab) — meaning you can reuse, redistribute and commercialize the data, including for litigation analytics SaaS, provided you cite the source.

**Why not scrape `legifrance.gouv.fr` HTML directly?**
HTML scraping is fragile (DOM changes monthly), incomplete (excerpt-only), and misses structured fields like `articles_cites` / `jurisprudences_citees`. The official API is rate-limited but structured, stable, and includes the citation graph.

**What's the difference between `mode=search` and `mode=lookup`?**
`search` paginates the `/search` endpoint with query + juridiction + date filters — best to discover decisions matching a topic. `lookup` calls `/consult/juri` directly for a list of known IDs — best to enrich an existing list (e.g. citations harvested from another source).

**What happens if I hit the PISTE quota?**
The actor returns a graceful error record (no `raise`), preserving any decisions already scraped. Re-run the next day or upgrade your PISTE tier.

***

⭐ **Found this Legifrance scraper useful? [Bookmark it](https://apify.com/dltik/legifrance-jurisprudence-scraper)** — Apify ranks actors by bookmarks, so it's the strongest single signal for Store visibility. One click.

### Other scrapers by dltik

| Actor | What it does | Price |
|-------|-------------|-------|
| [Pappers Sirene Scraper](https://apify.com/dltik/pappers-sirene-scraper) | 26M French companies (SIREN, SIRET, dirigeants) | $0.001/result |
| [BODACC Scraper](https://apify.com/dltik/bodacc-fr-scraper) | French commercial court announcements | $0.003/record |
| [France Travail Scraper](https://apify.com/dltik/francetravail-scraper) | 700K+ French job offers | $0.0015/job |
| [JORF Scraper](https://apify.com/dltik/jorf-fr-scraper) | Journal officiel de la Republique francaise | varies |
| [HATVP Scraper](https://apify.com/dltik/hatvp-fr-scraper) | French elected officials' financial declarations | varies |
| [Annuaire Administration FR](https://apify.com/dltik/annuaire-administration-fr-scraper) | French gov agencies & contacts | $0.003/org |
| [EUR-Lex Scraper](https://apify.com/dltik/eur-lex-scraper) | EU legislation (regulations, directives) | $0.008/doc |
| [Espacenet Patents Scraper](https://apify.com/dltik/espacenet-patents-scraper) | 130M+ patents (EPO OPS API) | $0.015/patent |
| [USPTO Patents Scraper](https://apify.com/dltik/uspto-patents-scraper) | US patent applications + grants | $0.01/patent |

License: MIT · Author: [dltik](https://apify.com/dltik) · Data source: [Legifrance DILA via PISTE](https://piste.gouv.fr) (Licence Ouverte v2.0)

# Actor input Schema

## `mode` (type: `string`):

search = keyword/filter search across French jurisprudence; lookup = fetch one or more specific JURI decision IDs (e.g. JURITEXT000048...).

## `query` (type: `string`):

Free-text search across decision content. Examples: 'rupture brutale relation commerciale', 'licenciement economique', 'droit au respect vie privee'. Combined with filters via AND.

## `decisionIds` (type: `array`):

List of Legifrance JURI decision IDs to fetch directly (e.g. \['JURITEXT000048465147', 'JURITEXT000048130128']). Use with mode=lookup.

## `juridictions` (type: `array`):

List of juridictions to include. Common values: 'Cour de cassation', 'Conseil d'Etat', 'Cour d'appel', 'Tribunal administratif', 'Cour administrative d'appel', 'Tribunaux des conflits'. Empty = all juridictions.

## `dateFrom` (type: `string`):

Lower bound of decision date (inclusive). Format: YYYY-MM-DD. Example: '2020-01-01'.

## `dateTo` (type: `string`):

Upper bound of decision date (inclusive). Format: YYYY-MM-DD. Example: '2026-06-20'. Defaults to today.

## `sort` (type: `string`):

PERTINENCE = relevance (default), DATE\_DESC = newest first, DATE\_ASC = oldest first.

## `includeFullText` (type: `boolean`):

Fetch the full decision text from the /consult/juri endpoint for each result (1 extra API call per record). Enable for legal-NLP pipelines, disable for cheap metadata-only scrape.

## `maxResults` (type: `integer`):

Maximum number of decisions to return. The PISTE search API caps at ~10,000 results per query; we paginate in batches of 10.

## `pisteClientId` (type: `string`):

Your PISTE (api.piste.gouv.fr) OAuth2 client\_id. Register free at https://piste.gouv.fr (sandbox + prod, ~2000 req/day free). If empty, the actor will look for the PISTE\_CLIENT\_ID environment variable.

## `pisteClientSecret` (type: `string`):

Your PISTE OAuth2 client\_secret (matches the client\_id). Keep secret. If empty, the actor will look for the PISTE\_CLIENT\_SECRET environment variable. WARNING: do NOT post credentials in shared task JSON.

## `proxyConfig` (type: `object`):

Optional Apify proxy. The PISTE API is open to all IPs once authenticated — proxy rarely needed unless your client\_id is rate-limited.

## Actor input object example

```json
{
  "mode": "search",
  "decisionIds": [],
  "juridictions": [],
  "sort": "PERTINENCE",
  "includeFullText": true,
  "maxResults": 25,
  "proxyConfig": {
    "useApifyProxy": false
  }
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dltik/legifrance-jurisprudence-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("dltik/legifrance-jurisprudence-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call dltik/legifrance-jurisprudence-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=dltik/legifrance-jurisprudence-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Legifrance Jurisprudence Scraper: French Case Law API (DILA)",
        "description": "Search French case law via the official Legifrance / PISTE API: Cour de cassation, Conseil d'Etat, CAA, TA. Decision text, ECLI, articles cites, jurisprudences citees, formations, solutions. Avocats, legal-tech, litigation analytics. $8/1K.",
        "version": "1.0",
        "x-build-id": "7Zd8NYfWvZ69Hs5SR"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/dltik~legifrance-jurisprudence-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-dltik-legifrance-jurisprudence-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/dltik~legifrance-jurisprudence-scraper/runs": {
            "post": {
                "operationId": "runs-sync-dltik-legifrance-jurisprudence-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/dltik~legifrance-jurisprudence-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-dltik-legifrance-jurisprudence-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "search",
                            "lookup"
                        ],
                        "type": "string",
                        "description": "search = keyword/filter search across French jurisprudence; lookup = fetch one or more specific JURI decision IDs (e.g. JURITEXT000048...).",
                        "default": "search"
                    },
                    "query": {
                        "title": "Search query",
                        "type": "string",
                        "description": "Free-text search across decision content. Examples: 'rupture brutale relation commerciale', 'licenciement economique', 'droit au respect vie privee'. Combined with filters via AND."
                    },
                    "decisionIds": {
                        "title": "Decision IDs (lookup mode)",
                        "type": "array",
                        "description": "List of Legifrance JURI decision IDs to fetch directly (e.g. ['JURITEXT000048465147', 'JURITEXT000048130128']). Use with mode=lookup.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "juridictions": {
                        "title": "Juridictions filter",
                        "type": "array",
                        "description": "List of juridictions to include. Common values: 'Cour de cassation', 'Conseil d'Etat', 'Cour d'appel', 'Tribunal administratif', 'Cour administrative d'appel', 'Tribunaux des conflits'. Empty = all juridictions.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "dateFrom": {
                        "title": "Decision date from (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Lower bound of decision date (inclusive). Format: YYYY-MM-DD. Example: '2020-01-01'."
                    },
                    "dateTo": {
                        "title": "Decision date to (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Upper bound of decision date (inclusive). Format: YYYY-MM-DD. Example: '2026-06-20'. Defaults to today."
                    },
                    "sort": {
                        "title": "Sort order",
                        "enum": [
                            "PERTINENCE",
                            "DATE_DESC",
                            "DATE_ASC"
                        ],
                        "type": "string",
                        "description": "PERTINENCE = relevance (default), DATE_DESC = newest first, DATE_ASC = oldest first.",
                        "default": "PERTINENCE"
                    },
                    "includeFullText": {
                        "title": "Include full decision text",
                        "type": "boolean",
                        "description": "Fetch the full decision text from the /consult/juri endpoint for each result (1 extra API call per record). Enable for legal-NLP pipelines, disable for cheap metadata-only scrape.",
                        "default": true
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of decisions to return. The PISTE search API caps at ~10,000 results per query; we paginate in batches of 10.",
                        "default": 25
                    },
                    "pisteClientId": {
                        "title": "PISTE client ID",
                        "type": "string",
                        "description": "Your PISTE (api.piste.gouv.fr) OAuth2 client_id. Register free at https://piste.gouv.fr (sandbox + prod, ~2000 req/day free). If empty, the actor will look for the PISTE_CLIENT_ID environment variable."
                    },
                    "pisteClientSecret": {
                        "title": "PISTE client secret",
                        "type": "string",
                        "description": "Your PISTE OAuth2 client_secret (matches the client_id). Keep secret. If empty, the actor will look for the PISTE_CLIENT_SECRET environment variable. WARNING: do NOT post credentials in shared task JSON."
                    },
                    "proxyConfig": {
                        "title": "Proxy (rarely needed)",
                        "type": "object",
                        "description": "Optional Apify proxy. The PISTE API is open to all IPs once authenticated — proxy rarely needed unless your client_id is rate-limited.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
