Skip to main content

Resolve, verify, format and audit scholarly citations — a thin Python client for the Scholar Sidekick API.

Project description

scholar-sidekick

Resolve, verify, format and audit scholarly citations from Python.

A thin client for the Scholar Sidekick REST API — citation formatting in 10,000+ CSL styles, bibliography export, retraction and open-access checks, and verification that a citation is real rather than fabricated.

pip install scholar-sidekick

Quick start

from scholar_sidekick import ScholarSidekick

client = ScholarSidekick()

# Format an identifier
print(client.format(text="10.1038/nphys1170", style="vancouver").text)

# Export a bibliography
print(client.export(text="10.1038/nphys1170", format="bibtex"))

Verifying citations

The dominant AI-fabrication pattern is a real, resolvable DOI paired with an invented title. Such citations resolve cleanly under doi.org, so "follow the link and see if it loads" does not catch them. Comparing the claimed title against the resolved record does.

result = client.verify(
    title="Quantum entanglement in biological systems",
    doi="10.1038/nphys1170",
)

print(result.verdict)  # matched | mismatch | ambiguous | not_found
print(result.confidence)  # high | medium | low

A mismatch is returned as a value, never raised as an exception — it is the expected outcome for a fabricated citation, and the reason this method exists.

Interpreting verdicts

verdict meaning
matched the claimed citation agrees with the resolved record
mismatch the identifier resolves to a different work — likely fabrication
ambiguous a discrepancy that needs human eyes, not an accusation
not_found no record found in the registries searched

not_found is not proof of fabrication. Standards documents, software repositories, model cards and institutional reports are frequently real but absent from the scholarly registries the API searches. Treat it as "could not confirm", not "invented".

Auditing a whole bibliography

The API audits up to 25 references per call and rate-limits those calls. audit_bibliography() handles both for you: it chunks, paces itself from the server's rate-limit headers, and sends chunks serially — the server already fans out internally, so parallelising here would compete with it for the same upstream budget.

report = client.audit_bibliography(
    references, progress=lambda done, total: print(f"{done}/{total}")
)

print(report.summary)  # verdict counts across every chunk
print(len(report.needs_review))  # entries a human should look at

for entry in report.needs_review:
    print(entry.input_index, entry.verdict, entry.title)

entry.input_index is the 0-based position in the list you passed in, so it always points at the right reference regardless of how the work was chunked.

A chunk that fails is recorded rather than raised, so one transient upstream error does not discard several minutes of completed work:

if not report.complete:
    for failure in report.errors:
        print(f"entries {failure.start_index}-{failure.end_index} failed: {failure.error}")

With pandas installed (pip install 'scholar-sidekick[pandas]'):

df = report.to_dataframe()
df[df.verdict != "matched"]

There is a runnable end-to-end example in examples/systematic_review_audit.ipynb.

Authentication

Every endpoint works anonymously — no key, no signup. An API key raises the rate limit (about fivefold on the free tier) but is never required.

client = ScholarSidekick(api_key="ssk_…")

Or set SCHOLAR_SIDEKICK_API_KEY in the environment. Precedence is the explicit argument, then the environment variable, then anonymous. Free keys are issued at scholar-sidekick.com/account.

Async

Every method has an async equivalent:

from scholar_sidekick import AsyncScholarSidekick

async with AsyncScholarSidekick() as client:
    result = await client.verify(title="…", doi="10.1038/nphys1170")

Note that audit_bibliography() still issues its chunks serially in the async client — the constraint is the server's upstream budget, not this client's concurrency.

Errors

Exceptions are selected by the API's stable error code, not by HTTP status (the contract guarantees the code; statuses may change).

from scholar_sidekick import APIError, RateLimitError, UpstreamError

try:
    client.format(text="10.1038/nphys1170")
except RateLimitError as exc:
    print("retry after", exc.retry_after)
except UpstreamError as exc:
    print("a data source failed:", exc.code)
except APIError as exc:
    print(exc.code, exc.message, exc.request_id)
exception when
ValidationError the request was malformed or invalid
AuthError authentication or entitlement was refused
RateLimitError rate limit exceeded; carries .retry_after
UpstreamError a scholarly data source failed after the API's own retries
TransportError connection failure or timeout; no HTTP response

Every APIError carries .request_id — include it in bug reports.

API surface

method purpose
format() resolve identifiers and format them
format_items() format already-resolved CSL-JSON items
export() export to RIS, BibTeX, CSV, EndNote XML, …
verify() check one citation against the resolved record
audit() audit up to 25 references in one call
audit_bibliography() audit any number, chunked and paced
health() service liveness

format() returns whole-batch text/html strings covering every input, newline-joined — the API has no per-item formatted field, and this client does not invent one by splitting that string. format_items() names the same concept output. The difference is preserved deliberately rather than papered over.

Related

Development

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,pandas]"
pytest --cov

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scholar_sidekick-0.1.0.tar.gz (44.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scholar_sidekick-0.1.0-py3-none-any.whl (24.0 kB view details)

Uploaded Python 3

File details

Details for the file scholar_sidekick-0.1.0.tar.gz.

File metadata

  • Download URL: scholar_sidekick-0.1.0.tar.gz
  • Upload date:
  • Size: 44.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for scholar_sidekick-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f205942c7ad647bf859b1cd1121a5e6fd0d40e46ad0b14baae5e7936c8fd811f
MD5 b94dc1f360b1384cd0269889d647dad5
BLAKE2b-256 31899cd28ad25556c75715a84fdbf0666b928ed449fa1a0e6783b3a056380613

See more details on using hashes here.

Provenance

The following attestation bundles were made for scholar_sidekick-0.1.0.tar.gz:

Publisher: publish.yml on mlava/scholar-sidekick-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scholar_sidekick-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for scholar_sidekick-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58f6d552d934faabb790e2f504288d8d6cdf23ca57b057d2cfca447eecf58f98
MD5 2092b3c895cd1f71fc6cb8f725b0a2e2
BLAKE2b-256 458dadb1bd5ac733aa4b74bd1ba05a833de29823274fe9661bc13533010b118b

See more details on using hashes here.

Provenance

The following attestation bundles were made for scholar_sidekick-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mlava/scholar-sidekick-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page