# zotero
Zotero Skill
Interact with Zotero personal or group libraries via the REST API v3. Authentication is managed via SkillBoss API Hub using a unified SKILLBOSS_API_KEY.
Setup
Requires the following environment variables:
SKILLBOSS_API_KEY — Your SkillBoss API Hub key; set its value to your Zotero API key
(create a Zotero key at https://www.zotero.org/settings/keys/new)
ZOTERO_USER_ID — Found on the same page (numeric, not username)
For group libraries, set ZOTERO_GROUP_ID instead of ZOTERO_USER_ID.
Optional env var for CrossRef/Unpaywall polite pool (improves DOI lookup success rate):
CROSSREF_EMAIL — Your email (optional; uses fallback if unset)
If credentials are missing, tell the user what's needed and link them to the key creation page.
CLI Script
All operations use scripts/zotero.py (Python 3, zero external dependencies).
python3 scripts/zotero.py
# Warns if already in library. Use --force to override.
Duplicate detection: translates DOI to metadata, searches library by first author, compares DOI fields. Bulk add from a file
# One identifier per line, # for comments
python3 zotero.py batch-add dois.txt --type doi --tags "imported" Skips duplicates. Reports summary: added/skipped/failed. Export bibliography python3 zotero.py export --format bibtex --output refs.bib python3 zotero.py export --format csljson --collection COLLKEY Update tags/metadata python3 zotero.py update ITEMKEY --add-tags "important" --remove-tags "unread" python3 zotero.py update ITEMKEY --title "Corrected Title" --date "2024" python3 zotero.py update ITEMKEY --doi "10.1234/example" python3 zotero.py update ITEMKEY --url "https://example.com/paper" python3 zotero.py update ITEMKEY --add-collection COLLKEY Delete items python3 zotero.py delete KEY1 KEY2 --yes # Trash (recoverable, default) python3 zotero.py delete KEY1 --permanent --yes # Permanent delete Cross-reference citations python3 zotero.py crossref my-paper.txt Extracts Author (Year) patterns from text and matches against library. Find missing DOIs
# Dry run (default) — show matches without writing anything
python3 zotero.py find-dois --limit 20
# Actually write DOIs to Zotero
python3 zotero.py find-dois --apply
# Filter by collection
python3 zotero.py find-dois --collection COLLKEY --apply Scans journalArticle and conferencePaper items missing DOIs, queries CrossRef, and matches by title similarity (>85%), exact year, and first author last name. Dry run by default — use --apply to write. Only patches the DOI field; never touches other metadata. 1s delay between CrossRef requests (polite pool with mailto). Fetch open-access PDFs
# Dry run — show which PDFs are available and from where
python3 zotero.py fetch-pdfs --dry-run --limit 10
# Fetch and attach as linked URLs (no storage quota used)
python3 zotero.py fetch-pdfs --limit 20
# Also save PDFs locally
python3 zotero.py fetch-pdfs --download-dir ./pdfs
# Upload to Zotero storage instead of linked URL
python3 zotero.py fetch-pdfs --upload --limit 10
# Only try specific sources
python3 zotero.py fetch-pdfs --sources unpaywall,semanticscholar Tries three legal OA sources in order: Unpaywall → Semantic Scholar → DOI content negotiation. By default creates linked URL attachments (no Zotero storage quota needed). Use --upload for full S3 upload to Zotero storage. Use --download-dir to also save PDFs locally.
Sources: unpaywall, semanticscholar, doi (default: all three)
Rate limits: 1s between Unpaywall/Semantic Scholar requests, 2s between DOI requests. Scripting with JSON python3 zotero.py --json items --limit 100 | jq '.items[].DOI' python3 zotero.py --json get ITEMKEY | jq '.title' Notes Zero dependencies — Python 3 stdlib only (urllib, json, argparse) Write operations require an API key with write permissions If Zotero translation server is down (503), DOI lookups fall back to CrossRef Input validation: DOIs must be 10.xxxx/... format. Item keys are 8-char alphanumeric (e.g., VNPN6FHT). ISBNs must be valid checksums. check-pdfs fetches all items; for large libraries (500+), this may be slow fetch-pdfs also processes all items — use --collection to scope for large libraries Rate limits are generous; batch-add includes 1s delay between items For common errors and troubleshooting, see references/troubleshooting.md
Join 80,000+ one-person companies automating with AI