Here we describe how to interact with the Inventory via the GraphQL API

Queries

A good source for learning the GraphQL syntax and concepts can be found here. The easiest way to execute a query is using the GraphiQL in-browser IDE which is embedded into the LeanIX Administration (Go to menu entry Developers / Tools). The following examples demonstrate some example queries and mutations based on the default out-of-the-box data model. If you have customized the data model, please make sure to adapt your queries.

The endpoint for queries is: https://<instance>.leanix.net/services/pathfinder/v1/graphql.

GraphiQL

You can explore the schema of your workspace on the right hand side in GraphiQL. An exclamation mark behind an attribute indicates a must field (may not be null).

GraphQL API

When sending queries directly to the GraphQL API endpoint, please ensure to correctly escape string breaking characters, see below for an example. The query itself needs to be provided in a string format. Examples are shown here.

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "26937ab6-e903-469d-acf9-ccc37b75f1e2", patches: $patches) {
    factSheet {
      ... on Application {
        displayName
        description
      }}}}

Variables:
{
  "patches": [
    {
      "op": "replace",
      "path": "/description",
      "value": "testing \"escape\" characters"
    }
  ]
}

Get a list of Fact Sheets

The following example shows how to pass a limit of 2 and a filter to the allFactSheets query. The result includes nodes of the type BaseFactSheet the displayName and the type of each Fact Sheet.

{
  allFactSheets(first: 2, filter: {facetFilters: [{facetKey: "FactSheetTypes", keys: ["Application"]}]}) {
    totalCount
    edges {
      node {
        id
        displayName
        type
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "totalCount": 116,
      "edges": [
        {
          "node": {
            "id": "RlM6ZWVkNTU2ZWQtZDRkZi00MDRkLTliMGUtMjYzNmQ3NjZhOWJj",
            "displayName": "AC Management",
            "type": "Application"
          }
        },
        {
          "node": {
            "id": "RlM6YTVmM2EyOTMtNmYzZS00ZWQ1LWIyNjYtMmQzYzUwMTk2Y2M4",
            "displayName": "AttorneyNet",
            "type": "Application"
          }
        }
      ]
    }
  }
}

Get a list of filtering facet keys

This example shows how to fetch a list of all the facet keys in a workspace.

{
  allFactSheets{
    filterOptions {
      facets {
        facetKey
        results {
          name
          key
        }
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "filterOptions": {
        "facets": [
          {
            "facetKey": "FactSheetTypes",
            "results": [
              {
                "name": "BusinessCapability",
                "key": "BusinessCapability"
              },
              {
                "name": "Process",
                "key": "Process"
              },
              {
                "name": "UserGroup",
                "key": "UserGroup"
              },
              {
                "name": "Project",
                "key": "Project"
              },
              {
                "name": "Application",
                "key": "Application"
              },
              {
                "name": "Interface",
                "key": "Interface"
              },
              {
                "name": "DataObject",
                "key": "DataObject"
              },
              {
                "name": "ITComponent",
                "key": "ITComponent"
              },
              {
                "name": "Provider",
                "key": "Provider"
              },
              {
                "name": "TechnicalStack",
                "key": "TechnicalStack"
              }
            ]
          },
          {
            "facetKey": "hierarchyLevel",
            "results": [
              {
                "name": "1",
                "key": "1"
              },
              {
                "name": "2",
                "key": "2"
              },
              {
                "name": "3",
                "key": "3"
              }
            ]
          },
          {
            "facetKey": "DataQuality",
            "results": [
              {
                "name": "noResponsible",
                "key": "_noResponsible_"
              },
              {
                "name": "qualitySealBroken",
                "key": "_qualitySealBroken_"
              },
              {
                "name": "noDescription",
                "key": "_noDescription_"
              },
              {
                "name": "noLifecycle",
                "key": "_noLifecycle_"
              }
            ]
          },
          {
            "facetKey": "_TAGS_",
            "results": [
              {
                "name": "Headquarter",
                "key": "aa51ccc9-db61-48df-89d1-f217f37757ea"
              },
              {
                "name": "Tag2",
                "key": "819d3d4f-f044-470a-8f5d-c11bc15eff67"
              }
            ]
          }
        ]
      }
    }
  },
  "errors": null
}

📘

Filtering on Attributes on Relations

It is currently not possible to filter based on attributes which exist within a relation.

Paging

For paging a list of results, the concept of cursors is employed. We use the concept of Relay Cursor Connections.

Pagination is done by inserting a cursor for the after argument. For the initial cursor, the empty string can be used (or the argument can be omitted, as in the example above).

The following query will retrieve the first 2 Fact Sheets from the beginning:

{
  allFactSheets(first: 2, after: "") {
    edges {
      cursor
      node {
        name
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjA=",
          "node": {
            "name": "AC Management"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjE=",
          "node": {
            "name": "accenture"
          }
        }
      ]
    }
  },
  "errors": null
}

A PageInfo object can be included in the request. This object contains informations about the paging state, e.g. if there are more pages available hasNextPage and the position of the current paging cursor endCursor.

{
  allFactSheets(first: 2, after: "") {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      cursor
      node {
        name
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "YXJyYXljb25uZWN0aW9uOjE="
      },
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjA=",
          "node": {
            "name": "AC Management"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjE=",
          "node": {
            "name": "accenture"
          }
        }
      ]
    }
  },
  "errors": null
}

In order to retrieve the next 2 results in the example above, one has to enter the value of endCursor for the argument after:

{
  allFactSheets(first: 2, after: "YXJyYXljb25uZWN0aW9uOjE=") {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      cursor
      node {
        name
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "YXJyYXljb25uZWN0aW9uOjM="
      },
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjI=",
          "node": {
            "name": "Account"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjM=",
          "node": {
            "name": "acctur"
          }
        }
      ]
    }
  },
  "errors": null
}

Access type-specific attributes

In the example above, only common attributes of the BaseFactSheet, such as displayName can be accessed. We use the concept of Union Types to cast the nodes to the right type and access specific attribute, in this case businessCriticality.

{
  allFactSheets(first: 2, filter: {facetFilters: [{facetKey: "FactSheetTypes", keys: ["Application"]}]}) {
    totalCount
    edges {
      node {
        id
        displayName
        ... on Application {
          businessCriticality
        }
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "totalCount": 109,
      "edges": [
        {
          "node": {
            "id": "b94dd413-7423-44f0-90ba-de794e55e2f0",
            "displayName": "AC Management",
            "businessCriticality": "missionCritical"
          }
        },
        {
          "node": {
            "id": "cfd7f79a-2ce2-4931-b4f4-91f69e48ff7e",
            "displayName": "AttorneyNet",
            "businessCriticality": "businessCritical"
          }
        }
      ]
    }
  },
  "errors": null
}

Filter for lifecycle attributes

This example shows how to fetch a list of all factsheets of a certain type (here: Applications) with a certain lifecycle (here: End of Life).
Make sure to add a date filter.

query allFactSheetsQuery($filter: FilterInput!) {
  allFactSheets(filter: $filter) {
    totalCount
    edges {
      node {
        ... on Application {
          id
          displayName
          ApplicationLifecycle: lifecycle {
            asString
          }
        }
      }
    }
  }
}


{"filter":{"facetFilters":[{"facetKey":"FactSheetTypes","operator":"OR","keys":["Application"]},
  {"facetKey":"lifecycle","operator":"OR","keys":["endOfLife"],
    "dateFilter":{"type":"TODAY","from":"2018-11-27","to":"2018-11-27"} } ] } }
{
  "data": {
    "allFactSheets": {
      "totalCount": 29,
      "edges": [
        {
          "node": {
            "id": "04ffff0d-490d-46db-9ad3-5124f790eee1",
            "displayName": "ABC",
            "ApplicationLifecycle": {
              "asString": "endOfLife"
            }
          }
        },
        {
          "node": {
            "id": "92ffc60e-a0e7-4139-a4a5-4d4271dfec23",
            "displayName": "QWERT",
            "ApplicationLifecycle": {
              "asString": "endOfLife"
            }
          }
        },
        {
          "node": {
            "id": "bfffd9a2-69ea-4245-8ebd-ed0aeecf384d",
            "displayName": "XYZ",
            "ApplicationLifecycle": {
              "asString": "endOfLife"
            }
          }
        },

Access related Fact Sheets and Children.

In the following example, we fetched all related IT Components of a single TechStack and his children with their related IT Components.

{
  factSheet(id: "7638b02f-edb3-4b21-94eb-b4098e3b18d9") {
    displayName
    ... on TechnicalStack {
      relTechnologyStackToITComponent {
        edges {
          node {
            id
            factSheet {
              name
              displayName
            }
          }
        }
      }
      relToChild {
        edges {
          node {
            id
            factSheet {
              displayName
              ... on TechnicalStack {
                relTechnologyStackToITComponent {
                  edges {
                    node {
                      id
                      factSheet {
                        name
                        displayName
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "factSheet": {
      "displayName": "Database",
      "relTechnologyStackToITComponent": {
        "edges": [
          {
            "node": {
              "id": "bc961789-4038-41ba-a364-2355c7d036b1",
              "factSheet": {
                "name": "Application Hosting",
                "displayName": "Acoce Application Hosting"
              }
            }
          },
          {
            "node": {
              "id": "243ceda1-9a57-406c-bfe4-24b380992c57",
              "factSheet": {
                "name": "Application Hosting",
                "displayName": "Application Hosting"
              }
            }
          },
          {
            "node": {
              "id": "cef20cca-eed8-42e7-bd4b-ab393f584ec6",
              "factSheet": {
                "name": "Application Hosting",
                "displayName": "AutoCAD Application Hosting"
              }
            }
          }
        ]
      },
      "relToChild": {
        "edges": [
          {
            "node": {
              "id": "034c78d6-4a40-447e-8b99-1a43d6cb4d67",
              "factSheet": {
                "name": "Non-relational Database",
                "displayName": "Database / Non-relational Database",
                "relTechnologyStackToITComponent": {
                  "edges": [
                    {
                      "node": {
                        "id": "8896dfb3-c33a-490f-bc06-601bd7446720",
                        "factSheet": {
                          "name": "Application Hosting",
                          "displayName": "Customer King Application Hosting"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "node": {
              "id": "764fb9d4-9bb5-4909-a8f2-26ae9db382e0",
              "factSheet": {
                "name": "Relational Database",
                "displayName": "Database / Relational Database",
                "relTechnologyStackToITComponent": {
                  "edges": [
                    {
                      "node": {
                        "id": "c9586ed8-cf40-4a07-8efb-26f63f3a04de",
                        "factSheet": {
                          "name": "SQL Server",
                          "displayName": "Microsoft SQL Server 2000 Standard Edition / 2000 Standard Edition"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "2ff1948a-2b30-4b26-9997-60c97f443102",
                        "factSheet": {
                          "name": "SQL Server",
                          "displayName": "Microsoft SQL Server 2005 Express Edition / 2005 Express Edition"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "cc6766d1-0d6c-4ebd-9081-05a2a676439e",
                        "factSheet": {
                          "name": "SQL Server",
                          "displayName": "Microsoft SQL Server 2008 Enterprise / 2008 Enterprise"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "b8ca2bf6-bbfe-4661-9871-6f0ae8343de9",
                        "factSheet": {
                          "name": "SQL Server",
                          "displayName": "Microsoft SQL Server 2008 Web / 2008 Web"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "2be23cc9-5f29-48c5-85f5-94007eeef491",
                        "factSheet": {
                          "name": "Database",
                          "displayName": "Oracle Database 10g 10.2 / 10g 10.2"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "9ebc63af-5dc3-4053-85ba-eee4ba0e15ad",
                        "factSheet": {
                          "name": "Database",
                          "displayName": "Oracle Database 11g 11.1 / 11g 11.1"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "6873451b-978a-423b-9213-eed9a7498e1a",
                        "factSheet": {
                          "name": "Database",
                          "displayName": "Oracle Database 11g 11.2 / 11g 11.2"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "e3c6e0ae-6700-490c-aac8-5a5fc7e82f20",
                        "factSheet": {
                          "name": "MySQL Database",
                          "displayName": "Oracle MySQL Database 5.0 / 5.0"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "b01dae8e-bd96-4d54-ad11-05171c7d1ff1",
                        "factSheet": {
                          "name": "MySQL Database",
                          "displayName": "Oracle MySQL Database 5.1 / 5.1"
                        }
                      }
                    },
                    {
                      "node": {
                        "id": "78e1bd28-80be-4ae5-8c70-8a511fefd118",
                        "factSheet": {
                          "name": "MySQL Database",
                          "displayName": "Oracle MySQL Database 5.5 / 5.5"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    }
  },
  "errors": null
}

Get a single Fact Sheet

A single Fact Sheet can be retrieved via its unique ID.

query {
  factSheet(id: "b94dd413-7423-44f0-90ba-de794e55e2f0") {
    displayName
    ... on Application {
      businessCriticality
    }
  }
}
{
  "data": {
    "factSheet": {
      "displayName": "AC Management",
      "businessCriticality": "missionCritical"
    }
  },
  "errors": null
}

Get a FactSheet by its External ID

If you want to search for Fact Sheets by the ExternalID field "externalId" and you want to find all matching the ID "1234", use the following query.

query {
  allFactSheets(first: 1, filter: {externalIds: ["externalId/1234"]}) {
    totalCount
    edges {
      node {
        id
        displayName
        ... on Application {
          externalId {
            externalId
          }
        }
      }
    }
  }
}
{
  "data": {
    "allFactSheets": {
      "totalCount": 1,
      "edges": [
        {
          "node": {
            "id": "2d774e7c-6a48-48d3-a1d3-38b3c0cba713",
            "displayName": "Test",
            "externalId": {
              "externalId": "1234"
            }
          }
        }
      ]
    }
  },
  "errors": null
}

Mutations

GraphQL Mutations are used to create, update or delete Fact Sheets.

Create a Fact Sheet

To add a Fact Sheet, the mutation createFactSheet is used. The fields name and type of the BaseFactSheetInput are mandatory to create a new Fact Sheet. The result includes the newly created id and revision rev.

mutation ($input: BaseFactSheetInput!) {
  createFactSheet(input: $input) {
    factSheet {
      id
      name
      rev
      type
    }
  }
}

Query Variables:
{
  "input":{"name":"New Fact Sheet", "type": "Application"}
}
{
  "data": {
    "createFactSheet": {
      "factSheet": {
        "id": "142d61ce-3dfc-4516-a108-a871fbe3f929",
        "name": "New Fact Sheet",
        "rev": 1,
        "type": "Application"
      }
    }
  },
  "errors": null
}

Update a Fact Sheet

The updateFactSheet mutation changes an existing Fact Sheet by following the "JSON Patch" logic described in RFC 6902. A list of patches is passed to the mutation. The patches will always be executed in the same order they appear in the list.
The result can include a query to the Fact Sheet. If a revision rev is given, it must match the current version in the inventory. Via the parameter validateOnly it is possible to test the mutation for potential errors.

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "142d61ce-3dfc-4516-a108-a871fbe3f929", 
    rev: 1, patches: $patches, validateOnly: false) {
    factSheet {
      ... on Application {
        rev
        displayName
        name
        release
        displayName
        alias
        description
      }
    }
  }
}

Query Variables:
{
 "patches": [{"op":"replace","path":"/name","value":"New Name"}]
}
{
  "data": {
    "result": {
      "factSheet": {
        "rev": 2,
        "displayName": "New Name",
        "name": "New Name",
        "release": "",
        "alias": "",
        "description": null
      }
    }
  },
  "errors": null
}

Adding relations between Fact Sheets

The updateFactSheet mutation can also be used in order to add one or more relations from one Fact Sheet to another Fact Sheet. A patch object with operation "add" needs to be provided with a "path" that identifies the relation attribute. Several adds on the same relation path can be done within a single request. To distinguish possible errors in the response we have to add a suffix /new_1 (for the next relation /new_2 and so on) to the paths to get dedicated error messages.

mutation ($patches: [Patch]!) {
  updateFactSheet(id: "142d61ce-3dfc-4516-a108-a871fbe3f929", rev: 2, patches: $patches) {
    factSheet {
      id
      displayName
      ... on Application {
        relApplicationToUserGroup {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  }
}

Query Variables:
{
  "patches": [
    {
      "op": "add",
      "path": "/relApplicationToUserGroup/new_1",
      "value": "{\"factSheetId\":\"5e85b861-97f7-4b87-987e-7566694d8fdf\"}"
    },
    {
      "op": "add",
      "path": "/relApplicationToUserGroup/new_2",
      "value": "{\"factSheetId\":\"ad45f3e0-4739-4533-a62b-dd2074420d55\"}"
    }
  ]
}

The following JSON response contains an example for an error message that might be returned by the server. Please note that the path now identifies the corresponding patch operation from the request.

{
  "message": "[FS_VALIDATION_RELATION_NOT_UNIQUE_OUTGOING] Outgoing relation to the same Fact Sheet occurred twice! relation name = 'applicationUserGroupRelation', from = 'New Name', from type = 'Application', to = 'Australia', to type = 'UserGroup'",
  "gqlPath": "updateFactSheet",
  "errorType": "MODEL_COMPLIANT",
  "entityType": "FACT_SHEET",
  "objectId": "142d61ce-3dfc-4516-a108-a871fbe3f929",
  "path": "/relApplicationToUserGroup/new_1"
}

Removing relations

Removing relations works with the updateFactSheet mutation as well, only with patch operation "remove". Note that you require the id of the relation in the patch.

mutation ($patches: [Patch]!) {
  updateFactSheet(id: "142d61ce-3dfc-4516-a108-a871fbe3f929", rev: 2, patches: $patches) {
    factSheet {
      id
      displayName
      ... on Application {
        relApplicationToUserGroup {
          edges {
            node {
              id
            }
          }
        }
      }
    }
  }
}

Query Variables:
{
  "patches": [
    {
      "op": "remove",
      "path": "/relApplicationToUserGroup/8c0bc078-1585-4b05-9450-2d83d970441f"
    }
  ]
}

Adding documents and subscriptions to a Fact Sheet

This topic is described in the advanced section here

Delete and recover a Fact Sheet

In LeanIX, deleting a Fact Sheet means changing its internal status to ARCHIVED. This change is executed via the updateFactSheet mutation. A comment needs to be provided. The Fact Sheet can be recovered again by setting the status to ACTIVE.

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "142d61ce-3dfc-4516-a108-a871fbe3f929", 
    rev: 1, comment: "Delete FS", patches: $patches, validateOnly: false) {
    factSheet {
      ... on Application {
        status
        rev
        type
      }
    }
  }
}

Query Variables:
{
 "patches":[{"op":"add","path":"/status","value":"ARCHIVED"}]
}
{
  "data": {
    "result": {
      "factSheet": {
        "status": "ARCHIVED",
        "rev": 4,
        "type": "Application"
      }
    }
  },
  "errors": null
}

Schema

Explore the meta-data

The following query retrieves the meta-data about the GraphQL schema. This introspection functionality is also used by the GraphiQL in-browser IDE to show the documentation on the right-hand side and to provide the typeahead functionality in the editor.

query {
  __schema {
    types {
      name
      kind
      interfaces {
        kind
        name
      }
      fields {
        name
      }
      inputFields {
        name
        defaultValue
      }
    }
    queryType {
      name
    }
  }
}