GraphQL API - Documentation - Riter

Documentation of riter.co — project management tool

GraphQL API

Riter provides a simple but full-featured API based on GraphQL standard for managing your application data. Here you will find a complete description of available operations and requirements you should comply with to use them.

Authentication with GraphQL

Riter's GraphQL API suggests the token-based authentication so you need to add your token to a request header in this way: -H "api-token: used-token".

The API endpoint

GraphQL API has a single endpoint which remains constant for all operations: http://company-domain-name/current-project-name/graphql. Riter's API supports two types of operations: queries and mutations. Use queries to get the required data and mutations to change them. The field name determines which modification (create, update or destroy) is executed.

To query GraphQL you should use POST HTTP method. Content-Type must be "application/json". You will receive all responses in JSON format. The following example makes a POST request with a JSON payload to Riter using cURL. As a result, it gets a title of a story with the specified slug:

curl -H "Content-type: application/json" -X POST -d '{"query": "{ story(slug: \"api-and-graphql\") { title } }"}' -H "api-token: token" "https://subdomain.riter.co/tracker/graphql"

Queries

The query type contains a set of operations which can retrieve all available records from the server. GraphQL allows you to extract only the data you need specifying required fields in your request. The maximum depth of nesting queries is 6.

Story queries

story(slug: !String): Story

Get a Story by the argument 'slug' among current projects of the current company.

stories: [Story]

Get an array of Stories among current projects of the current company. Note, that you can use pagination for querying stories.

Argument Type Description
scope String Type of stories required, such as "archived", "current", "overdue", "unscheduled". Also "deleted" stories or "with_deleted".
query String An embedded query to a specific story.
sprintStartedAtAfter String Specify the period for which stories should be shown.
sprintStartedAtBefore String
sprintStartedAt String Return stories for a particular sprint started at "yyyy-mm-dd".
projectSlug String Specify project with particular slug for which story should be created.
sprintsSlugs [String] Return stories for sprints with particular slugs

Sprints queries

sprints: [Sprint]

Get an array of Sprints among current projects of the current company. Note, that you can use pagination for querying sprints.

Argument Type Description
scope String Type of sprints required, such as "archived", "actual".
before String Specify the period for which sprints should be shown.
after String Specify the period for which sprints should be shown.
first Integer One or several first current sprints
last Integer One or several last current sprints
slugs String String with sprint slugs which separated by spaces

As a result of such a query you will get a list of object which can contain items in the following format:

{
  sprints{
    edges{
      node{
        slug
        title
        description
        companyOrder
        createdAt
        updatedAt
        storiesCount
        activeStoriesCount
        archivedStoriesCount
      }
    }
  }
}

State queries

state(storySlug: !String): State

Get a State by the argument 'storySlug' among current projects.

states: [State]

Get an array of StateItem among current projects of the current company. Note, that you can use pagination for querying stories.

Dashboard queries

dashboardItem(slug: !String): DashboardItem

Get a DashboardItem by the argument 'slug' among current projects of the current company.

Dashboard: [DashboardItem]

Get an array of DashboardItem among current projects of the current company. Note, that you can use pagination for querying stories.

Argument Type Description
projectSlug String Specify project with particular slug for which dashboard item should be created.
kinds [String] Type of dashboard item required, such as "annotation", "state", "timeinterval", "estimation", "sprint", "stories_user", "story_topic", "topic", "story", "user", "project".
from String Date in format 'yyyy-mm-dd' from which dashboard item should be shown.
to String Date in format 'yyyy-mm-dd' up to which dashboard item should be shown.
author String Nickname of user who create dashboard item. Also it can be bot

Timeinterval queries

You can execute timeinterval requests for a particular story (as a story object field) to get a whole list of timeintervals or a specific one by its slug.

timeinterval(slug: !String): Timeinterval

Find a Timeinterval by its slug field.

timeintervals: [Timeinterval]

Find an array of Timeintervals among the current project for a specific story.

{
  story(slug: "story-slug") {
    timeinterval(slug: "timeinterval-slug") {
      author
      day
      minutes
    }
  }
}

Time ranges queries

You can execute time range requests for a particular project (as a project object field) to get a list of time ranges or a sub-set by providing optional from , to , users arguments. Returned time ranges are limited to the last calendar week if none of from / to arguments provided.

time_ranges(from: ISOTime, to: ISOTime, users: [!String]): [TimeRange]

Retrieve an array of TimeRange objects for a specific project.

{
  project(slug: "demo-project") {
    time_ranges(from: "2019-01-21", to: "2019-01-27", users: ["watcher", "dragon"]) {
      id
      date
      startedAt
      finishedAt
      deletedAt
      timezone
      minutes
      user {
        slug
        nickname
        fullName
      }
    }
  }
}

Watcher queries

watchers(scope: [!String]): [Watcher]

Find an array of Watchers among the current project for a specific story.

Argument Type Description
scope String Type of watchers required, such as "self".

As a result of such a query you will get a list of object which can contain items in the following format:

{
  story(slug: "story-slug") {
    watchers(scope: "self") {
      nickname
      createdAt
      updatedAt
    }
  }
}

Annotation queries

annotation(storySlug: !String, slug: !String): Annotation

Find an Annotation by its slug.

annotations: [Annotation]

Find an array of Annotations among the current project for a specific story. Note, that you can use pagination for querying annotations.

Argument Type Description
storySlug !String Specify story with particular slug for which annotation should be found.
kinds [String] Type of annotations required, such as "comment" "content" "estimation" "question" "sprint" "state" "timeinterval" "topic" "user".
from String Date in format 'yyyy-mm-dd' from which annotations should be shown.
to String Date in format 'yyyy-mm-dd' up to which annotations should be shown.
author String Nickname of user who create annotation. Also it can be "historybot"

Topic queries

topic(name: !String): Topic

Find a Topic by its name or by aliases.

topics: [Topic]

Find an array of Topics of a specific story.

Argument Type Description
scope String Type of topics required, such as "active", "archived".

Mutations

If in REST we can use PUT or PATCH HTTP requests to manage server-side data, in GraphQL API we need to create mutations to modify it. A mutation can contain multiple fields, just like a query. However, while query fields are executed in parallel, mutation fields run in series, one after the other.

Story mutations

createStory

Create a new Story.

Argument Type Description
title !String A story title.
description String A story description.
state String A story state unique identifier. By default, Riter provides the following set of states (that can be extended by other values): "draft", "estimated", "in_process", "completed" and "approved".
estimation String Number of minutes required for the story implementation by a preliminary estimation.
questionMark Boolean A special mark which shows that story is unclear and requires discussion before implementation.
userNicknames [String] An array of users involved in the story implementation.
companyOrder Float A story order in a particular sprint, takes values from -9 999 999 999.0 to 9 999 999 999.0.
updateStory

Update an existing Story. Arguments of the function are identical to the previous createStory mutation.

{
  updateStory(slug: "...") {
    title: "New title"
    description: "New description"
    questionMark: True
  }
}
destroyStory(slug: !String)

Delete an existing Story with a specific slug.

Dashboard mutations

createDashboardItem

Create a new Dashboard.

Argument Type Description
boby !String A dashboard item body.
kind String By default, Riter provides the following set of kind: "annotation", "state", "timeinterval", "estimation", "stories_user", "sprint", "story_topic", "topic", "story", "user", "project".
format String Default format is a "html". Riter provides the following set of format: "markdown", "html", "text"
projectSlug String A project slug string which include its name values.
updateDashboardItem

Update an existing Dashboard. Arguments of the function are identical to the previous createDashboardItem mutation.

{
  updateDashboardItem(slug: "...") {
    body: "New *markdown* body"
    kind: "story"
    format: "markdown"
   }
}

Timeinterval mutations

Use the following mutations to modify timeintervals. You can execute mutations for a particular story context or set a story by its slug as an argument.

createTimeinterval

Create a new timeinterval for a particular story specified by a slug.

Argument Type Description
raw !String A raw timeinterval content.
storySlug String A slug of a story for which the timeinterval should be created.
updateTimeinterval

Update an existing timeinterval. Arguments are similar to the createTimeinterval mutation.

destroyTimeinterval(slug: String)

Destroy a timeinterval with a specified slug.

You can also use update and destroy fields of a specific timeinterval instead of two previous mutations with similar arguments.

{
  story(slug: "story-slug") {
    timeinterval(slug: "timeinterval-slug") {
      update(raw: "new timeinterval content") {
        slug
      }
    }
  }
}

Annotation mutations

Use the following mutations to modify annotations. You can execute mutations for a particular story object to create its annotation. The current user will be set as its author automatically. Run an update request to a specific annotation to change it.

createAnnotation(storySlug: !String, body: !String)

Create a new annotation to the particular story with specified body content.

mutation {
  createAnnotation(storySlug: "story-slug", body: "annotation content") {
    body
  }
}
updateAnnotation(storySlug: !String, slug: !String, body: !String)

Update a content of the specified annotation.

mutation {
  updateAnnotation(storySlug: "story-slug", slug: "annotation-slug", body: "new annotation content") {
    body
  }
}

Topic mutations

createTopic(name: !String, aliases: [String])

Create a new Topic.

Argument Type Description
name !String A topic name.
aliases [String] An array of related aliases.
assignTopic(name: !String)

Add a topic to a particular story.

unassignTopic(name: !String)

Remove a topic from a particular story.

updateTopic(name: !String, aliases: [String], absorbed_topic_name: String)

Update an exists topic Topic.

Argument Type Description
name !String A topic name.
aliases [String] An array of related aliases.
absorbed_topic_name [String] name of exists topic which should be absorbed.

User mutations

Assign/unassign User to/from story.

Argument Type Description
nickname !String A user nickname.
assignUser(name: !String)

Add a user to a particular story.

unassignUser(name: !String)

Remove a user from a particular story.

Watcher mutations

subscribe/unsubscribe Watcher to/from story.

Argument Type Description
nickname !String A user nickname.
subscribe(nickname: !String)

Subscribe a user to a particular story.

unsubscribe(nickname: !String)

Unsubscribe a user from a particular story.

{
  story(slug: "story-slug") {
    subscribe(nickname: ""user-nickname) {
      nickname
      createdAt
      updatedAt
    }
  }
}

Objects

Object types in GraphQL API represent the resources you can access. All Riter objects are listed below along with available fields and appropriate types.

Story

Represents a project story - some task which describes a particular job.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
slug !String A story slug string which includes its title, author's nickname and created_at field values.
title !String A story title.
description String A story description.
state !String A story state unique identifier. By default, Riter provides the following set of states (that can be extended by other values):
  • draft
  • estimated
  • in_process
  • completed
  • approved
stateBackgroundColor !String A story state color. By default, Riter provides the #eeeeee color
stateTextColor !String A story state text color. By default, Riter provides the #000000 color
stateName !String A state name.
stateAliases [String] An array of related aliases.
projectSlug !String A project slug string which include its name values.
questionMark !Boolean A special mark which shows that story is unclear and requires discussion before implementation.
estimation Int Number of minutes required for the story implementation by a preliminary estimation.
spentMinutes Int Number of minutes actually spent on the task.
companyOrder Float A story order in a particular sprint, takes values from -9 999 999 999.0 to 9 999 999 999.0.
annotationsCount Int A number of annotations to the story.
deletedAt ISOTime DataTime when the story was deleted.
author ! User Specifies a User who created the story.
project Project Specifies a project to which it belongs story
toStates [ State ] Specifies a state which can be changed from current story state.
timeintervals [ Timeinterval ] An array of the story's timeintervals.
users [ User ] An array of users involved in the story implementation.
topics [ Topic ] An array topics assigned to the story.
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • updated: !String
  • titleChanged: String
  • spentMinutesChanged: String
  • unestimated: String
  • estimated: String
  • reestimated: String
  • estimationChanged: String
  • stateChanged: String
  • questionAdded: String
  • questionRemoved: String
  • planned: String
  • unplanned: String
  • sprintChanged: String
  • positionChanged: String
  • archived: String
  • actived: String
  • destroyed: String
  • annotationCommentCreated: String
  • annotationCreated: String
  • annotationUpdated: String
  • annotationDestroyed: String
  • topicAdded: String
  • topicUpdated: String
  • topicDestroyed: String
  • assigned: String
  • unassigned: String
  • timeintervalCreated: String
  • timeintervalUpdated: String
  • timeintervalDestroyed: String
  • watcherCreated: String
  • watcherUpdated: String
  • watcherDestroyed: String
canChangePriority Boolean User ability to change of story priority
canChangeSprint Boolean User ability to change of story sprint
canChangeEstimation Boolean User ability to change of story estimation time
canChangeAssignee Boolean User ability to assign/unassign user on/from story
canChangeState Boolean User ability to change state of story
canChangeContent Boolean User ability to change title or description of story
canChangeTopics Boolean User ability to change topics of story
canChangeQuestionMark Boolean User ability to add/remove question mark to/from story

Timeinterval

Time interval when some part of a particular task was being executed.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
author ! User Specifies a User who created the timeinterval.
day !String Date of the period in format 'yyyy.mm.dd'.
deletedAt ISOTime Time of the timeinterval deletion.
description String The timeinterval description field.
finishedAt ISOTime Time when the interval was completed.
minutes Int Number of minutes spent directly on the task, not on the work process as a whole.
nicknames ![!String] Nicknames of the users who took part in a particular time interval work.
raw String A raw (primary) timeinterval content.
slug !String The time interval slug in the following format: "timeinterval-author_nickname-YYYY-MM-DDtHH24-MI-SS-USz".
startedAt ISOTime Time when the interval was started.
users ![! User ] An array of users involved in a particular time interval work.
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • updated: !String
  • destroyed: String
canUpdate Boolean User ability to update timeinterval
canDestroy Boolean User ability to destroy timeinterval

TimeRange

Time range represents working hours of the particular user on some project.

Field Type Description
id !Int Time range primary key.
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
date ! ISOTime Time range performed date.
startedAt ! ISOTime Start time of the time range.
finishedAt ! ISOTime Time range completion time.
deletedAt ISOTime Time range deletion timestamp.
minutes !Int Difference between finishedAt and startedAt in minutes.
timezone !String Timezone in which time range was created.
author ! User Specifies a User related to the time range.

User

Represents a Riter user who has an individual's account and can take a part in project development process.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
email !String The user email.
fullName !String The user full name (name and surname).
nickname !String The user nickname.
timezone !String The user timezone.

Annotation

Represents a story annotation - user's comment on a task.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
slug !String The annotation slug in format: "annotation-created_at" which includes date and time of the annotation creation (or last update).
body !String The annotation content.
author ! User The annotation author.
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • updated: !String
  • destroyed: String
canUpdate Boolean User ability to update annotation
canDestroy Boolean User ability to destroy annotation

Topic

Represents a topic - some keyword which serves to distinguish stories and navigate among them.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
slug !String A topic slug.
name !String A topic name.
aliases [String] An array of related aliases.
disabledAt ISOTime Time when the topic was disabled.
deletedAt ISOTime Time when the topic was deleted.
project Project Specifies a project to which it belongs topic
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • updated: !String
  • archived: String
  • activate: String
  • absorb: String
  • destroyed: String

State

Represents a state - condition which describe current status of story.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
uid !String A state uniq name uid for project.
slug String A state uniq slug for company.
name !String A state name.
aliases [String] An array of related aliases.
backgroundColor !String A hexadecimal color code.
textColor !String A hexadecimal color code.

Sprint

Represents a sprint - basic unit of development. The sprint is a timeboxed effort; that is, it is restricted to a specific duration.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
slug !String A sprint slug.
title String A sprint title.
storiesCount Int A count of all stories.
activeStoriesCount Int A count of stories which contain in active sprint.
archivedStoriesCoun Int A count of stories which contain in archived sprint.
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • updated: !String
  • archived: String
  • activate: String
  • destroyed: String
  • projectsSprintArchived: String
  • projectsSprintActivate: String
  • projectsSprintIsArchivedChanged: String
  • projectsSprintUpdated: String
  • storyCreated: String
  • storyDescriptionChanged: String
  • storyTitleChanged: String
  • storySpentMinutesChanged: String
  • storyUnestimated: String
  • storyEstimated: String
  • storyReestimated: String
  • storyEstimationChanged: String
  • storyStateChanged: String
  • storyQuestionAdded: String
  • storyQuestionRemoved: String
  • storyPlanned: String
  • storyUnplanned: String
  • storySprintChanged: String
  • storyPositionChanged: String
  • storyArchived: String
  • storyActived: String
  • storyUpdated: String
  • storyDestroyed: String

Project

Contemporary business and science treat as a project, involving research or design, that is carefully planned to achieve a particular aim.

Field Type Description
updatedAt ! ISOTime Time when an object was last updated.
createdAt ! ISOTime Time when an object was created.
slug !String A project slug.
shortname String A project shortname.
displayOverdueStories Boolean Stories with archived sprint
canCreateTopics Boolean Ability to create topics on current project
canCreateStory Boolean Ability to create stories on current project
canReadStory Boolean Ability to read topics on current project
canCreateSprint Boolean Ability to create sprint on current project
canCreateDashboardItem Boolean Ability to create item of dashboard on current project
canReadDashboardItem Boolean Ability to read item of dashboard on current project
canReadAnnotations Boolean Ability to read annotations on current project
time_ranges [! TimeRange ] List of time ranges for the current project. Example query with available arguments.
channels Hash An array of hash'es which contain key - name of channel and value - websockets channel like String
  • storyCreated: String
  • storyUpdated: String
  • storyDescriptionChanged: String
  • storyTitleChanged: String
  • storySpentMinutesChanged: String
  • storyUnestimated: String
  • storyEstimated: String
  • storyReestimated: String
  • storyEstimationChanged: String
  • storyStateChanged: String
  • storyQuestionAdded: String
  • storyQuestionRemoved: String
  • storyPlanned: String
  • storyUnplanned: String
  • storySprintChanged: String
  • storyPositionChanged: String
  • storyArchived: String
  • storyActived: String
  • storyDestroyed: String
  • annotationCommentCreated: String
  • annotationCreated: String
  • annotationUpdated: String
  • annotationDestroyed: String
  • topicAdded: String
  • topicUpdated: String
  • topicDestroyed: String
  • assignedUser: String
  • unassignedUser: String
  • timeintervalCreated: String
  • timeintervalUpdated: String
  • timeintervalDestroyed: String
  • projectsSprintArchived: String
  • projectsSprintActivate: String
  • projectsSprintIsArchivedChanged: String
  • projectsSprintUpdated: String
  • topicArchived: String
  • topicActivate: String
  • topicAbsorb: String

Scalars

While querying GraphQL API, you must specify nested subfields until you return only scalars. Riter API includes such scalar values as Int, Float, String, Boolean and ISOTime. Note, that any type (object or scalar) with an exclamation mark !Type means, that the field is non-nullable, so GraphQL service always expects to receive a value when you query this field. Square brackets represent an array of specific type: [Type].

Int

Represents signed whole numeric values.

Float

Represents signed double-precision values.

String

Represents textual data as UTF-8 character sequences.

Boolean

Represents true or false values.

ISOTime

An ISO-8601 encoded DateTime string.

Hash

Collection of unique keys and their values

Pagination

Riter API provides a cursor-based pagination for querying stories. By default, a page includes 25 records. The structure pageInfo tells you if there are more pages of data for the current request and how to fetch them.

pageInfo {
  endCursor
  startCursor
  hasNextPage
  hasPreviousPage
}

The startCursor and endCursor fields represent the current page identifiers that you should use to get a particular page. The hasNextPage and hasPreviousPage fields define if there are some next and previous pages of the list. You can use before or after query arguments to specify the cursor position - an encoded string which the required page should begin or end with, for example: stories(before: "AW7q=="). Each node in the edges collection has its unique cursor.

{
  stories {
    pageInfo {
      endCursor
      startCursor
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        title
        description
        slug
        state
        users { ...user }
        author { ...user }
        topics { name }
        createdAt
        deletedAt
      }
    }
  }
}
fragment user on User {
  nickname
  email
  fullName
  timezone
}