Reference documentation for the Tray.io Embedded GraphQL APIs
Please visit our Tray Embedded Documentation to familiarize yourself with Tray Embedded and learn how it can help you put the automation power of Tray.io in the hands of your End Users.
Use the examples with queries and mutations and the associated code samples to test out scripts using different input/filter criteria (e.g. 'Get User by Id' or 'Get Solution Instances by owner')
You can also click 'Run in Postman' button below to import and run the collection in your local Postman app. You can also try out our Insomnia Http Client collection as a local testing environment.
Note: The Tray GraphQL API is a backend API only and calls must be invoked server-side. Client-side Javascript calls to the API should not be made as they will be blocked by CORS.
Our demo app (built using Apollo GraphQL) is a good illustration of how you can create a UI which presents an End User with their available Solutions while making all API calls server-side - using a button to hand over the Solution Instance configuration to our End User Config Wizard in a pop-up or iframe.
When interacting with GraphQL APIs, depending on the call, you will need to use
Some calls like Get Authentications support both master and user token where using a master token gives all auths in your orgnaziation workspace while a user token only gives auths owned by that end user.
The Tray Embedded APIs use standard conventions for pagination, compatible with the Relay Pagination Container specification . Note that in our demo app all mutations make use of clientMutationId - if this parameter is specified in the input to the mutation, it will be returned unchanged in the payload. It is not necessary to use clientMutationId but it is used in Relay and Apollo.
Two very helpful articles on pagination with GraphQL can be found at https://www.howtographql.com/react-relay/8-pagination and https://blog.apollographql.com/tutorial-pagination-d1c3b3ee2823
Using a query such as Get Users it is possible to specify the cursor and page information that you need for pagination of results:
query { users(first: 2, after:"OGRiNDY2YzAtYTA0MS00OTM0LWFmMzUtMTU4YzcwNGM1OWRl") { edges { node { id name externalUserId } cursor } pageInfo { hasPreviousPage hasNextPage startCursor endCursor } } }
pageInfo is what GraphQL calls a connection. A connection stores additional data about the context of each item (edge/node), i.e. about the position of the item in the list as well as the items in the list that come directly before and after it.
Note that after in the above query specifies a particular cursor to begin the list from.
From the results you can see that the necessary page and cursor information is returned, as needed for pagination of results:
{ "data": { "users": { "edges": [ { "node": { "id": "d9b7302f-xxx-xxx-xxx-b403242e3f26", "name": "Danton Black", "externalUserId": "96fxxxx85cd7" }, "cursor": "ZDliNzMwMmYtxxxxxxxxxxxZmUtYjQwMzI0MmUzZjI2" }, { "node": { "id": "8db466c0-xxx-xxx-xxx-158c704c59de", "name": "Miguel Rangel", "externalUserId": "96b9327xxxxxxx-xxx86ce-b79e66872daa" }, "cursor": "OGRiNDY2YxxxxxxxxLWFmMzUtMTU4YzcwNGM1OWRl" } ], "pageInfo": { "hasPreviousPage": true, "hasNextPage": true, "startCursor": "ZDliNzxxxxxxxxxxxxxxxxxxxUtYjQwMzI0MmUzZjI2", "endCursor": "OGRiNDY2YzAxxxxxxxxxxxxxMTU4YzcwNGM1OWRl" } } } }
All endpoints are limited at a rate of 30 requests per second
There is limited burst capacity to allow for momentary spikes in usage, as long as the overall rate is not broken in a set window.
If you exceed a certain rate of requests, you will receive a response similar to the following:
{
"data": null,
"errors": [
{
"message": "Rate limit exceeded",
"path": [
"users"
],
"locations": [
{
"line": 2,
"column": 3
}
],
"extensions": {
"name": "PreconditionError",
"time_thrown": "2023-06-29T14:55:54.518Z",
"code": "access_not_allowed"
}
}
]
}
The path
property will tell you the query or the mutation that exceeded the threshold.
For the Get Users query, we recommend not using the externalUserId
as a means of looking up or retrieving Tray users in a high-throughput production environment.
In this case, you should consider storing the Tray user id
in your own application or data store, in order to facilitate creation of user tokens / deletion of users without making repeated calls to the Get Users query.
Similary, you should consider storing Tray Ids for other resources such as Solution Instances or Authentications.
Exactly how you will manage this will depend on your usecase and setup.
However these are the considerations that you need to be aware of.
Click here to download the Postman
collection. Or Fork the collection using the button below:
You can set environment variables on the Postman Collection to manage base_url
, master_token
, user_token
across different regions.
Click here to download our collection for the Insomnia Http client
This will provide you with a local testing environment which allows you to very quickly run queries and mutations on your live data, before inspecting the results.
Refer this page for detailed instructions on using the insomnia collection effectively.
Tray.io supports multiple regions to manage your end users.
The base_url
for all requests would change depending on the region your Tray account is in. This is indicated in the URL of the Tray app. For US (default), your Tray app URL is app.tray.io
, for EU app.eu1.tray.io
and for APAC, it is app.ap1.tray.io
.
Here is the list of base_url
for the Embedded APIs:
Tray operates in 3 segregated AWS regions:
Region | Base URL |
---|---|
US (AWS-West) | https://tray.io/graphql |
EU (AWS-Ireland) | https://eu1.tray.io/graphql |
APAC (AWS-Sydney) | https://ap1.tray.io/graphql |
Get all users including their name, id, and externalUserId.
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The query accepts a filter key criteria
which can take in following fields:
field | Notes |
---|---|
id | This is generated by Tray when you create a end user using Mutations/Users/Create New User |
externalUserId | This will be provided by you upon the time of creation. It is the unique Id of the user in your own app and hence a mapping is created between your end user and their corresponding Tray user |
name | This will be provided by you upon the time of creation. It is the name of the end user in your own app |
isTestUser | This will be provided by you upon the time of creation. This is a boolean flag that tells whether the user is billable or not |
Here are some sample queries:
query { users { edges { node { name id externalUserId isTestUser } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users (criteria: {userId: "13b3ab9c-XXXX-XXXX-XXXX-c4dd07fbbfa4"}){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users ( criteria: { externalUserId: "my-external-user-id" } ){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users ( criteria: { name: "Billy Bluehat" } ){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users ( criteria: { isTestUser: true } ){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users ( criteria: { isTestUser: true, name: "Billy Bluehat" } ){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
The query also accepts following pagination parameters:
parameter | Notes |
---|---|
first | number to filter the first n users from response |
last | number to filter the last n users from response |
before | pagination parameter to go to previous page of response |
after | pagination parameter to go to next page of repsonse |
Here are some sample queries:
query { users (after: "MTNiM2FiOWMtZTIyMi00NzM5LWE2OWItYzRkZDA3ZmJiZmE0"){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users (first: 2){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
query { users (first: 5, after: "MTNiM2FiOWMtZTIyMi00NzM5LWE2OWItYzRkZDA3ZmJiZmE0"){ edges { node { name id externalUserId } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } }
It can return the following data:
Returned Data | subfields | Notes |
---|---|---|
name | ||
id | Tray ID of the user | |
externalUserId | unique id for the user in your database | |
cursor | used for pagination | |
pageinfo | hasNextPage, endCursor, hasPreviousPage, startCursor | used for pagination |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "query {\n users {\n edges {\n node {\n name\n id\n externalUserId\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n hasPreviousPage\n startCursor\n }\n }\n}", "variables": {} }'
{- "data": {
- "users": {
- "edges": [
- {
- "node": {
- "name": "Michael Scott",
- "id": "13b3ab9c-XXXX-XXXX-XXXX-XXXX07fbbfa4",
- "externalUserId": "668341a0-XXXX-XXXX-XXXX-XXXX5c9ba02b"
}, - "cursor": "MTNiM2FiOWMtZTIyMi00NzM5LWE2OWItYzRkZDA3ZmJiZmE0"
}, - {
- "node": {
- "name": "Dwight Schrute",
- "id": "1a71daf1-97ba-4036-a5cc-dbb4ab325a55",
- "externalUserId": "323442a0-XXXX-XXXX-XXXX-XXXX5c9ba02b"
}, - "cursor": "XXXXXXXXZjEtOTdiYS00MDM2LWE1Y2MtZGJiNGFiMzI1YTU1"
}
], - "pageInfo": {
- "hasNextPage": false,
- "endCursor": "XXXXXXXXZjEtOTdiYS00MDM2LWE1Y2MtZGJiNGFiMzI1YTU1",
- "hasPreviousPage": false,
- "startCursor": "XXXXXXXXOWMtZTIyMi00NzM5LWE2OWItYzRkZDA3ZmJiZmE0"
}
}
}
}
Create a new external user of your Embedded application.
To exclude users from billing you can mark them as test users (see our Billing page for more info).
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following as inputs:
Input | Required | Note |
---|---|---|
name | Yes | |
externalUserId | Yes | can be used to link the End User to an ID you already have for them in your external database. It's important to be able to access key info, such as contact email, you may have stored in your external system. Example: dealing with Expired Auths |
isTestUser | No | Boolean value that defaults to true (billable user) if you don't pass it. A test user allows you to create Solution Instances and run test data for a user without incurring any charges. This is useful for end to end testing. Please read our billing page here. |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { createExternalUser(input: { name: "Dwight Schrute", externalUserId: "my-apps-user-id-for-dwight" }) { userId } }
mutation { createExternalUser(input: { name: "Dwight Schrute", externalUserId: "my-apps-user-id-for-dwight", clientMutationId: "some-mutation-id" #OPTIONAL - only needed for legacy Relay & Apollo clients }) { userId clientMutationId #OPTIONAL } }
It can return the following data:
Returned Data | Notes |
---|---|
userId | Tray Id of the user |
clientMutationId | Only relevant if using the Relay GraphQL client |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation($name: String!, $externalUserId: String!) {\n createExternalUser(input: { \n name: $name, \n externalUserId: $externalUserId \n }) {\n userId\n }\n}", "variables": { "name": "Dwight Schrute", "externalUserId": "my-apps-user-id-for-dwight" } }'
{- "data": {
- "createExternalUser": {
- "userId": "d235e0b1-XXXX-XXXX-XXXX-7d165cdf4171"
}
}
}
Create an accessToken for a given userId
A user token allows access to the APIs which require a user token (Create Solution Instance, Get Solution Instances, Create User Auth etc.) and should be passed as a Bearer in the Authorization header when calling those APIs.
Note: This access token expires after 2 days
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following as inputs:
Input | Required | Notes |
---|---|---|
userId | Yes | obtained when creating a user (Mutations/Users/Create New User) or getting users (Queries/Users/Get Users) |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { authorize(input: { userId: "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6" }) { accessToken } }
mutation { authorize(input: { userId: "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6", clientMutationId: "my-mutation-id" #OPTIONAL - only needed for legacy Relay & Apollo clients }) { accessToken clientMutationId #OPTIONAL } }
It can return the following data:
Returned Data | Notes |
---|---|
accessToken | a persistent token (valid for 2 days) that should be securely stored in your application. Allows access to the APIs which require a user token (e.g. createSolutionInstance) |
clientMutationId | Only relevant if using the Relay GraphQL client |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($userId: ID!) {\n authorize(input: {\n userId: $userId\n }) {\n accessToken\n }\n}", "variables": { "userId": "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6" } }'
{- "data": {
- "authorize": {
- "accessToken": "3346c4c957b74ca2a803dacf1485816d3fedde3a54b547b997cd64b72375a9d4"
}
}
}
Creates an authorization code that is used to configure config wizard URL or auth-only dialog URL. Refer this page on how it's used.
Note: This is a one-time use code which expires after 5 minutes
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following as inputs:
Input | Required | Notes |
---|---|---|
userId | Yes | obtained when creating a user (Mutations/Users/Create New User) or getting users (Queries/Users/Get Users) |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { generateAuthorizationCode( input: { userId: "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6" }) { authorizationCode } }
mutation { generateAuthorizationCode( input: { userId: "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6", clientMutationId: "my-mutation-id" #OPTIONAL - only needed for legacy Relay & Apollo clients }) { authorizationCode clientMutationId #OPTIONAL } }
It can return the following data:
Returned Data | Notes |
---|---|
authorizationCode | this is required to activate the Configuration Wizard |
clientMutationId | Only relevant if using the Relay GraphQL client |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($userId: ID!) {\n generateAuthorizationCode( input: {\n userId: $userId\n }) {\n authorizationCode\n }\n}", "variables": { "userId": "d869ec65-XXXX-XXXX-XXXX-ac5c1a3958b6" } }'
{- "data": {
- "generateAuthorizationCode": {
- "authorizationCode": "a61eb70884f9af554a941876a66560b4bbfe48cc"
}
}
}
Can be used to mark a user as a test user allowing you to create Solution Instances and run test data for a user without incurring any charges (see our Billing page for more info)
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following as inputs:
Input | Required | Note |
---|---|---|
id | Yes | |
isTestUser | Yes | Booelan value. A test user allows you to create Solution Instances and run test data for a user without incurring any charges |
Here is an example mutation:
mutation { updateExternalUser(input: { userId: "53824943-XXXX-XXXX-XXXX-088aee14038e", isTestUser: true }) { user{ name id externalUserId isTestUser } } }
mutation { updateExternalUser(input: { userId: "53824943-XXXX-XXXX-XXXX-088aee14038e", isTestUser: "true", clientMutationId: "some-mutation-id" #OPTIONAL - only needed for legacy Relay & Apollo clients }) { user{ name id externalUserId isTestUser clientMutationId #OPTIONAL } } }
It can return the following data:
Returned Data | Notes |
---|---|
name | |
id | |
externalUserId | |
isTestUser |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($userId: ID!, $isTestUser: Boolean ){\n updateExternalUser(input: {\n userId: $userId,\n isTestUser: $isTestUser\n }) {\n user{\n\t\t\tname\n\t\t\tid\n\t\t\texternalUserId\n\t\t\tisTestUser\n\t\t}\n }\n}", "variables": { "userId": "53824943-XXXX-XXXX-XXXX-088aee14038e", "isTestUser": true } }'
{- "data": {
- "updateExternalUser": {
- "user": {
- "name": "Dwaight Schrute",
- "id": "ad15b7ae-4c2d-4574-bf4f-5e8e1097a6e9",
- "externalUserId": "test003",
- "isTestUser": true
}
}
}
}
This mutation is used to delete a user from your Embedded application.
Note: Deleting a user will also disable and delete all Solution Instances associated with that user.
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following as inputs:
Input | Required | Notes |
---|---|---|
userId | Yes | obtained with Queries/Users/Get Users |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { removeExternalUser(input: { userId: "53824943-XXXX-XXXX-XXXX-088aee14038e" }) { clientMutationId # REQUIRED - must specify as return field, not required to provide this in mutation function } }
mutation { removeExternalUser(input: { userId: "53824943-XXXX-XXXX-XXXX-088aee14038e", clientMutationId: "someClientMutationId" }) { clientMutationId # REQUIRED - must specify as return field } }
It can return the following data:
Returned Data | Notes |
---|---|
clientMutationId | while this data is only relevant if using the Relay GraphQL client, it is actually required here as currently this mutation does not return any other data |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation {\n removeExternalUser(input: {userId: $userId}) {\n clientMutationId # REQUIRED - must specify as return field, not required to provide this in mutation function\n }\n}", "variables": { "userId": "53824943-XXXX-XXXX-XXXX-088aee14038e" } }'
{- "data": {
- "removeExternalUser": {
- "clientMutationId": null
}
}
}
Authentications represent the auth data used for authenticating to all the services that you would be integrating with Tray.
Query for retrieving the authentications used by your end users. You can also retrieve the auths created within your main embedded org by passing the Master token in the headers.
This query can be used to retrieve the authentications for a particular user.
Please also see our guide to Mapping and Editing Auths
Required Token | Notes |
---|---|
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application If Master token is used will return all the authentications from the Embedded Organization including all the auths created by owner/admin/contributors and NOT including your end user auths. |
Here is an example query:
query { viewer { authentications { edges { node { id name customFields service { id, name, icon, title, version } serviceEnvironment { id title } } } pageInfo{ hasNextPage hasPreviousPage } } } }
Returned Data | Subfields | Notes |
---|---|---|
id | the authentication id | |
name | the arbitrary name the end user has given to the authentication | |
service | id, name, icon, title, version | details of the service the authentication is for |
serviceEnvironment | id, title | relevant when Importing Authentications |
pageInfo | hasNextPage, hasPreviousPage | can be used for pagination |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_OR_MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "query {\n viewer {\n authentications {\n edges {\n node {\n id\n name\n customFields\n service {\n id,\n name,\n icon,\n title,\n version\n }\n }\n }\n pageInfo{\n hasNextPage\n hasPreviousPage\n }\n }\n }\n}", "variables": {} }'
{- "data": {
- "viewer": {
- "authentications": {
- "edges": [
- {
- "node": {
- "id": "569xxxxxx-xxxxx-xxxx-7e829d2c56d",
- "name": "Roger Ramjet's Slack Account",
- "service": {
- "id": "227312c4-3e5f-4b0d-22a0-5b9630ece00e",
- "name": "slack",
- "title": "Slack",
- "version": "1"
}
}
}, - {
- "node": {
- "id": "0b07xxxxxx-xxxxx-xxxx-b8d4121471c3",
- "name": "Roger Ramjet's Trello Account",
- "service": {
- "id": "72cef4e9-229f-4d7c-97e3-b6cd4d92146f",
- "name": "trello",
- "title": "Trello",
- "version": "1"
}
}
}, - {
- "node": {
- "id": "a29dxxxxxx-xxxxx-xxxx-99901f41c698",
- "name": "Roger Ramjet's Slack Account 2",
- "service": {
- "id": "227312c4-3e5f-4b0d-22a0-5b9630ece00e",
- "name": "slack",
- "title": "Slack",
- "version": "1"
}
}
}
]
}
}
}
}
Mutations for modifying the authentications used by your end users. You can also modify the auths created within your main embedded org by passing the Master token in the headers.
Create a user authentication for a service (e.g. Dropbox or Airtable) that is used in your Embedded application.
For full instructions on using this mutation please see Importing Authentications
To generate the inputs needed, navigate to your Tray and scroll down to the section titled 'Authentication import generator'
Required Token | Notes |
---|---|
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application |
Argument | Required | Note |
---|---|---|
name | Yes | Arbitrary. Can help you categorize authentications according to service and End User |
serviceId | Yes | See Importing Authentications |
serviceEnvironmentId | Yes | See Importing Authentications |
data | Yes | Used to specify auth data such as api key and domain. See Importing Auths |
formData | No | Data that may be seen in the authentication dialog in the workflow builder, e.g. 'subdomain' |
scopes | Yes | Can be empty array as below example. For setting scopes of access (read/write access to components) |
hidden | no | Controls if authentication should be hidden in UI. Default is False |
Here is an example mutation:
mutation { createUserAuthentication (input:{ name: "my-test-sqs-authentication-1", serviceId: "e73d8e91-XXXX-XXXX-XXXX-37df289242", serviceEnvironmentId: "a84eu2880-XXXX-XXXX-XXXX-7edd82904d", data: "{\"region\":\"us-east-1\",\"account_id\":\"1234\",\"access_key\":\"accesskey\",\"secret_key\":\"secretkey\"}", scopes: [], hidden: true }) { authenticationId } }
mutation { createUserAuthentication (input:{ name: "my-test-sqs-authentication-1", serviceId: "e73d8e91-XXXX-XXXX-XXXX-37df289242", serviceEnvironmentId: "a84eu2880-XXXX-XXXX-XXXX-7edd82904d", data: "{\"region\":\"us-east-1\",\"account_id\":\"1234\",\"access_key\":\"accesskey\",\"secret_key\":\"secretkey\"}", scopes: [], hidden: true, clientMutationId: "some-mutation-id" #OPTIONAL - only needed for legacy Relay & Apollo clients }) { authenticationId clientMutationId #OPTIONAL } }
Returned Data | Notes |
---|---|
authenticationId | This will be needed when using createSolutionInstance as detailed in Importing Authentications |
clientMutationId | Only relevant if using the Relay GraphQL client |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_OR_MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation (\n $authenticationName: String!,\n $serviceId: String!,\n $serviceEnvironmentId: String!,\n $authenticationData: Json!,\n $hidden: Boolean!\n ){ createUserAuthentication (input:{\n name: $authenticationName,\n serviceId: $serviceId,\n serviceEnvironmentId: $serviceEnvironmentId,\n data: $authenticationData,\n scopes: [],\n hidden: $hidden\n }) {\n authenticationId\n }\n}", "variables": { "authenticationName": "my-test-sqs-authentication-1", "serviceId": "e73d8e91-XXXX-XXXX-XXXX-37df289242", "serviceEnvironmentId": "a84eu2880-XXXX-XXXX-XXXX-7edd82904d", "authenticationData": "{\"region\":\"us-east-1\",\"account_id\":\"1234\",\"access_key\":\"accesskey\",\"secret_key\":\"secretkey\"}", "hidden": true } }'
{- "data": {
- "createUserAuthentication": {
- "authenticationId": "8ffexxxx-xxxx-xxxx-xxxx-xxxxxx7e8c1d"
}
}
}
Delete a user authentication
Required token | Notes |
---|---|
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application |
The mutation accepts the following as inputs:
Input | Required | Notes |
---|---|---|
authenticationId | Yes | obtained with Queries/Users/Get User Authentications also see our guide to Mapping and Editing Auths |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { removeAuthentication(input: { authenticationId: "dd36c246-XXXX-XXXX-XXXX-a600be2b39fe" }) { clientMutationId # REQUIRED - must specify as return field, it will be returned as NULL as it's not passed } }
mutation { removeAuthentication(input: { authenticationId: "dd36c246-XXXX-XXXX-XXXX-a600be2b39fe", clientMutationId: "some-mutaion-id" }) { clientMutationId # REQUIRED - must specify as return field } }
It can return the following data:
Returned Data | Notes |
---|---|
clientMutationId | while this data is only relevant if using the Relay GraphQL client, it is actually required here as currently this mutation does not return any other data |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_OR_MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($authenticationId: ID!){\n removeAuthentication(input: { authenticationId: $authenticationId }) {\n clientMutationId\n }\n}", "variables": { "authenticationId": "dd36c246-XXXX-XXXX-XXXX-a600be2b39fe" } }'
{- "data": {
- "removeAuthentication": {
- "clientMutationId": null
}
}
}
Retrive a list of solutions using various filters and pagination parameters.
Click 'Examples' to see different types of queries you can make when listing solutions
Required Token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The query accepts the following criteria:
Criteria | Notes |
---|---|
tags | If you have created tags in the Solution Editor, this field can be used to filter Solutions in your external application |
Here are some example queries:
query { viewer { solutions { edges { node { id title description tags customFields { key value } configSlots { externalId title defaultValue } authSlots { externalId title } } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } }
query { viewer { solutions (criteria: { tags: [ "marketing", "marketo" ] }) { edges { node { id title description tags customFields { key value } configSlots { externalId title defaultValue } authSlots { externalId title } } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } }
query { viewer { solutions(first: 5) { edges { node { id title description tags customFields { key value } configSlots { externalId title defaultValue } authSlots { externalId title } } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } }
query { viewer { solutions(first: 1, after: "MTNiM2FiOWMtZTIyMi00NzM5LWE2OWItYzRkZDA3ZmJiZmE0") { edges { node { id title description tags customFields { key value } configSlots { externalId title defaultValue } authSlots { externalId title } } cursor } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } }
Returned Data | Subfields | Notes |
---|---|---|
id | The solution id which needs to be passed when using the createSolutionInstance mutation. | |
title | ||
description | ||
configSlots | externalId title defaultValue |
This can be used to expose the externalId of Config Data which is required when Importing External Data |
authSlots | externalId title |
Array of all the auths required by your solution |
tags | If you have created tags in the Solution Editor, this field can be used to filter Solutions in your external application | |
custom fields | You can set these on the solution settings page. |
You can paginate the results of this query using the methods discussed in Pagination
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "query {\n viewer {\n solutions {\n edges {\n node {\n id\n title\n description\n tags\n customFields {\n key\n value\n }\n configSlots {\n externalId\n title\n defaultValue\n }\n authSlots {\n title\n externalId\n }\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n hasPreviousPage\n startCursor\n }\n }\n }\n}", "variables": {} }'
{- "data": {
- "viewer": {
- "solutions": {
- "edges": [
- {
- "node": {
- "id": "28233cac-XXXX-XXXX-XXXX-e464a6881c04",
- "title": "New Marketo Leads MailChimp Campaign",
- "description": "Add newly created Marketo leads to the New Leads MailChimp Campaign",
- "tags": [
- "marketing"
], - "customFields": [
- {
- "key": "my_custom_field",
- "value": "myCustomFieldValue"
}
], - "configSlots": [
- {
- "externalId": "external_campaignId",
- "title": "campaign ID",
- "defaultValue": "1234"
}
], - "authSlots": [
- {
- "externalId": "external_marketo_authentication",
- "title": "Marketo authentication"
}, - {
- "externalId": "external_mailchimp_authentication",
- "title": "mailchimp authentication"
}
]
}, - "cursor": "MjgyMzNjYWMtNzc1ZS00MTNlLWIyYWYtZTQ2NGE2ODgxYzA0"
}
], - "pageInfo": {
- "hasNextPage": false,
- "endCursor": "MjgyMzNjYWMtNzc1ZS00MTNlLWIyYWYtZTQ2NGE2ODgxYzA0",
- "hasPreviousPage": false,
- "startCursor": "MjgyMzNjYWMtNzc1ZS00MTNlLWIyYWYtZTQ2NGE2ODgxYzA0"
}
}
}
}
}
Solution Instances are the end user's configuration of your Solutions. Instances contain their own auths and config data.
Return the Solution Instances associated with a particular user.
Pay particular attention to solutionVersionFlags as a piece of returned data, which indicates if the Instance needs upgrading due to new information being required from the End User. For more information, refer the decision table.
Required token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. If using a Master token it is possible to filter Solution Instances by the owner of the Solution Instance, or by the ID of the Solution which it came from |
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application If a User token is used, the Solution Instances displayed will only be those owned by that End User |
The query accepts the following filter criteria:
Criteria | Notes |
---|---|
solutionId | Can be used to filter based on the Solution which the Instance came from. If used with a User Token it will only return instances owned by that user |
owner | This is the userId of an End User. Can only be used with a Master Token, in order to filter Solution Instances of a particular user |
Note that it is possible to filter by both owner and solutionId at the same time.
Returned Data | Subfields | Notes |
---|---|---|
totalCount | Note this is a top-level field, so is specified before 'edge' as per example query below The results returned by the totalCount will depend on the filter criteria specified: If solutionId is specified the total count will refer to the solution instances for that particular solution If owner (userId) is specified (when using a Master Token) the total count will refer to the solution instances for that end user If owner and solutionId are both specified the total count will refer to the solution instances for that user and for that solution |
|
id | the solutionInstance id | |
name | the name (derived from the parent Solution) | |
enabled | boolean to indicate whether the solutionInstance has been activated using Update Solution Instance | |
created | the date and time the solutionInstance was created | |
solutionVersionFlags | hasNewerVersion requiresUserInputToUpdateVersion requiresSystemInputToUpdateVersion |
boolean flags used to indicate if an underlying Solution has a newer version which might need upgrading as explained in Updating / Upgrading Solution Instances |
solution | id title description customFields configSlots authSlots |
details of the parent Solution |
workflows | id triggerUrl sourceWorkflowId sourceWorkflowName |
triggerUrl is the webhook url for the End User's version of that workflow (see Retrieving Webhook URLs) |
configValues | externalId value |
any config data that has been set for the End User of the solutionInstance |
authValues | externalId authId |
authentications associated with this solutionInstance |
You can paginate the results of this query using the methods discussed in Pagination
Here are some example queries:
query { viewer { solutionInstances(criteria: { owner: "13b3ab9c-XXXX-XXXX-XXXX-c4dd07fbbfa4" }) { edges { node { id name enabled owner created solutionVersionFlags { hasNewerVersion requiresUserInputToUpdateVersion requiresSystemInputToUpdateVersion } workflows { edges { node { triggerUrl id sourceWorkflowId sourceWorkflowName } } } authValues { externalId authId } configValues { externalId value } } cursor } pageInfo { startCursor endCursor hasNextPage hasPreviousPage } } } }
query { viewer { solutionInstances(criteria: { solutionId: "b73d4e07xxx-xxx-xxx-xxx-xxxafad23d94", owner: "13b3ab9c-XXXX-XXXX-XXXX-c4dd07fbbfa4" }) { edges { node { id name enabled owner created solutionVersionFlags { hasNewerVersion requiresUserInputToUpdateVersion requiresSystemInputToUpdateVersion } workflows { edges { node { triggerUrl id sourceWorkflowId sourceWorkflowName } } } authValues { externalId authId } configValues { externalId value } } cursor } pageInfo { startCursor endCursor hasNextPage hasPreviousPage } } } }
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_OR_MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "query ($ownerId: String!){\n\tviewer {\n\t\tsolutionInstances(criteria: { owner: $ownerId }) {\n\t\t\tedges {\n\t\t\t\tnode {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tenabled\n\t\t\t\t\towner\n\t\t\t\t\tcreated\n\t\t\t\t\tsolutionVersionFlags {\n\t\t\t\t\t\thasNewerVersion\n\t\t\t\t\t\trequiresUserInputToUpdateVersion\n\t\t\t\t\t\trequiresSystemInputToUpdateVersion\n\t\t\t\t\t}\n\t\t\t\t\tworkflows {\n\t\t\t\t\t\tedges {\n\t\t\t\t\t\t\tnode {\n\t\t\t\t\t\t\t\ttriggerUrl\n\t\t\t\t\t\t\t\tid\n\t\t\t\t\t\t\t\tsourceWorkflowId\n sourceWorkflowName\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tauthValues {\n\t\t\t\t\t\texternalId\n\t\t\t\t\t\tauthId\n\t\t\t\t\t}\n\t\t\t\t\tconfigValues {\n\t\t\t\t\t\texternalId\n\t\t\t\t\t\tvalue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcursor\n\t\t\t}\n\t\t\tpageInfo {\n\t\t\t\tstartCursor\n\t\t\t\tendCursor\n\t\t\t\thasNextPage\n\t\t\t\thasPreviousPage\n\t\t\t}\n\t\t}\n\t}\n}", "variables": { "ownerId": "13b3ab9c-XXXX-XXXX-XXXX-c4dd07fbbfa4" } }'
{- "data": {
- "viewer": {
- "solutionInstances": {
- "edges": [
- {
- "node": {
- "id": "533d48e8-XXXX-XXXX-XXXX-74ff887198d3",
- "name": "Sample Instance",
- "enabled": true,
- "owner": "13b3ab9c-XXXX-XXXX-XXXX-c4dd07fbbfa4",
- "created": "2019-12-03T21:11:09.456Z",
- "solution": {
- "id": "b73d4e07xxx-xxx-xxx-xxx-xxxafad23d94",
- "title": "Slack webhook solution",
- "description": "sends a message to a slack channel of your choice"
}, - "solutionVersionFlags": {
- "hasNewerVersion": true,
- "requiresUserInputToUpdateVersion": true,
- "requiresSystemInputToUpdateVersion": false
}, - "workflows": {
- "edges": [
- {
- "node": {
- "triggerUrl": null,
- "id": "89f8ebeb-XXXX-XXXX-XXXX-be070f3cd0f8",
- "sourceWorkflowId": "3af6461f-XXXX-XXXX-XXXX-91ada5769f90"
}
}
]
}, - "authValues": [
- {
- "externalId": "external_slack_authentication",
- "authId": "dcbc11f1-XXXX-XXXX-XXXX-b7f90dafcf28"
}
], - "configValues": [ ]
}, - "cursor": "NTMzZDQ4ZTgtNjM2Zi00M2FkLTk1ZjItNzRmZjg4NzE5OGQz"
}
], - "pageInfo": {
- "startCursor": "NTMzZDQ4ZTgtNjM2Zi00M2FkLTk1ZjItNzRmZjg4NzE5OGQz",
- "endCursor": "NTMzZDQ4ZTgtNjM2Zi00M2FkLTk1ZjItNzRmZjg4NzE5OGQz",
- "hasNextPage": false,
- "hasPreviousPage": false
}
}
}
}
}
This mutation is used to create a Solution Instance for an End User who has chosen to activate a particular Solution for their own use.
The steps involved in activating a Solution Instance for an End User are:
Use this mutation to create a Solution Instance which returns a id
Generate a Config Wizard authorization code with Users/Mutations/Create Config Wizard Authorization Code
Use the id from step 1 and the auth code from step 2 to activate the pop-up Configuration Wizard for the End User with the following url:
https://embedded.tray.io/external/solutions/${partnerId}/configure/${solutionInstanceId}?code=${authorizationCode}
Your app will receive a tray.configPopup.finish PostMessage as explained in Dealing with the Config Wizard
Once the Solution Instance is configured for the End User, use Solution Instances/Mutations/Update Solution Instance to set the status to 'enabled'
Required token | Notes |
---|---|
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
solutionId | Yes | obtained with Solutions/Queries/Get Solutions |
instanceName | Yes | |
authValues | No | can be used to import end user authentications. see Importing Auths |
configValues | No | can be used to import external data see Importing External Data |
Here is an example mutation:
mutation { createSolutionInstance(input: { solutionId: "b3422397-XXXX-XXXX-XXXX-57e7e66771b3" instanceName: "PetersGraphQLInstance" }) { solutionInstance { id name enabled created authValues { authId externalId } configValues { value externalId } solution { id title description tags customFields configSlots } workflows { edges { node { id sourceWorkflowId sourceWorkflowName triggerUrl } } } solutionVersionFlags { hasNewerVersion requiresUserInputToUpdateVersion requiresSystemInputToUpdateVersion } } } }
It can return the following data:
Returned Data | Subfields | Notes |
---|---|---|
id | ||
name | ||
created | ||
enabled | defaults to False so must be set to True with Mutations/Solution Instances/Update Solution Instance - Enable | |
solution | id, title, description, tags, customFields, configSlots | details of the parent solution |
workflows | id, sourceWorkflowId, sourceWorkflowName, triggerUrl | details of the source workflows, including webhook url (triggerUrl) |
authValues | authId, externalId | details of the auths associated with the instance |
configValues | value, externalId | details of config values associated with the user |
solutionVersionFlags | hasNewerVersion, requiresUserInputToUpdateVersion, requiresSystemInputToUpdateVersion | boolean flags used to indicate if an underlying Solution has a newer version which might need upgrading as explained in Updating / Upgrading Solution Instances |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($solutionId: ID!, $instanceName: String!){\n createSolutionInstance(input: {\n solutionId: $solutionId\n instanceName: $instanceName\n }) {\n solutionInstance {\n id\n name\n enabled\n created\n workflows {\n edges {\n node {\n id\n triggerUrl\n sourceWorkflowId\n }\n }\n }\n }\n }\n }", "variables": { "solutionId": "b3422397-XXXX-XXXX-XXXX-57e7e66771b3", "instanceName": "Gene Slack star instance 2" } }'
{- "data": {
- "createSolutionInstance": {
- "solutionInstance": {
- "id": "625xxx-xxx-xxx-xxx-xxx111f",
- "name": "Gene Slack star instance 2",
- "enabled": false,
- "created": "2019-02-25T11:02:21.884Z",
- "workflows": {
- "edges": [
- {
- "node": {
- "id": "98099de2-xxx-xxx-xxx-xxxxxb8ff7",
- "sourceWorkflowId": "378xxx-xxx-xxx-xxx-xxx-xxx4fd6"
}
}
]
}
}
}
}
}
The primary use of this mutation is to 'enable' the solution instance. This is a required step after creating and configuring the solution instance.
If you are dealing with new auth/config settings, the parent solution will be on a new version, and the instance must be upgraded by the end user re-running the Config Wizard or using Solution Instances/Mutations/Upgrade Solution Instance. This is explained in detail in Updating/Upgrading Solution Instances
Required token | Notes |
---|---|
User | Obtained after using Users/Mutations/Create User Token. The User Token is a persistent token that should be securely stored in your application for future use (expires after 2 days) |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
solutionInstanceId | Yes | obtained with Solution Instances/Queries/Get Solution Instances |
instanceName | No | |
enabled | No | set to True to enable the Solution Instance after it is created |
authValues | No | accepts an array of objects. Each object has two keys: externalId and authId . Check an example mutation below to see how it will be passed |
configValues | No | accepts an array of objects. Each object has two keys: externalId and value . Note that value is always a string. So it must be stringified if it is of any other type (object/array, boolean, number). Check an example mutation below to see how it will be passed |
Here is an example mutation:
mutation { updateSolutionInstance(input: { solutionInstanceId: "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266", instanceName: "test-instance", enabled: true }) { solutionInstance { id name enabled created } } }
mutation { updateSolutionInstance(input: { solutionInstanceId: "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266", configValues: [ { "externalId": "external_limit", "value": "10" }, { "externalId": "external_datamappings", "value": "{\"location\":\"**********\",\"email\":\"**********\"}" } ] authValues: [ { "externalId": "external_slack_authentication", "authId": "aaa67786-XXXX-XXXX-XXXX-97dedd1519b3" } ] }) { solutionInstance { id name enabled created } } }
Returned Data | Subfields | Notes |
---|---|---|
id | ||
name | ||
created | ||
enabled | defaults to False so must be set to True with this mutation | |
solution | id, title, description, tags, customFields, configSlots, authSlots | details of the parent solution |
workflows | id, sourceWorkflowId, sourceWorkflowName, triggerUrl | details of the source workflows, including webhook url (triggerUrl) |
authValues | authId, externalId | details of the auths associated with the instance |
configValues | value, externalId | details of config values associated with the user |
solutionVersionFlags | hasNewerVersion, requiresUserInputToUpdateVersion, requiresSystemInputToUpdateVersion | boolean flags used to indicate if an underlying Solution has a newer version which might need upgrading as explained in Updating / Upgrading Solution Instances |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($solutionInstanceId: ID!, $instanceName: String!, $enabled: Boolean!) {\n updateSolutionInstance(input: {\n solutionInstanceId: $solutionInstanceId,\n instanceName: $instanceName, \n enabled: $enabled\n }) {\n solutionInstance {\n id\n name\n enabled\n created\n }\n }\n}", "variables": { "solutionInstanceId": "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266", "instanceName": "myCustomersSolutionInstanceName", "enabled": true } }'
{- "data": {
- "updateSolutionInstance": {
- "solutionInstance": {
- "id": "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266",
- "name": "myCustomersSolutionInstanceName",
- "enabled": true,
- "created": "2019-02-25T11:02:21.884Z"
}
}
}
}
This mutation is used when a new version of a Solution has been published which contains new Config Data (which doesn't require user input) and you wish to upgrade an End User's Instance with the new Config Data, without asking them to use the Configuration Wizard again.
Please see our page on Updating / Upgrading Solution Instances for a full explanation of how to manage changes to your Workflows and Solutions.
Required token | Notes |
---|---|
User | Obtained after using Users/Mutations/Create User Token. The User Token is a persistent token that should be securely stored in your application for future use (expires after 2 days) |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
solutionInstanceId | Yes | obtained with Solution Instances/Queries/Get Solution Instances |
instanceName | No | |
authValues | No | Can be used to import End User authentications. See Importing Auths |
configValues | No | Can be used to import external data. See Importing External Data |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { upgradeSolutionInstance (input: { solutionInstanceId: "5f85b697-XXXX-XXXX-XXXX-5d7dabe22634", configValues: [ { "externalId": "external_support-email", "value": "support@example.com" } ], authValues: [ { "externalId": "external_slack_authentication", "authId": "aaa67786-XXXX-XXXX-XXXX-97dedd1519b3" } ] }) { solutionInstance { id configValues{ externalId value } authValues{ authId externalId } enabled owner created } } }
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($solutionInstanceId: ID!, $configValues: [ConfigValue!], $authValues: [AuthValue!] ){\n upgradeSolutionInstance (input: {\n solutionInstanceId: $solutionInstanceId, \n configValues: $configValues,\n authValues: $authValues\n }) \n { \n solutionInstance {\n id\n configValues{\n externalId\n value\n }\n authValues{\n authId\n externalId\n }\n enabled\n created\n }\n }\n}", "variables": { "solutionInstanceId": "625xxx-xxx-xxx-xxx-xxx111f", "configValues": [ { "externalId": "external_support-email", "value": "support@example.com" } ], "authValues": [ { "externalId": "external_slack_authentication", "authId": "aaa67786-XXXX-XXXX-XXXX-97dedd1519b3" } ] } }'
{- "data": {
- "upgradeSolutionInstance": {
- "solutionInstance": {
- "id": "625xxx-xxx-xxx-xxx-xxx111f",
- "enabled": true,
- "created": "2019-02-25T11:02:21.884Z",
- "configValues": [
- {
- "externalId": "external_support-email",
- "value": "support@example.com"
}
], - "authValues": [
- {
- "externalId": "external_slack_authentication",
- "authId": "aaa67786-XXXX-XXXX-XXXX-97dedd1519b3"
}
]
}
}
}
}
Used to delete a Solution Instance.
Please also see our page on Deleting Solutions and Projects
Required token | Notes |
---|---|
User | obtained after creating a user token (Users/Mutations/Create User Token) the user token is a persistent token (valid for 2 days) that should be securely stored in your application |
The mutation accepts the following as inputs:
Input | Required | Notes |
---|---|---|
solutionInstanceId | Yes | obtained with Solution Instances/Queries/Get Solution Instances |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here are some example mutations:
mutation { removeSolutionInstance(input: {solutionInstanceId: "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266"}) { clientMutationId } }
mutation { removeSolutionInstance(input: {solutionInstanceId: "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266", clientMutationId: "some-mutation-id"}) { clientMutationId } }
It can return the following data:
Returned Data | Notes |
---|---|
clientMutationId | while this data is Only relevant if using the Relay GraphQL client, it is actually required here as currently this mutation does not return any other data |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <USER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($solutionInstanceId: ID!){\n removeSolutionInstance(input: {solutionInstanceId: $solutionInstanceId}) {\n clientMutationId\n }\n}", "variables": { "solutionInstanceId": "2d38b2ec-xxxx-xxx-xxxx-b4ec68084266" } }'
{- "data": {
- "removeSolutionInstance": {
- "clientMutationId": null
}
}
}
The importProject mutation can be used to import and overwrite an existing project in your embedded account. This is handy when you want to import projects to your 'production' account from 'staging'.
That means before you start creating instances for this solution, it has to be published manually through UI.
Required token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
exportedProjectJson | Yes | Can be obtained either by exporting project json from UI or using the exportProject mutation (refer below) The JSON must be stringified. |
targetProjectId | Yes | obtained from the url of target Project page: https://app.tray.io/workspaces/{workspaceId}/projects/{projectId} |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { importProject (input: { exportedProjectJson: "{}", targetProjectId: "944dxxx-xxx-xxx-xxx-xxx222eb99" }) { clientMutationId } }
mutation { importProject (input: { exportedProjectJson: "{}", targetProjectId: "944dxxx-xxx-xxx-xxx-xxx222eb99", clientMutationId: "some-mutation-id" }) { clientMutationId } }
It can return the following data:
Returned Data | Notes |
---|---|
clientMutationId | while this data is only relevant if using the Relay GraphQL client, it is actually required here as currently this mutation does not return any other data |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($exportedProjectJson: String!, $targetProjectId: ID!) {\n importProject (input: {\n exportedProjectJson: $exportedProjectJson,\n targetProjectId: $targetProjectId\n }) {\n clientMutationId\n }\n}", "variables": { "exportedProjectJson": "{}", "targetProjectId": "944dxxx-xxx-xxx-xxx-xxx222eb99" } }'
{- "data": {
- "importProject": {
- "clientMutationId": null
}
}
}
The exportProject mutation can be used to export the projects from your embedded account. This is handy when you want to import project to your 'production' account from 'staging'.
Required token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
projectId | Yes | obtained from the url of the Project page: https://app.tray.io/workspaces/{workspaceId}/projects/{projectId} |
exportSolution | Yes | Boolean value. If set to true, the solution associated with the workflow is exported as part of the JSON structure. |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { exportProject (input: { projectId: "944dxxx-xxx-xxx-xxx-xxx222eb99", exportSolution: true }) { exportedProjectJson } }
It can return the following data:
Returned Data | Notes |
---|---|
exportedProjectJson | Stringified JSON of the project |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($projectId: ID!) {\n exportProject (input: {\n projectId: $projectId,\n exportSolution: true\n }) {\n exportedProjectJson\n }\n}", "variables": { "projectId": "944dxxx-xxx-xxx-xxx-xxx222eb99" } }'
{- "data": {
- "exportProject": {
- "exportedProjectJson": "{}"
}
}
}
The importWorkflows mutation can be used to import the workflow to your embedded account. This is handy when you want to import workflows to your 'production' account from 'staging'.
Note that it is possible to import multiple workflows (you would have to ensure that the workflows and workflowIds are listed in the exact same order in exportedWorkflowsJson and targetWorkflowIds - to make sure the correct workflow is imported to the correct target workflow)
However if you are working with multiple workflows, it is more likely that you will be importing a project.
Required token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
exportedWorkflowsJson | Yes | Can be obtained either by exporting workflow json from UI or using the exportWorkflows mutation (refer below) The JSON must be stringified. |
targetWorkflowIds | Yes | Array of workflow IDs Workflow ID can be obtained from the url of target workflow page: https://app.tray.io/workflow/{workflowId} |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is an example mutation:
mutation { importWorkflows (input: { exportedWorkflowsJson: "{\"tray_export_version\":4,\"export_type\":\"workflow\",\"workflows\":[{\"id\":\"ea3c20f5-xxxx-xxxx-xxxx-0ce2b7bb9f29\",\"created\":\"2023-05-15T11:26:14.794686Z\",\"workspace_id\":\"6c595d5b-xxxx-xxxx-xxxx-959ceb938eae\",\"creator\":\"6a4e56d9-xxxx-xxxx-xxxx-2429f79b40ff\",\"version\":{\"id\":\"018cc858-xxxx-xxxx-xxxx-2c8cfe0a7886\",\"created\":\"2023-05-16T22:25:42.413825Z\"},\"title\":\"webhook slack\",\"enabled\":false,\"tags\":[],\"settings\":{\"config\":{},\"input_schema\":{},\"output_schema\":{}},\"steps_structure\":[{\"name\":\"trigger\",\"type\":\"normal\",\"content\":{}}],\"steps\":{\"trigger\":{\"title\":\"Webhook\",\"connector\":{\"name\":\"webhook\",\"version\":\"2.3\"},\"operation\":\"fire_and_forget\",\"output_schema\":{},\"error_handling\":{},\"properties\":{}}},\"dependencies\":[]}],\"projects\":[]}", targetWorkflowIds: ["e5dc0748-xxxx-xxxx-xxxx-dfcc33795f12"] }) { clientMutationId } }
mutation { importWorkflows (input: { exportedWorkflowsJson: "{\"tray_export_version\":4,\"export_type\":\"workflow\",\"workflows\":[{\"id\":\"ea3c20f5-xxxx-xxxx-xxxx-0ce2b7bb9f29\",\"created\":\"2023-05-15T11:26:14.794686Z\",\"workspace_id\":\"6c595d5b-xxxx-xxxx-xxxx-959ceb938eae\",\"creator\":\"6a4e56d9-xxxx-xxxx-xxxx-2429f79b40ff\",\"version\":{\"id\":\"018cc858-xxxx-xxxx-xxxx-2c8cfe0a7886\",\"created\":\"2023-05-16T22:25:42.413825Z\"},\"title\":\"webhook slack\",\"enabled\":false,\"tags\":[],\"settings\":{\"config\":{},\"input_schema\":{},\"output_schema\":{}},\"steps_structure\":[{\"name\":\"trigger\",\"type\":\"normal\",\"content\":{}}],\"steps\":{\"trigger\":{\"title\":\"Webhook\",\"connector\":{\"name\":\"webhook\",\"version\":\"2.3\"},\"operation\":\"fire_and_forget\",\"output_schema\":{},\"error_handling\":{},\"properties\":{}}},\"dependencies\":[]}],\"projects\":[]}", targetWorkflowIds: ["e5dc0748-xxxx-xxxx-xxxx-dfcc33795f12"], clientMutationId: "some-mutation-id" }) { clientMutationId } }
It can return the following data:
Returned Data | Notes |
---|---|
clientMutationId | while this data is only relevant if using the Relay GraphQL client, it is actually required here as currently this mutation does not return any other data |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($exportedProjectJson: String!, $targetProjectId: ID!) {\n importProject (input: {\n exportedProjectJson: $exportedProjectJson,\n targetProjectId: $targetProjectId\n }) {\n clientMutationId\n }\n}", "variables": { "exportedProjectJson": "{}", "targetProjectId": "944dxxx-xxx-xxx-xxx-xxx222eb99" } }'
{- "data": {
- "importProject": {
- "clientMutationId": null
}
}
}
The exportWorkflows mutation can be used to export the workflows from your embedded account. This is handy when you want to import workflows to your 'production' account from 'staging'.
Note that it is possible to export multiple workflows
Required token | Notes |
---|---|
Master | Obtained from the Tray app UI. Refer this. |
The mutation accepts the following arguments:
Argument | Required | Note |
---|---|---|
workflowIds | Yes | Array of workflow IDs. Workflow ID can be obtained from the url of target workflow page: https://app.tray.io/workflow/{workflowId} |
Here is an example mutation:
mutation { exportWorkflows (input: { workflowIds: ["ea3c20f5-xxxx-xxxx-xxxx-0ce2b7bb9f29", "a6af4264-xxxx-xxxx-xxxx-70a1e59d72b2"] }) { exportedWorkflowsJson } }
It can return the following data:
Returned Data | Notes |
---|---|
exportedWorkflowsJson | Stringified JSON of the array of workflows |
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation ($projectId: ID!) {\n exportProject (input: {\n projectId: $projectId,\n exportSolution: true\n }) {\n exportedProjectJson\n }\n}", "variables": { "projectId": "944dxxx-xxx-xxx-xxx-xxx222eb99" } }'
{- "data": {
- "exportWorkflows": {
- "exportedWorkflowsJson": "{\"tray_export_version\":4,\"export_type\":\"workflow\",\"workflows\":[{\"id\":\"ea3c20f5-xxxx-xxxx-xxxx-0ce2b7bb9f29\",\"created\":\"2023-05-15T11:26:14.794686Z\",\"workspace_id\":\"6c595d5b-xxxx-xxxx-xxxx-959ceb938eae\",\"creator\":\"6a4e56d9-xxxx-xxxx-xxxx-2429f79b40ff\",\"version\":{\"id\":\"153485a5-xxxx-xxxx-xxxx-34bc1f9f08f4\",\"created\":\"2023-05-15T11:26:14.794685Z\"},\"title\":\"webhookslack\",\"enabled\":true,\"tags\":[],\"settings\":{\"config\":{},\"input_schema\":{},\"output_schema\":{}},\"steps_structure\":[{\"name\":\"trigger\",\"type\":\"normal\",\"content\":{}}],\"steps\":{\"trigger\":{\"title\":\"ManualTrigger\",\"connector\":{\"name\":\"noop\",\"version\":\"1.1\"},\"operation\":\"trigger\",\"output_schema\":{},\"error_handling\":{},\"properties\":{}}},\"dependencies\":[]},{\"id\":\"a6af4264-xxxx-xxxx-xxxx-70a1e59d72b2\",\"created\":\"2023-04-25T09:06:10.563859Z\",\"workspace_id\":\"6c595d5b-xxxx-xxxx-xxxx-959ceb938eae\",\"creator\":\"6c595d5b-xxxx-xxxx-xxxx-959ceb938eae\",\"version\":{\"id\":\"1a8c552e-xxxx-xxxx-xxxx-4ec119353733\",\"created\":\"2023-04-25T09:23:42.981741Z\"},\"title\":\"Sheetsratelimitingtest\",\"enabled\":true,\"tags\":[],\"settings\":{\"config\":{},\"input_schema\":{},\"output_schema\":{}},\"steps_structure\":[{\"name\":\"trigger\",\"type\":\"normal\",\"content\":{}},{\"name\":\"loop-1\",\"type\":\"loop\",\"content\":{\"_loop\":[{\"name\":\"boolean-condition-1\",\"type\":\"branch\",\"content\":{\"true\":[{\"name\":\"break-loop-1\",\"type\":\"break\",\"content\":{},\"target\":\"loop-1\"}],\"false\":[]}},{\"name\":\"slack-1\",\"type\":\"normal\",\"content\":{}}]}}],\"steps\":{\"slack-1\":{\"title\":\"Slack\",\"connector\":{\"name\":\"slack\",\"version\":\"9.1\"},\"operation\":\"list_users\",\"output_schema\":{},\"error_handling\":{},\"authentication\":{\"group\":\"14c77d41-xxxx-xxxx-xxxx-382944191584\",\"title\":\"MaelDuin'sslackaccount1\",\"service_icon\":{\"icon_type\":\"url\",\"value\":\"//s3.amazonaws.com/images.tray.io/artisan/icons/c25033a972715dbbdb7e73ac79261230.png\"},\"scopes\":[\"mpim:read\",\"im:read\",\"users:read.email\",\"channels:read\",\"chat:write:user\",\"files:read\",\"reminders:write\",\"channels:write\",\"groups:read\",\"chat:write:bot\",\"users:read\",\"groups:write\"],\"service_name\":\"slack\",\"service_version\":4},\"properties\":{\"token\":{\"type\":\"jsonpath\",\"value\":\"$.auth.access_token\"},\"limit\":{\"type\":\"integer\",\"value\":100}}},\"loop-1\":{\"title\":\"LoopCollection\",\"connector\":{\"name\":\"loop\",\"version\":\"1.3\"},\"operation\":\"loop_forever\",\"output_schema\":{\"type\":\"object\",\"$schema\":\"http://json-schema.org/draft-03/schema\",\"id\":\"http://jsonschema.net\",\"properties\":{\"index\":{\"type\":\"number\",\"id\":\"http://jsonschema.net/index\"}}},\"error_handling\":{},\"properties\":{}},\"boolean-condition-1\":{\"title\":\"BooleanCondition\",\"connector\":{\"name\":\"boolean-condition\",\"version\":\"2.3\"},\"operation\":\"boolean_condition\",\"output_schema\":{},\"error_handling\":{},\"properties\":{\"conditions\":{\"type\":\"array\",\"value\":[{\"type\":\"object\",\"value\":{\"value1\":{\"type\":\"jsonpath\",\"value\":\"$.steps.loop-1.index\"},\"comparison_type\":{\"type\":\"string\",\"value\":\"===\"},\"value2\":{\"type\":\"number\",\"value\":250}}}]},\"strictness\":{\"type\":\"string\",\"value\":\"All\"}}},\"break-loop-1\":{\"title\":\"BreakLoop\",\"connector\":{\"name\":\"break-loop\",\"version\":\"1.1\"},\"operation\":\"break\",\"output_schema\":{},\"error_handling\":{},\"properties\":{}},\"trigger\":{\"title\":\"ManualTrigger\",\"connector\":{\"name\":\"noop\",\"version\":\"1.1\"},\"operation\":\"trigger\",\"output_schema\":{},\"error_handling\":{},\"properties\":{}}},\"dependencies\":[]}],\"projects\":[]}"
}
}
}
This mutation can be used to call a specific connector operation.
This powerful feature is used in combination with a User Token and Authentication Id, to pull data from a particular service connector operation and display it in your app.
As an example, for a particular End User of your Embedded application, you could use it to display all of the 'Warm' Salesforce Leads assigned to them, or display all the customers with overdue payments.
The tool also gives insight into the output schema for those operations, which will help you process the result.
Please see full instructions for using this endpoint at [https://tray.io/documentation/embedded/advanced-topics/call-connector/](https://tray.io/documentation/embedded/adva nced-topics/call-connector/)
Required token | Notes |
---|---|
User or Master | Obtained after using Users/Mutations/Create User Token. The User Token is a persistent token that should be securely stored in your application for future use (expires after 2 days) |
The mutation accepts the following arguments:
Input | Required | Note |
---|---|---|
connector | Yes | The programatic connector name. Obtained from the workflow builder, see example below |
version | Yes | The version of the connector being used. Obtained from inspecting the Advanced settings of the input panel in the workflow builder, see example below |
operation | Yes | The programmatic name of the operation. This is usually the name of the operation visible in the workflow builder input panel, converted to snake case. Please reach out to support@tray.io if you get the error message The connector operation ### was not found |
authId | Yes | see prerequisites below on obtaining an authId |
input | Yes | The stringified JSON body representing the input parameters to the operation. You can explore the input schema for all connectors and their operations' in the Operations explorer app. |
clientMutationId | No | Only relevant if using the Relay GraphQL client |
Here is a sample mutation:
mutation { callConnector(input: { connector: "salesforce", version: "8.1", operation: "get_records", authId: "########-####-####-####-############", input: "{\\"limit\\":10,\\"conditions_type\\":\\"Match all conditions\\",\\"fields\\":[\\"Id\\",\\"Name\\"],\\"object\\":\\"Lead\\"}" }) { output } }
It returns the following data:
Returned Data | Notes |
---|---|
output | The stringified JSON body representing the data returned from the connector |
clientMutationId | Only relevant if using the Relay GraphQL client |
GraphQL provides the capability to send multiple mutations at once. If you need to use the same mutation multiple times, you can use aliases (avoid any duplicate names).
Here is an example mutation with two mutations merged into one using aliases listAllLeads
and listWarmLeads
.
mutation callSalesforce { listAllLeads: callConnector(input: { connector: "salesforce", version: "4.0", operation: "find_records", authId: "########-####-####-####-############", input: "{\\"limit\\":10,\\"conditions_type\\":\\"Match all conditions\\",\\"fields\\":[\\"Id\\",\\"Name\\"],\\"object\\":\\"Lead\\"}" }) { output }, listWarmLeads: callConnector(input: { connector: "salesforce", version: "4.0", operation: "find_records", authId: "########-####-####-####-############", input: "{\\"conditions_type\\":\\"Match all conditions\\",\\"fields\\":[\\"Id\\",\\"Name\\"],\\"conditions\\":[{\\"field\\":\\"Rating\\",\\"operator\\":\\"Equal to\\",\\"value\\":\\"Warm\\"}],\\"object\\":\\"Lead\\"}" }) { output } }
curl -i -X POST \ https://tray.io/graphql \ -H 'Authorization: Bearer <MASTER_TOKEN>' \ -H 'Content-Type: application/json' \ -d '{ "query": "mutation listLeads(\n $connector: String!, \n $version: String!, \n $operation: String!, \n $authId: String, \n){ listAllLeads: callConnector(input: {\n connector: $connector,\n version: $version,\n operation: $operation,\n authId: $authId,\n input: \"{\\\"limit\\\":10,\\\"conditions_type\\\":\\\"Match all conditions\\\",\\\"fields\\\":[\\\"Id\\\",\\\"Name\\\"],\\\"object\\\":\\\"Lead\\\"}\"\n }) {\n output\n }\n}", "variables": { "connector": "salesforce", "version": "8.7", "operation": "find_records", "authId": "062af7e2-b5xxx-xxx-xxx-xxx-xxxxx46d912" } }'
{- "data": {
- "listObjects": {
- "output": "{\"total\":10,\"next_page_offset\":null,\"records\":[{\"Id\":\"00Q8d000005HrKQEA0\",\"Name\":\"Mike Braund\"},{\"Id\":\"00Q8d000005HrKNEA0\",\"Name\":\"Bertha Boxer\"},{\"Id\":\"00Q8d000005HrKOEA0\",\"Name\":\"Phyllis Cotton\"},{\"Id\":\"00Q8d000005HrKPEA0\",\"Name\":\"Jeff Glimpse\"},{\"Id\":\"00Q8d000005HrKREA0\",\"Name\":\"Patricia Feager\"},{\"Id\":\"00Q8d000005HrKVEA0\",\"Name\":\"Tom James\"},{\"Id\":\"00Q8d000005HrKSEA0\",\"Name\":\"Brenda Mcclure\"},{\"Id\":\"00Q8d000005HrKTEA0\",\"Name\":\"Violet Maccleod\"},{\"Id\":\"00Q8d000005HrKUEA0\",\"Name\":\"Kathy Snyder\"},{\"Id\":\"00Q8d000005HrKWEA0\",\"Name\":\"Shelly Brownell\"}]}"
}
}
}