← All guides Export

Export UML 2.5.1 XMI for code generation.

EOModeller doesn't ship a language mapping. Instead, the model is available as standard UML 2.5.1 XMI at a stable URL, so you write the transform — script, AI, or a templating engine — and own how the model becomes code.

What you'll set up

  1. A personal access token (PAT) that doesn't expire every fifteen minutes the way a browser session does.
  2. A curl one-liner that pulls the XMI for a specific model.
  3. Optional: a local transform that turns the XMI into whatever artefact your toolchain needs.

Before you start

  • An EOModeller account with at least Viewer access to the workspace containing the model.
  • The model's workspace ID (or slug) and model ID. You can grab both from the dashboard URL when the model is selected: /eomodeller/edit/<workspaceId>/<modelId>.
  • A terminal with curl. The examples below also use jq for token parsing — install it or substitute your own JSON extractor.

Step 1 — Mint a personal access token

The browser uses short-lived JWTs that expire after fifteen minutes. A script needs something longer-lived. EOModeller's PATs are minted from the dashboard, last until they expire or you revoke them, and can be limited to read-only access and to particular workspaces.

  1. Open the dashboard → Account tab.
  2. Find the API tokens card.
  3. Enter a memorable label (e.g. "laptop code-gen" or "GitHub Actions").
  4. Choose its Access (Read only is enough to pull XMI), which Workspaces it can reach, and when it expires (90 days by default). Then click Create token.
  5. The plaintext token appears in an accent-tinted bubble. Copy it now — this is the only time you'll see it. If you dismiss the bubble without copying, mint a new one.

The token starts with the prefix eo_pat_. The prefix is intentional — it makes a leaked token spottable in logs, in git grep, and in GitHub's secret-scanner. Treat the rest like a password: don't commit it, don't paste it into chat, prefer environment variables over command-line arguments.

Give a PAT only the access it needs. A read-only token can fetch models but not change them, and a token limited to some workspaces can't see the rest. Within those limits it acts as you. When a PAT no longer matches what you're using it for, revoke it from the same Account → API tokens card.

Step 2 — Pull the XMI

The endpoint is:

GET /api/workspaces/<workspaceId>/models/<modelId>/export/xmi

Authentication is the standard Authorization: Bearer … header. Workspace membership is enough — a Viewer-role teammate can fetch the XMI for any model they can browse.

The minimum useful curl:

export EO_TOKEN="eo_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export EO_HOST="https://api.eomodeller.com"
export WORKSPACE="my-workspace"
export MODEL="my-model"

curl -H "Authorization: Bearer $EO_TOKEN" \
     "$EO_HOST/api/workspaces/$WORKSPACE/models/$MODEL/export/xmi" \
     -o model.xmi

The response is application/vnd.xmi+xml and includes a Content-Disposition header so browsers download it as <ModelName>.xmi. The body is one uml:Model wrapping the whole model: top-level packages nested as packagedElement xmi:type="uml:Package", with nested packages recursing naturally.

Step 3 — What's in the XMI

The serialiser covers the seven first-class UML diagram types EOModeller commits to (see the notation conformance page). Specifically:

What you authorHow it appears in the XMI
UML ClasspackagedElement xmi:type="uml:Class" with nested ownedAttribute and ownedOperation
AttributeownedAttribute xmi:type="uml:Property" with visibility, type, and lowerValue / upperValue for multiplicity
OperationownedOperation xmi:type="uml:Operation" with nested ownedParameter for each argument (carries direction and type)
Interfaceuml:Interface packagedElement
Use Case / Actoruml:UseCase / uml:Actor
Enumeration / DataType / PrimitiveType / SignalEach maps to the matching uml: metaclass
Component / Node / Device / ExecutionEnvironmentEach maps to the matching uml: metaclass
Package (incl. nested)uml:Package, recursing through child packages
GeneralisationInline <generalization general="…"/> on the specific class
RealizationTop-level uml:Realization with client / supplier references
Associationuml:Association with two memberEnd references and two ownedEnd properties (each with multiplicity bounds)
Element descriptionownedComment xmi:type="uml:Comment" nested in the element

The xmi:id values are the same UUIDs / slugs the model uses internally, lightly sanitised to XML NCName rules. They stay stable across exports, so a transform script can key its output on the IDs and not have to track names.

XMI covers the UML model. Anything EOModeller doesn't yet emit to XMI is omitted, with a per-element X-Eo-Warning response header listing what was skipped.

Step 4 — Run your transform

The XMI is plain XML. Use whatever transform suits the work:

  • XSLT for deterministic, audit-friendly code emission. The XMI namespaces are stable; old XSLT runs on new exports without surprises.
  • Python / Node / Go with an XML parser. Walk packagedElement nodes by xmi:type and emit whatever your toolchain needs.
  • An LLM with the XMI as context. Practical for one-off code-gen passes — paste the XMI in and ask for the artefact you want.

A typical bash pipeline:

curl -fsSL -H "Authorization: Bearer $EO_TOKEN" \
     "$EO_HOST/api/workspaces/$WORKSPACE/models/$MODEL/export/xmi" \
  | python3 my_transform.py \
  > generated/

The -f flag makes curl exit non-zero on HTTP failure, so your pipeline doesn't silently emit garbage from a 401 page if the token expired or got revoked.

Troubleshooting

401 Unauthorized
The token is wrong, expired (JWTs only), or revoked (PATs). For PATs, check the Account → API tokens card — revoked tokens appear faded with a "revoked" badge.
404 Not Found, "not found"
Either the workspace ID / model ID is wrong, or your account isn't a member of that workspace. The 404 is deliberate: it doesn't leak whether the workspace exists when you lack access.
200 OK but the XMI is just the model wrapper
The model has no classes / packages / associations yet. You're probably hitting a freshly-created model row. Check the X-Eo-Warning response headers for confirmation.
How do I know if my XMI is "complete"?
The notation conformance page lists exactly what EOModeller commits to for each diagram type. Anything outside that scope (BPMN, C4-as-a-dedicated-notation) is post-launch.

Reference

  • Endpoint: GET /api/workspaces/{workspaceId}/models/{modelId}/export/xmi
  • Authentication: Authorization: Bearer <token> — accepts either a JWT access token or a PAT (eo_pat_…)
  • Required access: workspace membership (Viewer role and up)
  • Content type: application/vnd.xmi+xml
  • Conformance: UML 2.5.1, XMI 2.5.1
  • Response headers of note: Content-Disposition (filename), X-Eo-Warning (zero or more — one per skipped element)
  • Token management API: POST /api/me/tokens (mint), GET /api/me/tokens (list), DELETE /api/me/tokens/{id} (revoke)