# Legal data

> Statutes, sanctions and exclusion lists, the Taiwan FSC news feed and Taiwan standard-form contracts.

Page: https://docs.aggre.org/api/data/legal · Section: API reference · All pages: https://docs.aggre.org/llms.txt

Statutes ([statutes guide](https://docs.aggre.org/datasets/legal-statutes.md)), government name lists, the FSC news feed and standard-form contracts ([regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md)). The Taiwan judgments routes are described in the [statutes guide](https://docs.aggre.org/datasets/legal-statutes.md#judgments-and-retrieval).

On this page:

- [Statutes across the ten statute datasets](#listStatuteInstruments): `GET /v1/legal/statutes/instruments`
- [One statute with its provisions](#getStatuteInstrument): `GET /v1/legal/statutes/instruments/{instrument_id}`
- [The provisions of one statute, paged](#listStatuteProvisions): `GET /v1/legal/statutes/instruments/{instrument_id}/provisions`
- [Entries of a sanctions or exclusion list](#listRegulatoryEntries): `GET /v1/legal/regulatory/entries`
- [One entry of a sanctions or exclusion list](#getRegulatoryEntry): `GET /v1/legal/regulatory/entry`
- [Taiwan FSC news (five RSS feeds)](#listFscNews): `GET /v1/legal/regulatory/fsc_news`
- [Taiwan standard-form contracts (定型化契約), without text](#listContractForms): `GET /v1/legal/contracts/tw_standard_forms`
- [One standard form with its versions and the text of its files](#getContractForm): `GET /v1/legal/contracts/tw_standard_forms/{form_id}`

## Statutes across the ten statute datasets {#listStatuteInstruments}

`GET /v1/legal/statutes/instruments`

Ordered by `instrument_id`; the list has no provisions and no foreword. `meta.restricted` / `attribution` / `licenses` carry the terms the data comes with. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `dataset` | query | no | `legal.statutes.tw_moj` \| `legal.statutes.jp_egov` \| `legal.statutes.uk_legislation` \| `legal.statutes.ca_laws` \| `legal.statutes.eu_eurlex` \| `legal.statutes.us_ecfr` \| `legal.statutes.de_gii` \| `legal.statutes.au_federal` \| `legal.statutes.cn_flk` \| `legal.statutes.sg_sso` | One of the ten statute dataset ids. |
| `jurisdiction` | query | no | string, pattern `^[A-Z]{2}$` | Two uppercase letters, e.g. TW, EU. |
| `language` | query | no | string | Exact, e.g. zh-Hant, en, ja. |
| `kind` | query | no | `act` \| `regulation` \| `order` \| `treaty` \| `other` |  |
| `status` | query | no | `in_force` \| `repealed` \| `abandoned` \| `withdrawn` |  |
| `q` | query | no | string | Title contains this text (case-insensitive, 1-200 characters). A catalogue filter, not full-text search. |
| `updated_since` | query | no | string | YYYY-MM-DD (00:00 UTC) or RFC 3339; `updated_at >=` this. |
| `include_removed` | query | no | boolean, default `false` | `true` also returns instruments the source stopped listing. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–200, default `50` |  |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/statutes/instruments?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: `StatuteInstrumentsResponse`.

| Field | Type | Required | Description |
|---|---|---|---|
| `data` | array of `StatuteInstrument` | yes |  |
| `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. |
| `next_cursor` | string or null | yes |  |

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One statute with its provisions {#getStatuteInstrument}

`GET /v1/legal/statutes/instruments/{instrument_id}`

At most 5000 provisions; longer ones set `provisions_truncated` and `next_from_seq`, continue with the provisions route. A removed instrument still answers 200 with `removed_on`. Takes no query parameters. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `instrument_id` | path | yes | string | A statute `instrument_id` such as `UK:LEG:ukpga/2020/1` or `TW:MOJ:A0000001:en`. It can contain `/` and `:`; the server accepts them literally or percent-encoded and sees the same id. A path ending `/provisions` is always the provisions route. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/statutes/instruments/<instrument_id>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: `StatuteDetailResponse`.

| Field | Type | Required | Description |
|---|---|---|---|
| `data` | `StatuteDetail` | yes | An instrument with its foreword, provisions (at most 5000 per answer) and attachments. |
| `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. |
| `next_cursor` | null | yes |  |

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## The provisions of one statute, paged {#listStatuteProvisions}

`GET /v1/legal/statutes/instruments/{instrument_id}/provisions`

[the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). A `from_seq` past the last provision answers 200 with an empty list.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `instrument_id` | path | yes | string | A statute `instrument_id` such as `UK:LEG:ukpga/2020/1` or `TW:MOJ:A0000001:en`. It can contain `/` and `:`; the server accepts them literally or percent-encoded and sees the same id. A path ending `/provisions` is always the provisions route. |
| `version` | query | no | integer, 1– | Read this version of the text (see `versions` on the instrument). Repeat it on the next page. Not with `as_of`. 404 when there is no such version. |
| `as_of` | query | no | string | Read the text Aggre held at this date or RFC 3339 time (encode `+` as %2B). Not with `version`. 404 before the history begins. |
| `from_seq` | query | no | integer, 0– | Start at this `seq` (default 0). Give this or `cursor`, not both. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `number` | query | no | string | An article number: the raw text as stored (`第 184 條`, `Article 15-1`, matched exactly) or its article key (`184`, `184-1`, `184之1`, `第184條之1`, `Article 184`; leading zeros ignored), which matches every provision whose number has the same key. `184` does not match `184-1`. The returned `number` is the raw text. [the statutes guide](https://docs.aggre.org/datasets/legal-statutes.md). |
| `limit` | query | no | integer, 1–1000, default `500` |  |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/statutes/instruments/<instrument_id>/provisions?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: `StatuteProvisionsResponse`.

| Field | Type | Required | Description |
|---|---|---|---|
| `data` | array of `StatuteProvision` | yes |  |
| `meta` | `Meta` | yes | Where the data came from and how fresh it is. Routes add a few keys of their own (listed); clients must ignore keys they do not know. |
| `next_cursor` | string or null | yes |  |
| `next_from_seq` | integer or null | no | seq of the next page's first provision; set together with next_cursor. |

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Entries of a sanctions or exclusion list {#listRegulatoryEntries}

`GET /v1/legal/regulatory/entries`

Served as published. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md); `meta.message` carries the terms status.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `dataset` | query | yes | `legal.regulatory.ofac_sdn` \| `legal.regulatory.un_sanctions` \| `legal.regulatory.us_exclusions` | The name list. |
| `q` | query | no | string | Name search on the normalized name key (letters and digits). |
| `match` | query | no | `prefix` \| `exact` (default `prefix`) | Only with `q`. |
| `kind` | query | no | `person` \| `entity` \| `vessel` \| `aircraft` \| `other` |  |
| `listed_from` | query | no | string, date | YYYY-MM-DD on `listed_on`. |
| `removed` | query | no | `exclude` \| `include` \| `only` (default `exclude`) | Entries the publisher removed: left out (default), included, or only those. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–1000, default `100` |  |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/regulatory/entries?dataset=legal.regulatory.ofac_sdn&limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_regulatory_entry`](https://docs.aggre.org/api/schemas.md#legal_regulatory_entry).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One entry of a sanctions or exclusion list {#getRegulatoryEntry}

`GET /v1/legal/regulatory/entry`

An entry the publisher removed is still found: it carries `removed_on`.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `dataset` | query | yes | `legal.regulatory.ofac_sdn` \| `legal.regulatory.un_sanctions` \| `legal.regulatory.us_exclusions` | The name list. |
| `entry_id` | query | yes | string | The entry id as published (1-256 bytes, no control characters). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/regulatory/entry?dataset=legal.regulatory.ofac_sdn&entry_id=<entry_id>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_regulatory_entry`](https://docs.aggre.org/api/schemas.md#legal_regulatory_entry).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Taiwan FSC news (five RSS feeds) {#listFscNews}

`GET /v1/legal/regulatory/fsc_news`

Items of the Financial Supervisory Commission's five official RSS feeds (press releases, penalty cases, announcements, draft-regulation notices, law interpretations), newest first (undated last), then category, then guid. Titles, links and publication days as published; the plain-text `description` only with `include=text` (then `limit` is at most 100). Not the articles behind the links; items that left a feed are kept; no search in V0. `meta.dataset` carries the item count and the per-category counts, `meta.dataDate` the newest publication day, `meta.lastReadAt` our newest successful run; `meta.message` says "Terms not read" while nobody has read the FSC's terms. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `category` | query | no | `news` \| `penalty` \| `announcement` \| `draft_law` \| `law_interp` |  |
| `published_from` | query | no | string, date | YYYY-MM-DD on `published_on`, inclusive; an undated item matches neither bound. |
| `published_to` | query | no | string, date | YYYY-MM-DD on `published_on`, inclusive. |
| `include` | query | no | `text` | `text` adds the plain-text `description`. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–200, default `50` | At most 100 with `include=text`. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/regulatory/fsc_news?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_fsc_news_item`](https://docs.aggre.org/api/schemas.md#legal_fsc_news_item).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## Taiwan standard-form contracts (定型化契約), without text {#listContractForms}

`GET /v1/legal/contracts/tw_standard_forms`

Model contracts (範本) and the terms a contract must and must not contain (應記載及不得記載事項), as the worker read them from the Executive Yuan's lists, ordered by `form_id`. No text and no attachments here: the single-form route has them. `q` is a literal, case-insensitive title substring. `issuer` is null on a form whose page named no ministry and matches exactly as stored. A form the publisher stopped listing is left out unless `include_removed=true` (it carries `removed_on`). 503 `terms_unread` until a person has read the publisher's terms. [the regulatory guide](https://docs.aggre.org/datasets/legal-regulatory.md).

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `kind` | query | no | `template` \| `required_terms` | `template` = 範本, `required_terms` = 應記載及不得記載事項. |
| `q` | query | no | string | Title contains this text (1-200 characters). |
| `issuer` | query | no | string | Exactly the stored issuer (1-200 characters). |
| `published_from` | query | no | string, date | YYYY-MM-DD, inclusive, on `published_on`. |
| `published_to` | query | no | string, date | YYYY-MM-DD, inclusive. Not before `published_from`. |
| `updated_since` | query | no | string | Rows changed at or after this moment (`YYYY-MM-DD` or an RFC 3339 timestamp), by our `updated_at`. With `cursor` this is a change feed. |
| `include_removed` | query | no | boolean, default `false` | Also forms the publisher stopped listing. |
| `cursor` | query | no | string | The previous page's `next_cursor`, unchanged. Opaque; a cursor from another route is 400. |
| `limit` | query | no | integer, 1–200, default `50` | Rows per page. |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/contracts/tw_standard_forms?limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_contract_form`](https://docs.aggre.org/api/schemas.md#legal_contract_form).

**Errors**: `400`, `401`, `403`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).

## One standard form with its versions and the text of its files {#getContractForm}

`GET /v1/legal/contracts/tw_standard_forms/{form_id}`

The form, every version (oldest first) and the files of one version with the text extracted from each. `version` picks an older version (default the current one); `text=false` leaves the text out. The text is machine-extracted and may contain errors, and a scanned file has none (`text_status`): `file_url` is the authoritative document. A removed form is still found (`removed_on`). 404 for an unknown form or version, 400 for an id that is not a GUID, 503 `terms_unread` until a person has read the publisher's terms.

**Parameters**

| Name | In | Required | Type | Description |
|---|---|---|---|---|
| `form_id` | path | yes | string, pattern `^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$` | The GUID of a standard form as listed by the collection route (36 characters; upper or lower case). |
| `version` | query | no | integer, 1– | A version number from `versions` (default the current one). |
| `text` | query | no | boolean, default `true` | `false` leaves the attachments' text out (default true). |

**Example**

```bash
curl -s "https://api.aggre.org/v1/legal/contracts/tw_standard_forms/<form_id>" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

**Response** `200`: the envelope `{ "data": [...], "meta": {...}, "next_cursor": ... }` (see [Response format](https://docs.aggre.org/concepts/response-format.md)); each row of `data` follows the schema [`legal_contract_form`](https://docs.aggre.org/api/schemas.md#legal_contract_form).

**Errors**: `400`, `401`, `403`, `404`, `429`, `503`, in the shared envelope ([Errors](https://docs.aggre.org/concepts/errors.md)).
