REST API
Programmatic access to the AAS Studio extraction pipeline. Send a PDF datasheet, get back a structured Asset Administration Shell extraction result. Useful for integrating AAS file generation into ERP, PLM, or PIM workflows.
Open interactive API explorer, try it out →Authentication
Every request needs a Bearer API key in the Authorization header. Generate one in Settings → API Keys. Keys are prefixed sk_aas_ and are shown ONCE at creation. Store them in a secret manager.
Authorization: Bearer sk_aas_a1b2c3d4...
AI EXTRACTION calls count against your monthly quota (Free 20, paid plans 50 or 500 depending on tier, Enterprise unlimited). Validation, repair, templates and the v3 surface do not: only /extractand the embed extraction endpoint consume it. "Each call" here previously said otherwise, which overstated what using the API costs you.
Quickstart: extract from a PDF
Use the official SDK for production work: typed, zero-deps, error classes for every status code. Or stay with curl for quick tests.
import { AasStudioClient } from '@aas-studio/sdk'
import { readFileSync } from 'node:fs'
const aas = new AasStudioClient({ apiKey: process.env.AAS_STUDIO_KEY! })
const { result, provider } = await aas.extract({
file: readFileSync('./datasheet.pdf'),
idPrefix: 'urn:acme:aas',
})
console.log(result.assetIdShort, '·', result.submodels.length, 'submodels via', provider)from aas_studio import AasStudioClient
aas = AasStudioClient(api_key=os.environ["AAS_STUDIO_KEY"])
with open("./datasheet.pdf", "rb") as f:
response = aas.extract(f.read(), id_prefix="urn:acme:aas")
print(response["result"]["assetIdShort"])curl (raw HTTP)
curl -X POST https://aas-studio.eu/api/v1/extract \ -H "Authorization: Bearer $AAS_STUDIO_KEY" \ -F "file=@datasheet.pdf" \ -F "idPrefix=urn:acme:aas"
Response (truncated):
{
"result": {
"assetIdShort": "UR10e",
"assetId": "urn:acme:aas:UR10e",
"assetDescription": "Universal Robots UR10e collaborative robot",
"submodels": [
{
"idShort": "Nameplate",
"elements": [
{ "idShort": "ManufacturerName", "value": "Universal Robots A/S",
"semanticIdIrdi": "0173-1#02-AAO677#002",
"confidence": 95, "tier": "high", "needsReview": false }
]
}
]
},
"provider": "gemini",
"warnings": []
}Endpoints
/api/v1/extract200Extraction succeeded, returns ExtractionResult401Missing or invalid Bearer key402Monthly quota exceeded (returns plan / used / limit)413File exceeds 20 MB422PDF could not be parsed (scanned image, malformed)502LLM provider failed/api/v1/health200Service is up, returns { ok: true, version }Errors
All non-2xx responses use a stable JSON envelope with an error machine code and a human-readable message. Many errors include an (id=…) correlation tag. Quote it when contacting support.
{
"error": "extraction_failed",
"message": "AI extraction failed (id=ab12-3c4d-...). Please retry."
}Rate limits & quota
Extractions are metered by a monthly quota that the API and the web app share on one counter. Plan caps are Free 20 / Individual 50 / Team 500 / Enterprise unlimited (monthly).
Hitting the cap returns HTTP 402 with your plan, current usage, and limit in the body. See pricing to upgrade.
CI/CD quality gate (validate on every push)
POST /api/v1/validate runs the same three-gate stack the Studio uses — the official AAS XSD, the AASd-* metamodel constraints, and structural checks — so your pipeline can block an export before it reaches a platform. The schema is picked from the AAS 3.x namespace your document declares (3.0 / 3.1 / 3.2; 3.1 when it declares none we recognise), and both version and the validation label name the schema that actually ran — so a 3.0 file reports xsd-3.0+constraints, never a fixed xsd-3.1. Send the AAS environment XML (multipart file or JSON { "xml": "..." }); the response carries valid plus an errors[] list. Fail the job when valid is not true:
# exits non-zero (and fails the CI step) on any validation error curl -sf https://aas-studio.eu/api/v1/validate \ -H "Authorization: Bearer $AAS_STUDIO_KEY" \ -F file=@dist/export.aas.xml | jq -e '.valid == true'
As a GitHub Action step:
- name: Validate AAS export (AAS 3.1 + AASd-*)
env:
AAS_STUDIO_KEY: ${{ secrets.AAS_STUDIO_KEY }}
run: |
RESPONSE=$(curl -sf https://aas-studio.eu/api/v1/validate \
-H "Authorization: Bearer $AAS_STUDIO_KEY" \
-F file=@dist/export.aas.xml)
echo "$RESPONSE" | jq .
echo "$RESPONSE" | jq -e '.valid == true' > /dev/null \
|| { echo "::error::AAS validation failed"; exit 1; }Exit codes: curl -sffails the step on HTTP 4xx/5xx (401 bad key, 413 over the 25 MB cap, 429 rate-limited — 30 validations/min per ACCOUNT, not per key: the limiter is keyed on the user, so two keys on one account share one budget); jq -e fails it when the file is well-formed but not valid. For a one-off manual check without a key, use the free Validate & Repair tool.
Gate on depth, not only valid. The response also reports how deep the check actually went: structural (schema only), semantic (schema + the AASd-* metamodel rules), or full (an official IDTA engine run on top). AAS JSON is validated against the official JSON Schema and then walked by the same AASd-* metamodel gate as XML, so a conformant JSON environment now reaches semantic too — and a JSON document with a real AASd-* violation now returns valid: false, exactly as the same document in XML always did. JSON falls back to structuralwhen the metamodel leg could not run (the JSON Schema rejected the document, or it could not be normalised). If your gate means “XML, fully checked”, assert all three:
echo "$RESPONSE" | jq -e '.valid == true and .depth == "semantic" and .format == "xml"'
OpenAPI schema
Full OpenAPI 3.0 schema lives at /api/v1/openapi.json. Drop it into Postman, Stoplight, openapi-generator-cli, or any AI agent framework that consumes OpenAPI to scaffold a typed client in seconds.