Creating and Signing an .isof File

Three approaches to producing a valid .isof file: exporting from the IsoFind interface, via the local API, or through programmatic construction using Python or a third-party LIMS.

An .isof file can be created from the IsoFind interface, via the local API, or programmatically using Python. This page covers all three methods and the available signing options. To understand the signature mechanism, see Digital Signatures.

From the IsoFind Interface

Exporting a Project or Selection

File Export Project (.isof)

IsoFind opens an export options window with the following settings:

OptionDescription
ScopeEntire project, a selection of samples, or filtered by element.
Include methodsEmbeds analytical protocols within the file.
Include purification yieldsEmbeds the purification block.
Sign (Level 1)Adds a SHA-256 fingerprint. Available with all licenses.
Sign (Level 2)Adds an ECDSA signature. Requires an active laboratory certificate and a Pro license.
OperatorName displayed in created_by.operator.
OrganizationName displayed in created_by.organisation and in the signature.
.isof export window with signature options Figure 1: Export window showing Level 1 and Level 2 signature options.

Signing an Existing File

An .isof file that has already been produced can be signed later without re-exporting the data.

File Sign an .isof File Choose File Select Level
Signing a file that already contains a signature of the same level will replace it. Signing a Level 1 file with a Level 2 signature preserves the Level 1 signature and adds the Level 2 signature.

Via the Local API

Exporting and Signing in a Single Request

import requests, json # Build the export payload payload = { "sample_ids": [1, 2, 3], # None = entire project "include_methods": True, "include_purification": True, "sign": True, "sign_level": 1, # 1 = SHA-256, 2 = ECDSA "operator": "Colin Ferrari", "organisation": "IsoFind SAS" } r = requests.post( "http://127.0.0.1:8001/api/isof/export", json=payload, headers=HEADERS ) # Save the returned file with open("export.isof", "w", encoding="utf-8") as f: json.dump(r.json(), f, indent=2, ensure_ascii=False)

Signing an Existing File via API

# POST /api/isof/sign: multipart: file + private key + certificate with open("export.isof") as fi, \ open("lab.key") as fk, \ open("lab.crt") as fc: r = requests.post( "http://127.0.0.1:8001/api/isof/sign", files={ "isof_file": ("export.isof", fi), "private_key": ("lab.key", fk), "certificate": ("lab.crt", fc), }, headers=HEADERS ) signed = r.json() print(signed["signature"]["signed_by"])

Via Python (Manual Construction)

To build an .isof file from scratch—for example, to export data from a LIMS or other software—here is the minimum valid structure.

import json, hashlib from datetime import datetime, timezone doc = { "isof_version": "1.0", "created_at": datetime.now(timezone.utc).isoformat(), "created_by": { "software": "MyLIMS", "software_version": "3.2", "operator": "Sophie Martin", "organisation": "CNRS: CRPG Nancy" }, "samples": [ { "id": "S01", "name": "ANT-BO-24-003", "material_type": "flotation concentrate", "sector": "Bolivia", "isotope_data": [ { "element": "Sb", "system": "123Sb/121Sb", "ratio": 0.74815, "ratio_2se": 0.00012, "standard": "NIST SRM 3102a" } ] } ] } # Add a Level 1 signature scope = ["created_by", "isof_version", "created_at", "samples"] payload = {k: doc[k] for k in scope} digest = hashlib.sha256( json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode() ).hexdigest() doc["signature"] = { "level": 1, "algorithm": "SHA-256", "scope": scope, "hash": digest, "signed_at": datetime.now(timezone.utc).isoformat(), "signed_by": "CNRS: CRPG Nancy" } with open("export.isof", "w", encoding="utf-8") as f: json.dump(doc, f, indent=2, ensure_ascii=False)
The signature scope should include all blocks containing analytical data. Omitting created_by or created_at from the scope allows metadata to be modified without invalidating the signature, which weakens the authenticity guarantee. IsoFind consistently includes these 7 blocks in the default scope.

File Naming

The recommended convention by the ISOF specification is as follows:

{project}_{date}_{laboratory}.isof # Example SDAT-2025-007_20250310_IsoFind.isof

This naming convention allows for natural chronological sorting and identifies the file's origin without opening it.