Remote Poster
Posts notices to a Polaris ILS database via the Polaris Leap (PAPI) API.
Setup
-
(Recommended) create and activate a virtual environment, then install dependencies:
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txtOn macOS with Homebrew Python you may get an "externally managed environment" error if you skip the venv and
pip installdirectly — the venv avoids that. -
Copy
.env.exampleto.envand fill in your server, org/workstation IDs, and staff login..envis gitignored, so real credentials never get committed.POLARIS_USERNAMEmust include the domain, e.g.MYLIB\Aladdin.POLARIS_ORGANIZATION_IDshould match theOrganizationIDyour staff login actually belongs to (visible in thePolarisUserobject returned on successful auth) — it's your logged-on org context, not the list of orgs you're posting notices to.POLARIS_PRODUCT_IDdefaults to7(Notices). If calls fail,19(PolarisApplicationServices) is the confirmed working alternative — see Notes below.
Usage
python post_notices.py --notice-type 2 --org-ids 3,4,5,6,7,8
--notice-type: the Notification Type ID to post (from your Polaris system tables).--org-ids: comma-separated Organization IDs to post notices for (the branches whose notices go out) — separate fromPOLARIS_ORGANIZATION_IDin.env, which is your login context.--delivery-option: optional, defaults to1(Mail) — currently the only value Polaris accepts.
On success it prints a confirmation. On failure (bad credentials, invalid IDs, etc.) it prints the error from Polaris and exits non-zero.
Every run sends real notices to real patrons — there's no dry-run mode. Double-check
--notice-type and --org-ids before running.
Notes on the API (things the published docs get wrong or omit)
While wiring this up against Osceola's live server, two things in the reference doc
(docs/polaris-papi-reference.md) turned out to be incomplete or misleading:
- The staff authentication URL is shorter than every other endpoint's. Most PAPI routes
follow
/api/{version}/{language}/{productId}/{siteDomain}/{organizationId}/{workstationId}/..., butauthentication/staffuseronly uses/api/{version}/{language}/{productId}/authentication/staffuser— nositeDomain,organizationId, orworkstationId. This makes sense in hindsight (those three describe a logged-on session, and you're not logged on yet when authenticating), but it isn't spelled out anywhere in the rendered help page — it's only visible as atitle="..."tooltip attribute in the raw HTML ofpolaris.applicationservices/help/authentication/post_staffuser, which a normal page read (rendered text, or an AI summary of the page) won't surface.polaris_client.pybuilds this URL separately from every other call (self.auth_urlvsself.base_url). productId:19(PolarisApplicationServices) is confirmed working against the live server;7(Notices) was the doc's best guess but untested — worth trying if19ever stops working, but don't be surprised if it 400s/404s.
If you hit a 404 with an empty response body on any call, that almost always means the URL
path itself doesn't match a route (wrong segment count, wrong product ID, etc.) rather than a
credentials problem — Polaris's own application-level errors come back as JSON with a
Message/ErrorCode, not an empty body.