Files
Remote-Poster/docs/polaris-papi-reference.md
2026-07-09 14:41:31 -04:00

311 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Polaris.ApplicationServices (PAPI) API Reference
Source: Osceola Library System's Polaris.ApplicationServices help docs
(`https://osceola.librarycatalog.info/polaris.applicationservices/help/...`)
Compiled for internal reference to support scripting against the Notices endpoint.
---
## 1. The API — Basics
- Base API version: `v1` (only supported version)
- Status check URL: `https://[your server name]/Polaris.ApplicationServices/api`
Returns a JSON blob with `ServiceName`, `Version`, `Major`, `Minor`, `Build`, `Revision`.
### URI structure
All URIs (other than API status and staff authentication) include these route segments, in order:
```
/api/{version}/{language}/{productId}/{siteDomain}/{organizationId}/{workstationId}/...
```
| Segment | Type | Required | Notes |
|---|---|---|---|
| `version` | string | Yes | `"v1"` |
| `language` | string | Yes | ISO 639-2 code — `eng`, `spa`, `fre`, `chi`, `ara`, `fas`, `hat`, `haw`, `kor`, `rus`, `vie`, etc. |
| `productId` | integer | Yes | See product ID table below |
| `siteDomain` | string | Yes | Customer site domain (default is `"polaris"`) |
| `organizationId` | integer | Yes | Logged-on organization ID |
| `workstationId` | integer | Yes | Logged-on workstation ID |
Example full URI:
```
/api/v1/eng/19/polaris/1/1/patrons/{id}/basicdata
```
Docs often show this in shorthand as `/api/.../patrons/{id}/basicdata`.
### Product IDs
| Value | Product |
|---|---|
| 0 | All |
| 1 | PowerPAC |
| 2 | ChildrensPAC |
| 3 | ActivePAC |
| 4 | ExpressCheck |
| 5 | InboundTelephony |
| 6 | OutboundTelephony |
| 7 | Notices |
| 8 | ILL |
| 9 | PolarisFusion |
| 10 | AcquisitionsExchange |
| 11 | MobilePAC |
| 12 | SIPService |
| 13 | NCIPService |
| 14 | ERMSPortal |
| 15 | Receipts |
| 16 | ContentXChange |
| 17 | PolarisImport |
| 18 | PolarisAPIConsumerService |
| 19 | PolarisApplicationServices |
| 20 | StaffWebClient |
| 21 | StaffClient |
| 22 | PolarisDatabase |
| 23 | SystemOutput |
| 24 | Vega |
> Since we're calling the Notices endpoint, `productId = 7` (Notices) is likely the semantically "correct" one to use, though `19` (PolarisApplicationServices) may also work depending on how the server is configured — worth confirming against a working example if you have one.
### HTTP response codes
| Code | Status | Notes |
|---|---|---|
| 200 | OK | Success |
| 201 | Created | Returns created object |
| 204 | No Content | Successful deletion |
| 400 | Bad Request | Validation errors, malformed params, etc. Body includes `Message`/`MessageDetail`, sometimes `ErrorCode`. |
| 401 | Unauthorized | `{"ErrorCode":10001,"Message":"User authentication failed."}` |
| 403 | Forbidden | Permission not granted; response includes override info (see Security section) |
| 404 | Not Found | Either "no matching route" or "record not found" (e.g. `ErrorCode 60027`) |
| 405 | Method Not Allowed | Wrong HTTP verb for the resource |
| 409 | Conflict | Object lock (`ErrorCode` 7000079999) or secured record (`ErrorCode` 10004) |
| 411 | Length Required | Missing `Content-Length` |
| 422 | Unprocessable Entity | Body isn't valid JSON |
| 500+ | Server Error | Unhandled exception |
---
## 2. Security and Authentication
Three supported auth mechanisms:
1. **HTTP Basic Authentication + Access Token/Secret** (the standard flow)
2. **ASP.NET Forms Authentication** (cookie-based, browser/JS clients on same domain)
3. **Bearer Token via OAuth2** (OpenID Connect + PKCE)
Plus: **Proxy-Authorization** for privilege overrides.
### 2.1 Basic Auth → Access Token/Secret (primary flow for scripting)
Step 1 — Call the staff auth endpoint with HTTP Basic Auth:
```
POST /api/.../authentication/staffuser
Authorization: Basic <base64(DOMAIN\username:password)>
```
- Username **must include the domain**, e.g. `MYLIB\Aladdin`.
- Combine as `"DOMAIN\username:password"`, then base64-encode the whole string.
- No request body.
Step 2 — Response contains an `AccessToken` and `AccessSecret`:
```json
{
"SiteDomain": "polaris",
"UserDomain": "iii.com",
"AccessToken": "NXmeihFv2kq6meg3EdYoenv2VagJrPHs",
"AccessSecret": "odXCBZuhXBkbwSo4",
"AuthExpDate": "2013-03-26T10:41:11.103",
"PolarisUser": {
"PolarisUserID": 923,
"OrganizationID": 3,
"Name": "Young",
"BranchID": null,
"Enabled": true,
"CreatorID": 895,
"ModifierID": null,
"CreationDate": "2011-02-16T20:28:16.177",
"ModificationDate": null
},
"ERMSNetworkAddress": "young-lt2.polarislibrary.com",
"DataSource": "RD-POLARIS"
}
```
Step 3 — Use the token/secret on all subsequent calls, in a custom `PAS` auth scheme (not base64-encoded):
```
Authorization: PAS {siteDomain}:{AccessToken}:{AccessSecret}
```
Example:
```
Authorization: PAS polaris:NXmeihFv2kq6meg3EdYoenv2VagJrPHs:odXCBZuhXBkbwSo4
```
### 2.2 Bearer Token (OAuth2) variant of staff auth
```
POST /api/.../authentication/staffuser/oauth
Authorization: Bearer <JWT access token>
```
- The JWT's `upn` claim must be `username@domain` format and match a Polaris staff user.
- Response shape is identical to the Basic Auth flow (still returns `AccessToken`/`AccessSecret` to use for follow-on calls).
### 2.3 API Key Authentication (alternative, no token/secret round-trip)
```
POST /api/.../authentication/staffuser
x-api-key: <your API key>
```
- No `Authorization` header — the key goes in the `x-api-key` header.
- Response does **not** include `AccessToken`/`AccessSecret` (they're blank strings) — the API key itself is presumably reused directly on subsequent calls (docs don't show that call shape explicitly, so confirm against a working example).
```json
{
"SiteDomain": "",
"UserDomain": "",
"AccessToken": "",
"AccessSecret": "",
"AuthExpDate": null,
"PolarisUser": {
"PolarisUserID": 1,
"OrganizationID": 5,
"Name": "PolarisExec",
"BranchID": null,
"Enabled": true,
"CreatorID": 1,
"ModifierID": 1,
"CreationDate": null,
"ModificationDate": "2020-12-11T10:28:20.69-05:00"
},
"ERMSNetworkAddress": "clvitn-pc197yjl.polarislibrary.com",
"DataSource": "CLVITN-PC197YJL",
"SiteCode": "MIS/"
}
```
### 2.4 Privilege overrides (403 handling)
If a call returns `403 Forbidden` because the authenticated user lacks a permission, you can supply override credentials via:
- `Proxy-Authorization` header, **or**
- `Polaris-Override-Authorization` custom header (supports multiple overrides per call)
Format (before base64 encoding):
```
username:password:permissionid:permissionownerid
```
Example:
```
Proxy-Authorization: Basic cG9sYXJpc2V4ZWNAZG9tYWluOnBhc3N3b3JkOjgzOjEwMw==
```
Multiple overrides via repeated headers or a comma-delimited list of `Basic ...` values in one header.
**Note:** the primary `Authorization` header (token/secret) is still required alongside any override header.
---
## 3. HTTP Headers Cheat Sheet
**GET requests** — set `Accept`:
```
Accept: application/json
```
(also valid: `text/json`, `image/jpg` for binary/image responses)
**PATCH / POST / PUT requests** — set `Content-Type`:
```
Content-Type: application/json
```
**Auth headers**:
```
Authorization: PAS {siteDomain}:{AccessToken}:{AccessSecret}
Proxy-Authorization: Basic <base64 override>
```
---
## 4. Notices — POST (the endpoint we care about)
### Post notices to the database
```
POST /api/.../notices/post?noticeType={notificationtypeid}&deliveryOption={deliveryoptionid}
```
#### Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| `noticeType` | integer | Yes | ID of the Notification Type |
| `deliveryOption` | integer | Yes | ID of the Delivery Option. **Only valid value is Mail (`1`).** |
#### Request body
A JSON string containing a comma-separated list of Organization IDs:
```json
"3,5,7"
```
#### Response
Returns a plain boolean.
- Success: `true`
- Failure: `false`
#### HTTP response codes
| Code | Meaning |
|---|---|
| 200 | OK. Success |
| 400 | Failure — bad request, invalid `noticeType`, or invalid `deliveryOption` |
#### Notes / open questions for implementation
- The docs don't enumerate valid `noticeType` (Notification Type) IDs on this page — that's presumably in Polaris's system tables or the "System Administration" section elsewhere in the docs (e.g. Parameters and Profiles, or a lookup table). Worth checking the Polaris database (`Polaris.SystemNotifications` or similar) or asking the vendor if you need the full list.
- `deliveryOption` is documented as only accepting `1` (Mail) right now, despite the API allowing an integer — so don't expect e.g. email/SMS options to work here even if other DeliveryOptions endpoints list more.
- The response being a bare `true`/`false` (not an object) means your client code should parse the raw JSON boolean rather than expecting a structured object — easy to trip up if you assume every endpoint returns a DTO.
- `productId` for this call is most likely `7` (Notices) per the product ID table — worth confirming with a test call.
---
## 5. Corrections confirmed against a live server (Osceola)
While building `post_notices.py` against Osceola's live Polaris.ApplicationServices instance,
two things in this doc turned out to be wrong or incomplete:
- **Staff authentication URL is shorter than section 1 implies.** The "all URIs other than API
status and staff authentication" caveat in section 1 undersells how different the auth route
is. It is **not** `/api/{version}/{language}/{productId}/{siteDomain}/{organizationId}/{workstationId}/authentication/staffuser`
— it's just `/api/{version}/{language}/{productId}/authentication/staffuser`, with no
`siteDomain`, `organizationId`, or `workstationId` segments at all. Calling the full-length
URL returns a `404` with an **empty body** (a routing miss, not an app-level error — Polaris's
real error responses come back as JSON with `Message`/`ErrorCode`). This exact URL shape isn't
visible anywhere in the rendered help page text; it only shows up as a `title="{version}/{language}/{productId}"`
attribute on the `<span>` wrapping the "..." in `POST /api/.../authentication/staffuser`, i.e.
you have to view-source the page (`polaris.applicationservices/help/authentication/post_staffuser`)
to find it — a plain fetch or rendered read of the page won't surface it.
- **`productId = 19`** (PolarisApplicationServices) is confirmed working end-to-end (auth +
`notices/post`) against Osceola's server. `productId = 7` (Notices) — this doc's original best
guess — was not confirmed; it may still be correct, but wasn't tested.
---
## 6. Gaps in this doc (pages that returned no additional content)
Two pages in the doc set — **Common Response Structures** and **Collections** (both under "Introduction") — returned only their page heading with no body content when fetched. This might mean:
- The content is loaded client-side via JavaScript that a simple page fetch won't execute, or
- Those particular pages are thin/placeholder pages in this Polaris version.
If you need the actual content of those two pages (e.g. for handling paginated list responses in the `notices` or other endpoints), it may be worth viewing them directly in a browser to check whether there's dynamically-loaded content, since a plain HTTP fetch didn't surface anything under those headings.