Generic ERP / PIM

Add AI-powered AAS extraction to any system that holds part records and stores datasheet PDFs as attachments, such as Microsoft Dynamics, Oracle, Infor, custom PIMs, etc.

Audience: Integration architects evaluating AAS Studio for a system not on our named list.

Topology

  1. Your ERP triggers a workflow when a part is created or its datasheet is updated
  2. Your integration layer (Logic Apps, n8n, Make, custom service) downloads the PDF
  3. POST to AAS Studio /api/v1/extract
  4. Map the structured result onto your ERP's part metadata table
  5. 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, so wrap in p-limit or your queue runner. The Python SDK is synchronous, so 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.

References

All integration guidesTry AAS Studio free

Command palette

Navigate + run actions