Skip to main content

Xurrent GraphQL API

The functions described on this page are designed to work with the Xurrent GraphQL API to retrieve and mutate data.

Compared to Xurrent's REST API, the GraphQL API has much more powerful filtering capabilities. In addition, GraphQL queries allow you to specify more precisely which data you need, including data from nested relations. This means that it is often possible to get all required data with a single query.

If you haven't used the GraphQL API before, we recommend that you work through the Xurrent GraphQL Training to learn more about it.

Xurrent.graphqlQuery

Performs a query to retrieve data from Xurrent.

This method takes two or three parameters:

  1. The record type, for example requests or problems.
  2. An options object that specifies what to retrieve, as detailed below.
  3. Account name (optional).

The options object has the following attributes, all of which are optional:

  • first: the maximum number of records to return. Defaults to 100 when not specified.
  • last: similar to first, but starts from the last record.
  • fields: the scalar fields to include in the result.
  • relations: the relational fields to include in the result. This is an object where each key is the name of a relation, and each value is an options object that specifies what to retrieve from the relation.
    • first: the maximum number of relation records to return. Defaults to 100 when not specified. This attribute can only be specified for relations that return a list of records.
    • last: similar to first, but starts from the last record.
    • fields: the scalar fields of the relation to include the result.
    • relations: the relational fields of the relation to include in the result. Each specified relation again takes first, last, fields and relations attributes.
  • filter: the filter(s) to apply, corresponding to the filter argument of the Xurrent GraphQL API.
  • order: the order(s) to apply, corresponding to the order argument of the Xurrent GraphQL API.
  • view: the view name, corresponding to the view argument of the Xurrent GraphQL API.

If no fields or relations are specified, only the id attribute of the records is retrieved.

The following simple example retrieves up to 100 enabled skill pools from Xurrent:

const skillPools = Xurrent.graphqlQuery("skillPools", {
fields: ["id", "name", "source", "sourceID"],
filter: { disabled: false }
});

The result is a list of skill pools, containing the id, name, source and source ID attributes.

The next example is more complex and illustrates how to use the relations option:

const problems = Xurrent.graphqlQuery("problems", {
first: 500,
fields: ["id", "subject", "category", "customFields"],
relations: {
manager: { fields: ["jobTitle"] },
serviceInstances: {
first: 5,
fields: ["name"],
relations: { service: { fields: ["name"] } } },
notes: {
last: 1,
fields: ["text"],
}
},
filter: {
impact: { values: ["none", "low"], negate: true },
customFilters: [{ name: "My custom filter", values: ["x"] }]
},
order: [{field: "createdAt", direction: "desc"}]
}, "my-xurrent-graphql-account");

This query retrieves at most 500 problem records, filtered by "Impact is NOT none or low" and "My custom filter is x".

The results are ordered descending by creation date, and include the following fields:

  • The id, subject, category and custom fields of the problem
  • The job title of the problem's manager
  • A list of the first 5 service instances linked to each problem, including the name of the SI and the name of service of the SI
  • The last (most recent) note of each problem

Fields and relations

As can be seen in the example above, when specifying what to retrieve from Xurrent, the query distinguishes between fields and relations.

A "relation" is a link to another Xurrent record type. This can either be a single record, such as the relation to the manager of the problem in the example, or a list of records, such as the relation to service instances. For each relation, you need to specify the fields and relations that you want to retrieve. The example above shows that this is a recursive process, which allows you to retrieve deeply nested objects.

A "field" is everything else, and we refer to this as "scalar" fields. This includes simple fields such as id and subject, which return string values, but also some fields with internal structure, such as custom fields and automation rule expressions.

Limits

The example query above explicitly specifies limits on the maximum number of problems and service instances to retrieve, using the first attribute. We recommend that you carefully consider how much data you need and set the limits as low as possible, especially when you need to retrieve lists of nested relations.

Total nodes limits

One reason for this is that Xurrent imposes a Total Nodes Limit, which is determined based on the specified limits and not on the actual number of records returned.

Suppose that, in the example above, we would have specified a limit of 10.000 problems and 100 service instances. The total node calculation would result in:

  • 10.000 problems +
  • 10.000 * 100 service instances +
  • 10.000 * 1 note

= 1.020.000 nodes. At the time of writing, this is way above the limit imposed by Xurrent, and the query would have been rejected.

With the specified limits of 500 and 5, the total node calculation stays within the limits:

  • 500 problems +
  • 500 * 5 service instances +
  • 500 * 1 note

= 3.500 nodes.

Request rate limits

Another reason for specifying low limits is that each API query counts towards the Request Rate Limit.

Xurrent limits the maximum number of records that can be retrieved per connection to 100, and the automator will automatically paginate queries that have specified a higher limit, performing an API query for each page, until the limit is reached or until all records have been retrieved.

If the limit is set very high and there are many records to retrieve, this may lead to hitting the rate limit.

Generic relations

The Xurrent GraphQL API also has some generic relations to other objects, which means that the type of the related object is not known in advance. For example, the AutomationRule object has an owner field which type is the interface HasAutomationRules, rather than a concrete object. This interface is implemented by objects that can have automation rules, such as Request and Workflow.

The GraphQL - Inline Fragments page of the Xurrent GraphQL Training explains how to write GraphQL queries that work with such generic relations.

The automator also supports such relations, and an example is given below.

const rules = Xurrent.graphqlQuery("automationRules", {
relations: {
owner: {
on: {
Request: { fields: ["requestId", "subject"] },
Workflow: { fields: ["category", "impact"] },
}
}
}
});

for (const rule of rules) {
if (rule.owner.__typename === "Request") {
// ...
} else if (rule.owner.__typename === "Workflow") {
// ...
}
};

This query fetches the owner of a list of automation rules, and selects specific fields depending on the type of the owner.

Note that for generic relations, the result includes a __typename meta-field to support type name introspection, allowing you to handle owners depending on their type.

Automatic retries

All GraphQL functions automatically retry failed requests based on the rules described here.

When all retries are exhausted, an exception is thrown.

Error handling

When something goes wrong, the GraphQL functions will throw an exception, and you can choose to either handle the exception by wrapping the function in a try-catch block, or let the exception go unhandled and abort the package execution.

In case the response from Xurrent includes an errors attribute at the top level, an XurrentGraphqlQueryError exception is raised.

The cause attribute of the exception contains the contents of the errors attribute, and the message attribute of the exception contains the concatenation of all error messages.

For example:

try {
Xurrent.graphqlQuery("...");
} catch (e) {
// Suppose Xurrent responds with an error, then:
log("Exception name", e.name); // = XurrentGraphqlQueryError
log("Exception message", e.message); // = "GraphQL error: message1; message2
log("Exception cause", e.cause); // = [{ message: "message1", location: ... }, { message: "message2", ... }]
}

When performing a mutation (create, update or delete), Xurrent indicates validation errors in a nested errors attribute. If there are any validation errors, the automator's GraphQL functions will throw a XurrentGraphqlValidationError exception containing the details.

For example:

try {
Xurrent.graphqlUpdate("...");
} catch (e) {
// Suppose Xurrent returns a validation error, then:
log("Exception name", e.name); // = XurrentGraphqlValidationError
log("Exception message", e.message); // = "GraphQL error: message1; message2
log("Exception cause", e.cause); // = [{ message: "message1", path: ... }, { message: "message2", ... }]
}

Xurrent.graphqlFindByIds

Performs a query to retrieve multiple records by their Node ID, and returns an object keyed by Node ID. This is based on the root-level nodes field mentioned here in the Xurrent GraphQL API documentation.

The method takes two or three parameters:

  1. An array of Node IDs.
  2. An options object with a single on property, which you can use to specify the fields and relations to retrieve for each record type. See the Generic relations section for more details.
  3. Account name (optional).
const recordsByNodeId = Xurrent.graphqlFindByIds(["nodeId1", "nodeId2"], {
on: {
Request: { fields: ["id", "subject", "impact"] },
Problem: { fields: ["id", "subject", "category"], relations: { ... } }
}
}, "my-xurrent-graphql-account");

const request = recordsByNodeId["nodeId1"];
if (request.impact === "high") {
// ...
};

A practical use case for this method is when you have custom fields for one or more records, and you want to retrieve the details of all custom-suggest field values, which might belong to different record types, in a single query.

const requests = Xurrent.graphqlQuery("requests", { fields: ["customFields"], filter: { ... } });

// Extract all unique Node IDs of the specified custom fields
const suggestFieldNodeIds = requests
.flatMap(r => r.customFields)
.filter(f => ["suggest-field1", "suggest-field2", "suggest-field3"].includes(f.id))
.flatMap(f => f.value ?? [])
.uniq();

// Retrieve details of the records with the specified Node IDs
const suggestFieldDetailsByNodeId = Xurrent.graphqlFindByIds(suggestFieldNodeIds, {
on: {
ConfigurationItem: { ... },
Person: { ... },
// ...
}
});

Xurrent.graphqlCreate

Performs a mutation to create a record in Xurrent.

This method takes two or three parameters:

  1. The record type, for example requests or problems.
  2. An options object that specifies the data of the record to be created, and the fields and relations that should be included in the response.
  3. Account name (optional).

The options object has the following attributes:

  • input: the data of the record to be created, corresponding to the input argument of the Xurrent GraphQL API.
  • fields: the scalar fields to include in the result (optional).
  • relations: the relational fields to include in the results (optional).

Refer to the Fields and relations section for more details about the fields and relations attributes. If neither fields nor relations are specified, the response includes only the id of the created record.

The method supports automatic retries and throws an exception if something goes wrong.

The following example creates a site, specifying the name and remarks, and returns the Node ID and name of the result:

const site = Xurrent.graphqlCreate("sites", {
input: {
name: "New Site",
remarks: "Remarks about the new site"
},
fields: ["id", "name"]
});

Xurrent.graphqlUpdate

Performs a mutation to update a record in Xurrent.

This method takes three or four parameters:

  1. The record type, for example requests or problems.
  2. The Node ID of the record to be updated.
  3. An options object that specifies the data of the record to be updated, and the fields and relations that should be included in the response.
  4. Account name (optional).

The options object has the following attributes:

  • input: the data of the record to be updated, corresponding to the input argument of the Xurrent GraphQL API.
  • fields: the scalar fields to include in the result (optional).
  • relations: the relational fields to include in the results (optional).

Refer to the Fields and relations section for more details about the fields and relations attributes. If neither fields nor relations are specified, the response includes only the id of the updated record.

The method supports automatic retries and throws an exception if something goes wrong.

The following example updates a problem, specifying a new subject and setting some custom fields:

const problem = Xurrent.graphqlUpdate("problems", "NodeIdOfProblem", {
input: {
subject: "New Subject",
customFields: [
{ id: "My custom field 1", value: "New value" },
{ id: "My custom field 2", value: 42 }
]
}
});

Xurrent.graphqlDelete

Performs a mutation to delete a record in Xurrent.

This method takes two or three parameters:

  1. The record type, for example webhooks.
  2. The Node ID of the record to be deleted.
  3. Account name (optional).

Only a few record types in Xurrent support deletion. In most cases, records that are no longer needed should be disabled instead.

The method supports automatic retries and throws an exception if something goes wrong.

Example:

Xurrent.graphqlDelete("webhooks", "NodeIdOfWebhook", "xurrent-graphql");