API Access
Last updated
Last updated
X-Assist allows integration with 3rd party software through its API. It provides access to all features and data available in X-Assist.
The GraphQL API is served from a single endpoint:
For first time users, we recommend using the interactive query tool available at . The tool offers a query editor with autocompletion and a documentation browser which allows you to explore the GraphQL schema of X-Assist.
For example, to retrieve the three most recent events, you would perform the following query:
The API then responds with a JSON object that looks like this:
POST
https://accounts.exop-group.com/oauth/token
client_id
string
The OAuth client ID of your application.
client_secret
string
The OAuth client secret of your application.
grant_type
string
The OAuth grant type to use. Must be set to "client_credentials".
Note that access tokens have a finite lifetime and expire at created_at + expires_in
seconds after the Unix epoch. After this time, you must request a new token from the IAM.
To query the GraphQL endpoint, the request must include an access token in the HTTP Authorization
header (preferred) or the access_token
query parameter.
POST
https://x-assist.exop-group.com/graphql
Authorization
string
The OAuth access token used to authenticate the request. Example value: "Bearer -sc-na0LtIghflDJ8rH8wBDdmRBSyd5iPF0znsVegeY"
query
string
The GraphQL operation to execute. Can be a query, mutation or a subscription. See https://graphql.org/learn/queries/.
operationName
string
Only required if multiple operations are present in the query. See https://graphql.org/learn/queries/#operation-name.
variables
object
A dictionary of dynamic query arguments. See https://graphql.org/learn/queries/#variables.
Here is a full example showing how to retrieve the three most recent events from X-Assist:
Timestamps and other time-related objects are crucial concepts in the X-Assist API, and it is critical that API clients handle them in the right way.
DateRange
objects combine two DateTime
fields to represent the time interval between the two points in time. The lower bound of the date range is always inclusive, while the upper bound is always exclusive.
ISO 8601 formatted durations can also be used in the DateTimeOrDuration
scalar, which is commonly used in the DateFilter
type. Here, durations are interpreted relative to the current time and negative values are permitted. For example, a date filter that covers the last 24 hours looks like this:
The X-Assist GraphQL schema uses the following types to represent geographical data:
GeoPoint
/ GeoPointInput
GeoJSON
The content of X-Assist is available in the following languages:
Chinese
English
French
German
Italian
Japanese
Portuguese
Spanish
The HTTP Accept-Language
header determines the language in which the content of an API response is returned. Additionally, some fields in the GraphQL schema support a language
argument that allows API clients to explicitly request content in a specific language.
For example, clients may wish to retrieve the original English headline of an event in addition to machine translated headline:
Collections of objects are exposed in the X-Assist API in two different ways. Collections with only a few items are exposed as plain lists (i.e. arrays) for simplicity:
Let's re-visit the earlier example query that retrieves the three most recent events:
The events
field in this query is a connection of type EventConnectionWithTotalCount
. Every connection has the fields pageInfo
, nodes
and edges
, and some connections (including the event connection) also provide additional fields such as totalCount
.
To support pagination, the query must be changed and some fields from the PageInfo
object must be added to the selections:
The new query result now contains a cursor that can be used to fetch the next page:
If there are more items in the connection (i.e. hasNextPage
is true
), the next three events can be fetched by passing the cursor value in the after
argument:
This process is repeated until hasNextPage
is false
and the entire collection has been traversed.
Do not change filter predicates or sorting halfway through the pagination process, as this will lead to undefined results.
All applications must treat object IDs as opaque strings and make no assumptions about their content or length.
The encoding scheme of these IDs may also change over time. These changes are backwards compatible (X-Assist will continue to accept IDs in previous formats), but applications that store references to X-Assist objects are encouraged to include the id
field in each query and update the IDs in their own data stores when a change is detected.
Many mutations use optimistic locking to prevent lost updates when multiple users make changes to existing data concurrently. The input objects for these mutations have a mandatory version
field.
When performing a mutation, pass the expected version of the object as input and add the version
field to your selections to get the new version of the object after the update. As an example, the mutation to update a site looks as follows:
The response contains the new version of the site:
If a version mismatch occurs, you will receive an error instead:
Do not make assumptions about the content and the behavior of the version field.
In particular, do not assume that the version of new objects is equal to 1 or that updates only increment the version by one. Be aware that background processes or other events can also change the version of an object without any requests being sent to X-Assist from an API client.
For maximum robustness, treat the version as an opaque string.
The X-Assist API provides different data consistency guarantees for different kinds of operations.
GraphQL mutation payloads provide strong consistency. When you perform a mutation, all fields in the response are guaranteed to return the most recent data and reflect your changes.
However, this does not apply to changes caused indirectly by a mutation. For instance, when you register a new trip in X-Assist, the trip itself will be visible immediately, but the person's itinerary stops (expected locations) will only be updated after a delay because they are re-computed by an asynchronous background job.
GraphQL subscriptions offer the same guarantees as mutations.
Unlike mutations, regular GraphQL queries only offer eventual consistency. This means that changes may not immediately visible to all clients, and that a query can return stale data.
Regular users and OAuth applications can make up to 1000 requests per hour, with a maximum number of 25 + 1 burst requests in rapid succession. This limit can be raised once your solution/integration has been validated by EXOP.
The HTTP response headers will show your current rate limit status:
When a request is blocked due to rate limiting, X-Assist will respond with HTTP status 429 ("Too Many Requests"):
X-RateLimit-Limit
The maximum number of available burst requests when no previous requests have been made, or the previous requests occurred long enough ago.
X-RateLimit-Remaining
The number of requests that can be made immediately (i.e. the remaining burst request count).
X-RateLimit-Reset
The time in seconds until the full number of burst requests will be available again.
Retry-After
Only present when the request was blocked to due rate limiting. For allowed requests that can be retried later (see note below), this header will contain the duration to wait in seconds before the request will be allowed.
When the request is forbidden due to complexity constraints, this header will have no value (i.e. an empty string).
Not all requests are equal. For example, a request with a very complex GraphQL operation may consume multiple "logical requests" at once.
It is therefore possible to create requests that will never succeed because they would consume more logical requests than the maximum number of available burst requests.
The X-Assist API uses to authenticate requests.
These tokens are issued by the module, which implements a standards-compliant OAuth 2.0 authorization server and OpenID Connect provider. You can access its configuration data at .
Server-side applications should use the to request an access token from the IAM's token endpoint.
If you do not want to implement the token management yourself, you can use one of the existing for your programming language/environment instead.
Fields with the scalar type DateTime
are the most basic ones. A DateTime
value is an that represents an instant on the global timeline. DateTime
values in API responses are usually in UTC (indicated by a trailing Z
), but API clients must be able to handle values with other offsets as well. Unqualified DateTime
inputs (with an unspecified offset) are assumed to be in UTC.
A DateTime
field on an object is frequently accompanied by a timeZone
field that contains an that API clients can use to convert the UTC value back into local time. The time zone field can be on the same object as the timestamp itself (as is the case with HotelSegment
objects, for example), or within a nested object (e.g. FlightLeg
objects do not have timeZone
fields, but the associated airports do).
Durations that do not refer to a fixed point in time are represented either as integers or as values of the type Duration
. For integers, the value is given in seconds. Duration
fields use .
These types always use / as spatial reference system.
Large collections use , a cursor-based pagination mechanism and the de-facto standard used by many GraphQL APIs.
Some types in X-Assist's GraphQL schema implement the Node
interface which allows API clients to retrieve one or more objects by ID. Refer to the chapter in the GraphQL documentation for further information.
API clients can handle such errors by re-fetching the object (see ) to get the current version, and then retrying the mutation.
We loosely follow the for rate limiting headers, but we do not use fixed-length time windows.