Privacy policy¶
Last updated: 2026-09-20
papio runs on your computer. It has no hosted service, user account, telemetry, or analytics. This policy covers the papio application (daemon and CLI) and the papio browser extension.
Summary¶
papio does not collect your data or send it to OrgMentem.
The extension communicates with the local papio application through the browser's native-messaging interface. It does not contact OrgMentem or any other external service on its own, except when it asks a provider page to turn a link into a PDF URL.
The local application does contact third-party scholarly services to find papers. These requests include the identifier you ask papio to resolve, such as a DOI, PMID, arXiv ID, or title. Some services also receive your configured email address or API credentials. The table below lists every destination and the data it receives.
If you configure the optional agent acquisition backend, the daemon also sends a limited article observation to TypeSafe as described below.
Requests to third-party services¶
Every destination below is contacted directly by the daemon on your computer. Most requests carry the identifier being looked up; the retraction-check fetch downloads a shared dataset instead and carries no library identifiers. The “Data sent besides the lookup” column lists anything else sent.
| Service | Data sent besides the lookup | Used for | Default |
|---|---|---|---|
api.typesafe.ai |
your TypeSafe key; article DOI, bounded article title, sanitized visible control labels/roles/disabled states, opaque IDs and observation revision | Optional agent acquisition decisions | Off — requires explicit papio config agent set enrollment or PAPIO_TYPESAFE_API_KEY in the daemon environment |
api.unpaywall.org |
your email (required by their terms) |
Resolving a DOI | On |
api.crossref.org |
your email, if set |
Adding metadata to a title-only request; checking a DOI's registered version relations when other candidates are exhausted | On |
api.labs.crossref.org |
your email, if configured |
Daily retraction checks for papers papio acquired (and your wider library when retraction.scope = "library") |
On |
www.ebi.ac.uk (Europe PMC) |
— | Resolving a DOI, PMID, or title | On |
export.arxiv.org |
— | Resolving an arXiv ID or DOI, and papio search when configured |
On |
doi.org |
your email, in the User-Agent |
Confirming that a DOI exists before an institutional handoff | On |
Your institution's configured delivery API (document_delivery.base_url — ILLiad in v1) |
your api_key, patron_ref, and the request's bibliographic identifiers |
Submitting or polling one of your document-delivery requests | Off — requires configuration |
api.openalex.org |
your email, your API key |
papio search and watches (the default discovery backend) |
On |
api.openalex.org |
your email, your API key |
Resolving | On (disable with [sources.openalex] enabled = false) |
api.core.ac.uk |
your API key | Resolving | Off |
api.crossref.org (TDM) |
your subscriber token | Resolving | Off |
api.semanticscholar.org |
your API key, if set | Resolving a DOI, arXiv ID, or PMID, and papio search when configured |
On |
api.openaire.eu |
your personal access token, or the access token exchanged from your client credentials, if set | Resolving | On |
aai.openaire.eu |
your OpenAIRE client_id and client_secret (HTTP Basic), sent only to this token endpoint |
Exchanging them for a short-lived access token that api.openaire.eu then receives |
Off — active only when an openaire_client credential (papio config credentials set sources.openaire) is configured |
iris.who.int, and any host you list in open_books.dspace_servers |
the ISBN; your email, in the User-Agent |
Resolving a request whose only identifier is an ISBN | On (iris.who.int only) |
library.oapen.org |
the ISBN; your email, in the User-Agent |
Resolving a request whose only identifier is an ISBN | Off; open_books.oapen = true enables it |
| Publisher and repository hosts | — | Downloading the PDF | On |
api.github.com |
nothing | Once a day, checking for a new papio or zotio release | On if you ran papio init (it enables updates.check unless you decline or pass --check-updates=false); the config key itself defaults to false. updates.check = false disables it |
raw.githubusercontent.com |
nothing | Once a day, fetching the signed adapter control file that can suspend a broken browser adapter | Follows updates.check, and only in a build that embeds the papio control key. updates.check = false disables it |
| Your webhook URL | job event and message | Job state changes | Off |
Important details¶
Email address. The email setting is sent to services that require or accept
it. Unpaywall and OpenAlex require an email address. Crossref metadata, Retraction Watch, and DOI lookup use it
when configured. The open_books repositories receive it in the User-Agent (IRIS on by default; OAPEN when open_books.oapen is on). Leaving it empty prevents Unpaywall and OpenAlex lookups.
Retraction checks. Retraction checks download the Retraction Watch dataset and match the DOIs of papers papio acquired (or, with retraction.scope = "library", your wider library) locally on your machine; the request carries no library DOIs, only your configured email as a mailto parameter when one is set. Disable them with
[sources.retraction_watch] enabled = false. With zotio.retraction_tags = true, a verified retraction is also written into your own Zotero library as the papio:retracted tag; that step looks up each retracted DOI through your local zotio and sends nothing to a third party.
Update checks. The updates.check key defaults to false, but papio init enables it unless you decline the prompt or pass --check-updates=false. When enabled, update checks make an unauthenticated request to the public
GitHub releases page. GitHub receives your IP address, as it would for any web
request, but papio does not send your identifiers or usage information. Disable
the check with updates.check = false.
Adapter control. With the update check on, the daemon also fetches one small
signed file from raw.githubusercontent.com once a day (change the address with
updates.control_url). The request is an anonymous GET, like the release check:
the host receives your IP address and nothing else, and papio sends no identifier,
count, or usage information. The file can only name packaged adapter revisions and
safety domains to suspend; it carries no host, selector, path, or URL for the
browser to act on. The daemon accepts it only when an Ed25519 signature verifies
against the papio control key built into the binary, and it never accepts an older
file than the one it holds. A suspended adapter stops downloading by itself and the
paper waits for you in the inbox; papio doctor names the suspension. A missing file
(HTTP 404) means nothing is published. The browser extension makes no request of its
own and keeps only the last accepted sequence number and a digest in its local
storage.
Document delivery. Document delivery is disabled unless you configure it. When enabled, papio contacts only the institution's configured delivery service and sends the credentials and bibliographic details required by that service. It never uses a shared or papio-operated delivery service. See the configuration reference for the full field list.
Browser extension¶
- No OrgMentem data collection. The extension has no backend and does not send data to OrgMentem. It communicates with the local native-messaging host
com.orgmentem.papio. - No browser credentials leave the page. You enter institutional credentials and complete MFA or CAPTCHA in your browser. The extension never reads a password field, a cookie, or your browsing history, and it never stores or transmits a username or a session token. To tell whether your library session is live, the check it runs inside the configured library page does read that page's own visible affordances and its
localStorageandsessionStorageentries, including whether a session token found there has expired and whether it carries an identity claim. Every value is discarded in the page: only the resultingsigned in/signed out/unknownclassification comes back, and nothing else is stored or sent. - No background scraping, and scanning is explicit. Page scanning runs only when you click it, reads only the top frame of that one tab, and runs entirely inside the page: identifier detection is local JavaScript, not a network request. Your explicit click is the consent for that one scan; no separate site approval exists. Selection acts only on the papers you choose, with a maximum of 200 canonical keys per durable cohort, submitted in bounded chunks. It does not crawl, harvest, or auto-submit pages.
- Institution-session checks follow your local keep-warm mode. The default While papio has work mode checks the configured library resolver only while institutional papers are active. Always for current library keeps that resolver warm even when no paper currently needs it. Off stops automatic resolver checks. When a paper is waiting for sign-in, a completed HTTPS navigation on that paper's declared publisher host can schedule a check of the configured library resolver. This publisher-triggered path reads no publisher page content. The publisher page cannot set the popup's signed-in or signed-out verdict; that comes only from the configured library page. If papio's own resolver tab is still paused on an identity-provider page, the trigger leaves that page open and creates a muted background resolver tab for the check. The replacement surfaces only when the resolver itself says that sign-in is still required. A tracked papio tab returning from authentication can still provide the existing, same-origin release evidence for queued work, subject to current resolver access. Other hosts, queued-only work, missing institution bindings, and ambiguous institutions do not authorize this trigger. No new landing URL, page-derived publisher data, title, path, query, fragment, cookie, credential, or session token enters extension storage or a native message.
- What a scan sends to the local application. The scan itself sends nothing. When the selection workspace opens, the detected identifiers (each a
doi,pmid,arxiv, oropenalexkind and value) plus a structural count of visible records go to the local papio application so it can mark which papers you already own and which are eligible. When you submit, only the canonical keys of the rows you selected are acquired, along with the page's bare lowercase HTTPS origin and the detector name. The short citation label shown beside each row — up to 240 characters of the nearest citation-shaped container's visible text — is display-only and stays in the browser; it is never sent. No page text, path, query, fragment, page title, or credential leaves the browser for a scan. - The host-page action acknowledgement is ephemeral and local. When a popup action succeeds and transient acknowledgements are set to show for all requests, the extension briefly draws a small chip in the page you acted on. It carries one of four fixed short phrases and nothing else — no identifier, title, URL, provider name, or job id — is not interactive, sends nothing anywhere, stores nothing, and removes itself after three seconds. It reads no page content and installs no watcher or content script.
- The loss toast prefers the page when all-sites access is active. When papio loses a tab it opened for a paper, it can offer to reopen that route. With all-sites access granted, "Show the lost-tab message in the page you are reading" is on by default and draws the message into the page in front of you. Turn it off to use the small papio window instead. Revoking all-sites access turns the in-page route off, and re-granting access does not restore an explicit opt-out. Both routes show the same fixed sentence, one button, and papio's own mark. They carry no identifier, title, URL, provider name, or job reference, disappear eight seconds after arriving, and commit nothing when they go. Neither appears while a papio surface holds focus.
- The in-page loss message reads nothing. The all-sites grant lets papio reach the current HTTPS page. The loss-toast setting selects the integrated route or the separate window. When papio draws the message, it adds one element and reads nothing from the page. No selector runs, no page text is collected, and nothing about the page is stored or sent. The message renders inside a shadow root, so the page's scripts and styles do not reach it. It removes itself before reporting your choice. It is never drawn into a page papio is driving, a non-HTTPS page, or a PDF. A withdrawn grant, blocked injection, or unsafe page always falls back to papio's own window.
- Focused-surface presence is minimal and local. The feature-gated
surface_presence_v1hint carries only an opaque per-instance id, the focused surface type (popuporinbox), a boolean focused value, and a timestamp. It goes to the local daemon only. It contains no URL, title, tab id, host, identifier, or page content. - Page-bulk recovery is origin-bounded. The browser-local restart-safe cohort record stores only a bare lowercase HTTPS origin, a bounded detector identifier, and canonical keys (plus the recovery bookkeeping needed to replay chunks). It stores no path, query, fragment, page title, or bearer value.
- Ownership marks come from a local check, not the network. A page-bulk row's
owned_with_pdf/owned_missing_pdf/ownership_unknownmarks can come from your Zotero library through zotio, which the local application invokes as a local subprocess in local-only mode: the lookup answers from zotio's existing on-disk library mirror, and no network request is made for this check — in particular, papio never triggers a Zotero-account sync from a workspace scan. The mirror refreshes only through your own zotio activity (for example, when a paper is filed after acquisition), so a stale or failed check reportsownership_unknownhonestly rather than a false "not owned." - Normal browser session. The extension uses browser extension APIs and native messaging. It does not use WebDriver, CDP, or other browser-automation frameworks.
Local storage¶
Browser storage. The extension stores its settings and temporary job and tab state in browser storage. This data stays in the browser so the extension can survive service-worker suspension and reconnect to the local application. For an active institutional job, browser storage can also retain the configured library resolver as one bare HTTPS origin. A pending session-recheck reason can survive service-worker suspension beside it. Neither value contains the publisher landing, an identity-provider address, a path, query, fragment, title, cookie, credential, or permission pattern.
The dedicated page_bulk_cohort_recovery_v1 browser-local record is limited to
restart-safe replay data: a bare lowercase HTTPS origin, a detector identifier,
and the ordered canonical keys, together with opaque cohort/chunk bookkeeping
and timestamps. It never stores a path, query, fragment, page title, or bearer
value.
Browser storage for page scanning. Page scanning requires an explicit click for each scan. The browser stores only the restart-safe page-bulk cohort record described above, with no path, query, fragment, page title, or bearer value.
Application storage. The local application stores papers, metadata, and job
records in its data directory. Validated PDFs live in artifacts/. Downloaded
candidates awaiting validation live in quarantine/. Papers go only to your own
Zotero library if you enable that integration. Notification routing also keeps
the notification_intents ledger in papio.db; its payloads are durable and
may retain identifiers such as a retraction finding's DOI indefinitely. For a
single-finding integrity notice, the DOI may also appear in the macOS
Notification Center notification text, subject to your operating system's
notification and lock-screen settings.
Diagnostic captures. Diagnostic captures are sanitized HTML from pages you
choose to capture. They are stored in <data_dir>/captures/<host>/ and may still
contain article text, account labels, or other page content. Sanitization removes
scripts, query strings, form values, token-shaped values, email addresses, and
IPv4 and IPv6 addresses; some provider error pages print your IP address. A
capture whose sidecar records sanitizer_version 1 predates the address rule
and may still contain your IP address. Captures are retained
for 14 days and up to 10 per host by default; both limits are configurable in
[captures]. Run papio adapter captures purge --all to remove every capture, or
papio adapter captures purge --host <host> to remove captures for one host.
Bug reports. The data directory may also contain papio.db (request history,
titles, identifiers, and notification-intent payloads), native-host.log
(browser-session diagnostics, including URLs), a legacy adoptions/ directory
on installs that predate the browser-download adoption root, and the
update-cache*.json and retraction-cache.json files. Browser-downloaded
files awaiting adoption now live in the adoption root itself
(<your download folder>/papio by default). papio does not upload any of
these. Review and minimize them before sharing a bug report; they describe
what you have been reading.
Adapter evidence. Reaching a provider with no adapter can create a sanitized diagnostic capture, but papio never uploads it, opens a public issue, or sends telemetry. Review and minimize a capture before sharing it yourself. Sanitized HTML can still contain article text, account labels, or other page content.
Acquisition history and impact figures. The extension's figures — papers acquired, success rate, weekly acquisition trend, access-route breakdown, and human-handoff rate — are calculated locally from job records. They are displayed only to you and are never transmitted anywhere.
Agent acquisition¶
Saving a key with papio config agent set, or supplying
PAPIO_TYPESAFE_API_KEY to the daemon, enables cloud decisions for
eligible delegated acquisitions. The extension sends the local daemon a matching
article DOI, a title of at most 400 characters, and at most 80 visible article
controls with labels of at most 240 characters. TypeSafe receives that projection
and your TypeSafe credential. The projection excludes page URLs, document bodies,
form values, browser credentials, account areas and unrelated tabs. URL-like and
credential-like strings in labels are redacted. Labels are page-derived text;
this minimization is not a guarantee that all possible personal text is detected.
Saved integration credentials use macOS Keychain, Windows Credential Manager or Linux Secret Service. Config stores typed references; it does not receive resolved secrets. References survive config moves but do not sync secrets to another machine. Each profile explicitly chooses its records, and TypeSafe setup enrolls only that profile. Webhook records include the complete endpoint URL because its path or query can contain a token.
An explicit environment reference supports headless use. Selected variables are
removed before child processes start. The older PAPIO_TYPESAFE_API_KEY override
still works until the profile has an explicit agent reference; an empty legacy
value disables the backend. papio config agent remove detaches enrollment;
remove any legacy environment override and restart the daemon to disable it.
Detaching does not delete a shared OS record. Deletion is a separate explicit
credential command.
Legacy TOML secrets remain supported until you run
papio config credentials migrate. Migration verifies new records before
replacing config, refuses observed concurrent edits, leaves old TypeSafe records
intact and saves the previous config to config.toml.bak (mode 0600). That file
can still hold the literal secrets, so delete it after you check the result.
Credential status reports local availability without printing values; it does not
claim the provider has authenticated them. Browser passwords, cookies and SSO
remain browser-owned; Zotero credentials remain zotio-owned.
The daemon retains request/permit IDs, observation revisions, outcomes and usage counts locally. It does not retain the model projection or raw response in those receipts. Existing diagnostic captures remain separate and local. No repair trace or analytics is sent to OrgMentem. The decision interface also accepts local backends without cloud credentials; a local model runtime is not yet bundled.
For Firefox agent downloads, the extension sends the local daemon the exact browser download path, size, start time and download ID. The path stays local and is not retained in the job's event receipts or sent to the model. The daemon copies only a new file from its configured download directory and keeps the browser's original file. A restart before publication can leave an incomplete attempt; Papio does not repeat the click to recover it.
Permissions¶
Each browser permission is used to perform a requested download, read a page
needed for that job, run an explicit one-shot scan of the current tab, check a
configured library session while a paper is waiting for sign-in, or report a
result to the local application. For example, nativeMessaging reaches the
local daemon, downloads saves the requested PDF, activeTab permits the
top-frame scan only after you click it, and host permissions allow the
extension to read the relevant library and publisher pages. On Firefox only,
webRequest, webRequestBlocking and webRequestFilterResponse let the
extension keep a copy of a publisher's one-time PDF response in a tab papio
opened for a paper, and save it to your download folder; the bytes do not leave
your computer. The extension store listing explains each permission in detail.
Third parties¶
papio does not sell your data or share it for advertising, credit decisions, or unrelated purposes.
The third-party scholarly services in the table receive the data listed there because they are needed to find or download the paper you requested. During browser handoff, your browser contacts your institution and the publisher directly. papio is not an intermediary for those requests.
Changes¶
If this policy changes, the “Last updated” date above will change. The current version will always be available at this URL.
Contact¶
Questions about privacy: open an issue at github.com/OrgMentem/papio.