diff --git a/cl/api/templates/alert-api-docs-vlatest.html b/cl/api/templates/alert-api-docs-vlatest.html index de6e2dd4e9..ab0e00557c 100644 --- a/cl/api/templates/alert-api-docs-vlatest.html +++ b/cl/api/templates/alert-api-docs-vlatest.html @@ -17,7 +17,7 @@
@@ -26,7 +26,7 @@{% url "alert-list" version="v3" %}
{% url "alert-list" version=version %}
Search Alerts update you when there is new information in our search engine.
This system scales to support thousands or even millions of alerts, allowing organizations to stay updated about numerous topics. This is a powerful system when used with webhooks.
@@ -77,7 +77,7 @@{% url "alert-list" version
To learn more about this API, make an HTTP OPTIONS
request:
curl -X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "alert-list" version=version %}"
Example Usage
Let's say we want to know about case law involving Apple Inc. On the front end, we search for "Apple Inc" (in quotes) and get query parameters like:
@@ -89,10 +89,10 @@
Example Usage
--data 'query=q=%22Apple%20Inc%22&type=o' \
--data 'rate=rt' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "alert-list" version=version %}"
The response:
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/alerts/4839/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/alerts/4839/",
"id": 4839,
"date_created": "2024-05-02T15:29:32.048912-07:00",
"date_modified": "2024-05-02T15:29:32.048929-07:00",
@@ -108,18 +108,18 @@ Example Usage
curl -X PATCH \
--data 'rate=dly' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "alert-detail" version="v3" pk="4839" %}"
+ "{% get_full_host %}{% url "alert-detail" version=version pk="4839" %}"
Search Alerts can be deleted with HTTP DELETE
requests:
curl -X DELETE \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "alert-detail" version="v3" pk="4839" %}"
+ "{% get_full_host %}{% url "alert-detail" version=version pk="4839" %}"
To list your alerts, send an HTTP GET
request with no filters:
curl -X GET \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "alert-list" version=version %}"
- Docket Alerts — {% url "docket-alert-list" version="v3" %}
+ Docket Alerts — {% url "docket-alert-list" version=version %}
Docket Alerts keep you updated about cases by sending notifications by email or webhook whenever there is new information in our system. Use this API to create, modify, list, and delete Docket Alerts.
Docket Alerts are always sent as soon as an update is available. See the help page on Docket Alerts to learn more about how we get updates.
@@ -138,7 +138,7 @@
Docket Alerts — {% url "docket-alert-list"
To learn more about this API, make an HTTP OPTIONS
request:
curl -X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
- "{% get_full_host %}{% url "docket-alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "docket-alert-list" version=version %}"
Example Usage
To create a Docket Alert, send a POST request with the docket
ID you wish to subscribe to.
@@ -147,7 +147,7 @@
Example Usage
curl -X POST \
--data 'docket=1' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "docket-alert-list" version=version %}"
The response:
{
"id": 133013,
@@ -161,17 +161,17 @@ Example Usage
To unsubscribe from a docket, you can either delete the alert with an HTTP DELETE
request:
curl -X DELETE \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-alert-detail" version="v3" pk="133013" %}"
+ "{% get_full_host %}{% url "docket-alert-detail" version=version pk="133013" %}"
Or, if you are using @recap.email and have auto-subscribe enabled, you can send an HTTP PATCH
request to change it from a subscription (alert_type=1
) to an unsubscription (alert_type=0
):
curl -X PATCH \
--data 'alert_type=0' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-alert-detail" version="v3" pk="133013" %}"
+ "{% get_full_host %}{% url "docket-alert-detail" version=version pk="133013" %}"
To list your Docket Alerts, send an HTTP GET
request with no filters:
curl -X GET \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-alert-list" version="v3" %}"
+ "{% get_full_host %}{% url "docket-alert-list" version=version %}"
Coming Soon
We are currently developing a scalable alert system that will update you when keywords appear in PACER documents or cases. To join the beta test for this system, please get in touch.
diff --git a/cl/api/templates/case-law-api-docs-vlatest.html b/cl/api/templates/case-law-api-docs-vlatest.html
index 4eedcdcc6f..9e4330162c 100644
--- a/cl/api/templates/case-law-api-docs-vlatest.html
+++ b/cl/api/templates/case-law-api-docs-vlatest.html
@@ -18,7 +18,7 @@
@@ -27,7 +27,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -101,7 +101,7 @@ Case Law API
The APIs
- Dockets — {% url "docket-list" version="v3" %}
+ Dockets — {% url "docket-list" version=version %}
{% include "includes/docket-endpoint.html" %}
The name of a docket can change in response to the outside world, but the names of clusters do not change. Therefore, we have case_name
fields on both the docket and the cluster.
@@ -110,7 +110,7 @@ Dockets — {% url "docket-list" version=
For more information on case names, see the help article on this topic.
- Clusters — {% url "opinioncluster-list" version="v3" %}
+ Clusters — {% url "opinioncluster-list" version=version %}
This is a major API that provides the millions of Opinion Clusters
that are available on CourtListener.
As with all other APIs, you can look up the field descriptions, filtering, ordering, and rendering options by making an OPTIONS
request:
@@ -118,7 +118,7 @@
Clusters — {% url "opinioncluster-list
curl -v \
-X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}"
+ "{% get_full_host %}{% url "opinioncluster-list" version=version %}"
A few notes:
-
@@ -136,7 +136,7 @@
Clusters — {% url "opinioncluster-list
- Opinions — {% url "opinion-list" version="v3" %}
+ Opinions — {% url "opinion-list" version=version %}
This API contains the text and other metadata about specific decisions.
As with all other APIs, you can look up the field descriptions, filtering, ordering, and rendering options by making an OPTIONS
request:
@@ -144,7 +144,7 @@
Opinions — {% url "opinion-list" versi
curl -v \
-X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinion-list" version="v3" %}"
+ "{% get_full_host %}{% url "opinion-list" version=version %}"
A few notes:
-
@@ -195,7 +195,7 @@
Opinions — {% url "opinion-list" versi
- Courts — {% url "court-list" version="v3" %}
+ Courts — {% url "court-list" version=version %}
{% include "includes/court-endpoint.html" %}
@@ -205,15 +205,14 @@ Filtering to Opinions in a Court
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinion-list" version="v3" %}?cluster__docket__court=scotus"
+ "{% get_full_host %}{% url "opinion-list" version=version %}?cluster__docket__court=scotus"
That returns:
{
- "count": 521329,
- "next": "https://www.courtlistener.com/api/rest/v3/opinions/?cluster__docket__court=scotus&page=2",
+ "next": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/?cluster__docket__court=scotus&page=2",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/opinions/9973155/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/9973155/",
"id": 9973155,
...
Such an approach is fine if all you want is the opinion object, but often you'll want the docket and the cluster too.
@@ -223,25 +222,25 @@
Filtering to Opinions in a Court
For example, this gets the dockets from SCOTUS:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}?court=scotus"
+ "{% get_full_host %}{% url "docket-list" version=version %}?court=scotus"
The first result contains a clusters
key like:
"clusters": [
- "{% get_full_host %}{% url "opinioncluster-detail" version="v3" pk="9502621" %}"
+ "{% get_full_host %}{% url "opinioncluster-detail" version=version pk="9502621" %}"
],
So we can simply get that URL:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinioncluster-detail" version="v3" pk="9502621" %}"
+ "{% get_full_host %}{% url "opinioncluster-detail" version=version pk="9502621" %}"
That returns a cluster, which has the following keys:
- "docket": "{% get_full_host %}{% url "docket-detail" version="v3" pk="68533094" %}",
+ "docket": "{% get_full_host %}{% url "docket-detail" version=version pk="68533094" %}",
"sub_opinions": [
- "{% get_full_host %}{% url "opinion-detail" version="v3" pk="9969234" %}"
+ "{% get_full_host %}{% url "opinion-detail" version=version pk="9969234" %}"
],
Finally, GET the links in the sub_opinions
field to have the complete object:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinion-detail" version="v3" pk="9969234" %}"
+ "{% get_full_host %}{% url "opinion-detail" version=version pk="9969234" %}"
Filtering by Docket Number
@@ -250,15 +249,15 @@ Filtering by Docket Number
A docket by docket number:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}?docket_number=23A994"
+ "{% get_full_host %}{% url "docket-list" version=version %}?docket_number=23A994"
A cluster by docket number:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}?docket__docket_number=23A994"
+ "{% get_full_host %}{% url "opinioncluster-list" version=version %}?docket__docket_number=23A994"
An opinion by docket number:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinion-list" version="v3" %}?cluster__docket__docket_number=23A994"
+ "{% get_full_host %}{% url "opinion-list" version=version %}?cluster__docket__docket_number=23A994"
Docket numbers are not unique, so you'll want to add a court filter too:
@@ -281,7 +280,7 @@ Finding a Case by URL
This case can be found in the cluster API using that same ID:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinioncluster-detail" version="v3" pk="2812209" %}"
+ "{% get_full_host %}{% url "opinioncluster-detail" version=version pk="2812209" %}"
Opinion IDs do not reliably match cluster IDs.
diff --git a/cl/api/templates/citation-api-docs-vlatest.html b/cl/api/templates/citation-api-docs-vlatest.html
index 2fd1fc4883..0f27031f38 100644
--- a/cl/api/templates/citation-api-docs-vlatest.html
+++ b/cl/api/templates/citation-api-docs-vlatest.html
@@ -18,7 +18,7 @@
@@ -27,7 +27,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -49,14 +49,14 @@ Legal Citation API
To look up specific citations, see our citation lookup and verification API.
- Opinions Cited/Citing API
{% url "opinionscited-list" version="v3" %}
+ Opinions Cited/Citing API
{% url "opinionscited-list" version=version %}
This endpoint provides an interface into the citation graph that CourtListener provides between opinions in our case law database.
You can look up the field descriptions, filtering, ordering, and rendering options by making an OPTIONS
request:
curl -v \
-X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinionscited-list" version="v3" %}"
+ "{% get_full_host %}{% url "opinionscited-list" version=version %}"
That query will return the following filter options:
{
"id": {
@@ -79,49 +79,49 @@ Opinions Cited/Citing API
{% url "opinio
"lookup_types": "See available filters for 'Opinions'"
}
}
- To understand RelatedFilters
, see our filtering documentation.
+ To understand RelatedFilters
, see our filtering documentation.
These filters allow you to filter to the opinions that an opinion cites (its "Authorities" or backward citations) or the later opinions that cite it (forward citations).
For example, opinion 2812209
is the decision in Obergefell v. Hodges. To see what it cites:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinionscited-list" version="v3" %}?citing_opinion=2812209"
+ "{% get_full_host %}{% url "opinionscited-list" version=version %}?citing_opinion=2812209"
Which returns (in part):
{
"count": 75,
- "next": "https://www.courtlistener.com/api/rest/v3/opinions-cited/?citing_opinion=2812209&page=2",
+ "next": "https://www.courtlistener.com/api/rest/{{ version }}/opinions-cited/?citing_opinion=2812209&page=2",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/opinions-cited/167909003/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/opinions-cited/167909003/",
"id": 167909003,
- "citing_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/2812209/",
- "cited_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/96405/",
+ "citing_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/2812209/",
+ "cited_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/96405/",
"depth": 1
},
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/opinions-cited/167909002/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/opinions-cited/167909002/",
"id": 167909002,
- "citing_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/2812209/",
- "cited_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/2264443/",
+ "citing_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/2812209/",
+ "cited_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/2264443/",
"depth": 1
},
…
To go the other direction, and see what cites Obergefell, use the cited_opinion
parameter instead:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "opinionscited-list" version="v3" %}?cited_opinion=2812209"
+ "{% get_full_host %}{% url "opinionscited-list" version=version %}?cited_opinion=2812209"
That returns (in part):
{
"count": 403,
- "next": "https://www.courtlistener.com/api/rest/v3/opinions-cited/?cited_opinion=2812209&page=2",
+ "next": "https://www.courtlistener.com/api/rest/{{ version }}/opinions-cited/?cited_opinion=2812209&page=2",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/opinions-cited/213931728/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/opinions-cited/213931728/",
"id": 213931728,
- "citing_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/10008139/",
- "cited_opinion": "https://www.courtlistener.com/api/rest/v3/opinions/2812209/",
+ "citing_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/10008139/",
+ "cited_opinion": "https://www.courtlistener.com/api/rest/{{ version }}/opinions/2812209/",
"depth": 4
},
…
diff --git a/cl/api/templates/citation-lookup-api.html b/cl/api/templates/citation-lookup-api-vlatest.html
similarity index 95%
rename from cl/api/templates/citation-lookup-api.html
rename to cl/api/templates/citation-lookup-api-vlatest.html
index 82d6662c75..f9c4464284 100644
--- a/cl/api/templates/citation-lookup-api.html
+++ b/cl/api/templates/citation-lookup-api-vlatest.html
@@ -17,7 +17,7 @@
@@ -26,7 +26,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -48,7 +48,7 @@ Table of Contents
Citation Lookup and Verification API
- {% url "citation-lookup-list" version="v3" %}
+ {% url "citation-lookup-list" version=version %}
Use this API to look up citations in CourtListener's database of {{ cite_count|intcomma }} citations.
This API can look up either an individual citation or can parse and look up every citation in a block of text. This can be useful as a guardrail to help prevent hallucinated citations.
@@ -60,13 +60,13 @@ {% url "citation-lookup-list" version="v3" %}
Usage
The simplest way to query this API is to send it a blob of text. If the text does not have any citations, it will simply return an empty JSON object:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=Put some text here'\
[]
If the text contains valid citations, it will return a list of the citations, analyzing each. This example contains a single citation that is found:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=Obergefell v. Hodges (576 U.S. 644) established the right to marriage among same-sex couples'
[
@@ -84,7 +84,7 @@ Usage
]
If you have the volume, reporter, and page for a citation, you can look it up as follows:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'volume=576' \
--data 'reporter=U.S.' \
@@ -133,7 +133,7 @@ Limitations & Throttles
API Examples
Basic, Valid Lookup
The following is a basic lookup using the text
parameter and a block of text:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=Obergefell v. Hodges (576 U.S. 644) established the right to marriage among same-sex couples'
[
@@ -151,7 +151,7 @@ Basic, Valid Lookup
]
Failed Lookup
This query uses the volume-reporter-page triad, but fails because the citation does not exist:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'volume=1' \
--data 'reporter=U.S.' \
@@ -178,7 +178,7 @@ Failed Lookup
Throttled Citations
If your request contains more than {{max_citation_per_request}} citations, the {{max_citation_per_request|add:1}}st and subsequent citations will be returned with 429 status
fields:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=Imagine a very long blob here, with {{max_citation_per_request|add:1}} citations.'
[
@@ -205,7 +205,7 @@ Throttled Citations
Typoed/Non-Canonical Reporter Abbreviation
If you query the non-canonical reporter abbreviation or if your reporter contains a known typo, we will provide the corrected citation in the normalized_citations
key. The following example looks up a citation using "US" instead of the correct "U.S.":
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=576 US 644'
[
@@ -225,7 +225,7 @@ Typoed/Non-Canonical Reporter Abbreviation
Ambiguous Citation
This lookup is for an ambiguous citation abbreviated as "H." This reporter abbreviation can refer to Handy's Ohio Reports, the Hawaii Reports, or Hill’s New York Reports. Only two of those reporter series have cases at the queried volume and page number, so the API returns two possible matches for the citation:
- curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version="v3" %}" \
+ curl -X POST "{% get_full_host %}{% url "citation-lookup-list" version=version %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
--data 'text=1 H. 150'
[
diff --git a/cl/api/templates/field-help.html b/cl/api/templates/field-help.html
index 6d67c94cee..54a7e90d08 100644
--- a/cl/api/templates/field-help.html
+++ b/cl/api/templates/field-help.html
@@ -17,7 +17,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -80,9 +80,9 @@ Case Names
case_name_full
: This is the full list of plaintiffs and defendants in a case, sometimes going on for hundreds of words, and often including titles or other information. For example: Roe Et Al v. Wade, District Attorney of Dallas County.
- All cases have at least one of these values, many have two values, and some have all three. A case_name_short
was generated algorithmically for every case possible, but about 40% of cases were too complicated for our program to process and so they were left blank. Human editors have ensured that every Supreme Court case from 1945 to 2018 has a case_name_short
value.
+
All cases have at least one of these values, many have two values, and some have all three. A case_name_short
was generated algorithmically for every case possible, but about 40% of cases were too complicated for our program to process and so they were left blank. Editors have ensured that every Supreme Court case from 1945 to 2018 has a case_name_short
value.
- case_name
is available for the majority of cases, except those that were imported from Resource.org, which only provided case_name_full
values. When that happened, there was no way for us to condense a case_name_full
, so until a human editor is available to review them, they will lack this value. All cases have either a case_name
or a case_name_full
value.
+
case_name
is available for the majority of cases, except those that were imported from Resource.org, which only provided case_name_full
values. When that happened, there was no way for us to condense a case_name_full
, so until an editor is available to review them, they will lack this value. All cases have either a case_name
or a case_name_full
value.
Our advice is to use a case_name
if it is available and to fall back on the case_name_full
if it is not. If you are interested in sponsoring trained humans to improve this data, please get in touch.
@@ -100,7 +100,7 @@ The absolute_url
Field
$type: This is the type of object that has been returned, for example, "docket" indicates that you have gotten a docket as your result.
-
- $id: This is a numeric ID for the document. This value increments as we add content to the system. Note that due to deletions and modifications the numeric IDs are not always sequential, but they will never be duplicated within an document type.
+ $id: This is a numeric ID for the document. This value increments as we add content to the system. Note that due to deletions and modifications the numeric IDs are not always sequential, but they will never be duplicated within a document type.
-
$name-of-the-case: This is the "slug" of the document, and generally mirrors its case name. This value can change if we clean up a case name, but provided it is not omitted completely, this part of the URL can be any value without affecting the page that is loaded.
diff --git a/cl/api/templates/financial-disclosure-api-docs-vlatest.html b/cl/api/templates/financial-disclosure-api-docs-vlatest.html
index fb4ce9c00a..fa2f538168 100644
--- a/cl/api/templates/financial-disclosure-api-docs-vlatest.html
+++ b/cl/api/templates/financial-disclosure-api-docs-vlatest.html
@@ -19,7 +19,7 @@
@@ -28,7 +28,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -74,34 +74,34 @@ Financial Disclosures API
Available APIs
The Ethics in Government Act details the types of information required, and prescribes the general format and procedures for the reports themselves.
The APIs described below mirror the Act's language, with APIs corresponding to each required disclosure type.
- Disclosures — {% url "financialdisclosure-list" version="v3" %}
+ Disclosures — {% url "financialdisclosure-list" version=version %}
This API contains information about the main document itself and is the link between the other financial disclosure endpoints and the judges in our system.
- Investments — {% url "investment-list" version="v3" %}
+ Investments — {% url "investment-list" version=version %}
This API lists the source and type of investment income held by a judge, including dividends, rents, interest, capital gains, or income from qualified or excepted trusts.
- Positions — {% url "disclosureposition-list" version="v3" %}
+ Positions — {% url "disclosureposition-list" version=version %}
This API lists the positions held as an officer, director, trustee, general partner, proprietor, representative, executor, employee, or consultant of any corporation, company, firm, partnership, trust, or other business enterprise, any nonprofit organization, any labor organization, or any educational or other institution other than the United States.
- Agreements — {% url "agreement-list" version="v3" %}
+ Agreements — {% url "agreement-list" version=version %}
This API lists any agreements or arrangements of the filer in existence at any time during the reporting period.
- Non-Investment Income
{% url "noninvestmentincome-list" version="v3" %}
+ Non-Investment Income
{% url "noninvestmentincome-list" version=version %}
This API lists the source, type, and the amount or value of earned or other non-investment income aggregating $200 or more from any one source that is received during the reporting period.
- Non-Investment Income (Spouse)
{% url "spouseincome-list" version="v3" %}
+ Non-Investment Income (Spouse)
{% url "spouseincome-list" version=version %}
This API lists the source and type earned of non-investment income from the spouse of the filer.
- Reimbursements — {% url "reimbursement-list" version="v3" %}
+ Reimbursements — {% url "reimbursement-list" version=version %}
This API lists the source identity and description (including travel locations, dates, and nature of expenses provided) of any travel-related reimbursements aggregating more than $415 in value that are received by the filer from one source during the reporting period.
- Gifts — {% url "gift-list" version="v3" %}
+ Gifts — {% url "gift-list" version=version %}
This API lists the source, a brief description, and the value of all gifts aggregating more than $415 in value that are received by the filer during the reporting period from any one source.
- Debts — {% url "debt-list" version="v3" %}
+ Debts — {% url "debt-list" version=version %}
All liabilities specified by that section that are owed during the period beginning on January 1 of the preceding calendar year and ending fewer than 31 days before the date on which the report is filed.
Fields
Understanding the Fields
Like most of our APIs, field definitions can be obtained by sending an HTTP OPTIONS
request to any of the APIs. For example, this request, piped through jq
, shows you the fields of the Gifts API:
-
curl -X OPTIONS "{% get_full_host %}{% url "gift-list" version="v3" %}" \
+ curl -X OPTIONS "{% get_full_host %}{% url "gift-list" version=version %}" \
| jq '.actions.POST'
{
@@ -181,15 +181,14 @@ Redactions
This field can be used as a filter. For example, here are all the investments with redacted information:
- curl "{% get_full_host %}{% url "investment-list" version="v3" %}?redacted=True" \
+ curl "{% get_full_host %}{% url "investment-list" version=version %}?redacted=True" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
{
- "count": 27404,
- "next": "https://www.courtlistener.com/api/rest/v3/investments/?page=2&redacted=True",
+ "next": "https://www.courtlistener.com/api/rest/{{ version }}/investments/?page=2&redacted=True",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/investments/5385644/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/investments/5385644/",
"id": 5385644,
"date_created": "2023-04-17T11:03:22.404170-07:00",
"date_modified": "2023-04-17T11:03:22.404185-07:00",
@@ -207,7 +206,7 @@ Redactions
"transaction_gain_code": "",
"transaction_partner": "",
"has_inferred_values": false,
- "financial_disclosure": "https://www.courtlistener.com/api/rest/v3/financial-disclosures/34187/"
+ "financial_disclosure": "https://www.courtlistener.com/api/rest/{{ version }}/financial-disclosures/34187/"
},
...
@@ -248,10 +247,10 @@ Inferred Values
API Examples
You can query for investments by stock name, transaction dates and even gross values. For example, the following query is for financial disclosures with individual investments valued above $50,000,000.00. Note that this uses a value code as explained in the general notes above:
- curl "{% get_full_host %}{% url "investment-list" version="v3" %}?gross_value_code=P4&fields=investments" \
+ curl "{% get_full_host %}{% url "investment-list" version=version %}?gross_value_code=P4&fields=investments" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
Additionally, you could pinpoint gifts of individual judges when combining the gift database with our judicial database. The following query returns all reported gifts by the late Ruth Bader Ginsburg (her ID is 1213):
- curl "{% get_full_host %}{% url "financialdisclosure-list" version="v3" %}?person=1213&fields=gifts" \
+ curl "{% get_full_host %}{% url "financialdisclosure-list" version=version %}?person=1213&fields=gifts" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
In 2024, we presented these APIs at the NICAR conference and created many more examples you can explore.
diff --git a/cl/api/templates/includes/docket-endpoint.html b/cl/api/templates/includes/docket-endpoint.html
index 1135bf3950..4d44499193 100644
--- a/cl/api/templates/includes/docket-endpoint.html
+++ b/cl/api/templates/includes/docket-endpoint.html
@@ -8,23 +8,23 @@
curl -v \
-X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}"
+ "{% get_full_host %}{% url "docket-list" version=version %}"
To look up a particular docket, use its ID:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-detail" version="v3" pk="4214664" %}"
+ "{% get_full_host %}{% url "docket-detail" version=version pk="4214664" %}"
The response you get will not list the docket entries, parties, or attorneys for the docket (doing so doesn't scale), but will have many other metadata fields:
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/dockets/4214664/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/4214664/",
"id": 4214664,
- "court": "https://www.courtlistener.com/api/rest/v3/courts/dcd/",
+ "court": "https://www.courtlistener.com/api/rest/{{ version }}/courts/dcd/",
"court_id": "dcd",
"original_court_info": null,
"idb_data": null,
"clusters": [],
"audio_files": [],
- "assigned_to": "https://www.courtlistener.com/api/rest/v3/people/1124/",
+ "assigned_to": "https://www.courtlistener.com/api/rest/{{ version }}/people/1124/",
"referred_to": null,
"absolute_url": "/docket/4214664/national-veterans-legal-services-program-v-united-states/",
"date_created": "2016-08-20T07:25:37.448945-07:00",
@@ -66,7 +66,7 @@
"blocked": false,
"appeal_from": null,
"tags": [
- "https://www.courtlistener.com/api/rest/v3/tag/1316/"
+ "https://www.courtlistener.com/api/rest/{{ version }}/tag/1316/"
],
"panel": []
}
diff --git a/cl/api/templates/includes/toc_migration_guide_sidebar.html b/cl/api/templates/includes/toc_migration_guide_sidebar.html
new file mode 100644
index 0000000000..49de496a6d
--- /dev/null
+++ b/cl/api/templates/includes/toc_migration_guide_sidebar.html
@@ -0,0 +1,83 @@
+
+ Table of Contents
+
+ - What's Happening?
+ - Timeline for Changes
+ - What If I Do Nothing?
+ - What New Features Can I Expect?
+
+ [+]
+
+
+
+ - Breaking Changes to v3 of the Search API
+
+ [+]
+
+
+
+ - How Do I Migrate Database APIs?
+
+ [+]
+
+
+
+ - How Do I Migrate the Search API?
+
+ [+]
+
+
+
+ - Enhancements in v4
+
+ [+]
+
+
+
+ - Search API crawls are no longer limited to 100 pages
+ - Result sorting is more consistent
+ - Highlighting is more consistent
+ - Empty fields are standardized
+
+ - Backwards incompatible changes in v4
+
+ [+]
+
+
+
+ - High query counts are estimated
+ - Highlighting
+ - Nested keys (documents) for type=o and type=p
+ - type=r is now for dockets with nested documents
+ - type=rd is a new result type for documents
+ - type=d still returns dockets
+ - Removed fields
+ - Changed field values
+ - Dates and times
+ - No more random sorting
+ - Stemming and Synonyms
+ - Changes to GET parameters
+ - Bad Request Error Code: 400
+ - Server Error Code: 500
+ - Not Found Error Code: 404
+
+
+
+
diff --git a/cl/api/templates/judge-api-docs-vlatest.html b/cl/api/templates/judge-api-docs-vlatest.html
index e771b372e8..3e5c1ff90b 100644
--- a/cl/api/templates/judge-api-docs-vlatest.html
+++ b/cl/api/templates/judge-api-docs-vlatest.html
@@ -19,7 +19,7 @@
@@ -28,7 +28,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -85,7 +85,7 @@ Judge and Justice API
The APIs
- People (Judges and Appointers)
{% url "person-list" version="v3" %}
+ People (Judges and Appointers)
{% url "person-list" version=version %}
This API contains the central "person" object. As explained above, people can be judges, appointers, or both.
This object holds the core metadata about the person, including their biographical data, positions held, educational history, ABA ratings, and political affiliations.
@@ -122,7 +122,7 @@
People (Judges and Appointers)
{
Positions
- {% url "position-list" version="v3" %}
+ {% url "position-list" version=version %}
Use this API to learn the positions held by a person, including their time as president, in private practice, as a judge, or in any number of other roles in society or the judiciary.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -130,11 +130,11 @@
Positions
To filter to positions for a particular person:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "position-list" version="v3" %}?person=20"
+ "{% get_full_host %}{% url "position-list" version=version %}?person=20"
Political Affiliations
- {% url "politicalaffiliation-list" version="v3" %}
+ {% url "politicalaffiliation-list" version=version %}
Use this API to learn the political affiliations of a person. Political affiliations are gathered from a number of sources such as ballots or appointments, and have start and end dates.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -142,7 +142,7 @@
Political Affiliations
Educations and Schools
- {% url "education-list" version="v3" %}
+ {% url "education-list" version=version %}
Use this API to learn about the educational history of a person, including which schools they went to, when, and what degrees they received. Each education object can include a school object based on data from the Department of Education.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -151,10 +151,10 @@
Educations and Schools
To filter for judges educated at a particular school:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "person-list" version="v3" %}?educations__school__name__contains=Rochester"
+ "{% get_full_host %}{% url "person-list" version=version %}?educations__school__name__contains=Rochester"
ABA Ratings
- {% url "abarating-list" version="v3" %}
+ {% url "abarating-list" version=version %}
These are the American Bar Association ratings that are given to many judges, particularly those that are nominated to federal positions.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -162,7 +162,7 @@
ABA Ratings
Retention Events
- {% url "retentionevent-list" version="v3" %}
+ {% url "retentionevent-list" version=version %}
These are the events that keep a judge in a position, such as a retention vote, or reappointment.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -170,7 +170,7 @@
Retention Events
Sources
- {% url "source-list" version="v3" %}
+ {% url "source-list" version=version %}
This API keeps a list of sources that explain how we built this database.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
diff --git a/cl/api/templates/migration-guide.html b/cl/api/templates/migration-guide.html
new file mode 100644
index 0000000000..44bac10e17
--- /dev/null
+++ b/cl/api/templates/migration-guide.html
@@ -0,0 +1,445 @@
+{% extends "base.html" %}
+{% load static %}
+{% load extras %}
+
+{% block title %}V4 API Migration Guide – CourtListener.com{% endblock %}
+{% block description %}
+{% endblock %}
+
+{% block sidebar %}{% endblock %}
+
+{% block footer-scripts %}
+ {% include "includes/anchors.html" %}
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+ V4 API Migration Guide
+ What's Happening?
+
+ After several years of planning and development, we have released v4 of our APIs. In conjunction with this migration,
+ we are replacing our Solr search engine with an ElasticSearch cluster. v4 of the API responds to feedback we
+ have received over the years, and should be much better for our users — faster, more featureful, more scalable, and more accurate.
+
+
+ Unfortunately, we couldn't make these new APIs completely backwards compatible, so this guide explains the changes
+ in the new APIs and what it will take to migrate to them.
+
+ Timeline for Changes
+ v4 of the API is available now and is the default version for anybody creating new systems. Before its full release, a number of organizations beta tested it.
+
+
+ All of our APIs except for our search API are powered by our database. We do not have plans at present to deprecate
+ any of these APIs, but we'd like to remove them someday and urge you to migrate to v4 as soon as possible so we can do that.
+
+
+ That said, the v3 Search API is currently powered by Solr. v4 is powered by ElasticSearch. In nine weeks, we aim to switch v3 so it uses ElasticSearch too.
+ This will change v3 in small backwards incompatible ways, but will allow us to continue supporting it even after turning off our Solr server.
+
+
+ If you are a v3 Search API user, you will soon get an email from us to communicate and discuss timelines.
+
+ What If I Do Nothing?
+
+ You might be fine. Most of the database and search APIs are only changing slightly and v3 will be supported for some period of time.
+ But you should read this guide to see if any changes are needed to your application.
+
+ The remainder of this guide is in three section:
+
+ - New features you can expect
+ - How to migrate database APIs
+ - How to migrate search APIs
+
+
+ We're very excited to be releasing v4 of our APIs. We hope you will review these changes so we can all have a smooth transition.
+
+ What New Features Can I Expect?
+ Cursor-based pagination
+ Our database-powered APIs now support cursor-based pagination. This allows you to crawl very deeply in the API. In v3, any page past 100 was blocked.
+
+ ElasticSearch
+ v4 of the Search API is powered by ElasticSearch instead of Solr. This is a huge upgrade to our API and search engine.
+
+ Some of the improvements include:
+
+ - In v4, all PACER cases are now searchable. In v3 you only got results if a case had a docket entry.
+
+ - You can search for PACER filings based on what decisions they cite.
+
+ - You can now search for exact words like "Deposit" and not get back results for things like "Deposition."
+
+ - We've added about 800 legal acronyms like "IRS" to make sure those bring back results.
+
+ - Better relevancy for edge cases:
+
+
+ - Small words like "of," "to," and "the" are now searchable.
+ - Camelcase words like "McDonalds" are more searchable.
+ - Highlighting is more consistent and can be disabled for better performance.
+
+ - Emojis and unicode characters are now searchable.
+ - Docket number and other fielded searches are more robust.
+ - Timezone handling is more consistent.
+ - We've added a number of new searchable fields.
+
+
+ For more details please see our blog.
+ Breaking Changes to v3 of the Search API
+ We cannot continue running Solr forever, but we can do our best to support v3 of the API. To do this, on November 25, 2024,
+ v3 of the Search API will be upgraded to use Elastic behind the scenes. This will cause some breaking changes.
+ If you have not migrated to v4 when we make this swap, these are the breaking changes you should prepare for:
+
+ RECAP (type=r)
+
+ - Fields removed:
+
+ - attorney
+ - attorney_id
+ - firm
+ - firm_id
+ - party
+ - party_id
+ - docket_absolute_url
+
+
+
+ - Fielded text queries that includes party fields won't work, for instance:
+
firm_id:1245 AND party:(United States)
+
+
+
+ - The
type=d
uses a cardinality aggregation to compute the result count, which has an error of ±6% if results are over 2000.
+
+
+ Opinions (type=o)
+
+ - Fields removed:
+
+ - caseNameShort
+ - pagerank
+ - status_exact
+ - non_participating_judge_ids
+ - source
+
+ - Field added:
+
+ - date_created
+
+ snippet
has changed. In the Solr version, it included content from all fields, while in ES it displays only the Opinion text content.
+
+ - The
type=o
uses a cardinality aggregation to compute the result count, which has an error of ±6% if results are over 2000 hits.
+
+
+ Oral Arguments (type=oa)
+
+ - In this case, the API response will be fully compatible with the Solr version.
+ - The only change is in the content of the
snippet
field, which previously stored different audio fields in Solr. Now, it stores the audio transcription.
+
+
+ People
+
+ - No breaking changes. V3 is currently working on ES.
+
+ How Do I Migrate Database APIs?
+ Total count of results
+
+ - The total count of the results is no longer available in the response.
+ Most users don't need this when crawling the API, and computing the count for each response slows down the API.
+ If this value is essential to your service, let us know so we can discuss adding a new API with this feature.
+
+
+ Invalid cursor error code: 404
+
+ - A new type of error found in the V4 API is Invalid cursor with a 404 status code.
+ - This error can occur if a user starts a request using one sorting key, then switches to a different one without clearing the cursor from the parameters.
+ For example:
+
First request: /api/rest/v4/dockets/?cursor=cD0yMDI0LTA4LTA5KzE4JTNBMTMlM0E1Ny4xODQ0MjUlMkIwMCUzQTAw&order_by=date_created
+
+ Second request: /api/rest/v4/dockets/?cursor=cD0yMDI0LTA4LTA5KzE4JTNBMTMlM0E1Ny4xODQ0MjUlMkIwMCUzQTAw&order_by=id
+
+
+ - The reason for this error is that cursor pagination maintains the original sorting key type for consistency.
+ If the new key type does not match the one stored in the cursor, the error is triggered.
+
+ - Additionally, if a user starts pagination with a key that supports cursor pagination and then switches to one that doesn't, the cursor parameter in the request will be ignored, and the new request will start from page 1.
+ Similarly, if the user begins with a non-cursor key and switches to one that supports CBP, the
page
parameter will be ignored, and the request will restart from page 1.
+
+
+ How Do I Migrate the Search API?
+ Enhancements in v4
+ Search API crawls are no longer limited to 100 pages
+
+ - Deep pagination of search results is now possible.
+ - Users cannot directly jump to a specific page. Look at and follow the
next
and previous
parameters provided in each response. Navigation of the API is exclusively through those keys in each API response.
+
+
+ Result sorting is more consistent
+
+ - When sorting the API results, we now add a tie-breaking field to all responses. This ensures that ordering is consistent even when the ordering key has identical values for multiple results.
+
+ - If your sorting field has null values, those results will be sorted at the end of the query, regardless of whether you sort in ascending or descending order.
+ For example if you sort by a date that is null for an opinion, that opinion will go at the end of the result set.
+
+
+ Highlighting is more consistent
+
+ - When enabled, highlighting will more consistently highlight the fields in the response.
+
+ Empty fields are standardized
+
+ - Empty fields are now more consistent in their response types, and follow the conventions provided by Django.
+ This means that dates, date times, and integers return
null
, strings return an empty string, and lists return an empty array.
+
+
+ Backwards incompatible changes in v4
+ High query counts are estimated
+
+ - To enhance performance, query counts above 2,000 hits are approximate.
+ For those exceeding this threshold, counts can be off by as much as six percent.
+ We recommend noting this in your interface by saying something like, "About 5,000 results," instead of presenting the value as exact.
+
+
+ Highlighting
+
+ - To enhance performance, results are not highlighted by default. To enable highlighting, include
highlight=on
in your request.
+
+ - When highlighting is disabled, the first 500 characters of
snippet
fields are returned for types o
, r
, and rd
.
+
+
+ Nested keys (documents) for type=o
and type=p
+
+ - To enhance the structure of the API, sub-opinions are now nested within clusters in case law results (
type=o
), and positions
are nested within judges in judge results (type=p
).
+
+
+ type=r
is now for dockets with nested documents
+
+ - To align the API results with the front end results,
type=r
no longer returns a flat list of documents.
+ Instead, it now returns a list of dockets with up to three matching documents nested within each docket's recap_documents
key.
+
+ - To return a flat list of documents, as in the past, try the new
type=rd
parameter.
+ This can be useful for those upgrading from v3 to v4 of the search API.
+
+ - If there are more than three matching documents, the
more_docs
field for the docket result will be true.
+ As in the front end, you can get the remaining documents for a docket by placing a docket ID query like:
+ type=rd&q=(original query) AND docket_id:XYZ
+
+ - This response type includes two counts of the results:
count
is the number of dockets returned. document_count
is the number of documents.
+
+
+ type=rd
is a new result type for documents
+
+ type=rd
returns a flat list of PACER documents, and is similar to type=r
in v3 of the API.
+ Results for this type can be queried by any docket fields except the party
and attorney
fields.
+
+ - The field differences between
r
in v3 and rd
in v4 are that all the docket-level fields were removed:
+
+
+ - assignedTo
+ - assigned_to_id
+ - caseName
+ - cause
+ - court
+ - court_citation_string
+ - court_exact
+ - court_id
+ - dateArgued
+ - dateFiled
+ - dateTerminated
+ - docketNumber
+ - jurisdictionType
+ - juryDemand
+ - referredTo
+ - referred_to_id
+ - suitNature
+
+ docket_id
is still available in the rd
type so users can identify the docket and pull additional docket data from the docket API.
+
+ - One field that changed is
entry_date_filed
. In r
v3, it was a datetime
field with PST midnight as the default time.
+ Now, it's simply a date field.
+
+ - The
timestamp
field has been moved to the new meta
field, which also contains date_created
.
+
+
+ type=d
still returns dockets
+
+ type=d
returns dockets without nested documents. If all you need in the response is the docket information, this response type will be significantly faster.
+ You can query document fields with this response type even though they will not be returned.
+
+
+ Removed fields
+
+ - The following fields have been removed from the case law search results (
type=o
):
+
+
+ - caseNameShort
+ - pagerank
+ - status_exact
+ - non_participating_judge_ids
+
+
+ Changed field values
+
+ - For legibility, in the case law search results (
type=o
), some type
field values have changed:
+
+
+ - 010combined → combined-opinion
+ - 015unamimous → unanimous-opinion
+ - 020lead → lead-opinion
+ - 025plurality → plurality-opinion
+ - 030concurrence → concurrence-opinion
+ - 035concurrenceinpart → in-part-opinion
+ - 040dissent → dissent
+ - 050addendum → addendum
+ - 060remittitur → remittitur
+ - 070rehearing → rehearing
+ - 080onthemerits → on-the-merits
+ - 090onmotiontostrike → on-motion-to-strike
+
+
+
+ - Some of the values of the
status
field in the case law search results have changed:
+
+
+ - precedential → published
+ - non-precedential → unpublished
+ - errata → errata
+ - separate opinion → separate
+ - in-chambers → in-chambers
+ - relating-to orders → relating-to
+ - unknown status → unknown
+
+ - The
snippet
field in the case law search results previously included more than one opinion text field.
+ It now only contains the best text field, based on the following priority and determined by availability:
+
+
+ - html_columbia
+ - html_lawbox
+ - xml_harvard
+ - html_anon_2020
+ - html
+ - plain_text
+
+
+ Dates and times
+
+ - All dates and times are in UTC instead of PST.
+ - Date objects are now rendered as an ISO-8601 date instead of an ISO-8601 datetime.
+
+
+ The following is a full list of date fields that are now date objects (rather than datetime objects, which they were in v3):
+
+
+ - types
r
and d
:
+
+ - dateArgued
+ - dateFiled
+ - dateTerminated
+
+ - types
r
and rd
:
+
+ entry_date_filed
(in type r
is available in documents nested within the recap_documents key
)
+
+ - type
o
:
+
+ - dateArgued
+ - dateFiled
+ - dateReargued
+ - dateReargumentDenied
+
+ - type
oa
:
+
+ - dateArgued
+ - dateReargued
+ - dateReargumentDenied
+
+ - type
p
:
+
+ - dob
+ - dod
+ - The following fields are available within the nested
positions
key:
+
+
+ - date_confirmation
+ - date_elected
+ - date_hearing
+ - date_judicial_committee_action
+ - date_nominated
+ - date_recess_appointment
+ - date_referred_to_judicial_committee
+ - date_retirement
+ - date_start
+ - date_termination
+
+
+
+ No more random sorting
+
+ - You can no longer sort the results randomly. This was only used by developers and was difficult to support.
+
+
+ Stemming and Synonyms
+
+ - To provide better relevancy, stemming and synonyms are disabled on the
caseName
fields.
+
+ - This is because broadening a query to include synonyms and other words with the same stem are not relevant when a user searches for a case by name.
+ For example, when searching for a case name that includes the word "Howells" results for a search on the word "Howell" would not be relevant.
+
+ - This change applies to both the
case_name
filter and the text query.
+
+
+ Changes to GET parameters
+
+ - When searching the case law status fields, the GET parameters have been changed as follows:
+
+ - stat_Precedential → stat_Published
+ - stat_Non-Precedential → stat_Unpublished
+ - stat_Errata → stat_Errata
+ - stat_Separate Opinion → stat_Separate
+ - stat_In-chambers → stat_In-chambers
+ - stat_Relating-to orders → stat_Relating-to
+ - stat_Unknown Status → stat_Unknown
+
+
+ Bad Request Error Code: 400
+
+ - The error can contain one of the following custom messages in the
detail
key, explaining the reason for the error:
+
+
+ - The query contains unbalanced parentheses.
+ - The query contains unbalanced quotes.
+ - The query contains an unrecognized proximity token.
+
+
+ Server Error Code: 500
+
+ - Any other error, such as a connection error or a parsing error of the ES query, will raise
Server Error
Code: 500
.
+ - And the message in the detail key:
Internal Server Error. Please try again later or review your query.
+
+ Not Found Error Code: 404
+
+ - In the V4 Search API or other V4 database-based endpoints using cursor pagination, the following error can be raised:
Not Found Error
Code: 404
+
+ - Message in the
detail
key: Invalid cursor
+
+ - This can happen if the cursor was modified manually or if the ordering key changed and doesn't match the ordering key in the cursor.
+
+ - To avoid this problem, when changing the sorting key, restart your request by removing the cursor key from your request.
+
+
+
+{% endblock %}
diff --git a/cl/api/templates/oral-argument-api-docs-vlatest.html b/cl/api/templates/oral-argument-api-docs-vlatest.html
index 829b934193..8b0f0fea44 100644
--- a/cl/api/templates/oral-argument-api-docs-vlatest.html
+++ b/cl/api/templates/oral-argument-api-docs-vlatest.html
@@ -19,7 +19,7 @@
@@ -28,7 +28,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -50,7 +50,7 @@ Oral Argument Recoding APIs
The APIs
- Oral Argument Recordings — {% url "audio-list" version="v3" %}
+ Oral Argument Recordings — {% url "audio-list" version=version %}
Use this API to gather data about oral argument recordings. This API is linked to the docket API (below), which contains data about each case. It is also linked to the judge API, which has information about the judges in the case.
The audio files we gather from court websites come in many formats. After we gather the files, we convert them into optimized MP3s that have a 22050Hz sample rate and 48k bitrate. After converting the files, we set the ID3 tags to better values that we scraped. Finally, we set the cover art for the MP3 to the seal of the court, and set the publisher album art to our logo.
@@ -64,10 +64,10 @@
Oral Argument Recordings — {% url
curl -v \
-X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "audio-list" version="v3" %}"
+ "{% get_full_host %}{% url "audio-list" version=version %}"
- Dockets — {% url "docket-list" version="v3" %}
+ Dockets — {% url "docket-list" version=version %}
{% include "includes/docket-endpoint.html" %}
{% include "includes/donate_footer_plea.html" %}
diff --git a/cl/api/templates/pacer-api-docs-vlatest.html b/cl/api/templates/pacer-api-docs-vlatest.html
index 5a28526e03..7eed828e35 100644
--- a/cl/api/templates/pacer-api-docs-vlatest.html
+++ b/cl/api/templates/pacer-api-docs-vlatest.html
@@ -18,7 +18,7 @@
@@ -27,7 +27,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -69,18 +69,18 @@ Dockets, Courts, Docket Entries, and Documents
- Dockets — {% url "docket-list" version="v3" %}
+ Dockets — {% url "docket-list" version=version %}
{% include "includes/docket-endpoint.html" %}
Ideally, docket entries, parties, and attorneys would be nested within the docket object you request, but this is not possible because some dockets have a vast number of these objects. Listing so many values in a single response from the server is impractical. To access docket entries, parties, or attorneys for a specific docket, use the docket entry, party, or attorney endpoints and filter by docket ID.
The court fields are references to our Court API, described below.
- Courts — {% url "court-list" version="v3" %}
+ Courts — {% url "court-list" version=version %}
{% include "includes/court-endpoint.html" %}
- Docket Entries — {% url "docketentry-list" version="v3" %}
+ Docket Entries — {% url "docketentry-list" version=version %}
Docket Entry
objects represent the rows on a PACER docket, and contain one or more nested documents. This follows the design on PACER, in which a single row on a docket represents a document with its associated attachments.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -89,7 +89,7 @@
Docket Entries — {% url "docketen
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docketentry-list" version="v3" %}?docket=4214664"
+ "{% get_full_host %}{% url "docketentry-list" version=version %}?docket=4214664"
Such a request will return up to 20 docket entries per page. Each docket entry returned can contain a number of nested documents in the recap_document
key, including their full extracted text (see details in the next section below). As a result, this response can be quite large.
A few field-level notes:
@@ -131,7 +131,7 @@ Docket Entries — {% url "docketen
{% endif %}
- Documents — {% url "recapdocument-list" version="v3" %}
+ Documents — {% url "recapdocument-list" version=version %}
Each docket entry contains several documents, which we call RECAP Document
objects.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -174,7 +174,7 @@
Documents — {% url "recapdocume
- Parties — {% url "party-list" version="v3" %}
+ Parties — {% url "party-list" version=version %}
The Party
endpoint provides details about parties that have been involved in federal cases in PACER, and contains nested attorney information.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS
request.
@@ -186,37 +186,36 @@
Parties — {% url "party-list" version="v
For example, this query returns the parties for docket number 123
:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "party-list" version="v3" %}?docket=123"
+ "{% get_full_host %}{% url "party-list" version=version %}?docket=123"
It returns something like:
{
-① "count": 35,
- "next": "https://www.courtlistener.com/api/rest/v3/parties/?docket=123&page=2",
+① "next": "https://www.courtlistener.com/api/rest/{{ version }}/parties/?docket=123&page=2",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/parties/42/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/parties/42/",
"id": 42,
② "attorneys": [
{
- "attorney": "https://www.courtlistener.com/api/rest/v3/attorneys/1/",
+ "attorney": "https://www.courtlistener.com/api/rest/{{ version }}/attorneys/1/",
"attorney_id": 1,
"date_action": null,
- "docket": "https://www.courtlistener.com/api/rest/v3/dockets/123/",
+ "docket": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/123/",
"docket_id": 123,
"role": 10
},
{
- "attorney": "https://www.courtlistener.com/api/rest/v3/attorneys/2/",
+ "attorney": "https://www.courtlistener.com/api/rest/{{ version }}/attorneys/2/",
"attorney_id": 2,
"date_action": null,
- "docket": "https://www.courtlistener.com/api/rest/v3/dockets/456/",
+ "docket": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/456/",
"docket_id": 456,
"role": 2
}
],
③ "party_types": [
{
- "docket": "https://www.courtlistener.com/api/rest/v3/dockets/123/",
+ "docket": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/123/",
"docket_id": 123,
"name": "Plaintiff",
"date_terminated": null,
@@ -257,28 +256,27 @@ Parties — {% url "party-list" version="v
{% endif %}
- Attorneys — {% url "attorney-list" version="v3" %}
+ Attorneys — {% url "attorney-list" version=version %}
Use this API to look up an attorney in our system.
To look up field descriptions or options for filtering, ordering, or rendering, complete an HTTP OPTIONS request.
Like docket entries and parties, attorneys can be filtered to a particular docket. For example:
curl -v \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "attorney-list" version="v3" %}?docket=4214664"
+ "{% get_full_host %}{% url "attorney-list" version=version %}?docket=4214664"
Returns:
{
- "count": 108,
- "next": "https://www.courtlistener.com/api/rest/v3/attorneys/?docket=4214664&page=2",
+ "next": "https://www.courtlistener.com/api/rest/{{ version }}/attorneys/?docket=4214664&page=2",
"previous": null,
"results": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/attorneys/9247906/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/{{ version }}/attorneys/9247906/",
"id": 9247906,
"parties_represented": [
{
"role": 10,
- "docket": "https://www.courtlistener.com/api/rest/v3/dockets/4214664/",
- "party": "https://www.courtlistener.com/api/rest/v3/parties/13730908/",
+ "docket": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/4214664/",
+ "party": "https://www.courtlistener.com/api/rest/{{ version }}/parties/13730908/",
"date_action": null
}
],
@@ -299,7 +297,7 @@ Attorneys — {% url "attorney-list" ve
{% endif %}
- Originating Court — {% url 'originatingcourtinformation-list' version="v3" %}
+ Originating Court — {% url 'originatingcourtinformation-list' version=version %}
Originating Court Information
represents the information gathered at an appellate court about a case when it was in a lower court or administrative body.
The information in this table is joined via a one-to-one relationship to the Docket
object. Generally, this table is only completed for appellate cases that we acquire from PACER.
@@ -308,7 +306,7 @@
Originating Court — {% url
- Integrated Database — {% url 'fjcintegrateddatabase-list' version='v3' %}
+ Integrated Database — {% url 'fjcintegrateddatabase-list' version=version %}
FJC Integrated Database
objects represent the information available in the Federal Judicial Center's Integrated Database, a regularly updated source of metadata about federal court cases. You can learn more about the IDB from the following sources:
@@ -322,18 +320,17 @@ Integrated Database — {% url 'f
- Fast Document Lookup — {% url "fast-recapdocument-list" version="v3" %}
+ Fast Document Lookup — {% url "fast-recapdocument-list" version=version %}
This API is used to check if documents with known IDs are available in our system.
To use it, provide a court ID and a comma-separated list of pacer_doc_id
's:
curl \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- '{% get_full_host %}{% url "fast-recapdocument-list" version="v3" %}?docket_entry__docket__court=dcd&pacer_doc_id__in=04505578698,04505578717' \
+ '{% get_full_host %}{% url "fast-recapdocument-list" version=version %}?docket_entry__docket__court=dcd&pacer_doc_id__in=04505578698,04505578717' \
This will return one entry for each document found, up to a maximum of 300 items:
{
- "count": 2,
"next": null,
"previous": null,
"results": [
diff --git a/cl/api/templates/recap-api-docs-vlatest.html b/cl/api/templates/recap-api-docs-vlatest.html
index bbc495e604..7087769324 100644
--- a/cl/api/templates/recap-api-docs-vlatest.html
+++ b/cl/api/templates/recap-api-docs-vlatest.html
@@ -18,7 +18,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -63,16 +63,16 @@ RECAP APIs for PACER
The endpoints for RECAP are:
-
-
{% url "pacerfetchqueue-list" version="v3" %}
— Use this API to scrape PACER data, including dockets, PDFs, and more.
+
{% url "pacerfetchqueue-list" version=version %}
— Use this API to scrape PACER data, including dockets, PDFs, and more.
-
-
{% url "processingqueue-list" version="v3" %}
— Use this API to upload PACER data to CourtListener and to check on the progress of an upload.
+
{% url "processingqueue-list" version=version %}
— Use this API to upload PACER data to CourtListener and to check on the progress of an upload.
- PACER Fetch — {% url "pacerfetchqueue-list" version="v3" %}
+ PACER Fetch — {% url "pacerfetchqueue-list" version=version %}
Use this API to buy PACER content and add it to CourtListener so that it is available via our website, APIs, webhooks, and replicated database. This is a free API, but it uses your PACER credentials to purchase and download PACER content. You'll still have to pay your PACER bill when it comes.
Because downloading content from PACER takes time, this API is asynchronous. After you send an HTTP POST
, it immediately responds with an ID for the request and places the request in a queue to be downloaded by our scrapers. Most requests are completed within seconds.
@@ -158,7 +158,7 @@
Purchasing PDFs
--data 'pacer_password=yyy' \
--data 'recap_document=112' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "pacerfetchqueue-list" version="v3" %}"
+ "{% get_full_host %}{% url "pacerfetchqueue-list" version=version %}"
If you have a client code, you can provide it to the API with the client_code
parameter.
If we do not have the pacer_doc_id
for a particular recap_document
, we will not be able to download it. If that's the case, you'll get an error message asking you to download the docket, which will get us the pacer_doc_id
we need. Once that is completed you can retry your PDF purchase.
@@ -195,7 +195,7 @@ Purchasing Dockets
--data 'docket_number=5:16-cv-00432' \
--data 'court=okwd' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
-"{% get_full_host %}{% url "pacerfetchqueue-list" version="v3" %}"
+"{% get_full_host %}{% url "pacerfetchqueue-list" version=version %}"
This is the same, but includes parties and counsel:
curl -X POST \
--data 'request_type=1' \
@@ -205,7 +205,7 @@ Purchasing Dockets
--data 'court=okwd' \
--data 'show_parties_and_counsel=true' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
-"{% get_full_host %}{% url "pacerfetchqueue-list" version="v3" %}"
+"{% get_full_host %}{% url "pacerfetchqueue-list" version=version %}"
Finally, this request updates an existing docket in CourtListener by its ID, but only gets the parties and counsel. Docket entries are excluded by requesting only ones from before 1980:
curl -X POST \
@@ -216,14 +216,14 @@ Purchasing Dockets
--data 'show_parties_and_counsel=true' \
--data 'de_date_end=1980-01-01' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
-"{% get_full_host %}{% url "pacerfetchqueue-list" version="v3" %}"
+"{% get_full_host %}{% url "pacerfetchqueue-list" version=version %}"
Sometimes, we get a PDF before we get a docket, making it impossible to know what case the PDF is associated with. We call these "orphan documents" because they do not have valid parent objects in our system.
Later, when we receive new or updated docket information, we have an opportunity to fix this problem by checking our system for orphan documents. When this happens, the orphans will automatically be associated with the new docket information, and the case will have PDFs linked to it.
- RECAP Upload API — {% url "processingqueue-list" version="v3" %}
+ RECAP Upload API — {% url "processingqueue-list" version=version %}
This API is used by the RECAP extension and a handful of special partners to upload PACER content to the RECAP Archive. This API is not available to the public. If you have a collection of PACER data you wish to donate to the RECAP Archive so it is permanently available to the public, please get in touch.
We describe the process for completing these uploads below, and you can see examples of them in CourtListener's automated test suite. Uploads to these endpoints should be done using HTTP POST
requests and multipart form data.
@@ -333,7 +333,7 @@
A Complete Example
--form court=dcd \
--form pacer_case_id=<some-value> \
--form debug=true \
- '{% get_full_host %}{% url "processingqueue-list" version="v3" %}'
+ '{% get_full_host %}{% url "processingqueue-list" version=version %}'
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
In response, you would receive an object like this:
{
@@ -356,13 +356,13 @@ A Complete Example
}
Then, to check the status, you can poll it with:
curl \
- '{% get_full_host %}{% url "processingqueue-detail" version="v3" pk="13684105" %}'
+ '{% get_full_host %}{% url "processingqueue-detail" version=version pk="13684105" %}'
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
Which will soon return:
{
"id": 13684105,
"court": "dcd",
- "docket": "https://www.courtlistener.com/api/rest/v3/dockets/8903924/",
+ "docket": "https://www.courtlistener.com/api/rest/{{ version }}/dockets/8903924/",
"docket_entry": null,
"recap_document": null,
"date_created": "2024-05-18T08:01:14.457637-07:00",
diff --git a/cl/api/templates/rest-docs-v3.html b/cl/api/templates/rest-docs-v3.html
new file mode 100644
index 0000000000..61966fd674
--- /dev/null
+++ b/cl/api/templates/rest-docs-v3.html
@@ -0,0 +1,533 @@
+{% extends "base.html" %}
+{% load static %}
+{% load extras %}
+
+{% block title %}REST API, v3.15 – CourtListener.com{% endblock %}
+{% block description %}REST API for federal and state case law, PACER data, the searchable RECAP Archive, oral argument recordings and more. Provided by Free Law Project, a 501(c)(3) non-profit. Please donate to support this service.{% endblock %}
+{% block og_description %}REST API for federal and state case law, PACER data, the searchable RECAP Archive, oral argument recordings and more. Provided by Free Law Project, a 501(c)(3) non-profit. Please donate to support this service.{% endblock %}
+
+{% block sidebar %}{% endblock %}
+
+{% block footer-scripts %}
+ {% include "includes/anchors.html" %}
+{% endblock %}
+
+{% block content %}
+
+
+
+ These notes are for a version of the API that is deprecated.
+ New implementations should use the latest version of the API
+ and existing software should be upgraded.
+ These notes are maintained to help with migrations.
+
+
+ REST API – v3.15
+
+ APIs for developers and researchers that need granular legal data.
+
+ After more than a decade of development, these APIs are powerful. Our case law API was the first. Our PACER and oral argument APIs are the biggest. Our webhooks push data to you. Our citation lookup tool can fight hallucinations in AI tools.
+
+ Let's get started. To see and browse all the API URLs, click the button below:
+
+
+ We could have also pulled up that same information using curl, with a command like:
+ curl "{% get_full_host %}{% url "api-root" version="v3" %}"
+ Note that when you press the button in your browser, you get an HTML result, but when you run curl
you get a JSON object. This is discussed in more depth below.
+
+ Listen Up! Something else that's curious just happened. You didn't authenticate to the API. To encourage experimentation, many of our APIs are open by default. The biggest gotcha people have is that they forget to enable authentication before deploying their code. Don't make this mistake! Remember to add authentication.
+
+ The APIs listed in this response can be used to make queries against our database or search engine.
+
+ To learn more about an API, you can send an HTTP OPTIONS request to it, like so:
+
+ curl -X OPTIONS "{% get_full_host %}{% url "api-root" version="v3" %}"
+ An OPTIONS
request is one of the best ways to understand the API.
+
+
+
+ Support
+ Questions about the APIs can be sent to our GitHub Discussions forum or via our contact form.
+
+ We prefer that questions be posted in the forum so they can help others. If you are a private organization posting to that forum, we will avoid sharing details about your organization.
+
+
+ Ask in GitHub Discussions
+ Send us a Private Message
+
+
+
+ Data Models
+ The two images below show how the APIs work together. The first image shows the models we use for people, and the second shows the models we use for documents and metadata about them. You can see that these models currently link together on the Docket, Person, and Court tables. (Here's a version of this diagram that shows everything all at once.)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ API Overview
+ This section explains the general principles of the API. These principals are driven by the features supported by the Django REST Framework. To go deep on any of these sections, we encourage you to check out the documentation there.
+
+
+
+ Permissions
+ Some of our APIs are only available to select users. If you need greater access to these APIs, please get in touch.
+
+ All other endpoints are available according to the throttling and authentication limitations listed below.
+
+
+
+
+ Your Authorization Token
+ {% if user.is_authenticated %}
+ Your permanent token for use with this API is:
+ {{ user.auth_token }}
+ Do not share your API token. Keep it private like a password.
+
+
+ {% else %}
+
+ {% endif %}
+
+
+
+ Authentication
+ Authentication is necessary to monitor and throttle usage of the system, and so we can assist with any errors that may occur.
+
+ Per our privacy policy, we do not track your queries in the API, though we do collect statistical information for system monitoring.
+
+ There are currently three types of authentication available on the API:
+
+
+ -
+ HTTP Token Authentication
+
+ -
+ Cookie/Session Authentication
+
+ -
+ HTTP Basic Authentication
+
+
+ All of these methods are secure, so the choice of which to use is generally a question of what's most convenient for the context of your work. Our recommendations are:
+
+
+ - Use Token Authentication for programmatic API access.
+
+ - Use Cookie/Session Authentication if you already have a user's cookie or are developing a system where you can ask the user to log into CourtListener.
+
+ - Use Basic Authentication if that's all your client supports.
+
+
+ Token Authentication
+ To use token authentication, use the Authorization
HTTP Header. The key should prefix the Token
, with whitespace separating the two strings. For example:
+
+ Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}
+ Using curl, this looks like:
+ curl "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}" \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
+ Note that quotes are used to enclose the whitespace in the header.
+ Careful! A common mistake is to forget the word "Token" in the header.
+
+ {% if user.is_authenticated %}
+ Your permanent token for use with this API is being used in the examples above and is:
+ {{ user.auth_token }}
+ Do not share this value publicly via code check ins, emails, etc. Treat this value as you would a password. Do not email it to us.
+
+ {% else %}
+ Sign in to see your authorization token in this documentation.
+
+ {% endif %}
+
+ Cookie Authentication
+ To use Cookie Authentication log into Courtlistener and pass the cookie value using the standard cookie headers.
+
+
+ HTTP Basic Authentication
+ To do HTTP Basic Authentication using curl, you might do something like this:
+
+ curl --user "harvey:your-password" \
+ "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}"
+ You can also do it in your browser with a url like:
+ {% get_full_host username='harvey' password='your-password' %}{% url "opinioncluster-list" version="v3" %}
+ But if you're using your browser, you might as well just log in.
+
+
+
+ Serialization Formats
+ Requests may be serialized as HTML, JSON, or XML. JSON is the default if no format is specified. The format you wish to receive is requested via the HTTP Accept
header.
+
+ The following media types and parameters can be used:
+
+
+ - HTML: The media type for HTML is
text/html
.
+ - JSON: The media type for JSON is
application/json
. Providing the indent
media type parameter allows clients to set the indenting for the response, for example: Accept: application/json; indent=2
.
+
+ - XML: The media type for XML is
application/xml
.
+
+ By default, browsers send an Accept
header similar to:
+
+ text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+ This states that text/html
is the preferred serialization format. The API respects that, returning HTML when requested by a browser and returning JSON when no Accept
header is provided, because JSON is the default.
+
+ If you wish to set the Accept
header using a tool like cURL, you can do so using the --header
flag:
+
+ curl --header "Accept: application/xml" \
+ "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}"
+ All data is serialized using the utf-8 charset.
+
+
+ Parsing Uploaded Content
+ If you are a user that has write access to these APIs (most users do not), you will need to use the Content-Type
HTTP header to explicitly set the format of the content you are uploading. The header can be set to any of the values that are available for serialization or to application/x-www-form-urlencoded
or multipart/form-data
, if you are sending form data.
+
+
+
+ Filtering
+ With the exception of the search API, these APIs can be filtered using a technique similar to Django's field lookups.
+
+ To see how an endpoint can be filtered, do an OPTIONS
request on the API and inspect the filters
key in the response.
+
+ In the filters
key, you'll find a dictionary listing the fields that can be used for filtering along with their types, lookup fields, and any values (aka choices) that can be used for specific lookups.
+
+ For example, this uses jq
to look at the filters on the docket API:
+ curl -X OPTIONS \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "docket-list" version="v3" %}" | jq '.filters'
+ That returns something like:
+ {
+ "id": {
+ "type": "NumberRangeFilter",
+ "lookup_types": [
+ "exact",
+ "gte",
+ "gt",
+ "lte",
+ "lt",
+ "range"
+ ]
+ },
+...
+ This means that you can filter dockets using the ID field, and that you can do exact, greater than or equal, greater than, less than or equal, less than, or range filtering.
+
+ You can use these filters with a double underscore. For example, this gets IDs greater than 500 and less than 1,000:
+ curl \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "docket-list" version="v3" %}?id__gt=500&id__lt=1000" | jq '.count'
+499
+ It also allows ranges (inclusive):
+ curl \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "docket-list" version="v3" %}?id__range=500,1000" | jq '.count'
+501
+ Filters can be combined using multiple GET
parameters.
+ There are a few special types of filters. The first are Related Filters
, which allow you to join filters across APIs. For example, when you are using the docket API, you'll see that it has a filter for the court API:
+
+
+"court": {
+ "type": "RelatedFilter",
+ "lookup_types": "See available filters for 'Courts'"
+}
+ This means that you can use any of the court filters on the docket API. If you do an OPTIONS
request on the court API, you'll see its filters:
+
+ curl -X OPTIONS \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "court-list" version="v3" %}" | jq '.filters'
+ Again, one of the fitlers is the ID field, but it only allows exact values on this API:
+
+"id": {
+ "type": "CharFilter",
+ "lookup_types": [
+ "exact"
+ ]
+}
+ Putting this together, here's how you look up dockets for a particular court:
+
+ curl \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "docket-list" version="v3" %}?court=scotus&id__range=500,1000" | jq '.count'
+36
+ This opens up many possibilities. For example, another filter on the Court
endpoint is for jurisdictions
. To use it, you would use a GET parameter like court__jurisdictions=FD
. In this case, the double underscore allows you to join the filter from the other court API to the docket API.
+
+ If you want to join a filter, you could do something like court__full_name__startswith=district
. That would return dockets in courts where the court's name starts with "district".
+
+ RelatedFilters
can span many objects. For example, if you want to get all the Supreme Court Opinion
objects, you will need to do that with a query such as:
+
+ curl "{% get_full_host %}{% url "opinion-list" version="v3" %}?cluster__docket__court=scotus"
+ This uses the Opinion
API to get Opinions
that are part of Opinion Clusters
that are on Dockets
in the Court
with the ID of scotus
. To understand this data model better, see the case law API documentation.
+
+ To use date filters, supply dates in ISO-8601 format.
+
+ A final trick that can be used with the filters is the exclusion parameter. Any filter can be converted into an exclusion filter by prepending it with an exclamation mark. For example, this returns Dockets
from non-Federal Appellate jurisdictions:
+
+ curl "{% get_full_host %}{% url "docket-list" version="v3" %}?court__jurisdiction!=F"
+ You can see more examples of filters in our automated tests.
+
+
+
+
+ Ordering
+ With the exception of the search API, you can see which fields can be used for ordering, by looking at the ordering
key in an OPTIONS
request. For example, the Position
endpoint contains this:
+
+
+"ordering": [
+ "id",
+ "date_created",
+ "date_modified",
+ "date_nominated",
+ "date_elected",
+ "date_recess_appointment",
+ "date_referred_to_judicial_committee",
+ "date_judicial_committee_action",
+ "date_hearing",
+ "date_confirmation",
+ "date_start",
+ "date_retirement",
+ "date_termination"
+]
+ Thus, you can order using any of these fields in conjunction with the order_by
parameter.
+
+ Descending order can be done using a minus sign. Multiple fields can be requested using a comma-separated list. This, for example, returns judicial Positions
ordered by the most recently modified, then by the most recently elected:
+
+ curl "{% get_full_host %}{% url "position-list" version="v3" %}?order_by=-date_modified,-date_elected"
+ Ordering by fields with duplicate values is non-deterministic. If you wish to order by such a field, you should provide a second field as a tie-breaker to consistently order results. For example, ordering by date_filed
will not return consistent ordering for items that have the same date, but this can be fixed by ordering by date_filed,id
. In that case, if two items have the same date_filed
value, the tie will be broken by the id
field.
+
+
+
+ Field Selection
+ To save bandwidth and increase serialization performance, fields can be limited by using the fields
parameter with a comma-separated list of fields.
+
+ For example, to only receive the educations
and date_modified
fields from the Judge
endpoint you could do so with:
+
+ curl "{% get_full_host %}{% url "person-list" version="v3" %}?fields=educations,date_modified"
+{
+ "educations": [
+ {
+ "resource_uri": "https://www.courtlistener.com/api/rest/v3/educations/12856/",
+ "id": 12856,
+ "school": {
+ "resource_uri": "https://www.courtlistener.com/api/rest/v3/schools/4240/",
+ "id": 4240,
+ "is_alias_of": null,
+ "date_created": "2010-06-07T17:00:00-07:00",
+ "date_modified": "2010-06-07T17:00:00-07:00",
+ "name": "University of Maine",
+ "ein": 16000769
+ },
+ "person": "https://www.courtlistener.com/api/rest/v3/people/16214/",
+ "date_created": "2023-03-31T07:15:28.556198-07:00",
+ "date_modified": "2023-03-31T07:15:28.556222-07:00",
+ "degree_level": "jd",
+ "degree_detail": "",
+ "degree_year": 1979
+ }
+ ],
+ "date_modified": "2023-03-31T07:15:28.409594-07:00"
+},
+...
+ You can also exclude fields using fields!=educations,date_modified
.
+
+ Unfortunately, this cannot be used for nested resources, though there is an open issue tracking this.
+
+
+
+ Rate Limits
+ Our APIs allow 5,000 queries per hour to authenticated users. Unauthenticated users are allowed 100 queries per day for experimentation.
+
+ To debug throttling issues:
+
+ - Try browsing the API while logged into the website. If this works and your code fails, it usually means that your token authentication is not configured properly, and your code is getting throttled as an anonymous user, not according to your token.
+
+ - Review your recent API usage by looking in your profile, but remember that it will show stats for the browsable API as well.
+
+ - Review the authentication/throttling tips in our forum.
+
+ If, after checking the above, you need your rate limit increased, please get in touch so we can help.
+
+
+
+ Performance Tips
+ A few things to consider that may increase your performance:
+
+ -
+
When doing deep crawls of the data, going to very high page numbers will incur increasingly bad performance. This is common in databases because to go to a high page number means sorting the entire data set, then counting to the correct location. Page 50 isn't a big deal. Page 2,000 starts getting slower.
+
+ The fix to this solution is often to work with "slices" of the data. Instead of paginating across the whole result set, use a date field or another range-type field to only paginate over a smaller set of the data. For example, you could slice a large result set by the month of the date filing field to prevent deep pagination.
+
+ Be careful to slice using a field with a normal distribution. Do not use one like date_created
, which could have extreme spikes of activity.
+
+
+ -
+
Avoid doing queries like court__id=xyz
when you can instead do court=xyz
. Doing queries with the extra __id
introduces a join that can be expensive.
+
+ -
+
In general, less data is easier and faster to get than more. Could you use a field to filter your result set down to something smaller?
+
+
+ -
+
When using the search
endpoint, smaller result sets are faster. It isn't always possible to tweak your query to return fewer results, but sometimes it is possible to do a more precise query first, thus making a broader query unnecessary. For example, a search for an individual in their expected jurisdiction will be faster than doing it in the entire corpus. This will benefit from profiling in your use case and application.
+
+
+
+
+ Advanced Field Definitions
+ Placing an HTTP OPTIONS
request on an API is the best way to learn about its fields, but some fields require further explanation. Click below to learn about these fields.
+
+
+
+
+ APIs
+ Case Law APIs
+ We started collecting case law in 2009 and launched this API in 2013 as the first API for legal decisions.
+
+ Use this API to build your own collection of case law, complete complex legal research, and more.
+
+
+ Learn More
+
+
+ PACER Data APIs
+ We have almost half a billion PACER-related objects in the RECAP Archive. Use these APIs to access and understand this data.
+
+
+ Learn More
+
+
+ RECAP APIs
+ Use these APIs to gather data from PACER and to share your PACER data with the public.
+
+
+ Learn More
+
+
+ Search API
+ CourtListener allows you to search across hundreds of millions of items with advanced fields and operators. Use this API to automate the CourtListener search engine.
+
+
+ Learn More
+
+
+ Judge APIs
+ Use these APIs to query and analyze thousands of federal and state court judges, including their biographical information, political affiliations, education and employment histories, and more.
+
+
+ Learn More
+
+
+ Financial Disclosure APIs
+ All federal judges and many state judges must file financial disclosure documents to indicate any real or perceived biases they may have.
+
+ Use these APIs to work with this information.
+
+ Learn More
+
+
+ Oral Argument APIs
+ CourtListener is home to the largest collection of oral argument recordings on the Internet. Use thees APIs to gather and analyze our collection.
+
+
+ Learn More
+
+
+ Citation Lookup and Verification API
+ Use this API to look up citations in CourtListener's database of millions of citations.
+ This API can look up either an individual citation or can parse and look up every citation in a block of text. This can be useful as a guardrail to help prevent hallucinated citations.
+
+
+ Learn More
+
+
+ Citation Network APIs
+ Use these APIs to traverse and analyze our network of citations between legal decisions.
+
+
+ Learn More
+
+
+ Alert APIs
+ CourtListener is a scalable system for sending alerts by email or webhook based on search queries or for particular cases. Use these APIs to create, modify, list, and delete alerts.
+
+ Learn More
+
+
+ Visualization APIs
+ To see and make Supreme Court case visualizations, use these APIs.
+
+ Learn More
+
+
+
+
+ Available Jurisdictions
+ We currently have {{ court_count }} jurisdictions that can be accessed with our APIs. Details about the jurisdictions that are available, including all abbreviations, can be found here.
+
+
+ Upgrades and Fixes
+ Like the rest of the CourtListener platform, this API and its documentation are open source. If it lacks functionality that you desire or if you find this documentation lacking, pull requests providing improvements are encouraged. Just get in touch via our contact form to discuss your ideas. Or, if it's something quick, just go ahead and send us a pull request.
+
+ Getting this kind support is one of the most rewarding things possible for an organization like ours and is a major goal of Free Law Project. Many of the features you use on CourtListener were built this way. We're building something together.
+
+
+ Maintenance Schedule
+ There is a weekly maintenance window from 21:00-23:59PT on Thursday nights. If you are scheduling cron jobs or otherwise crawling the API, you may experience downtime during this window.
+
+ Additionally, we regularly perform bulk tasks on our servers and maintain a public calendar for tracking them. You may encounter larger delays while bulk processing jobs are running.
+
+
+
+ API Change Log
+
+
+ Copyright
+ Our data is free of known copyright restrictions.
+
+
+
+
+
+ {% include "includes/donate_footer_plea.html" %}
+
+
+{% endblock %}
diff --git a/cl/api/templates/rest-docs-vlatest.html b/cl/api/templates/rest-docs-vlatest.html
index fdf13b7d40..fc761f8374 100644
--- a/cl/api/templates/rest-docs-vlatest.html
+++ b/cl/api/templates/rest-docs-vlatest.html
@@ -2,7 +2,7 @@
{% load static %}
{% load extras %}
-{% block title %}REST API, v3.15 – CourtListener.com{% endblock %}
+{% block title %}REST API, v4 – CourtListener.com{% endblock %}
{% block description %}REST API for federal and state case law, PACER data, the searchable RECAP Archive, oral argument recordings and more. Provided by Free Law Project, a 501(c)(3) non-profit. Please donate to support this service.{% endblock %}
{% block og_description %}REST API for federal and state case law, PACER data, the searchable RECAP Archive, oral argument recordings and more. Provided by Free Law Project, a 501(c)(3) non-profit. Please donate to support this service.{% endblock %}
@@ -25,20 +25,22 @@
{% include "includes/toc_sidebar.html" %}
+
+
+
- REST API – v3.15
+ REST API – v4.0
APIs for developers and researchers that need granular legal data.
+ Update! V4 of the API is now live! We encourage you to use the latest version. You can view information on previous versions of the API here.
+
After more than a decade of development, these APIs are powerful. Our case law API was the first. Our PACER and oral argument APIs are the biggest. Our webhooks push data to you. Our citation lookup tool can fight hallucinations in AI tools.
Let's get started. To see and browse all the API URLs, click the button below:
-
We could have also pulled up that same information using curl, with a command like:
- curl "{% get_full_host %}{% url "api-root" version="v3" %}"
+ curl "{% get_full_host %}{% url "api-root" version="v4" %}"
Note that when you press the button in your browser, you get an HTML result, but when you run curl
you get a JSON object. This is discussed in more depth below.
Listen Up! Something else that's curious just happened. You didn't authenticate to the API. To encourage experimentation, many of our APIs are open by default. The biggest gotcha people have is that they forget to enable authentication before deploying their code. Don't make this mistake! Remember to add authentication.
@@ -47,7 +49,7 @@
REST API – v3.15
To learn more about an API, you can send an HTTP OPTIONS request to it, like so:
- curl -X OPTIONS "{% get_full_host %}{% url "api-root" version="v3" %}"
+ curl -X OPTIONS "{% get_full_host %}{% url "api-root" version="v4" %}"
An OPTIONS
request is one of the best ways to understand the API.
@@ -102,7 +104,7 @@ API Overview
Permissions
Some of our APIs are only available to select users. If you need greater access to these APIs, please get in touch.
- All other endpoints are available according to the throttling and authentication limitations listed below.
+
All other endpoints are available according to the throttling and authentication limitations listed below.
@@ -155,7 +157,7 @@ Token Authentication
Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}
Using curl, this looks like:
- curl "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}" \
+ curl "{% get_full_host %}{% url "opinioncluster-list" version="v4" %}" \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}'
Note that quotes are used to enclose the whitespace in the header.
Careful! A common mistake is to forget the word "Token" in the header.
@@ -178,9 +180,9 @@
HTTP Basic Authentication
To do HTTP Basic Authentication using curl, you might do something like this:
curl --user "harvey:your-password" \
- "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}"
+ "{% get_full_host %}{% url "opinioncluster-list" version="v4" %}"
You can also do it in your browser with a url like:
- {% get_full_host username='harvey' password='your-password' %}{% url "opinioncluster-list" version="v3" %}
+ {% get_full_host username='harvey' password='your-password' %}{% url "opinioncluster-list" version="v4" %}
But if you're using your browser, you might as well just log in.
@@ -204,7 +206,7 @@ Serialization Formats
If you wish to set the Accept
header using a tool like cURL, you can do so using the --header
flag:
curl --header "Accept: application/xml" \
- "{% get_full_host %}{% url "opinioncluster-list" version="v3" %}"
+ "{% get_full_host %}{% url "opinioncluster-list" version="v4" %}"
All data is serialized using the utf-8 charset.
@@ -223,7 +225,7 @@ Filtering
For example, this uses jq
to look at the filters on the docket API:
curl -X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}" | jq '.filters'
+ "{% get_full_host %}{% url "docket-list" version="v4" %}" | jq '.filters'
That returns something like:
{
"id": {
@@ -243,12 +245,12 @@ Filtering
You can use these filters with a double underscore. For example, this gets IDs greater than 500 and less than 1,000:
curl \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}?id__gt=500&id__lt=1000" | jq '.count'
+ "{% get_full_host %}{% url "docket-list" version="v4" %}?id__gt=500&id__lt=1000" | jq '.count'
499
It also allows ranges (inclusive):
curl \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}?id__range=500,1000" | jq '.count'
+ "{% get_full_host %}{% url "docket-list" version="v4" %}?id__range=500,1000" | jq '.count'
501
Filters can be combined using multiple GET
parameters.
There are a few special types of filters. The first are Related Filters
, which allow you to join filters across APIs. For example, when you are using the docket API, you'll see that it has a filter for the court API:
@@ -262,8 +264,8 @@
Filtering
curl -X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "court-list" version="v3" %}" | jq '.filters'
- Again, one of the fitlers is the ID field, but it only allows exact values on this API:
+ "{% get_full_host %}{% url "court-list" version="v4" %}" | jq '.filters'
+ Again, one of the filters is the ID field, but it only allows exact values on this API:
"id": {
"type": "CharFilter",
@@ -275,7 +277,7 @@ Filtering
curl \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}?court=scotus&id__range=500,1000" | jq '.count'
+ "{% get_full_host %}{% url "docket-list" version="v4" %}?court=scotus&id__range=500,1000" | jq '.count'
36
This opens up many possibilities. For example, another filter on the Court
endpoint is for jurisdictions
. To use it, you would use a GET parameter like court__jurisdictions=FD
. In this case, the double underscore allows you to join the filter from the other court API to the docket API.
@@ -283,14 +285,14 @@ Filtering
RelatedFilters
can span many objects. For example, if you want to get all the Supreme Court Opinion
objects, you will need to do that with a query such as:
- curl "{% get_full_host %}{% url "opinion-list" version="v3" %}?cluster__docket__court=scotus"
+ curl "{% get_full_host %}{% url "opinion-list" version="v4" %}?cluster__docket__court=scotus"
This uses the Opinion
API to get Opinions
that are part of Opinion Clusters
that are on Dockets
in the Court
with the ID of scotus
. To understand this data model better, see the case law API documentation.
To use date filters, supply dates in ISO-8601 format.
A final trick that can be used with the filters is the exclusion parameter. Any filter can be converted into an exclusion filter by prepending it with an exclamation mark. For example, this returns Dockets
from non-Federal Appellate jurisdictions:
- curl "{% get_full_host %}{% url "docket-list" version="v3" %}?court__jurisdiction!=F"
+ curl "{% get_full_host %}{% url "docket-list" version="v4" %}?court__jurisdiction!=F"
You can see more examples of filters in our automated tests.
@@ -319,7 +321,7 @@ Ordering
Descending order can be done using a minus sign. Multiple fields can be requested using a comma-separated list. This, for example, returns judicial Positions
ordered by the most recently modified, then by the most recently elected:
- curl "{% get_full_host %}{% url "position-list" version="v3" %}?order_by=-date_modified,-date_elected"
+ curl "{% get_full_host %}{% url "position-list" version="v4" %}?order_by=-date_modified,-date_elected"
Ordering by fields with duplicate values is non-deterministic. If you wish to order by such a field, you should provide a second field as a tie-breaker to consistently order results. For example, ordering by date_filed
will not return consistent ordering for items that have the same date, but this can be fixed by ordering by date_filed,id
. In that case, if two items have the same date_filed
value, the tie will be broken by the id
field.
@@ -329,14 +331,14 @@ Field Selection
For example, to only receive the educations
and date_modified
fields from the Judge
endpoint you could do so with:
- curl "{% get_full_host %}{% url "person-list" version="v3" %}?fields=educations,date_modified"
+ curl "{% get_full_host %}{% url "person-list" version="v4" %}?fields=educations,date_modified"
{
"educations": [
{
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/educations/12856/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/v4/educations/12856/",
"id": 12856,
"school": {
- "resource_uri": "https://www.courtlistener.com/api/rest/v3/schools/4240/",
+ "resource_uri": "https://www.courtlistener.com/api/rest/v4/schools/4240/",
"id": 4240,
"is_alias_of": null,
"date_created": "2010-06-07T17:00:00-07:00",
@@ -344,7 +346,7 @@ Field Selection
"name": "University of Maine",
"ein": 16000769
},
- "person": "https://www.courtlistener.com/api/rest/v3/people/16214/",
+ "person": "https://www.courtlistener.com/api/rest/v4/people/16214/",
"date_created": "2023-03-31T07:15:28.556198-07:00",
"date_modified": "2023-03-31T07:15:28.556222-07:00",
"degree_level": "jd",
@@ -360,6 +362,9 @@ Field Selection
Unfortunately, this cannot be used for nested resources, though there is an open issue tracking this.
+ Cursor-based Pagination
+ Search API crawls are no longer limited to 100 pages. Deep pagination of search results is now possible. Users cannot directly jump to a specific page. Look at and follow the next
and previous
parameters provided in each response. Navigation of the API is exclusively through those keys in each API response.
+
Rate Limits
Our APIs allow 5,000 queries per hour to authenticated users. Unauthenticated users are allowed 100 queries per day for experimentation.
@@ -380,14 +385,6 @@
Rate Limits
Performance Tips
A few things to consider that may increase your performance:
- -
-
When doing deep crawls of the data, going to very high page numbers will incur increasingly bad performance. This is common in databases because to go to a high page number means sorting the entire data set, then counting to the correct location. Page 50 isn't a big deal. Page 2,000 starts getting slower.
-
- The fix to this solution is often to work with "slices" of the data. Instead of paginating across the whole result set, use a date field or another range-type field to only paginate over a smaller set of the data. For example, you could slice a large result set by the month of the date filing field to prevent deep pagination.
-
- Be careful to slice using a field with a normal distribution. Do not use one like date_created
, which could have extreme spikes of activity.
-
-
-
Avoid doing queries like court__id=xyz
when you can instead do court=xyz
. Doing queries with the extra __id
introduces a join that can be expensive.
@@ -494,6 +491,7 @@ Visualization APIs
Available Jurisdictions
We currently have {{ court_count }} jurisdictions that can be accessed with our APIs. Details about the jurisdictions that are available, including all abbreviations, can be found here.
+
Upgrades and Fixes
Like the rest of the CourtListener platform, this API and its documentation are open source. If it lacks functionality that you desire or if you find this documentation lacking, pull requests providing improvements are encouraged. Just get in touch via our contact form to discuss your ideas. Or, if it's something quick, just go ahead and send us a pull request.
diff --git a/cl/api/templates/search-api-docs-v3.html b/cl/api/templates/search-api-docs-v3.html
new file mode 100644
index 0000000000..deee13ae9b
--- /dev/null
+++ b/cl/api/templates/search-api-docs-v3.html
@@ -0,0 +1,238 @@
+{% extends "base.html" %}
+{% load extras %}
+
+{% block title %}Legal Search API – CourtListener.com{% endblock %}
+{% block og_title %}Legal Search API – CourtListener.com{% endblock %}
+
+{% block description %}Use this API to search case law, federal filings and cases, judges, and oral argument audio files.{% endblock %}
+{% block og_description %}Use this API to search case law, federal filings and cases, judges, and oral argument audio files.{% endblock %}
+
+{% block sidebar %}{% endblock %}
+
+{% block footer-scripts %}
+ {% include "includes/anchors.html" %}
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+ Legal Search API
+ {% url "search-list" version="v3" %}
+ Use this API to search case law, PACER data, judges, and oral argument audio recordings.
+ To get the most out of this API, see our coverage and advanced operators documentation.
+
+
+ Basic Usage
+ This API uses the same GET parameters as the front end of the website. To use this API, place a search query on the front end of the website. That will give you a URL like:
+
+ {% get_full_host %}/q=foo
+ To make this into an API request, copy the GET parameters from this URL to the API endpoint, creating a request like:
+
+ curl -X GET \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ '{% get_full_host %}{% url "search-list" version="v3" %}?q=foo'
+ That returns:
+ {
+ "count": 2369,
+ "next": "https://www.courtlistener.com/api/rest/v3/search/?page=2&q=foo",
+ "previous": null,
+ "results": [
+ {
+ "absolute_url": "/opinion/106359/fong-foo-v-united-states/",
+ "attorney": "Arthur Richenthal argued the causes for petitioners and filed briefs for petitioner in No. 65. David E. Feller filed briefs for petitioners in No. 64., Solicitor General Cox argued the causes for the United States. With him on the briefs were Assistant Attorney General Miller, Stephen J. Poliak, Beatrice Rosenberg, Philip R. Monahan and J. F. Bishop.",
+ "author_id": null,
+ "caseName": "Fong Foo v. United States",
+ "caseNameShort": "Fong Foo",
+ "citation": [
+ "7 L. Ed. 2d 629",
+ "82 S. Ct. 671",
+ "369 U.S. 141",
+ "1962 U.S. LEXIS 1600"
+ ],
+ "citeCount": 357,
+ "cites": [
+ 94515,
+ 98794,
+ 100989,
+ 101974,
+ 106273,
+ 253004
+ ],
+ "cluster_id": 106359,
+ "court": "Supreme Court of the United States",
+ "court_citation_string": "SCOTUS",
+ "court_exact": "scotus",
+ "court_id": "scotus",
+ "dateArgued": null,
+ "dateFiled": "1962-03-19T00:00:00-08:00",
+ "dateReargued": null,
+ "dateReargumentDenied": null,
+ "docketNumber": "64",
+ "docket_id": 1153854,
+ "download_url": null,
+ "id": 106359,
+ "joined_by_ids": null,
+ "judge": "Harlan, Clark, Whittaker",
+ "lexisCite": "1962 U.S. LEXIS 1600",
+ "local_path": null,
+ "neutralCite": null,
+ "non_participating_judge_ids": null,
+ "pagerank": null,
+ "panel_ids": null,
+ "per_curiam": null,
+ "scdb_id": "1961-048",
+ "sibling_ids": [
+ 106359,
+ 9422362,
+ 9422363,
+ 9422364
+ ],
+ "snippet": "\n\n\n \n369 U.S. 141 (1962)\nFONG FOO ET AL.\nv.\nUNITED STATES.\nNo. 64.\nSupreme Court of United States.…Court of the United States\nscotus\nSCOTUS\n\n\n\n FONG FOO Et Al. v. UNITED STATES\n\n\nHarlan, Clark, Whittaker",
+ "source": "LRU",
+ "status": "Precedential",
+ "status_exact": "Precedential",
+ "suitNature": "",
+ "timestamp": "2024-03-01T14:12:07.892000-08:00",
+ "type": "010combined"
+ },
+ ...
+ That's the simple version. Read on to learn the rest.
+
+
+ Understanding the API
+ Unlike most APIs on CourtListener, this API is powered by our search engine, not our database.
+
+ This means that it does not use the same approach to ordering, filtering, or field definitions as our other APIs, and sending an HTTP OPTIONS
request won't be useful.
+
+
+ Setting the Result type
+ The most important parameter in this API is type
. This parameter sets the type of object you are querying:
+
+
+
+
+ Type
+ Definition
+
+
+
+
+ o
+ Case law opinions
+
+
+ r
+ Federal filing documents from PACER
+
+
+ d
+ Federal cases (dockets) from PACER
+
+
+ p
+ Judges
+
+
+ oa
+ Oral argument audio files
+
+
+
+ For example, this query searches case law:
+ {% get_full_host %}/q=foo&type=o
+ And this query searches federal filings in the PACER system:
+ {% get_full_host %}/q=foo&type=r
+ If the type
parameter is not provided, the default is to search case law.
+
+
+ Ordering Results
+ Each search type
can be sorted by certain fields. These are available on the front end in the ordering drop down, which sets the order_by
parameter.
+
+
+
+ Filtering Results
+ Results can be filtered with the input boxes provided on the front end or by advanced query operators provided to the q
parameter.
+
+ The best way to refine your query is to do so on the front end, and then copy the GET parameters to the API.
+
+
+
+ Fields
+ Unlike most of the fields on CourtListener, many fields on this API are provided in camelCase instead of snake_case. This is to make it easier for users to place queries like:
+
+ caseName:foo
+ Instead of:
+ case_name:foo
+ All available fields are listed on the advanced operators help page.
+
+ To understand the meaning of a field, find the object in our regular APIs that it corresponds to, and send an HTTP OPTIONS
request to the API.
+
+ For example, the docketNumber
field in the search engine corresponds to the docket_number
field in the docket
API, so an HTTP OPTIONS
request to that API returns its definition:
+
+ curl -X OPTIONS \
+ --header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
+ "{% get_full_host %}{% url "docket-list" version="v3" %}" \
+ | jq '.actions.POST.docket_number
+ After filtering through jq
, that returns:
+ {
+ "type": "string",
+ "required": false,
+ "read_only": false,
+ "label": "Docket number",
+ "help_text": "The docket numbers of a case, can be consolidated and quite long. In some instances they are too long to be indexed by postgres and we store the full docket in the correction field on the Opinion Cluster."
+}
+
+
+ Special Notes
+ A few fields deserve special consideration:
+
+ -
+
As in the front end, when the type
is set to return case law, only published results are returned by default. To include unpublished and other statuses, you need to explicitly request them.
+
+
+ -
+
The snippet
field contains the same values as are found on the front end. This uses the HTML5 <mark>
element to identify up to five matches in a document.
+
+ This field only responds to arguments provided to the q
parameter. If the q
parameter is not used, the snippet
field will show the first 500 characters of the text
field.
+
+
+
+
+
+ Monitoring a Query for New Results
+ To monitor queries for new results, use the Alert API, which will send emails or webhook events when there are new results.
+
+
+ {% include "includes/donate_footer_plea.html" %}
+
+{% endblock %}
diff --git a/cl/api/templates/search-api-docs-vlatest.html b/cl/api/templates/search-api-docs-vlatest.html
index deee13ae9b..4923378c89 100644
--- a/cl/api/templates/search-api-docs-vlatest.html
+++ b/cl/api/templates/search-api-docs-vlatest.html
@@ -17,7 +17,7 @@
@@ -26,7 +26,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -47,7 +47,7 @@ Table of Contents
Legal Search API
- {% url "search-list" version="v3" %}
+ {% url "search-list" version=version %}
Use this API to search case law, PACER data, judges, and oral argument audio recordings.
To get the most out of this API, see our coverage and advanced operators documentation.
@@ -60,71 +60,72 @@ Basic Usage
curl -X GET \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- '{% get_full_host %}{% url "search-list" version="v3" %}?q=foo'
+ '{% get_full_host %}{% url "search-list" version=version %}?q=foo'
That returns:
{
- "count": 2369,
- "next": "https://www.courtlistener.com/api/rest/v3/search/?page=2&q=foo",
- "previous": null,
- "results": [
- {
- "absolute_url": "/opinion/106359/fong-foo-v-united-states/",
- "attorney": "Arthur Richenthal argued the causes for petitioners and filed briefs for petitioner in No. 65. David E. Feller filed briefs for petitioners in No. 64., Solicitor General Cox argued the causes for the United States. With him on the briefs were Assistant Attorney General Miller, Stephen J. Poliak, Beatrice Rosenberg, Philip R. Monahan and J. F. Bishop.",
- "author_id": null,
- "caseName": "Fong Foo v. United States",
- "caseNameShort": "Fong Foo",
- "citation": [
- "7 L. Ed. 2d 629",
- "82 S. Ct. 671",
- "369 U.S. 141",
- "1962 U.S. LEXIS 1600"
- ],
- "citeCount": 357,
- "cites": [
- 94515,
- 98794,
- 100989,
- 101974,
- 106273,
- 253004
- ],
- "cluster_id": 106359,
- "court": "Supreme Court of the United States",
- "court_citation_string": "SCOTUS",
- "court_exact": "scotus",
- "court_id": "scotus",
- "dateArgued": null,
- "dateFiled": "1962-03-19T00:00:00-08:00",
- "dateReargued": null,
- "dateReargumentDenied": null,
- "docketNumber": "64",
- "docket_id": 1153854,
- "download_url": null,
- "id": 106359,
- "joined_by_ids": null,
- "judge": "Harlan, Clark, Whittaker",
- "lexisCite": "1962 U.S. LEXIS 1600",
- "local_path": null,
- "neutralCite": null,
- "non_participating_judge_ids": null,
- "pagerank": null,
- "panel_ids": null,
- "per_curiam": null,
- "scdb_id": "1961-048",
- "sibling_ids": [
- 106359,
- 9422362,
- 9422363,
- 9422364
- ],
- "snippet": "\n\n\n \n369 U.S. 141 (1962)\nFONG FOO ET AL.\nv.\nUNITED STATES.\nNo. 64.\nSupreme Court of United States.…Court of the United States\nscotus\nSCOTUS\n\n\n\n FONG FOO Et Al. v. UNITED STATES\n\n\nHarlan, Clark, Whittaker",
- "source": "LRU",
- "status": "Precedential",
- "status_exact": "Precedential",
- "suitNature": "",
- "timestamp": "2024-03-01T14:12:07.892000-08:00",
- "type": "010combined"
- },
+ "count": 2343,
+ "next": "https://www.courtlistener.com/api/rest/v4/search/?cursor=cz0yMzUuODcxMjUmcz04MDUzNTUzJnQ9byZkPTIwMjQtMDktMTY%3D&q=foo",
+ "previous": null,
+ "results": [
+ {
+ "absolute_url": "/opinion/6613686/foo-v-foo/",
+ "attorney": "",
+ "caseName": "Foo v. Foo",
+ "caseNameFull": "Foo v. Foo",
+ "citation": [
+ "101 Haw. 235",
+ "65 P.3d 182"
+ ],
+ "citeCount": 0,
+ "cluster_id": 6613686,
+ "court": "Hawaii Intermediate Court of Appeals",
+ "court_citation_string": "Haw. App.",
+ "court_id": "hawapp",
+ "dateArgued": null,
+ "dateFiled": "2003-01-10",
+ "dateReargued": null,
+ "dateReargumentDenied": null,
+ "docketNumber": "24158",
+ "docket_id": 63544014,
+ "judge": "",
+ "lexisCite": "",
+ "meta": {
+ "timestamp": "2024-06-22T10:26:35.320787Z",
+ "date_created": "2022-06-26T23:24:18.926040Z"
+ },
+ "neutralCite": "",
+ "non_participating_judge_ids": [],
+ "opinions": [
+ {
+ "author_id": null,
+ "cites": [],
+ "download_url": null,
+ "id": 6489975,
+ "joined_by_ids": [],
+ "local_path": null,
+ "meta": {
+ "timestamp": "2024-06-24T21:14:41.408206Z",
+ "date_created": "2022-06-26T23:24:18.931912Z"
+ },
+ "per_curiam": false,
+ "sha1": "",
+ "snippet": "\nAffirmed in part, reversed in part, vacated and remanded\n",
+ "type": "lead-opinion"
+ }
+ ],
+ "panel_ids": [],
+ "panel_names": [],
+ "posture": "",
+ "procedural_history": "",
+ "scdb_id": "",
+ "sibling_ids": [
+ 6489975
+ ],
+ "source": "U",
+ "status": "Published",
+ "suitNature": "",
+ "syllabus": ""
+ },
...
That's the simple version. Read on to learn the rest.
@@ -152,6 +153,10 @@ Setting the Result type
r
+ List of Federal cases (dockets) with up to three nested documents. If there are more than three matching documents, the more_docs
field for the docket result will be true.
+
+
+ rd
Federal filing documents from PACER
@@ -178,6 +183,8 @@ Setting the Result type
Ordering Results
Each search type
can be sorted by certain fields. These are available on the front end in the ordering drop down, which sets the order_by
parameter.
+ If your sorting field has null values, those results will be sorted at the end of the query, regardless of whether you sort in ascending or descending order. For example if you sort by a date that is null for an opinion, that opinion will go at the end of the result set.
+
Filtering Results
@@ -201,7 +208,7 @@ Fields
curl -X OPTIONS \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "docket-list" version="v3" %}" \
+ "{% get_full_host %}{% url "docket-list" version=version %}" \
| jq '.actions.POST.docket_number
After filtering through jq
, that returns:
{
@@ -225,7 +232,19 @@ Special Notes
This field only responds to arguments provided to the q
parameter. If the q
parameter is not used, the snippet
field will show the first 500 characters of the text
field.
+ This field only displays Opinion text content.
+
+
-
+
To enhance performance, results are not highlighted by default. To enable highlighting, include highlight=on
in your request.
+
+ When highlighting is disabled, the first 500 characters of snippet fields are returned for fields o
, r
, and rd
.
+
+
+ -
+
type=d
and type=r
use cardinality aggregation to compute the result count, which has an error of ±6% if results are over 2000.
+
+
diff --git a/cl/api/templates/visualizations-api-docs-vlatest.html b/cl/api/templates/visualizations-api-docs-vlatest.html
index 5e7f8fe0a4..6fa134ee68 100644
--- a/cl/api/templates/visualizations-api-docs-vlatest.html
+++ b/cl/api/templates/visualizations-api-docs-vlatest.html
@@ -19,7 +19,7 @@
@@ -28,7 +28,7 @@
- Back to API Docs
+ Back to API Docs
Table of Contents
@@ -42,7 +42,7 @@ Table of Contents
Supreme Court Visualization API
- {% url "scotusmap-list" version="v3" %}
+ {% url "scotusmap-list" version=version %}
Use this API to programmatically see and create visualizations of Supreme Court networks in CourtListener.
All visualizations are associated with a user and are private by default. When you GET these endpoints, you will see data for visualizations that have been made public by their owners or that you have created yourself.
@@ -52,11 +52,11 @@
{% url "scotusmap-list" version="v3" %}
Creating Visualizations
To create a new visualization, send an HTTP POST
with a title, a starting cluster ID, and an ending cluster ID:
curl -X POST \
- --data 'cluster_start=/api/rest/v3/clusters/105659/' \
- --data 'cluster_end=/api/rest/v3/clusters/111891/' \
+ --data 'cluster_start=/api/rest/{{ version }}/clusters/105659/' \
+ --data 'cluster_end=/api/rest/{{ version }}/clusters/111891/' \
--data 'title=A map from Trop to Salerno' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "scotusmap-list" version="v3" %}"
+ "{% get_full_host %}{% url "scotusmap-list" version=version %}"
The cluster_start
and cluster_end
parameters use URLs instead of IDs.
The above command creates a visualization unless there are no connections between the start and end clusters or the network becomes too large to generate.
@@ -68,7 +68,7 @@ Editing and Deleting Visualizations
curl -X PATCH \
--data 'published=True' \
--header 'Authorization: Token {% if user.is_authenticated %}{{ user.auth_token }}{% else %}<your-token-here>{% endif %}' \
- "{% get_full_host %}{% url "scotusmap-detail" version="v3" pk="1" %}"
+ "{% get_full_host %}{% url "scotusmap-detail" version=version pk="1" %}"
Similar commands can be used to update other non-readonly fields.
To soft-delete a visualization, flip the deleted
field to True
. To hard-delete, send an HTTP DELETE
request.
diff --git a/cl/api/urls.py b/cl/api/urls.py
index 7413a287b4..68066fc79a 100644
--- a/cl/api/urls.py
+++ b/cl/api/urls.py
@@ -194,98 +194,98 @@
path("help/api/", views.api_index, name="api_index"),
path("help/api/jurisdictions/", views.court_index, name="court_index"),
re_path(
- r"^help/api/rest/(?Pv[123])?/?$",
+ r"^help/api/rest/(?Pv[1234])?/?$",
views.rest_docs,
name="rest_docs",
),
- path(
- "help/api/rest/v3/citation-lookup/",
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?citation-lookup/$",
views.citation_lookup_api,
name="citation_lookup_api",
),
- path(
- "help/api/rest/v3/case-law/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?case-law/$",
+ views.VersionedTemplateView.as_view(
template_name="case-law-api-docs-vlatest.html",
extra_context={"private": False},
),
name="case_law_api_help",
),
- path(
- "help/api/rest/v3/citations/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?citations/$",
+ views.VersionedTemplateView.as_view(
template_name="citation-api-docs-vlatest.html",
extra_context={"private": False},
),
name="citation_api_help",
),
- path(
- "help/api/rest/v3/pacer/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?pacer/$",
+ views.VersionedTemplateView.as_view(
template_name="pacer-api-docs-vlatest.html",
extra_context={"private": False},
),
name="pacer_api_help",
),
- path(
- "help/api/rest/v3/recap/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?recap/$",
+ views.VersionedTemplateView.as_view(
template_name="recap-api-docs-vlatest.html",
extra_context={"private": False},
),
name="recap_api_help",
),
- path(
- "help/api/rest/v3/judges/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?judges/$",
+ views.VersionedTemplateView.as_view(
template_name="judge-api-docs-vlatest.html",
extra_context={"private": False},
),
name="judge_api_help",
),
- path(
- "help/api/rest/v3/oral-arguments/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?oral-arguments/$",
+ views.VersionedTemplateView.as_view(
template_name="oral-argument-api-docs-vlatest.html",
extra_context={"private": False},
),
name="oral_argument_api_help",
),
- path(
- "help/api/rest/v3/visualizations/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?visualizations/$",
+ views.VersionedTemplateView.as_view(
template_name="visualizations-api-docs-vlatest.html",
extra_context={"private": False},
),
name="visualization_api_help",
),
- path(
- "help/api/rest/v3/financial-disclosures/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?financial-disclosures/$",
+ views.VersionedTemplateView.as_view(
template_name="financial-disclosure-api-docs-vlatest.html",
extra_context={"private": False},
),
name="financial_disclosures_api_help",
),
- path(
- "help/api/rest/v3/search/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?search/$",
+ views.VersionedTemplateView.as_view(
template_name="search-api-docs-vlatest.html",
extra_context={"private": False},
),
name="search_api_help",
),
- path(
- "help/api/rest/v3/alerts/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?alerts/$",
+ views.VersionedTemplateView.as_view(
template_name="alert-api-docs-vlatest.html",
extra_context={"private": False},
),
name="alert_api_help",
),
- path(
- "help/api/rest/v3/fields/",
- TemplateView.as_view(
+ re_path(
+ r"^help/api/rest/(?:(?Pv[34])/)?fields/$",
+ views.VersionedTemplateView.as_view(
template_name="field-help.html",
extra_context={"private": True},
),
@@ -367,4 +367,13 @@
"api/replication/",
RedirectView.as_view(pattern_name="replication_docs", permanent=True),
),
+ # V4 Migration guide
+ path(
+ "help/api/v4/migration-guide/",
+ TemplateView.as_view(
+ template_name="migration-guide.html",
+ extra_context={"private": False},
+ ),
+ name="migration_guide",
+ ),
]
diff --git a/cl/api/views.py b/cl/api/views.py
index 86941007b0..69e781a08e 100644
--- a/cl/api/views.py
+++ b/cl/api/views.py
@@ -10,6 +10,7 @@
from django.shortcuts import aget_object_or_404 # type: ignore[attr-defined]
from django.template.response import TemplateResponse
from django.views.decorators.cache import cache_page
+from django.views.generic import TemplateView
from requests import Session
from cl.lib.elasticsearch_utils import do_es_alert_estimation_query
@@ -128,7 +129,10 @@ def parse_throttle_rate_for_template(rate: str) -> tuple[int, str] | None:
return int(num), duration_as_str[period[0]]
-async def citation_lookup_api(request: HttpRequest) -> HttpResponse:
+async def citation_lookup_api(
+ request: HttpRequest, version=None
+) -> HttpResponse:
+
cite_count = await Citation.objects.acount()
rate = settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["citations"] # type: ignore
default_throttle_rate = parse_throttle_rate_for_template(rate)
@@ -141,13 +145,17 @@ async def citation_lookup_api(request: HttpRequest) -> HttpResponse:
return TemplateResponse(
request,
- "citation-lookup-api.html",
+ [
+ f"citation-lookup-api-{version}.html",
+ "citation-lookup-api-vlatest.html",
+ ],
{
"cite_count": cite_count,
"default_throttle_rate": default_throttle_rate,
"custom_throttle_rate": custom_throttle_rate,
"max_citation_per_request": settings.MAX_CITATIONS_PER_REQUEST, # type: ignore
"private": False,
+ "version": version if version else "v4",
},
)
@@ -343,3 +351,19 @@ async def webhooks_docs(request, version=None):
[f"webhooks-docs-{version}.html", "webhooks-docs-vlatest.html"],
context,
)
+
+
+class VersionedTemplateView(TemplateView):
+ """Custom template view to handle the right template based on the path
+ version requested.
+ """
+
+ def get_template_names(self):
+ version = self.kwargs.get("version", "vlatest")
+ base_template = self.template_name.replace("-vlatest", f"-{version}")
+ return [base_template, self.template_name]
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["version"] = self.kwargs.get("version", "v4")
+ return context
@@ -27,7 +27,7 @@
@@ -26,7 +26,7 @@