alterlab-labarchive — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited alterlab-labarchive (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
LabArchives is an electronic lab notebook platform for research documentation and data management. Its REST API (XML responses, HMAC-signed requests) exposes notebooks, the page tree, entries, attachments, and backups.
This skill should be used when:
| Scenario | Use Instead |
|---|---|
| Benchling registry, inventory, ELN entries, or workflow tasks | alterlab-benchling |
| Searching, writing, or publishing protocols on protocols.io | alterlab-protocolsio |
| Designing REDCap instruments/data dictionaries or CDISC mapping | alterlab-redcap-cdisc |
| Choosing a data repository (Zenodo, Dryad, OSF) or FAIR data-sharing plan | alterlab-open-science |
Two Python clients exist; pick by task:
| Client | Install | Use for |
|---|---|---|
| labapi (NIMH DSST; PyPI, current 1.2.0, Python >=3.10) | uv pip install "labapi[dotenv]" | Recommended for new work: signing, XML parsing, page-tree navigation, text entries, attachments, backups |
labarchives-py (labarchivespy import; git-only) | uv pip install "git+https://github.com/mcmero/labarchives-py" | Minimal signed GET wrapper (make_call); used by the bundled scripts |
Prerequisites:
password for users/user_access_info, not your login password.Regional API endpoints (labarchives-py api_url; labapi's API_URL omits the trailing /api):
https://api.labarchives.com/apihttps://auapi.labarchives.com/apihttps://ukapi.labarchives.com/apiCreate the bundled scripts' config.yaml with python3 scripts/setup_config.py (prompts for secrets without echoing them and writes the file with mode 600):
api_url: https://api.labarchives.com/api # or regional endpoint
access_key_id: YOUR_ACCESS_KEY_ID
access_password: YOUR_ACCESS_PASSWORD
user_email: [email protected]
user_external_password: YOUR_LA_APP_AUTH_TOKENEvery call is signed: the client appends akid, expires (ms timestamp), and sig = base64 HMAC of akid + method name + expires keyed by the access password, so the password itself is never sent. For detailed setup and troubleshooting, see references/authentication_guide.md.
users/user_access_info returns the user ID (UID) and the notebooks the user can open (<notebook> elements with <id>, <name>, <is-default>):
# labapi
import os
from labapi import Client
with Client() as client: # reads API_URL, ACCESS_KEYID, ACCESS_PWD
user = client.login(os.environ["LA_EMAIL"], os.environ["LA_APP_TOKEN"])
print(list(user.notebooks)) # notebook names
page = user.notebooks["Lab Notebook"].traverse("Experiments/2026/Run-12")# labarchives-py (signed GET)
import xml.etree.ElementTree as ET
from labarchivespy.client import Client
client = Client(api_url, access_key_id, access_password)
response = client.make_call('users', 'user_access_info',
params={'login_or_email': user_email, 'password': auth_token})
root = ET.fromstring(response.content)
uid = root[0].text
notebooks = [(nb.findtext('id'), nb.findtext('name')) for nb in root.iter('notebook')]The labarchives-py wrapper does not URL-encode parameter values, so pass only simple values through make_call (or use labapi).
notebooks/notebook_backup (params uid, nbid, optional json=true, no_attachments=true) returns the notebook as a 7-Zip archive; only the notebook owner can download it (error 4547 otherwise).
# Back up one notebook (credentials come from config.yaml)
python3 scripts/notebook_operations.py backup --nbid NOTEBOOK_ID
# Without attachments, JSON data inside the archive
python3 scripts/notebook_operations.py backup --nbid NOTEBOOK_ID --json --no-attachments
# List notebooks, or back up every notebook you can open
python3 scripts/notebook_operations.py list
python3 scripts/notebook_operations.py backup-all --output backups/With labapi: user.notebooks["Lab Notebook"].backup("backups/lab_notebook.7z").
For the API method reference, see references/api_reference.md.
Entries live on pages of the notebook tree, so writes need the notebook ID (nbid) and the page tree ID (pid):
| Operation | API method | Notes |
|---|---|---|
| Create a page or folder | tree_tools/insert_node | parent_tree_id, display_text, is_folder |
| Add a text entry | entries/add_entry (POST) | form field entry_data; part_type = text entry (HTML), plain text entry, or heading |
| Add an attachment | entries/add_attachment (POST) | raw file bytes as the body; filename, caption, change_description |
| Update a text entry | entries/update_entry (POST) | eid + entry_data |
| List a page's entries | tree_tools/get_entries_for_page |
# labapi: text entry + attachment on a page
from labapi import Attachment, AttachmentEntry, TextEntry
page.entries.create(TextEntry, "<p>Run 12 complete; see attached plate map.</p>")
page.entries.create(AttachmentEntry, Attachment.from_file("plate_map.pdf"))# Bundled script (labarchives-py signing, POSTs issued by the script)
python3 scripts/entry_operations.py create --nbid NOTEBOOK_ID --pid PAGE_ID --content "Results from today's experiment..."
python3 scripts/entry_operations.py upload --nbid NOTEBOOK_ID --pid PAGE_ID --file /path/to/file.pdf --caption "Raw data"
python3 scripts/entry_operations.py batch-upload --nbid NOTEBOOK_ID --pid PAGE_ID --directory ./experiment_data/Comments are not covered by either client; look up the comment method in the LabArchives API notebook before scripting it. Record provenance (instrument, software version, timestamp) in the attachment caption or a text entry instead. Check the per-file size limit (users/max_file_size) before large uploads.
LabArchives documents institution-level reports (detailed usage, notebook inventory, PDF/offline generation, members, settings) under a site_reports class for Enterprise administrators. The method names in references/api_reference.md are unverified here — confirm them in your institution's API documentation before use.
LabArchives integrates with Protocols.io, GraphPad Prism (8+), SnapGene, Geneious, Jupyter, REDCap, Qeios, and SciSpace, mostly through in-app export features; newer integrations use OAuth. Programmatic bridges (Jupyter → entry, REDCap export → entry, protocol import) are in references/integrations.md.
scripts/setup_config.py)python3 scripts/notebook_operations.py backup-all --output backups/notebook.traverse("Experiments/2026/Run-12") in labapi, or its tree ID).ipynb as an attachment on the experiment pagerequirements.txt/environment.yml) as a second attachmentnbid/pid exist and the user can open the notebookusers/max_file_size and the file typeFor additional support, contact LabArchives at [email protected].
setup_config.py: interactive configuration file generator (hidden secret prompts, mode 600)notebook_operations.py: list notebooks and back them up (single or all)entry_operations.py: add text entries and upload attachments to a pageapi_reference.md: API classes, methods, and parametersauthentication_guide.md: authentication setup and configurationintegrations.md: third-party integration setup guides and codePart of the AlterLab Academic Skills suite.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.