API Interface
Overview
Additionally, the REST API can be used as an API export – it gives you the ability to retrieve your inspection equipment data from memida at any time. You decide when, how often, and which data you export – individual inspection equipment, entire lists, or specifically documents such as calibration certificates and inspection protocols.
While the JSON export and the VDI 2623 export provide the entire data inventory as a ZIP archive, the API offers selective access in real time, without daily limits.
Prerequisites
For an export via the API, you must have the API enabled in your plan. For a detailed guide on how to use the REST API, please refer to our API Reference.
Practical Examples
The following examples show typical export scenarios. Expand an example to see the complete code.
Export all inspection equipment (Bash / cURL)
This script reads all inspection equipment page by page from the API and saves them to a JSON file.
#!/bin/bash
# Export all inspection equipment via the API
API_KEY="live XXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL="https://api.memida.de"
OUTPUT_FILE="apparatuses_export.json"
PAGE=1
LIMIT=100
ALL_DATA="[]"
while true; do
RESPONSE=$(curl -s \
-H "Auth: $API_KEY" \
-H "Accept: application/json" \
"$BASE_URL/api/v1/apparatuses?limit=$LIMIT&page=$PAGE")
# Extract data from the response
DATA=$(echo "$RESPONSE" | jq '.data')
PAGE_COUNT=$(echo "$RESPONSE" | jq '.paginator.pageCount')
# Merge data
ALL_DATA=$(echo "$ALL_DATA $DATA" | jq -s '.[0] + .[1]')
echo "Page $PAGE of $PAGE_COUNT exported"
# Check if last page reached
if [ "$PAGE" -ge "$PAGE_COUNT" ]; then
break
fi
PAGE=$((PAGE + 1))
done
echo "$ALL_DATA" | jq '.' > "$OUTPUT_FILE"
echo "Export completed: $(echo "$ALL_DATA" | jq 'length') inspection equipment in $OUTPUT_FILE"
Retrieve single inspection equipment with inspection history (Python)
Retrieves an inspection equipment by its identification number – including inspections, test plans and comments.
import requests
API_KEY = "live XXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL = "https://api.memida.de"
IDENTNO = "PM-2024-001"
headers = {
"Auth": API_KEY,
"Accept": "application/json"
}
response = requests.get(
f"{BASE_URL}/api/v1/apparatuses/identno/{IDENTNO}",
headers=headers
)
if response.status_code == 200:
apparatus = response.json()["data"]
print(f"Equipment: {apparatus['apparatus_fullname']}")
print(f"Status: {apparatus['status']}")
print(f"Ident no.: {apparatus['identno']}")
print(f"Serial no.: {apparatus.get('serial_number', '–')}")
print(f"Next inspection: {apparatus.get('next_check_at', '–')}")
for inspection in apparatus.get("inspections", []):
result = inspection["inspection_result"]["name"]
checked = inspection["checked_at"]
insp_type = inspection.get("inspection_type", {})
type_name = insp_type.get("name", "–") if insp_type else "–"
print(f" Inspection: {type_name} on {checked} → {result}")
elif response.status_code == 404:
print(f"Inspection equipment with ident no. '{IDENTNO}' not found.")
else:
print(f"Error: {response.status_code}")
Example output:
Equipment: Druck DPI 620 Multifunction Pressure Calibrator
Status: operational
Ident no.: PM-2024-001
Serial no.: SN-123456
Next inspection: 2026-06-15
Inspection: DAkkS Calibration on 2025-06-14T09:00:00+02:00 → operational
Identify due inspection equipment (Python)
Identifies all inspection equipment whose next inspection date is within the next 30 days – e.g. for audit preparation.
import requests
from datetime import datetime, timedelta
API_KEY = "live XXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL = "https://api.memida.de"
DAYS_AHEAD = 30
headers = {
"Auth": API_KEY,
"Accept": "application/json"
}
today = datetime.now().date()
deadline = today + timedelta(days=DAYS_AHEAD)
page = 1
due_items = []
while True:
response = requests.get(
f"{BASE_URL}/api/v1/apparatuses",
headers=headers,
params={"limit": 100, "page": page}
)
data = response.json()
for apparatus in data["data"]:
next_check = apparatus.get("next_check_at")
if next_check and apparatus.get("checkup"):
check_date = datetime.strptime(next_check, "%Y-%m-%d").date()
if today <= check_date <= deadline:
due_items.append({
"identno": apparatus["identno"],
"name": apparatus["apparatus_fullname"],
"next_check_at": next_check,
"days_remaining": (check_date - today).days
})
paginator = data["paginator"]
if page >= paginator["pageCount"]:
break
page += 1
due_items.sort(key=lambda x: x["days_remaining"])
print(f"\n{len(due_items)} inspection equipment due within the next {DAYS_AHEAD} days\n")
for item in due_items:
print(f" [{item['days_remaining']:3d} days] {item['identno']:<15} {item['name']}")
Example output:
======================================================================
3 inspection equipment due within the next 30 days
======================================================================
[ 5 days] PM-2024-017 Fluke 8588A Digital Multimeter
[ 12 days] PM-2024-003 Endress+Hauser Promag P300 Flow Meter
[ 28 days] PM-2024-042 Mettler Toledo XPR205 Analytical Balance
Download calibration certificates (Python)
Downloads all inspection documents (calibration certificates, protocols) of a specific inspection equipment.
import os
import requests
API_KEY = "live XXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL = "https://api.memida.de"
APPARATUS_ID = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
DOWNLOAD_DIR = "./calibration_certificates"
headers = {
"Auth": API_KEY,
"Accept": "application/json"
}
response = requests.get(
f"{BASE_URL}/api/v1/apparatuses/{APPARATUS_ID}",
headers=headers
)
apparatus = response.json()["data"]
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
print(f"Downloading documents for: {apparatus['apparatus_fullname']}")
# Download device files
if apparatus.get("files"):
files = apparatus["files"] if isinstance(apparatus["files"], list) else [apparatus["files"]]
for file_info in files:
file_response = requests.get(
f"{BASE_URL}/api/v1/files/{file_info['id']}",
headers={"Auth": API_KEY}
)
if file_response.status_code == 200:
filepath = os.path.join(DOWNLOAD_DIR, file_info["name"])
with open(filepath, "wb") as f:
f.write(file_response.content)
print(f" ✓ {file_info['name']}")
# Download inspection files (calibration certificates etc.)
for inspection in apparatus.get("inspections", []):
for file_info in inspection.get("files", []):
file_response = requests.get(
f"{BASE_URL}/api/v1/files/{file_info['id']}",
headers={"Auth": API_KEY}
)
if file_response.status_code == 200:
filepath = os.path.join(DOWNLOAD_DIR, file_info["name"])
with open(filepath, "wb") as f:
f.write(file_response.content)
print(f" ✓ {file_info['name']}")
print(f"\nAll documents saved in '{DOWNLOAD_DIR}'.")
CSV export for Excel (Python)
Exports all inspection equipment as a CSV file that can be opened directly in Excel.
import csv
import requests
API_KEY = "live XXXXXXXXXXXXXXXXXXXXXXX"
BASE_URL = "https://api.memida.de"
OUTPUT_FILE = "inspection_equipment_export.csv"
headers = {
"Auth": API_KEY,
"Accept": "application/json"
}
CSV_COLUMNS = [
"identno", "apparatus_fullname", "serial_number",
"manufacturer_name", "status", "costcenter_name",
"next_check_at", "latest_checked",
"check_interval", "interval_unit", "apparatus_type_names",
]
page = 1
all_rows = []
while True:
response = requests.get(
f"{BASE_URL}/api/v1/apparatuses",
headers=headers,
params={"limit": 100, "page": page, "sort": "identno", "direction": "asc"}
)
data = response.json()
for apparatus in data["data"]:
row = {col: apparatus.get(col, "") for col in CSV_COLUMNS}
all_rows.append(row)
paginator = data["paginator"]
if page >= paginator["pageCount"]:
break
page += 1
with open(OUTPUT_FILE, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS, delimiter=";")
writer.writeheader()
writer.writerows(all_rows)
print(f"CSV export completed: {len(all_rows)} inspection equipment in '{OUTPUT_FILE}'")
Tip: The
utf-8-sigencoding and the semicolon as delimiter ensure that the file opens correctly in Microsoft Excel with umlauts and proper column separation.
Inspection equipment status summary (JavaScript / Node.js)
const API_KEY = "live XXXXXXXXXXXXXXXXXXXXXXX";
const BASE_URL = "https://api.memida.de";
async function fetchStatusSummary() {
const statusCount = {};
let page = 1;
let totalPages = 1;
while (page <= totalPages) {
const response = await fetch(
`${BASE_URL}/api/v1/apparatuses?limit=100&page=${page}`,
{
headers: {
"Auth": API_KEY,
"Accept": "application/json"
}
}
);
const json = await response.json();
totalPages = json.paginator.pageCount;
for (const apparatus of json.data) {
const status = apparatus.status;
statusCount[status] = (statusCount[status] || 0) + 1;
}
page++;
}
console.log("\nInspection Equipment Status Overview:");
console.log("─".repeat(40));
const total = Object.values(statusCount).reduce((a, b) => a + b, 0);
for (const [status, count] of Object.entries(statusCount).sort((a, b) => b[1] - a[1])) {
const pct = ((count / total) * 100).toFixed(1);
console.log(` ${status.padEnd(22)} ${String(count).padStart(5)} (${pct}%)`);
}
console.log("─".repeat(40));
console.log(` ${"Total".padEnd(22)} ${String(total).padStart(5)}`);
}
fetchStatusSummary();
Example output:
Inspection Equipment Status Overview:
────────────────────────────────────────
operational 285 (82.1%)
not_operational 23 (6.6%)
locked 18 (5.2%)
out_of_house 12 (3.5%)
decommissioned 9 (2.6%)
────────────────────────────────────────
Total 347
Notes
- Your data, your access: The API is available to you without daily export limits. You can retrieve your data as often and to the extent you need.
- Date formats: All timestamps follow ISO 8601 (e.g.
2026-02-11T14:30:00+01:00). Pure date fields useYYYY-MM-DD. - Encoding: All responses are UTF-8 encoded.
- Documents: Calibration certificates, inspection protocols and other files are delivered via
/api/v1/files/{file_id}as binary data with the appropriate Content-Type. - Complete reference: The detailed description of all fields, status values and inspection results can be found in the API Reference.