lean-ix — SAP LeanIX GraphQL Proxy
⚠️ DEPRECATED — this package has been merged into dvm-eahelper (
pip install dvm-eahelper), which combines the proxy, download and graph loading in one CLI and adds KuzuDB support. Useeahelper proxy/eahelper downloadinstead. This repo is archived and receives no further updates.
A local proxy server that:
- Connects to your already-logged-in browser via Playwright CDP
- Extracts the active Bearer token from LeanIX network requests
- Exposes a local GraphQL endpoint that proxies to LeanIX
- Serves a GraphiQL UI for interactive exploration
Prerequisites
- Python 3.14+ and uv
- Google Chrome or Microsoft Edge installed
- Playwright browsers installed (one-time step)
# One-time: install Playwright browser binaries
uv run playwright install chromium
Quick Start
Step 1 — Launch a debug Edge/Chrome instance
If Edge or Chrome is already running, you cannot simply add
--remote-debugging-portto a new shortcut — the flag is silently ignored and the port never opens. You must launch a separate isolated instance using a different--user-data-dir.
# Edge (recommended — already installed on Windows)
Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"
# Chrome
Start-Process "C:\Program Files\Google\Chrome\Application\chrome.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\chrome-debug --no-first-run"
Verify the debug port is active before continuing:
Invoke-RestMethod http://localhost:9222/json/version
You should see a JSON response with browser version info. If you get a connection error, the
browser did not start with the debug port — check that you closed all existing windows of
that browser first, or that the --user-data-dir path differs from your normal profile.
Log in to LeanIX in that browser window before proceeding.
Step 2 — Start the proxy
cd lean-ix
dvm-leanix
You will be prompted for the LeanIX workspace URL if not provided via --url.
The tool connects to Chrome, captures the Bearer token, then starts the local server.
Step 3 — Open GraphiQL
Navigate to: http://localhost:8765/graphql
CLI Options
dvm-leanix [OPTIONS]
Options:
--url URL LeanIX workspace base URL
(default: https://eu-10.leanix.net/YourInstance)
--port PORT Local port (default: 8765)
--connect CDP_URL Chrome DevTools Protocol endpoint (default: http://localhost:9222)
--token TOKEN Use this Bearer token directly — skips browser extraction
--api-token KEY LeanIX Technical User API key — exchanges for Bearer token via OAuth2
(no browser needed; also read from env var LEANIX_API_TOKEN)
--ca-bundle PATH PEM CA bundle (corporate SSL proxy fix)
--no-verify-ssl Disable SSL verification entirely (insecure)
Examples
# Use default URL, prompted if missing
dvm-leanix
# Specify workspace URL explicitly
dvm-leanix --url https://eu-10.leanix.net/MyOtherWorkspace
# Use Technical User API key (no browser needed)
dvm-leanix --api-token "your-api-key-here"
# API key via environment variable
$env:LEANIX_API_TOKEN = "your-api-key-here"
dvm-leanix
# Corporate SSL proxy — point at exported CA bundle
dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"
# Disable SSL verification (quick test only)
dvm-leanix --no-verify-ssl
# Use a known Bearer token (no browser needed)
dvm-leanix --token "eyJhbGci..."
# Different port
dvm-leanix --port 9000
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | / |
Redirects to /graphql |
| GET | /graphql |
GraphiQL interactive UI |
| POST | /graphql |
GraphQL proxy to LeanIX |
| GET | /health |
Health check + upstream URL |
| GET | /token |
Show masked current Bearer token |
| POST | /token |
Replace Bearer token at runtime |
Replace token at runtime
If the token expires, refresh it without restarting:
Invoke-RestMethod -Uri http://localhost:8765/token -Method POST `
-ContentType "application/json" `
-Body '{"token": "eyJhbGci..."}'
Technical User Credentials (No Browser Required)
For automated scripts, CI pipelines, or headless environments you can authenticate with a Technical User API key instead of a browser session.
Create a Technical User
- In your LeanIX workspace go to Administration → Technical Users
- Click Create Technical User, set a name, assign roles
- Copy the generated API key (shown only once)
Start the proxy with an API key
# Pass directly
dvm-leanix --api-token "your-api-key-here"
# Or export as environment variable
$env:LEANIX_API_TOKEN = "your-api-key-here"
dvm-leanix
The proxy exchanges the key for a Bearer token via OAuth2 at startup and automatically re-exchanges it whenever the token expires — no browser interaction needed.
How it works
API key
│
│ POST /services/mtm/v1/oauth2/token
│ auth: ("apitoken", API_KEY)
│ body: grant_type=client_credentials
▼
Bearer access_token
│
▼
server.py (FastAPI on localhost:8765)
│ POST /graphql { query, variables }
│ Authorization: Bearer <token>
▼
https://eu-10.leanix.net/services/pathfinder/v1/graphql
SAP LeanIX GraphQL API
Full reference: docs/graphql-api.md
The SAP LeanIX GraphQL API conforms to the October 2021 GraphQL specification.
Key concepts
| Concept | Detail |
|---|---|
| Fact Sheets | Core entities: Application, ITComponent, BusinessCapability, Process, Interface, DataObject, Provider, TechnicalStack, UserGroup, Project |
| Queries | Read data — factSheet(id), allFactSheets(filter, sort, first, after) |
| Mutations | Write data — createFactSheet, updateFactSheet, archiveFactSheet |
| Pagination | Relay cursor-based (first + after with pageInfo.endCursor) |
| Filtering | facetFilters with OR / AND / NOR operators on facet keys |
GraphQL endpoint
POST https://{HOST}/services/pathfinder/v1/graphql
Authorization: Bearer {access_token}
Content-Type: application/json
Quick example
{
allFactSheets(factSheetType: Application, first: 10) {
totalCount
pageInfo { hasNextPage endCursor }
edges {
node { id name displayName lxState completion { percentage } }
}
}
}
Error handling
GraphQL always returns HTTP 200. Check the errors array in the response body:
{
"data": null,
"errors": [{ "message": "No fact sheet found with id '...'" }]
}
See docs/graphql-api.md for filtering, pagination, mutations, the REST migration guide, and best practices.
Architecture
Browser (logged in)
│
│ Chrome DevTools Protocol (port 9222)
▼
token.py ── intercepts Authorization header ──► Bearer token
│
▼
server.py (FastAPI on localhost:8765)
│ POST /graphql { query, variables }
│
│ Authorization: Bearer <token>
▼
https://eu-10.leanix.net/services/pathfinder/v1/graphql
Troubleshooting
"Could not connect to browser at http://localhost:9222"
→ If Edge/Chrome is already running, the --remote-debugging-port flag is silently ignored by any new window you open — it only works on a fresh browser process. Launch a separate isolated instance with its own profile:
Start-Process "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" `
"--remote-debugging-port=9222 --user-data-dir=C:\Temp\edge-debug --no-first-run --no-default-browser-check"
Then verify the port is open before retrying lean-ix:
Invoke-RestMethod http://localhost:9222/json/version # must return JSON
"Timed out waiting for a Bearer token"
→ No LeanIX API calls were detected. Make sure you are logged in and try navigating within LeanIX to trigger an API request.
SSL: CERTIFICATE_VERIFY_FAILED — self-signed certificate in chain
→ Your corporate network uses SSL inspection (a man-in-the-middle proxy that replaces certificates with ones signed by an internal CA). Python's SSL stack rejects these because the corporate root CA is not in its trust bundle.
Option 1 — Export the corporate CA and point lean-ix at it (recommended)
# Export all trusted root CAs from the Windows certificate store to a PEM file
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
$pem = $certs | ForEach-Object { "-----BEGIN CERTIFICATE-----`n" + [Convert]::ToBase64String($_.RawData, 'InsertLineBreaks') + "`n-----END CERTIFICATE-----" }
$pem | Set-Content -Path "$env:USERPROFILE\.lean-ix\corporate-ca.pem" -Encoding ascii
Then run lean-ix with the bundle:
dvm-leanix --ca-bundle "$env:USERPROFILE\.lean-ix\corporate-ca.pem"
Option 2 — Disable verification entirely (quick test only, not recommended)
dvm-leanix --no-verify-ssl
Token expired mid-session
→ Navigate in the LeanIX browser tab (which triggers a token refresh) then POST the new token to /token, or restart lean-ix.
Metadata
Release files for dvm-leanix 0.5.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dvm_leanix-0.5.3.tar.gz | 97.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dvm_leanix-0.5.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.7 kB
Release files / dvm_leanix-0.5.3.tar.gz
| Download URL | dvm_leanix-0.5.3.tar.gz |
|---|---|
| Size | 97.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9fbdb73bf7f78dab0cd4778b2f69cc1cbbc8eb431bbae3643ed971a058ba9e8c
|
|
BLAKE2b-256 checksum How to use checksums |
53013d29c358683642eead707dbc6ecb587ab2660d6a20502b77342290d24b33
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logRelease files / dvm_leanix-0.5.3-py3-none-any.whl
| Download URL | dvm_leanix-0.5.3-py3-none-any.whl |
|---|---|
| Size | 33.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
df742e3c69b3f240eca9f70984a243e200ecb58993593c80ba782b09ddad90ee
|
|
BLAKE2b-256 checksum How to use checksums |
0de5e7a98717e2304faa0f7ef0717e13a8c0564762ca365fff78a94c33d5daa5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency log