Generic ERP / PIM
Add AI-powered AAS extraction to any system that holds part records and stores datasheet PDFs as attachments — Microsoft Dynamics, Oracle, Infor, custom PIMs, etc.
Audience: Integration architects evaluating AAS Studio for a system not on our named list.
Topology
- Your ERP triggers a workflow when a part is created or its datasheet is updated
- Your integration layer (Logic Apps, n8n, Make, custom service) downloads the PDF
- POST to AAS Studio /api/v1/extract
- Map the structured result onto your ERP's part metadata table
- Optionally store the AAS Studio extraction id as a part attribute for traceability — fetch the audit-replay anytime via /api/v1/extractions/{id}
TypeScript
import { AasStudioClient } from '@aas-studio/sdk'
const aas = new AasStudioClient({ apiKey: process.env.AAS_STUDIO_KEY! })
// Generic n8n / Logic Apps / serverless function pattern
export async function handler(event: { partId: string; pdfUrl: string }) {
// 1. Fetch the PDF from your ERP attachment URL
const pdf = await fetch(event.pdfUrl).then(r => r.arrayBuffer())
// 2. Extract
const { result } = await aas.extract({
file: new Uint8Array(pdf),
fileName: `${event.partId}.pdf`,
idPrefix: `urn:acme:erp:${event.partId}`,
})
// 3. Flatten onto your part metadata
const flat: Record<string, string> = {}
for (const sm of result.submodels) {
for (const el of sm.elements) {
if (el.value) flat[`${sm.idShort}.${el.idShort}`] = el.value
}
}
// 4. Push into your ERP
await fetch(process.env.ERP_PART_API + '/' + event.partId, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.ERP_TOKEN}` },
body: JSON.stringify({ metadata: flat, aasExtractionId: result.assetId }),
})
}Install: npm install @aas-studio/sdk
Python
import os
import requests
from aas_studio import AasStudioClient
aas = AasStudioClient(api_key=os.environ["AAS_STUDIO_KEY"])
def handler(event):
pdf_bytes = requests.get(event["pdfUrl"]).content
response = aas.extract(
pdf_bytes,
file_name=f"{event['partId']}.pdf",
id_prefix=f"urn:acme:erp:{event['partId']}",
)
result = response["result"]
flat = {}
for sm in result["submodels"]:
for el in sm["elements"]:
if el.get("value"):
flat[f"{sm['idShort']}.{el['idShort']}"] = el["value"]
requests.patch(
f"{os.environ['ERP_PART_API']}/{event['partId']}",
headers={"Authorization": f"Bearer {os.environ['ERP_TOKEN']}"},
json={"metadata": flat, "aasExtractionId": result["assetId"]},
)Install: pip install aas-studio
Common pitfalls
- For high-volume ingest, batch by spinning up a worker pool. The TypeScript SDK is async — wrap in p-limit or your queue runner. The Python SDK is synchronous — use a ThreadPoolExecutor or asyncio.to_thread.
- Idempotency: AAS Studio extractions aren't deterministic at the LLM level. If your workflow can re-trigger (e.g. PDF re-upload), guard with a hash check on the PDF before re-extracting — same SHA-256 → skip and reuse the saved /api/v1/extractions entry.
- Authority context: when you flatten the result for your ERP, low-confidence elements (tier !== "high") should NOT silently overwrite human-curated values. Either gate writes by confidence, or write to a "candidate" field and surface a review UI.
- For multi-tenant ERPs, give each tenant its own AAS Studio API key — quota lives at the key level, not the workspace level. One tenant blowing through the limit shouldn't affect others.