Over the past months I've been blogging my way through the SAP LeanIX discovery journey managing SAP Build projects, creating transparency across SAP BTP, Cloud Foundry environments, and digging into the tech stack hiding inside them. Each time, SAP LeanIX did the discovery for you. Today I want to flip that around: What if the data you need isn't covered by a ready‑made integration?
That's where the new Custom Discovery Connector (CDC) comes in. With CDC you describe a source in plain language, let AI generate a small fetch script, map the results onto fact sheets, and review everything before it touches your inventory. To make it concrete, I'll use a scenario that I discussed with customers in different situations: Surfacing the SaaS applications that SAP LeanIX SaaS Discovery decided not to put in your inbox.
Why would SaaS Discovery hide anything?
SaaS Discovery streamlines getting your SaaS applications into SAP LeanIX. Connect a source such as Microsoft Entra ID, and it pushes discovered SaaS into the SaaS Discovery Inbox with a deliberate filter: It only promotes applications it can match against the SAP LeanIX reference catalog. That keeps the inbox clean and high‑signal, which is exactly what you want most of the time.
But "most of the time" isn't "always." The applications that don't match the reference catalog (home‑grown tools, the thing someone signed up for last Tuesday) never reach the inbox. For an enterprise architect hunting shadow IT, those can be interesting too, but don't fit into the SaaS discovery inbox. Thus, (and this is the smaller news) we extended the GET /discoveries endpoint so that you can fetch these rejected or unknown items. Now you only have to get them into your LeanIX inventory.
How to get there
With a ~70‑line custom connector you get a second, complementary view of the very same SaaS Discovery data:
- every discovered SaaS application your SaaS Discovery integration marked "rejected" or "unknown",
- mapped to Application fact sheets, so they sit right next to the rest of your landscape,
- staged in a review area where you decide what becomes inventory so that nothing is created behind your back.
In short: SaaS Discovery tells you what it's sure about; the Custom Discovery Connector lets you decide about the rest.
Following along: the three‑step integration journey
CDC walks you through three steps: Build the code → Map the data → Review & push. Here's how it plays out for our scenario. (The full product documentation has the details and screenshots, so I'll keep to the headlines.)
Step 1: Build Let your AI buddy write the fetch code
Go to Admin > Integrations, choose Add Integration > Custom Discovery Connector. Provide a name & description and on the next step download the skill file. Hand that skill file to your AI coding assistant and describe what you want. For my example, say: "call the SAP LeanIX SaaS Discovery getDiscoveries API, keep only the rejected and unknown items, and return them." A minute later you'll have a JavaScript like this:
const BASE_URL = new URL('https://<your-workspace>.leanix.net');
export async function main() {
// 1. Retrieve the LeanIX API token from context secrets
const apiToken = context.secrets["integration_<your-integration-id>_apiToken"].value;
// 2. Read the opaque pagination cursor from the previous execution (undefined on first run)
const cursor = data.page;
// 3. Authenticate: exchange the API token for a short-lived OAuth2 bearer token.
// LeanIX uses the fixed client_id "apitoken" and the API token as the client_secret.
const tokenUrl = new URL('/services/mtm/v1/oauth2/token', BASE_URL);
const credentials = btoa(`apitoken:${apiToken}`);
const tokenResponse = await fetch(tokenUrl.toString(), {
method: 'POST',
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'grant_type=client_credentials',
});
if (!tokenResponse.ok) {
throw new Error(`Authentication failed: ${tokenResponse.status} ${tokenResponse.statusText}`);
}
const { access_token: accessToken } = await tokenResponse.json();
// 4. Ask SaaS Discovery for exactly the items it did NOT push to the inbox.
// matchStatus is appended twice so BOTH statuses come back in one call.
const url = new URL('/services/discovery-saas/v1/discoveries', BASE_URL);
url.searchParams.append('matchStatus', 'reject');
url.searchParams.append('matchStatus', 'unknown');
url.searchParams.set('integrationID', '<your-saas-discovery-integration-id>');
// Pass the opaque cursor returned by the previous page (omit on the first run)
if (cursor) {
url.searchParams.set('cursor', cursor);
}
// 5. Fetch one page of discoveries
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Failed to fetch discoveries: ${response.status} ${response.statusText}`);
}
const result = await response.json();
// 6. Map to the three required fields, then keep every original field too.
const items = (result.data || []).map(item => ({
externalId: item.id,
name: item.displayName.trim().slice(0, 255),
type: 'discovery',
...item,
}));
// 7. Return this page; nextPage carries the cursor forward (null = last page).
return {
data: items,
nextPage: result.nextCursor || null,
};
}A few things worth noting for anyone adapting this:
- Swap in your own host and IDs: your workspace URL and the
integrationIDof the integration setup shown above the code editor need to be put into the script. - ID of the SaaS discovery integration: if you want to narrow down results to only one setup integration, you need to add the integration ID e.g. of the Entra ID integration which you can fetch from its URL when opening its overview page.
On the Credentials tab, add your API token as a secret. Hit Next to execute it against the endpoints and eyeball the Results tab, then Finish.
Step 2: Map to Application fact sheets
Saving captures a sample of the data, and CDC's second step can use this in a second skill to propose a mapping. Alternatively, you configure the mapping yourself manually step by step:
- You pick your meta models fact sheet type.
In my example, set the target fact sheet type to Application. - Filter the raw data upon your need,
- map any raw data to fact sheet fields, and
- configure how the raw data should be matched to existing fact sheets.
Matching to your inventory can be on any field: display name, external ID, fact sheet ID ...
The Preview shows exactly what would be created, updated, or left unchanged.
Step 3: Review & push
CDC drops everything into its own review area, separate for every connector, where each item shows up as Create, Update, Conflict, or No change. And there they are: the rejected and unknown SaaS applications that never made it into the standard inbox - ready for you to link to existing fact sheets, create new ones, or reject for good. Confirm, and only the items you chose flow into your inventory.
You can keep a manual eye on the items or auto-approve any discovery.
Mission accomplished
AI assisted and with one small script you've turned SaaS Discovery's "no" pile into a reviewable shortlist of Application fact sheets.
This SaaS‑Discovery example is just the one I reach for first. Next time I'll show you how to set up the whole thing conversationally, by letting an AI agent drive the Custom Discovery Connector through the LeanIX MCP server - no clicking required. Stay tuned.
Food for thought
As always, I'd love your feedback: Which source system would you point a custom connector at first? Are you looking to create new fact sheets or are you using the fact sheet ID to enrich existing ones?
Let me know in the comments!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.