> ## Documentation Index
> Fetch the complete documentation index at: https://docs.law4devs.eu/llms.txt
> Use this file to discover all available pages before exploring further.

# Frameworks

> List, inspect, and iterate EU regulatory frameworks with the Law4Devs Python SDK.

## Overview

Frameworks are the top-level resource — every article, recital, requirement, and annex belongs to one. Use the `client.frameworks` resource to query them.

***

## Methods

### `list()`

Returns the first page of frameworks.

```python theme={null}
page = client.frameworks.list(page=1, per_page=20)

print(page.meta.total)   # total number of frameworks
for fw in page.data:
    print(fw.slug, fw.name)
```

**Parameters**

| Parameter  | Type  | Default | Description            |
| ---------- | ----- | ------- | ---------------------- |
| `page`     | `int` | `1`     | Page number            |
| `per_page` | `int` | `20`    | Items per page (1–100) |

**Returns** `Page[Framework]`

***

### `get()`

Fetch a single framework by its slug.

```python theme={null}
fw = client.frameworks.get("gdpr")

print(fw.name)            # "General Data Protection Regulation"
print(fw.eurlex_url)      # "https://eur-lex.europa.eu/..."
print(fw.requirement_count)
print(fw.coverage)        # dict with sync coverage info
```

**Parameters**

| Parameter | Type  | Description                                      |
| --------- | ----- | ------------------------------------------------ |
| `slug`    | `str` | Framework slug, e.g. `"gdpr"`, `"cra"`, `"nis2"` |

**Returns** `FrameworkDetail`

***

### `iter()`

Iterate over every framework across all pages without manual pagination.

```python theme={null}
for fw in client.frameworks.iter():
    print(fw.slug, fw.name)
```

**Parameters** — same kwargs as `list()` (except `page`, which is managed internally).

**Returns** `Iterator[Framework]`

***

## Models

### `Framework`

Returned by `list()` and `iter()`.

| Field               | Type          | Description                              |
| ------------------- | ------------- | ---------------------------------------- |
| `id`                | `int`         | Internal numeric ID                      |
| `slug`              | `str`         | URL-safe identifier, e.g. `"gdpr"`       |
| `name`              | `str`         | Full official name                       |
| `short_name`        | `str`         | Abbreviated name, e.g. `"GDPR"`          |
| `celex_number`      | `str \| None` | EUR-Lex CELEX identifier                 |
| `description`       | `str \| None` | Plain-text summary                       |
| `is_active`         | `bool`        | Whether the framework is in force        |
| `status`            | `str`         | `"active"`, `"draft"`, or `"superseded"` |
| `expected_articles` | `int \| None` | Known article count from official text   |
| `expected_recitals` | `int \| None` | Known recital count                      |
| `last_synced_at`    | `str \| None` | ISO 8601 timestamp of last data sync     |
| `created_at`        | `str`         | ISO 8601 timestamp of record creation    |
| `article_count`     | `int`         | Articles currently in the database       |
| `recital_count`     | `int`         | Recitals currently in the database       |

### `FrameworkDetail`

Returned by `get()`. Extends `Framework` with:

| Field               | Type          | Description                              |
| ------------------- | ------------- | ---------------------------------------- |
| `eurlex_url`        | `str \| None` | Canonical EUR-Lex URL                    |
| `requirement_count` | `int`         | Parsed compliance requirements           |
| `annex_count`       | `int`         | Annexes in the database                  |
| `tag_count`         | `int`         | Tags applied to this framework's content |
| `coverage`          | `dict`        | Sync coverage statistics                 |

***

## Examples

### Print a framework summary table

```python theme={null}
from law4devs import Law4DevsClient

client = Law4DevsClient()

print(f"{'Slug':<12} {'Name':<45} {'Articles':>8} {'Status'}")
print("-" * 75)

for fw in client.frameworks.iter():
    print(f"{fw.slug:<12} {fw.name:<45} {fw.article_count:>8} {fw.status}")
```

### Filter active frameworks only

```python theme={null}
active = [fw for fw in client.frameworks.iter() if fw.status == "active"]
print(f"{len(active)} active frameworks")
```

### Inspect a framework's coverage

```python theme={null}
fw = client.frameworks.get("cra")
print(f"CRA: {fw.article_count}/{fw.expected_articles} articles synced")
print(f"     {fw.recital_count}/{fw.expected_recitals} recitals synced")
```

### Look up a framework by short name

```python theme={null}
all_frameworks = list(client.frameworks.iter())
match = next((f for f in all_frameworks if f.short_name == "NIS2"), None)
if match:
    print(match.slug)  # "nis2"
```

<Note>
  Framework slugs are stable identifiers — safe to hardcode in your application. They will not change between API versions.
</Note>

<Warning>
  Some frameworks have `status="superseded"` (e.g. NIS1). The data is still accessible and browsable, but these frameworks are no longer in force.
</Warning>
