Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
name: ci
name: Deploy Jupyter Book to GitHub Pages
on:
push:
branches:
- main
branches: [main]
env:
BASE_URL: /${{ github.event.repository.name }}

permissions:
contents: write
contents: read
pages: write
id-token: write

concurrency:
group: 'pages'
cancel-in-progress: false

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

- name: Setup Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b

- name: Install dependencies
run: uv sync

- name: Build HTML Assets
run: uv run jupyter-book build --html --execute

- name: Upload artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9
with:
key: mkdocs-material-${{ env.cache_id }}
path: ~/.cache
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: mkdocs gh-deploy --force
path: './_build/html'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ var/
.installed.cfg
*.egg
.DS_Store

# MyST build outputs
_build
188 changes: 112 additions & 76 deletions docs/api/quickstart.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Quick start

!!! tip "Time estimate: 5 minutes"
This tutorial walks you through your first requests to the OpenCitations API. You'll start by counting citations for a paper, then retrieve the full citation data, and finally look up bibliographic metadata.
:::{admonition} Time estimate: 5 minutes
:class: tip
This tutorial walks you through your first requests to the OpenCitations API. You'll start by counting citations for a paper, then retrieve the full citation data, and finally look up bibliographic metadata.

No account, no API key, no setup required.
No account, no API key, no setup required.
:::

## What is the OpenCitations API?

Expand Down Expand Up @@ -56,56 +58,72 @@ You just made your first API call. You opened a URL, and OpenCitations responded

Now let's do the same thing from the command line and from Python, which is how you'll use the API in practice:

=== "curl"
::::{tab-set}
:sync-group: code

```bash
curl 'https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023'
```

=== "Python"

```python
import requests
:::{tab-item} curl
:sync: curl
```bash
curl 'https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023'
```
:::

:::{tab-item} Python
:sync: python
```python
import requests

response = requests.get(
"https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023"
)
result = response.json()
print(result)
```
:::

response = requests.get(
"https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023"
)
result = response.json()
print(result)
```
::::

| Field | Meaning |
|-------|---------|
| `count` | Number of works that cite the queried paper |

!!! note "Try it yourself"
Replace the DOI in the URL with any DOI you care about. The pattern is always `/index/v2/citation-count/doi:<your-doi>`.
:::{admonition} Try it yourself
:class: note
Replace the DOI in the URL with any DOI you care about. The pattern is always `/index/v2/citation-count/doi:<your-doi>`.

The endpoint also accepts `pmid:` and `omid:` prefixes.
The endpoint also accepts `pmid:` and `omid:` prefixes.
:::

## Step 2: Get the full list of citations

A count is useful, but often you need to know *which* works cited the paper. The `citations` endpoint returns the complete list with details about each citation.

=== "curl"
::::{tab-set}
:sync-group: code

```bash
curl 'https://api.opencitations.net/index/v2/citations/doi:10.1162/qss_a_00023'
```

=== "Python"

```python
response = requests.get(
"https://api.opencitations.net/index/v2/citations/doi:10.1162/qss_a_00023"
)
citations = response.json()
:::{tab-item} curl
:sync: curl
```bash
curl 'https://api.opencitations.net/index/v2/citations/doi:10.1162/qss_a_00023'
```
:::

:::{tab-item} Python
:sync: python
```python
response = requests.get(
"https://api.opencitations.net/index/v2/citations/doi:10.1162/qss_a_00023"
)
citations = response.json()

for cit in citations[:3]:
print(f"Cited by: {cit['citing']}")
print(f" Date: {cit['creation']}")
print()
```
:::

for cit in citations[:3]:
print(f"Cited by: {cit['citing']}")
print(f" Date: {cit['creation']}")
print()
```
::::

The response is a JSON array. Each element is one citation:

Expand Down Expand Up @@ -133,32 +151,41 @@ The response is a JSON array. Each element is one citation:

The `citing` and `cited` fields contain multiple identifiers separated by spaces. OpenCitations stores all the known IDs for a given work: its internal OMID, the DOI, the OpenAlex ID, etc.

!!! info "What is an OCI?"
The **Open Citation Identifier** (OCI) is a persistent identifier that OpenCitations assigns to each citation. It is composed of two numbers separated by a dash: the first refers to the citing work, the second to the cited work. More details in [What are OCIs](concepts/oci.md).
:::{admonition} What is an OCI?
:class: info
The **Open Citation Identifier** (OCI) is a persistent identifier that OpenCitations assigns to each citation. It is composed of two numbers separated by a dash: the first refers to the citing work, the second to the cited work. More details in [What are OCIs](concepts/oci.md).
:::

## Step 3: Retrieve bibliographic metadata

The Index API tells you *who cites whom*, but not the titles or authors. That information lives in the **Meta API**.

=== "curl"
::::{tab-set}
:sync-group: code

```bash
curl 'https://api.opencitations.net/meta/v1/metadata/doi:10.1162/qss_a_00023'
```

=== "Python"

```python
response = requests.get(
"https://api.opencitations.net/meta/v1/metadata/doi:10.1162/qss_a_00023"
)
metadata = response.json()[0]
:::{tab-item} curl
:sync: curl
```bash
curl 'https://api.opencitations.net/meta/v1/metadata/doi:10.1162/qss_a_00023'
```
:::

:::{tab-item} Python
:sync: python
```python
response = requests.get(
"https://api.opencitations.net/meta/v1/metadata/doi:10.1162/qss_a_00023"
)
metadata = response.json()[0]

print(f"Title: {metadata['title']}")
print(f"Authors: {metadata['author']}")
print(f"Published: {metadata['pub_date']}")
print(f"Venue: {metadata['venue']}")
```
:::

print(f"Title: {metadata['title']}")
print(f"Authors: {metadata['author']}")
print(f"Published: {metadata['pub_date']}")
print(f"Venue: {metadata['venue']}")
```
::::

Response:

Expand Down Expand Up @@ -216,27 +243,36 @@ To get started:
2. Get your token
3. Include it in your requests:

=== "curl"
::::{tab-set}
:sync-group: code

```bash
curl -H 'Authorization: YOUR-OPENCITATIONS-ACCESS-TOKEN' \
'https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023'
```

=== "Python"

```python
session = requests.Session()
session.headers["Authorization"] = "YOUR-OPENCITATIONS-ACCESS-TOKEN"
:::{tab-item} curl
:sync: curl
```bash
curl -H 'Authorization: YOUR-OPENCITATIONS-ACCESS-TOKEN' \
'https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023'
```
:::

:::{tab-item} Python
:sync: python
```python
session = requests.Session()
session.headers["Authorization"] = "YOUR-OPENCITATIONS-ACCESS-TOKEN"

# Use session instead of requests for all your calls
result = session.get(
"https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023"
).json()
```
:::

# Use session instead of requests for all your calls
result = session.get(
"https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023"
).json()
```
::::

!!! warning "Rate limits"
API calls are rate-limited to **180 requests per minute** per IP address. This limit exists to guarantee fair access to the service for everyone, regardless of who they are or where they come from. For large-scale data retrieval, use the [database dumps](https://download.opencitations.net/) instead.
:::{admonition} Rate limits
:class: warning
API calls are rate-limited to **180 requests per minute** per IP address. This limit exists to guarantee fair access to the service for everyone, regardless of who they are or where they come from. For large-scale data retrieval, use the [database dumps](https://download.opencitations.net/) instead.
:::

## What you've learned

Expand All @@ -251,4 +287,4 @@ At this point you know how to:
## Next steps

- [**Index API v2 full documentation**](https://api.opencitations.net/index/v2): all available operations, parameters, and examples
- [**Meta API v1 full documentation**](https://api.opencitations.net/meta/v1): all metadata operations, including search by author and editor
- [**Meta API v1 full documentation**](https://api.opencitations.net/meta/v1): all metadata operations, including search by author and editor
26 changes: 21 additions & 5 deletions docs/api/use-cases.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
kernelspec:
name: python3
display_name: Python 3
---
# Use cases

Two practical examples of what you can build with the OpenCitations API.
Expand All @@ -15,7 +20,8 @@ INPUT_FILE = "list_of_papers.txt" # one DOI per line
OUTPUT_FILE = "citation_counts.csv"
API_BASE = "https://api.opencitations.net/index/v2/citation-count/doi:"

# Optional: use an access token for better tracking
# Optional: include your access token to help OpenCitations
# monitor anonymous usage of its services
# https://opencitations.net/accesstoken
TOKEN = None

Expand Down Expand Up @@ -78,8 +84,10 @@ doi,citation_count
...
```

!!! warning "Rate limits and large datasets"
At 180 requests per minute, processing 5000 DOIs takes about 28 minutes. If you need citation data for tens of thousands of papers, consider using the [database dumps](https://download.opencitations.net/) instead.
:::{admonition} Rate limits and large datasets
:class: warning
At 180 requests per minute, processing 5000 DOIs takes about 28 minutes. If you need citation data for tens of thousands of papers, consider using the [database dumps](https://download.opencitations.net/) instead.
:::

## 2. Live citation counts on your website

Expand All @@ -101,6 +109,14 @@ Add this snippet wherever you want the count to appear, and replace the DOI with
</script>
```

The visitor will see:
Here is the same call executed with Python to show the real result:

> **101** citations
```{code-cell} python
import requests

response = requests.get(
"https://api.opencitations.net/index/v2/citation-count/doi:10.1162/qss_a_00023"
)
data = response.json()
print(f'Results: {data[0]["count"]} citations')
```
Binary file added docs/assets/oc_logo_small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading