The JupiterOne platform exposes a number of public GraphQL endpoints.
Base URL: https://api.us.jupiterone.io
Endpoint for query and graph operations: /graphql
Endpoint for alert and rules operations: /rules/graphql
Rate Limits: rate limiting is enforced per account at 30 query requests per minute with an allowable burst of 30 requests at once
An experimental node.js client and CLI can be found on Github.
Entity and Relationship Queries
Endpoint: /graphql
Querying the graph with J1QL
This query will allow you to run J1QL queries for fetching data. The GraphQL resolver requires that one parameter is provided:
query
: A J1QL query string that describes what data to return
Optionally, additional parameters can be provided:
variables
: AJSON
map of values to be used as parameters for the querycursor
: A token that can be exchanged to fetch the next page of information.includeDeleted
: When set totrue
, recently deleted information will be included in the results.deferredResponse
: This option allows for a deferred response to be returned. When a deferred response is returned, aurl
pointing the state of the query is provided. Upon completion of the query, theurl
will provide a link to the query results. The results contain the sametype
,data
, andcursor
fields that the non-deferred GraphQL response would contain. Allowed values areDISABLED
andFORCE
.
Note: When paging through data, it is highly recommended that cursors
are leveraged instead of adding limit
and skip
clauses to queries.
Example GraphQL query:
query J1QL( $query: String!, $variables: JSON, $cursor: String ) { queryV1( query: $query, variables: $variables, cursor: $cursor ) { type data cursor } }
Example variables:
{ "query": "find Person with _type=${type} return Person.name", "variables": { "type": "employee" }, "cursor": "eyJjYWNoZUtleSI6IjFlNDg3MT..." }
Example queryV1
resolver result:
{ "type": "list", "data": [ { "Person.name": "Mochi" } ], "cursor": "eyJjYWNoZUtleSI6IjFlNDg3MT..." }
Example GraphQL query using with deferred responses:
query J1QL( $query: String!, $variables: JSON, $cursor: String $deferredResponse: DeferredResponseOption ) { queryV1( query: $query, variables: $variables, deferredResponse: $deferredResponse, cursor: $cursor ) { type url } }
Example variables:
{ "query": "find Person with _type=${type}", "deferredResponse": "FORCE", "variables": { "type": "employee" }, "cursor": "eyJjYWNoZUtleSI6IjFlNDg3MT..." }
Example queryV1
resolver result when using a deferred response:
{ "type": "deferred", "url": "https://example.com/state.json" }
Example state responses:
{ "status": "IN_PROGRESS", "correlationId": "912788f1-e0c7-43bd-b853-455c0031be8a" }
{ "status": "COMPLETED", "url": "https://example.com/results.json", "correlationId": "912788f1-e0c7-43bd-b853-455c0031be8a" }
Fetching Graph Data
This query will be used for fetching graph data. The returned data includes the details of all vertices found on the graph as well as the edges that connect the vertices.
Note: At the moment, a canned query for IAM Role data is run. No input variables need to be provided.
query testQuery { queryGraph { vertices { id entity { _id _key _type _accountId _integrationName _integrationDefinitionId _integrationInstanceId _version _createdOn _beginOn _endOn _deleted displayName } properties } edges { id toVertexId fromVertexId relationship { _id _key _type _accountId _integrationName _integrationDefinitionId _integrationInstanceId _version _createdOn _beginOn _endOn _deleted _fromEntityKey _toEntityKey displayName } properties } } }
Retrieving a Single Vertex by ID
This query will be used for fetching a vertex and its properties by its ID. The query requires one of two parameters:
id
: The ID as a stringfilters
: A set of filters that define the desired vertex.
The example below contains all of the currently available filters.
NOTE: Only one of the variables (id
or filters
) is required. Specifying both
is allowed but somewhat redundant unless you want to assert that a vertex with
the specified id
exists and has specific entity properties.
query VertexQuery($id: String!, $filters: VertexFilters) { vertex(id: $id, filters: $filters) { id entity { _id _key _type _accountId _integrationName _integrationDefinitionId _integrationInstanceId _version _createdOn _beginOn _endOn _deleted displayName } properties } }
Variables:
{ "id": "<a vertex id>", "filters": { "_id": "<an entity id>", "_key": "<an entity key>", "_type": ["<a entity type>"], "_class": ["<a entity class>"] } }
Fetching Neighbors of a Vertex
The Vertex
type allows you to retrieve vertex and edge neighbors up to a
certain depth using the neighbors
field. The return type of the neighbors
resolver is the same as that of a graph query. This query requires two
parameters:
id
: The ID of the vertex as a stringdepth
: An integer specifying how many "levels" deep the query will go to look for neighbors.
query VertexQuery($id: String!, $depth: Int) { vertex(id: $id) { id entity { displayName } neighbors(depth: $depth) { vertices { id entity { displayName } } edges { id relationship { displayName } } } } }
Variables:
{ "id": "<a vertex id>", "depth": 5 }
NOTE: The depth that is supplied must be a value between 1 and 5 (inclusive)
Retrieving an Edge by ID
This query allows you to fetch an edge, its properties, and the relationship it describes by its ID or label and filters. The query requires one or two of three parameters:
id
: The ID as a string.label
: The label displayed on the edge.filters
: A set of filters that define the desired vertex.
The example below contains all of the currently available filters.
NOTE: Only one of the variables (id
, label
, or filters
) is required.
Specifying label
and filters
with id
is allowed but somewhat redundant
unless you want to assert that a vertex with the specified id
exists and has
the specific label and properties.
query VertexQuery($id: String!) { edge(id: $id, label: $id, filters: $id) { id relationship { _id _key _type _accountId _integrationName _integrationDefinitionId _integrationInstanceId _version _createdOn _beginOn _endOn _deleted _fromEntityKey _toEntityKey displayName } properties } }
Variables:
{ "id": "<an edge id>", "label": "<edge label>", "filters": { "_id": "<a relationship id>", "_key": "<a relationship key>", "_type": "<a relationship type>", "_class": "<a relationship class>" } }
Fetching the Count of Entities Via a _type and/or _class
This query allows you to fetch the count of entities. The _id
, _key
,
_type
, or _class
fields can be supplied as filters. This query only counts
the latest versions of entities matching the filter criteria. This query
requires two parameters:
filters
: A set of vertex filters that describe the entities that are to be returned.filterType
: AFilterType
(AND
orOR
).
If OR
is specified as the filter type, any entity that has any class in the
filter will be included in the count. By default, the query uses AND
, which
only includes entities that have all of the specified classes in the count.
Note: This resolver uses the JSON
scalar as the return type.
query testQuery($filters: VertexFilters, $filterType: FilterType) { entityCount(filters: $filters, filterType: $filterType) }
Note: Use field aliases to request the counts of multiple different entities.
query testQuery { Users: entityCount(filters: { _class: ["User"] }, filterType: "AND") Repos: entityCount(filters: { _class: ["CodeRepo"] }, filterType: "OR") }
Example result:
{ "User": 40, "CodeRepo": 153 }
Fetching the Count of All Types and Classes
This query returns the entity counts for all types and classes.
Note: This resolver uses the JSON
scalar as the return type.
query testQuery { allEntityCounts }
Example result:
{ "typeCounts": { "iam_user": 12, "iam_managed_policy": 10, "iam_role_policy": 10 }, "classCounts": { "User": 12, "AccessPolicy": 20 } }
Fetching the Count of All Types With a Set of Classes
This query returns all types that have the specified classes. The query requires two parameters:
classes
: An array of strings detailing which classes should be returned.filterType
: AFilterType
(AND
orOR
).
If OR
is specified as the filter type, any entity that has any class in the
filter will be included in the count. By default, the query uses AND
, which
only includes entities that have all of the specified classes in the count.
Note: This resolver uses the JSON
scalar as the return type.
query testQuery ($classes: [String], filterType: FilterType) { typeCounts (classes: $classes, filterType: $filterType) }
Example result:
{ "iam_user": 12, "iam_managed_policy": 10, "iam_role_policy": 10 }
Listing Vertices Via a _type and/or _class
For fetching entities with specified filters. The _id
, _key
, _type
and
_class
fields can be supplied as filters. This query only returns the latest
versions of entities matching the filter criteria. This query accepts three
parameters:
filters
: A set of vertex filters that describe the entities to return (required).after
: A string to begin searching after (required).filterType
: AFilterType
(AND
orOR
).
If OR
is specified as the filter type, any entity that has any class in the
filter will be included in the count. By default, the query uses AND
, which
only includes entities that have all of the specified classes in the count.
query testQuery($filters: VertexFilters, $filterType: FilterType, $after: String) { listVertices(filters: $filters, filterType: $filterType, after: $after) { vertices { id entity { // entity details here } properties } total pageInfo { endCursor hasNextPage } } }
Variables:
{ "filters": { "_type": ["<an entity type>"], "_class": ["<an entity class>"] }, "filterType": "<AND or OR>", "after": "the value of pageInfo.endCursor" }
Example result
{ "vertices": [ { "id": "some-id", "entity": { "displayName": "Laptop-2345" } } ], "total": 1, "pageInfo": { "endCursor": "some-base64-cursor", "hasNextPage": true } }
Entity Mutations
Endpoint: /graphql
Create Entity
This mutation creates a JupiterOne entity with the given specifications. This mutation requires three parameters (with two optional parameters):
entityKey
: A string that gives the key value for the entity so that this entity can be referenced later.entityType
: A string that gives the type of the entity being created.entityClass
: A string that gives the class of the entity being created.- Optional Parameters
timestamp
:properties
: AJSON
list that gives specific properties that the entity will have.
mutation CreateEntity ( $entityKey: String! $entityType: String! $entityClass: String! $timestamp: Long $properties: JSON ) { createEntity ( entityKey: $entityKey, entityType: $entityType, entityClass: $entityClass, timestamp: $timestamp, properties: $properties ) { entity { _id ... } vertex { id, entity { _id ... } properties } } }
Variables:
{ "entityKey": "<an entity key>", "entityType": "<an entity type>", "entityClass": "<an entity class>", "timestamp": 1529329792552, "properties": { // Custom properties on the Entity ... } }
Updating Entity
This mutation updates an already existing entity (does not create an entity).
You cannot change the entityKey
, entityClass
, or entityType
.
This mutation requires one parameter (with two optional parameters):
entityId
: A string specific to the entity that finds the entity.- Optional Parameters:
timestamp
:properties
: AJSON
list of properties to be changed.
mutation UpdateEntity ( $entityId: String! $timestamp: Long $properties: JSON ) { updateEntity ( entityId: $entityId, timestamp: $timestamp, properties: $properties ) { entity { _id ... } vertex { id, entity { _id ... } properties } } }
Variables:
{ "entityId": "<an entity Id (entity._id)>", "timestamp": 1529329792552, "properties": { // Custom properties to get updated ... } }
Deleting Entity
This mutation deletes an existing entity. This mutation requires one parameter (with one optional parameter):
entityId
: A string specific to the entity that finds the entity.- Optional Parameters:
timestamp
:
mutation DeleteEntity ( $entityId: String! $timestamp: Long ) { deleteEntity ( entityId: $entityId, timestamp: $timestamp, ) { entity { _id ... } vertex { id, entity { _id ... } properties } } }
Variables:
{ "entityId": "<an entity Id (entity._id)>", "timestamp": 1529329792552 }
Relationship Mutations
Endpoint: /graphql
Create Relationship
mutation CreateRelationship ( $relationshipKey: String! $relationshipType: String! $relationshipClass: String! $fromEntityId: String! $toEntityId: String! $timestamp: Long $properties: JSON ) { createRelationship ( relationshipKey: $relationshipKey, relationshipType: $relationshipType, relationshipClass: $relationshipClass, fromEntityId: $fromEntityId, toEntityId: $toEntityId, timestamp: $timestamp, properties: $properties ) { relationship { _id ... } edge { id toVertexId fromVertexId relationship { _id ... } properties } } }
Variables:
{ "relationshipKey": "<a relationship key>", "relationshipType": "<a relationship type>", "relationshipClass": "<a relationship class>", "fromEntityId": "<the _id of the from entity>", "toEntityId": "<the _id of the to entity>", "timestamp": 1529329792552, "properties": { // Custom properties on the relationship ... } }
Update Relationship
mutation UpdateRelationship ( $relationshipId: String! $timestamp: Long $properties: JSON ) { updateRelationship ( relationshipId: $relationshipId, timestamp: $timestamp, properties: $properties ) { relationship { _id ... } edge { id toVertexId fromVertexId relationship { _id ... } properties } } }
Variables:
{ "relationshipId": "<a relationship Id (relationship._id)>", "timestamp": 1529329792552, "properties": { // Custom properties to get updated ... } }
Delete Relationship
mutation DeleteRelationship ( $relationshipId: String! $timestamp: Long ) { deleteRelationship ( relationshipId: $relationshipId, timestamp: $timestamp, ) { relationship { _id ... } edge { id toVertexId fromVertexId relationship { _id ... } properties } } }
Variables:
{ "relationshipId": "<a relationship Id (relationship._id)>", "timestamp": 1529329792552 }
Entity and Relationship Synchronization (Bulk Upload)
An integration job is responsible for sending all of the latest entities and relationships to the persister and the persister will compare the new state to the old state and automatically apply the changes to the graph.
The persister exposes a public REST API that will be used when developing, testing, and running integrations outside the JupiterOne cloud infrastructure.
The synchronization API also supports synchronizing a grouping of entities and
relationships from an API source by using a scope property. That is, a group
of entities and relationships can be loggically grouped together by an arbitrary
scope value and uploaded to the persister via the synchronization API and the
create, update, and delete operations will be automatically determined within
the given scope. The scope value is stored on the entities and relationships in
the _scope
property.
Integration Job Bookkeeping
While an integration job is running, the persister will need to keep track of data as the job progresses.
This information will be tracked:
- New entities
- New relationships
- Raw data associated with entities (including
Content-Type
) - Job status and progress counters
- Job metadata (start time, source, etc.)
Phases of Synchronization
Data Collection: An integration job or other tools runs and collects all data and stores it temporarily on filesystem.
Data Upload: All data that represents "new state" is uploaded to the persister and associated with an integration job identifier. The "new state" will consist of entities, relationships, and raw data.
Finalization: Once an integration has uploaded all data to the persister "finalization" is triggered. During the "finalization" phase, the persister will compare the "new state" with "old state" and determine changes. Any changes that are detected will cause operations to be produced will persisted during the run of the finalization task (they will not be enqueued on a Kinesis stream).
Entities are finalized first and relationships are finalized afterward (since relationships might reference new entities).
Synchronization API Usage
Start a synchronization job
Sample request:
POST /persister/synchronization/jobs
{ "source": "api", "scope": "my-sync-job" }
Sample request:
POST /persister/synchronization/jobs
{ "source": "integration-managed", "integrationInstanceId": "5465397d-8491-4a12-806a-04792839abe3" }
Sample response:
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "AWAITING_UPLOADS", "startTimestamp": 1586915139427, "numEntitiesUploaded": 0, "numEntitiesCreated": 0, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 0, "numRelationshipsCreated": 0, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Get status of synchronization job
Sample request:
GET /persister/synchronization/jobs/f445397d-8491-4a12-806a-04792839abe3
Sample response:
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "AWAITING_UPLOADS", "startTimestamp": 1586915139427, "numEntitiesUploaded": 0, "numEntitiesCreated": 0, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 0, "numRelationshipsCreated": 0, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Upload batch of entities
Sample request:
POST /persister/synchronization/jobs/f445397d-8491-4a12-806a-04792839abe3/entities
{ "entities": [ { "_key": "1", "_type": "fake_entity" }, { "_key": "2", "_type": "fake_entity" }, { "_key": "3", "_type": "fake_entity" } ] }
Sample response:
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "AWAITING_UPLOADS", "startTimestamp": 1586915752483, "numEntitiesUploaded": 3, "numEntitiesCreated": 0, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 0, "numRelationshipsCreated": 0, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Upload batch of relationships
Sample request:
POST /persister/synchronization/jobs/f445397d-8491-4a12-806a-04792839abe3/relationships
{ "relationships": [ { "_key": "a", "_type": "fake_relationship", "_fromEntityKey": "1", "_toEntityKey": "2" }, { "_key": "b", "_type": "fake_relationship", "_fromEntityKey": "2", "_toEntityKey": "3" } ] }
Sample response:
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "AWAITING_UPLOADS", "startTimestamp": 1586915752483, "numEntitiesUploaded": 3, "numEntitiesCreated": 0, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 2, "numRelationshipsCreated": 0, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Finalize synchronization job
Sample request:
POST /persister/synchronization/jobs/f445397d-8491-4a12-806a-04792839abe3/finalize
Sample response (when running locally):
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "FINISHED", "startTimestamp": 1586915752483, "numEntitiesUploaded": 3, "numEntitiesCreated": 3, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 2, "numRelationshipsCreated": 2, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Sample response (when running in AWS):
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "FINALIZE_PENDING", "startTimestamp": 1586915752483, "numEntitiesUploaded": 3, "numEntitiesCreated": 0, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 2, "numRelationshipsCreated": 0, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Synchronization job status upon completion
Sample request:
GET /persister/synchronization/jobs/f445397d-8491-4a12-806a-04792839abe3
Sample response:
{ "job": { "source": "api", "scope": "my-sync-job", "id": "f445397d-8491-4a12-806a-04792839abe3", "status": "FINISHED", "startTimestamp": 1586915752483, "numEntitiesUploaded": 3, "numEntitiesCreated": 3, "numEntitiesUpdated": 0, "numEntitiesDeleted": 0, "numRelationshipsUploaded": 2, "numRelationshipsCreated": 2, "numRelationshipsUpdated": 0, "numRelationshipsDeleted": 0 } }
Building CSV Report
Endpoint: /graphql
mutation BuildCsv( $filters: VertexFilters $propertyFilters: JSON $filterType: FilterType ) { buildCsv( filters: $filters propertyFilters: $propertyFilters filterType: $filterType ) { stateFileUrl } }
Variables:
{ "filters": { "_type": ["<an entity type>"], "_class": ["<an entity class>"] }, "filterType": "<AND or OR>", "propertyFilters": { ... } }
Alert and Rules Operations
Endpoint: /rules/graphql
Create an alert rule
mutation CreateQuestionRuleInstance ( $instance: CreateQuestionRuleInstanceInput! ) { createQuestionRuleInstance ( instance: $instance ) { id name description version pollingInterval question { queries { query version } } operations { when actions } outputs } }
variables:
{ "instance": { "name": "unencrypted-prod-data", "description": "Data stores in production tagged critical and unencrypted", "version": "v1", "pollingInterval": "ONE_DAY", "outputs": [ "alertLevel" ], "operations": [ { "when": { "type": "FILTER", "version": 1, "condition": [ "AND", [ "queries.unencryptedCriticalData.total", "!=", 0 ] ] }, "actions": [ { "type": "SET_PROPERTY", "targetProperty": "alertLevel", "targetValue": "CRITICAL" }, { "type": "CREATE_ALERT" } ] } ], "question": { "queries": [ { "query": "Find DataStore with (production=true or tag.Production=true) and classification='critical' and encrypted!=true as d return d.tag.AccountName as Account, d.displayName as UnencryptedDataStores, d._type as Type, d.encrypted as Encrypted", "version": "v1", "name": "unencryptedCriticalData" } ] } } }
Note that the recommended interval for query based alert rules (aka a question
)
is ONE_DAY
. \
Supported intervals for enterprise customers are:
DISABLED
, THIRTY_MINUTES
, ONE_HOUR
, FOUR_HOURS
, EIGHT_HOURS
,
TWELVE_HOURS
, ONE_DAY
, and ONE_WEEK
.
Free accounts only have access to the ONE_WEEK
interval by default, but
any upgrades to Compliance, Security, or Integrations will provide access
to the ONE_DAY
polling interval too.
Update an alert rule
mutation UpdateQuestionRuleInstance ( $instance: UpdateQuestionRuleInstanceInput! ) { updateQuestionRuleInstance ( instance: $instance ) { id name description version pollingInterval question { queries { query version } } operations { when actions } outputs } }
variables:
{ "instance": { "id": "b1c0f75d-770d-432a-95f5-6f59b4239c72", "name": "unencrypted-prod-data", "description": "Data stores in production tagged critical and unencrypted", "version": "v1", "pollingInterval": "ONE_DAY", "outputs": [ "alertLevel" ], "operations": [ { "when": { "type": "FILTER", "version": 1, "condition": [ "AND", [ "queries.unencryptedCriticalData.total", "!=", 0 ] ] }, "actions": [ { "type": "SET_PROPERTY", "targetProperty": "alertLevel", "targetValue": "CRITICAL" }, { "type": "CREATE_ALERT" } ] } ], "question": { "queries": [ { "query": "Find DataStore with (production=true or tag.Production=true) and classification='critical' and encrypted!=true as d return d.tag.AccountName as Account, d.displayName as UnencryptedDataStores, d._type as Type, d.encrypted as Encrypted", "version": "v1", "name": "unencryptedCriticalData" } ] } } }
Note that the only difference here for update
is the "id"
property
associated with the rule instance. All settings of a rule instance can be
modified.
Delete an alert rule
mutation DeleteRuleInstance ($id: ID!) { deleteRuleInstance ( id: $id ) { id } }
variables:
{ "id": "b1c0f75d-770d-432a-95f5-6f59b4239c72" }
Note that deleting an alert rule this way will not dismiss active alerts already triggered by this rule. It is recommended to Disable a rule in the alerts app UI instead of deleting one.
Trigger an alert rule on demand
mutation EvaluateRuleInstance ($id: ID!) { evaluateRuleInstance ( id: $id ) { outputs { name value } } }
variables:
{ "id": "b1c0f75d-770d-432a-95f5-6f59b4239c72" }
Question Operations
Endpoint: /graphql
Create a Question
mutation CreateQuestion($question: CreateQuestionInput!) { createQuestion(question: $question) { id title description queries { name query version } variables { name required default } compliance { standard requirements } accountId integrationDefinitionId } }
variables:
{ "question": { "title": "What are my production resources?", "tags": ["SecOps"], "description": "Returns a list of all production entities.", "queries": [ { "name": "prodresources", "query": "Find * with tag.Production=true" } ], "compliance": [ { "standard": "NIST CSF", "requirements": ["ID.AM-1"] } ] } }
Notes on "named queries":
name
field is optionalname
should be a single word without special characters- queries named
good
,bad
, andunkown
are used to determine gaps/issues and to perform continuous compliance assessment
Update a question
mutation UpdateQuestion($id: ID!, $update: QuestionUpdate!) { updateQuestion(id: $id, update: $update) { id title description queries { name query version } variables { name required default } compliance { standard requirements } accountId integrationDefinitionId } }
variables:
{ "id": "sj3j9f0j2ndlsj300swdjfjs", "update": { "title": "What are my production resources?", "tags": ["SecOps"], "description": "Returns a list of all production entities.", "queries": [ { "name": "prodresources", "query": "Find * with tag.Production=true" } ], "compliance": [ { "standard": "NIST CSF", "requirements": ["ID.AM-1"] } ] } }
Note that the only difference here for update
is the "id"
property
associated with the question.
Delete a question
mutation DeleteQuestion($id: ID!) { deleteQuestion(id: $id) { id title description queries { query name version } variables { name required default } tags accountId integrationDefinitionId } } }
variables:
{ "id": "slj3098s03j-i2ojd0j2-sjkkdjf" }
Integration Operations
Finding an Integration Definition based on a type
This query returns an Integration Definition. This query requires an Integration Type.
query testQuery ($integrationType: String!) { findIntegrationDefinition (integrationType: $integrationType) { id name type title integrationType integrationClass configFields { key displayName description } } }
Getting an Integration Definition with an ID
This query returns a Integration Definition. This query requires an ID.
query getIntegrationDefinition($id: String) { integrationDefinition(id: $id) { id name type title } }
List Integration Definitions
This query returns a list of all Integration Definitions.
query testQuery { integrationDefinitions { definitions { id name type title } pageInfo { endCursor hasNextPage } } }
Example Usage
Creating entities and a relationship between them NOTE: The following mutations utilize a J1Client.
const CREATE_ENTITY = gql` mutation createEntity ( $entityKey: String! $entityType: String! $entityClass: String! $timestamp: Long $properties: JSON ) { createEntity( entityKey: $entityKey entityType: $entityType entityClass: $entityClass properties: $properties ) { . . . }`; const CREATE_RELATIONSHIP = gql` mutation CreateRelationship ( $relationshipKey: String! $relationshipType: String! $relationshipClass: String! $fromEntityId: String! $toEntityId: String! ) { createRelationship ( relationshipKey: $relationshipKey relationshipType: $relationshipType relationshipClass: $relationshipClass fromEntityId: $fromEntityId toEntityId: $toEntityId ) { . . . }`; const entity1 = await j1Client.mutate({ mutation: CREATE_ENTITY, variable: { entityKey: 'Example Key', entityType: 'ExampleType', entityClass: 'ExampleClass', properties: { 'tag.key': 'tagvalue' } } }); const entity2 = await j1Client.mutate({ mutation CREATE_ENTITY, variable: { entityKey: 'Other Example Key', entityType: 'OtherType', entityClass: 'OtherClass', properties: { 'tag.key': 'tag' } } }); const relationship = await j1Client.mutate({ mutation: CREATE_RELATIONSHIP, variable: { relationshipKey: entity1._key + ' |uses| ' + entity2._key, relationshipClass: 'entity_uses_entity', relationshipType: 'USES', toEntityId: entity2._id, toEntityKey: entity1._id, } });
Comments
1 comment
555-555-0199@example.com
Please sign in to leave a comment.