almaapitk
A Python toolkit for interacting with the Ex Libris Alma ILS (Integrated Library System) API.
📖 Documentation: https://hagaybar.github.io/AlmaAPITK/ — guides plus a full API reference generated from the source.
Features
- Simple API Client: Easy-to-use HTTP client with automatic authentication and error handling
- Domain Classes: High-level abstractions for common Alma operations
Acquisitions- POL operations, invoicing, item receivingAdmin- Sets management (BIB_MMS, USER), full CRUD + member managementAnalytics- Analytics reports with pagination supportBibliographicRecords- Bib records, holdings, items; structure-driven record creation (create_record_from_fields, optional pymarc adapter)Configuration- Libraries/locations, code tables, letters, mapping tables (active expansion area — more endpoints land in each 0.x release)ResourceSharing- Lending/borrowing via Partners APIUsers- User management, loans, requests, CRUD, search, expiry processing; resource-sharing borrowing requests with a body builder (build_user_rs_request) and opt-in code-table validation
- Environment Support: Seamless switching between Sandbox and Production
- Response Wrapper: Consistent response handling with
AlmaResponse - Comprehensive Logging: Built-in logging with automatic API key redaction
Installation
pip install almaapitk
Or with Poetry:
poetry add almaapitk
Quick Start
Setup
Set your Alma API keys as environment variables:
export ALMA_SB_API_KEY="your-sandbox-api-key"
export ALMA_PROD_API_KEY="your-production-api-key"
Basic Usage
from almaapitk import AlmaAPIClient, AlmaAPIError
# Initialize client (uses ALMA_SB_API_KEY)
client = AlmaAPIClient('SANDBOX')
# Make API calls
try:
response = client.get('almaws/v1/conf/libraries')
if response.success:
libraries = response.json()
for lib in libraries.get('library', []):
print(f"Library: {lib['name']}")
except AlmaAPIError as e:
print(f"API error: {e} (status: {e.status_code})")
Using Domain Classes
from almaapitk import AlmaAPIClient, Acquisitions, Users
client = AlmaAPIClient('SANDBOX')
# Acquisitions operations
acq = Acquisitions(client)
# Note: Acquisitions.get_pol returns a plain dict directly
pol = acq.get_pol("POL-12345")
print(f"POL Status: {pol['status']['value']}")
# User operations
# Note: get_user takes a primary ID (NOT email) and returns an AlmaResponse
users = Users(client)
user_response = users.get_user("PRIMARY_ID_12345")
user_data = user_response.json()
print(f"User: {user_data['full_name']}")
Working with Bibliographic Records
from almaapitk import AlmaAPIClient, BibliographicRecords
client = AlmaAPIClient('SANDBOX')
bibs = BibliographicRecords(client)
# Get a bib record (signature: get_record(mms_id, view="full", expand=None))
record = bibs.get_record("99123456789")
# Get holdings for a bib
holdings = bibs.get_holdings("99123456789")
Resource Sharing
from almaapitk import AlmaAPIClient, ResourceSharing
client = AlmaAPIClient('SANDBOX')
rs = ResourceSharing(client)
# Create a lending request
# Mandatory: partner_code, external_id, owner, format_type, title
# (citation_type is required unless mms_id is supplied)
result = rs.create_lending_request(
partner_code="PARTNER_CODE",
external_id="EXT-2025-001",
owner="MAIN", # resource sharing library code
format_type="PHYSICAL",
title="Introduction to Python",
citation_type="BOOK",
author="Smith, John",
)
Analytics Reports
from almaapitk import AlmaAPIClient, Analytics
# Analytics API only works with PRODUCTION
client = AlmaAPIClient('PRODUCTION')
analytics = Analytics(client)
# Get column headers for a report
report_path = "/shared/University/Reports/MyReport"
headers = analytics.get_report_headers(report_path)
print(f"Columns: {headers}")
# Fetch rows with pagination (limit must be 25-1000)
rows = analytics.fetch_report_rows(report_path, limit=100, max_rows=500)
for row in rows:
print(row) # Dict with Column0, Column1, etc.
# Optional: pass a progress_callback to track progress for large reports.
# The callback receives one argument: the cumulative row count fetched so far.
def show_progress(rows_so_far: int) -> None:
print(f" fetched {rows_so_far} rows...")
rows = analytics.fetch_report_rows(
report_path,
limit=100,
max_rows=500,
progress_callback=show_progress,
)
API Reference
Core Classes
| Class | Description |
|---|---|
AlmaAPIClient |
Main HTTP client for Alma API |
AlmaResponse |
Response wrapper with .data, .json(), .success, .status_code |
AlmaAPIError |
Base exception for API errors |
AlmaValidationError |
Exception for validation failures |
Domain Classes
| Class | Description |
|---|---|
Acquisitions |
POL operations, invoicing, item receiving |
Analytics |
Analytics reports with pagination (ResumptionToken) |
Users |
User management, email updates |
BibliographicRecords |
Bib records, holdings, items, scan-in |
Admin |
Sets management (BIB_MMS, USER sets) |
Configuration |
Libraries/locations, code tables, letters, mapping tables (active growth area) |
ResourceSharing |
Lending/borrowing via Partners API |
Utilities
| Class | Description |
|---|---|
TSVGenerator |
TSV file generation utilities |
CitationMetadataError |
Exception for citation metadata errors |
Environment Configuration
See Quick Start → Setup for environment variable setup. The client
automatically picks ALMA_SB_API_KEY for 'SANDBOX' and ALMA_PROD_API_KEY
for 'PRODUCTION'.
Error Handling
from almaapitk import AlmaAPIClient, AlmaAPIError, AlmaValidationError
client = AlmaAPIClient('SANDBOX')
try:
response = client.get('almaws/v1/users/invalid-user')
except AlmaValidationError as e:
# Input validation failed
print(f"Validation error: {e}")
except AlmaAPIError as e:
# API returned an error
print(f"API error: {e}")
print(f"Status code: {e.status_code}")
print(f"Response: {e.response}")
Requirements
- Python 3.12+
- requests
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Links
Metadata
Release files for almaapitk 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| almaapitk-0.5.1.tar.gz | 155.9 kB | With provenance | Details for almaapitk-0.5.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| almaapitk-0.5.1-py3-none-any.whl | Python 3 | none | any | Details for almaapitk-0.5.1-py3-none-any.whl |
Total release size: 316.0 kB
Release files / almaapitk-0.5.1.tar.gz
| Download URL | almaapitk-0.5.1.tar.gz |
|---|---|
| Size | 155.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73cd874d0058ea2f68ba4f4e9a9884e6f7826004e5ab426bd2c14d2e386a06d6
|
|
BLAKE2b-256 checksum How to use checksums |
0d79a45cb0242e295179ba970f4cf13410b79d10276f86a279e1d09361d6f0c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / almaapitk-0.5.1-py3-none-any.whl
| Download URL | almaapitk-0.5.1-py3-none-any.whl |
|---|---|
| Size | 160.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
778127d150964a3972f7ce0c16a00d6e3132ccd288baaffc15663a135e57d53e
|
|
BLAKE2b-256 checksum How to use checksums |
dde3d0a7ed2b4fdab6f8c1cff3552bc422961c25a47a0d6b03a7544cff961ac2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logSecurity for almaapitk 0.5.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for almaapitk-0.5.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.