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
}
}
}