"Que sigo" on the home page lists the open tickets I follow, whoever works on them; `watching` filters my issues (REST, GraphQL, MCP) and a project's search (none without a session). Followers now also hear when a ticket's priority or due date changes, and when it enters or leaves a sprint. Smaller edits (title, labels…) still do not notify. Docs (with the REPLIED row the replies change missed), Word and PDF updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1371 lines
28 KiB
GraphQL
1371 lines
28 KiB
GraphQL
# ------------------------------------------------------
|
|
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
|
|
# ------------------------------------------------------
|
|
|
|
type Activity {
|
|
actor: UserRef!
|
|
id: ID!
|
|
issueId: ID
|
|
issueKey: String
|
|
occurredAt: String!
|
|
projectId: ID!
|
|
summary: String!
|
|
type: String!
|
|
}
|
|
|
|
input AddChecklistItemInput {
|
|
issueId: ID!
|
|
text: String!
|
|
}
|
|
|
|
type AreaOption {
|
|
archived: Boolean!
|
|
id: String!
|
|
name: String!
|
|
}
|
|
|
|
input AreaOptionInput {
|
|
archived: Boolean! = false
|
|
id: String!
|
|
name: String!
|
|
}
|
|
|
|
"""
|
|
A file on a ticket. Download it from the REST API: GET /api/issues/{issueId}/attachments/{id}
|
|
"""
|
|
type Attachment {
|
|
"""The comment it was attached to, if any"""
|
|
commentId: ID
|
|
fileName: String!
|
|
id: ID!
|
|
mimeType: String!
|
|
|
|
"""Bytes"""
|
|
size: Int!
|
|
uploadedAt: String!
|
|
uploadedBy: UserRef!
|
|
}
|
|
|
|
"""When this happens to a ticket, if it is like this, do that"""
|
|
type Automation {
|
|
action: AutomationActionSpec!
|
|
active: Boolean!
|
|
conditions: AutomationConditions!
|
|
createdAt: String!
|
|
createdBy: UserRef!
|
|
id: ID!
|
|
|
|
"""Why the last run did nothing"""
|
|
lastError: String
|
|
lastRunAt: String
|
|
name: String!
|
|
projectId: ID!
|
|
runs: Int!
|
|
trigger: AutomationTriggerSpec!
|
|
}
|
|
|
|
"""What a rule does to the ticket"""
|
|
enum AutomationAction {
|
|
ADD_COMMENT
|
|
ADD_LABEL
|
|
ADD_TO_ACTIVE_SPRINT
|
|
ASSIGN
|
|
ASSIGN_REPORTER
|
|
SET_PRIORITY
|
|
SET_STATUS
|
|
}
|
|
|
|
input AutomationActionInput {
|
|
kind: AutomationAction!
|
|
value: String
|
|
}
|
|
|
|
type AutomationActionSpec {
|
|
kind: AutomationAction!
|
|
|
|
"""Status, member id, label, priority or comment text"""
|
|
value: String
|
|
}
|
|
|
|
type AutomationConditions {
|
|
areas: [String!]
|
|
label: String
|
|
priorities: [IssuePriority!]
|
|
types: [String!]
|
|
}
|
|
|
|
input AutomationConditionsInput {
|
|
areas: [String!]
|
|
label: String
|
|
priorities: [IssuePriority!]
|
|
types: [String!]
|
|
}
|
|
|
|
"""What starts a rule"""
|
|
enum AutomationTrigger {
|
|
COMMENT_ADDED
|
|
ISSUE_ASSIGNED
|
|
ISSUE_CREATED
|
|
PULL_REQUEST_MERGED
|
|
STATUS_CHANGED
|
|
}
|
|
|
|
input AutomationTriggerInput {
|
|
kind: AutomationTrigger!
|
|
status: String
|
|
}
|
|
|
|
type AutomationTriggerSpec {
|
|
kind: AutomationTrigger!
|
|
|
|
"""STATUS_CHANGED: only into this status"""
|
|
status: String
|
|
}
|
|
|
|
type BoardColumn {
|
|
issues: [Issue!]!
|
|
status: String!
|
|
total: Int!
|
|
}
|
|
|
|
type BulkIssueResult {
|
|
error: String
|
|
issueId: ID!
|
|
ok: Boolean!
|
|
}
|
|
|
|
type BulkResult {
|
|
results: [BulkIssueResult!]!
|
|
updated: Int!
|
|
}
|
|
|
|
input BulkUpdateIssuesInput {
|
|
addLabels: [String!]
|
|
assigneeId: ID
|
|
issueIds: [ID!]!
|
|
|
|
"""Out of their release"""
|
|
noRelease: Boolean
|
|
|
|
"""Back to the backlog"""
|
|
noSprint: Boolean
|
|
priority: IssuePriority
|
|
releaseId: ID
|
|
sprintId: ID
|
|
status: String
|
|
|
|
"""Unassign everything"""
|
|
unassign: Boolean
|
|
}
|
|
|
|
input ChangeIssueStatusInput {
|
|
issueId: ID!
|
|
|
|
"""Required by statuses with requiresReason"""
|
|
reason: String
|
|
|
|
"""A status id"""
|
|
status: String!
|
|
}
|
|
|
|
"""A step inside a ticket that does not deserve a ticket of its own"""
|
|
type ChecklistItem {
|
|
done: Boolean!
|
|
id: ID!
|
|
text: String!
|
|
}
|
|
|
|
"""How far the tickets hanging from one have got"""
|
|
type ChildProgress {
|
|
"""Done or cancelled"""
|
|
finished: Int!
|
|
finishedStoryPoints: Int!
|
|
percent: Int!
|
|
storyPoints: Int!
|
|
total: Int!
|
|
}
|
|
|
|
"""
|
|
Writes are acknowledged immediately; the read model catches up asynchronously. Wait for a subscription event with version >= this version to see the change.
|
|
"""
|
|
type CommandResult {
|
|
id: ID!
|
|
key: String
|
|
version: Int!
|
|
}
|
|
|
|
type Comment {
|
|
author: UserRef!
|
|
|
|
"""Empty on a deleted comment kept for its replies"""
|
|
body: String!
|
|
createdAt: String!
|
|
|
|
"""Deleted, but kept (without its text) while it has replies"""
|
|
deleted: Boolean!
|
|
editedAt: String
|
|
id: ID!
|
|
issueId: ID!
|
|
|
|
"""The top-level comment it answers; null for a top-level one"""
|
|
replyTo: ID
|
|
version: Int!
|
|
}
|
|
|
|
type CommentChange {
|
|
action: String!
|
|
actorId: ID!
|
|
|
|
"""Null when deleted"""
|
|
comment: Comment
|
|
commentId: ID!
|
|
issueId: ID!
|
|
version: Int!
|
|
}
|
|
|
|
type CommentPage {
|
|
items: [Comment!]!
|
|
total: Int!
|
|
}
|
|
|
|
type CountByAssignee {
|
|
count: Int!
|
|
|
|
"""Null = unassigned"""
|
|
user: UserRef
|
|
}
|
|
|
|
type CountByKey {
|
|
count: Int!
|
|
key: String!
|
|
}
|
|
|
|
type CountByStatus {
|
|
count: Int!
|
|
|
|
"""Status id"""
|
|
key: String!
|
|
}
|
|
|
|
input CreateAutomationInput {
|
|
action: AutomationActionInput!
|
|
conditions: AutomationConditionsInput
|
|
name: String!
|
|
projectId: ID!
|
|
trigger: AutomationTriggerInput!
|
|
}
|
|
|
|
input CreateIssueInput {
|
|
"""An area id"""
|
|
area: String
|
|
assigneeId: ID
|
|
description: String
|
|
dueDate: String
|
|
|
|
"""Figma frame for UI changes"""
|
|
figmaUrl: String
|
|
labels: [String!]
|
|
|
|
"""Epic or ticket of the same project the new one breaks down"""
|
|
parentId: ID
|
|
priority: IssuePriority
|
|
projectId: ID!
|
|
releaseId: ID
|
|
|
|
"""When work should start (roadmap), YYYY-MM-DD"""
|
|
startDate: String
|
|
storyPoints: Int
|
|
title: String!
|
|
|
|
"""A ticket type id"""
|
|
type: String!
|
|
}
|
|
|
|
input CreateProjectInput {
|
|
description: String
|
|
|
|
"""Readable by anyone, also without signing in"""
|
|
isPublic: Boolean
|
|
|
|
"""2-10 chars, e.g. "TS" → tickets TS-1, TS-2..."""
|
|
key: String!
|
|
name: String!
|
|
}
|
|
|
|
input CreateReleaseInput {
|
|
description: String
|
|
|
|
"""e.g. v1.4.0"""
|
|
name: String!
|
|
projectId: ID!
|
|
targetDate: String
|
|
}
|
|
|
|
input CreateSprintInput {
|
|
"""YYYY-MM-DD, included"""
|
|
endDate: String!
|
|
goal: String
|
|
name: String!
|
|
projectId: ID!
|
|
|
|
"""YYYY-MM-DD"""
|
|
startDate: String!
|
|
}
|
|
|
|
input CreateWebhookInput {
|
|
"""Event names, family.* or *"""
|
|
events: [String!]!
|
|
projectId: ID!
|
|
url: String!
|
|
}
|
|
|
|
type CreatedResolved {
|
|
created: Int!
|
|
resolved: Int!
|
|
|
|
"""Monday of the week (YYYY-MM-DD)"""
|
|
week: String!
|
|
}
|
|
|
|
type CumulativeFlow {
|
|
dates: [String!]!
|
|
series: [FlowSeries!]!
|
|
}
|
|
|
|
"""A commit, branch or pull request that mentions the ticket"""
|
|
type DevLink {
|
|
at: String!
|
|
author: String
|
|
kind: DevLinkKind!
|
|
|
|
"""github, gitea or gitlab"""
|
|
provider: String!
|
|
|
|
"""Short SHA, branch or PR number"""
|
|
ref: String!
|
|
|
|
"""The project's name for the repository it came from"""
|
|
repository: String
|
|
state: DevLinkState
|
|
title: String!
|
|
url: String!
|
|
}
|
|
|
|
enum DevLinkKind {
|
|
BRANCH
|
|
COMMIT
|
|
PULL_REQUEST
|
|
}
|
|
|
|
enum DevLinkState {
|
|
CLOSED
|
|
MERGED
|
|
OPEN
|
|
}
|
|
|
|
type DurationStats {
|
|
averageDays: Float
|
|
count: Int!
|
|
|
|
"""85% of tickets take at most this long"""
|
|
p85Days: Float
|
|
}
|
|
|
|
"""A top-level ticket that groups others, with their progress"""
|
|
type Epic {
|
|
issue: Issue!
|
|
progress: ChildProgress!
|
|
}
|
|
|
|
type FlowSeries {
|
|
counts: [Int!]!
|
|
status: String!
|
|
}
|
|
|
|
"""
|
|
Webhooks from GitHub, Gitea or GitLab: commits, branches and pull requests naming a ticket key are linked to it
|
|
"""
|
|
type GitIntegration {
|
|
"""On while there is at least one repository"""
|
|
enabled: Boolean!
|
|
repositories: [GitRepository!]!
|
|
|
|
"""Path of the webhook on this API, the same for every repository"""
|
|
webhookPath: String!
|
|
}
|
|
|
|
"""A repository whose webhooks the project accepts"""
|
|
type GitRepository {
|
|
createdAt: String!
|
|
id: ID!
|
|
|
|
"""The project's name for it: api, web, admin…"""
|
|
name: String!
|
|
|
|
"""Webhook secret of this repository; only owners and admins see it"""
|
|
secret: String
|
|
}
|
|
|
|
type Issue {
|
|
"""Statuses this ticket can move to next (project's workflow)"""
|
|
allowedTransitions: [String!]!
|
|
|
|
"""An area id"""
|
|
area: String
|
|
assignee: UserRef
|
|
attachments: [Attachment!]!
|
|
checklist: [ChecklistItem!]!
|
|
commentCount: Int!
|
|
comments(limit: Int! = 50, offset: Int! = 0): CommentPage!
|
|
createdAt: String!
|
|
description: String
|
|
|
|
"""Commits, branches and pull requests that mention it"""
|
|
devLinks: [DevLink!]!
|
|
dueDate: String
|
|
figmaUrl: String
|
|
|
|
"""History of this ticket"""
|
|
history(limit: Int! = 50): [Activity!]!
|
|
id: ID!
|
|
|
|
"""Human key, e.g. TS-42"""
|
|
key: String!
|
|
labels: [String!]!
|
|
|
|
"""Linked tickets I can see"""
|
|
linkedIssues: [Issue!]!
|
|
links: [IssueLink!]!
|
|
number: Int!
|
|
|
|
"""The epic or ticket this one breaks down"""
|
|
parent: IssueParent
|
|
priority: IssuePriority!
|
|
projectId: ID!
|
|
projectKey: String!
|
|
|
|
"""
|
|
Place in the backlog and in its board column (ascending, compare as text)
|
|
"""
|
|
rank: String!
|
|
release: ReleaseRef
|
|
reporter: UserRef!
|
|
sprint: SprintRef
|
|
|
|
"""When work should start (roadmap)"""
|
|
startDate: String
|
|
|
|
"""A status id of the project's settings"""
|
|
status: String!
|
|
statusCategory: StatusCategory!
|
|
storyPoints: Int
|
|
title: String!
|
|
|
|
"""In the trash since then; null when it is not"""
|
|
trashedAt: String
|
|
|
|
"""A ticket type id of the project's settings"""
|
|
type: String!
|
|
updatedAt: String!
|
|
version: Int!
|
|
|
|
"""People following the ticket"""
|
|
watchers: [UserRef!]!
|
|
}
|
|
|
|
type IssueChange {
|
|
action: String!
|
|
actorId: ID!
|
|
issue: Issue!
|
|
version: Int!
|
|
}
|
|
|
|
input IssueFilterInput {
|
|
areas: [String!]
|
|
assigneeId: ID
|
|
categories: [StatusCategory!]
|
|
|
|
"""Due on or after this day (YYYY-MM-DD)"""
|
|
dueFrom: String
|
|
|
|
"""Due on or before this day (YYYY-MM-DD)"""
|
|
dueTo: String
|
|
labels: [String!]
|
|
|
|
"""Only tickets in no sprint"""
|
|
noSprint: Boolean
|
|
|
|
"""Only the tickets hanging from this one"""
|
|
parentId: ID
|
|
priorities: [IssuePriority!]
|
|
projectId: ID!
|
|
releaseId: ID
|
|
|
|
"""Matches key, title or description"""
|
|
search: String
|
|
sort: IssueSort = RECENT
|
|
sprintId: ID
|
|
statuses: [String!]
|
|
types: [String!]
|
|
unassigned: Boolean
|
|
|
|
"""Only the tickets I follow (none when anonymous)"""
|
|
watching: Boolean
|
|
}
|
|
|
|
type IssueLink {
|
|
"""OUTWARD: this issue → other. INWARD: other → this issue."""
|
|
direction: LinkDirection!
|
|
issueId: ID!
|
|
issueKey: String!
|
|
type: IssueLinkType!
|
|
}
|
|
|
|
enum IssueLinkType {
|
|
BLOCKS
|
|
DEPENDS_ON
|
|
DUPLICATES
|
|
RELATES_TO
|
|
TESTS
|
|
}
|
|
|
|
type IssuePage {
|
|
items: [Issue!]!
|
|
total: Int!
|
|
}
|
|
|
|
"""The ticket another one hangs from"""
|
|
type IssueParent {
|
|
id: ID!
|
|
key: String!
|
|
title: String!
|
|
}
|
|
|
|
enum IssuePriority {
|
|
CRITICAL
|
|
HIGH
|
|
LOW
|
|
LOWEST
|
|
MEDIUM
|
|
}
|
|
|
|
"""RECENT: last updated first. RANK: backlog order."""
|
|
enum IssueSort {
|
|
RANK
|
|
RECENT
|
|
}
|
|
|
|
"""What a new ticket of the type starts with"""
|
|
type IssueTemplate {
|
|
"""Steps added to every new ticket"""
|
|
checklist: [String!]!
|
|
|
|
"""Used when the ticket comes without a description"""
|
|
description: String
|
|
}
|
|
|
|
input IssueTemplateInput {
|
|
checklist: [String!]! = []
|
|
description: String
|
|
}
|
|
|
|
type IssueTypeOption {
|
|
archived: Boolean!
|
|
color: String!
|
|
icon: String!
|
|
id: String!
|
|
name: String!
|
|
template: IssueTemplate
|
|
}
|
|
|
|
input IssueTypeOptionInput {
|
|
archived: Boolean! = false
|
|
color: String!
|
|
icon: String!
|
|
id: String!
|
|
name: String!
|
|
template: IssueTemplateInput
|
|
}
|
|
|
|
enum LinkDirection {
|
|
INWARD
|
|
OUTWARD
|
|
}
|
|
|
|
input LinkIssuesInput {
|
|
issueId: ID!
|
|
targetIssueId: ID!
|
|
type: IssueLinkType!
|
|
}
|
|
|
|
type Me {
|
|
"""Roles inside the task-stream OAuth client"""
|
|
appRoles: [String!]!
|
|
email: String!
|
|
id: ID!
|
|
isActive: Boolean!
|
|
name: String!
|
|
|
|
"""Global roles in Pireon"""
|
|
roles: [String!]!
|
|
}
|
|
|
|
type Mutation {
|
|
"""Add a step to a ticket's checklist"""
|
|
addChecklistItem(input: AddChecklistItemInput!): CommandResult!
|
|
|
|
"""
|
|
Comment on a ticket, or answer a comment (replyTo; one level of replies)
|
|
"""
|
|
addComment(body: String!, issueId: ID!, replyTo: ID): CommandResult!
|
|
|
|
"""
|
|
Add a repository with its own secret (the first turns the integration on)
|
|
"""
|
|
addGitRepository(name: String!, projectId: ID!): GitRepository!
|
|
|
|
"""Add a Pireon user to the project"""
|
|
addProjectMember(input: ProjectMemberInput!): CommandResult!
|
|
archiveRelease(releaseId: ID!): CommandResult!
|
|
|
|
"""Assign (or unassign with null) a project member"""
|
|
assignIssue(assigneeId: ID, issueId: ID!): CommandResult!
|
|
|
|
"""
|
|
The same change on up to 100 tickets; each goes through the normal rules and may refuse on its own
|
|
"""
|
|
bulkUpdateIssues(input: BulkUpdateIssuesInput!): BulkResult!
|
|
|
|
"""Move a ticket through the workflow (incl. QA)"""
|
|
changeIssueStatus(input: ChangeIssueStatusInput!): CommandResult!
|
|
changeProjectMemberRole(input: ProjectMemberInput!): CommandResult!
|
|
|
|
"""
|
|
Close the sprint under way. Unfinished tickets move to carryOverToSprintId, or back to the backlog when it is null.
|
|
"""
|
|
closeSprint(carryOverToSprintId: ID, sprintId: ID!): CommandResult!
|
|
|
|
"""
|
|
Add a rule. It acts as TaskStream, within the workflow, and what it does triggers no other rule.
|
|
"""
|
|
createAutomation(input: CreateAutomationInput!): Automation!
|
|
createIssue(input: CreateIssueInput!): CommandResult!
|
|
createProject(input: CreateProjectInput!): CommandResult!
|
|
createRelease(input: CreateReleaseInput!): CommandResult!
|
|
|
|
"""Plan a sprint (owners and admins)"""
|
|
createSprint(input: CreateSprintInput!): CommandResult!
|
|
createWebhook(input: CreateWebhookInput!): WebhookCreated!
|
|
deleteAutomation(automationId: ID!): Boolean!
|
|
|
|
"""Author or project admin"""
|
|
deleteComment(commentId: ID!): CommandResult!
|
|
|
|
"""
|
|
Delete the project (owner only), with its tickets, comments and releases. `confirmKey` must be the project key.
|
|
"""
|
|
deleteProject(confirmKey: String!, projectId: ID!): CommandResult!
|
|
|
|
"""Delete a view: whoever saved it, or an admin if it is shared"""
|
|
deleteSavedFilter(id: ID!): Boolean!
|
|
|
|
"""Delete a sprint that never started; its tickets go back to the backlog"""
|
|
deleteSprint(sprintId: ID!): CommandResult!
|
|
deleteWebhook(webhookId: ID!): Boolean!
|
|
editComment(body: String!, commentId: ID!): CommandResult!
|
|
|
|
"""Relate tickets, e.g. FE DEPENDS_ON BE, QA TESTS FE"""
|
|
linkIssues(input: LinkIssuesInput!): CommandResult!
|
|
|
|
"""Mark these as read, or all of them when `ids` is omitted"""
|
|
markNotificationsRead(ids: [ID!]): Boolean!
|
|
|
|
"""
|
|
Ship the release. Fails while it has unfinished tickets unless force = true.
|
|
"""
|
|
publishRelease(force: Boolean! = false, releaseId: ID!): CommandResult!
|
|
|
|
"""Move a ticket in the backlog, between two others of the same project"""
|
|
rankIssue(input: RankIssueInput!): CommandResult!
|
|
|
|
"""
|
|
Remove a file from a ticket (whoever uploaded it, or an owner/admin). Upload with the REST API.
|
|
"""
|
|
removeAttachment(attachmentId: ID!, issueId: ID!): CommandResult!
|
|
removeChecklistItem(issueId: ID!, itemId: ID!): CommandResult!
|
|
|
|
"""Remove a repository; what it linked stays on the tickets"""
|
|
removeGitRepository(projectId: ID!, repositoryId: ID!): Boolean!
|
|
removeProjectMember(projectId: ID!, userId: ID!): CommandResult!
|
|
|
|
"""Back from the trash"""
|
|
restoreIssue(issueId: ID!): CommandResult!
|
|
|
|
"""A new secret for a repository; the old one stops working"""
|
|
rotateGitRepositorySecret(projectId: ID!, repositoryId: ID!): GitRepository!
|
|
|
|
"""Save the current board filters under a name (members of the project)"""
|
|
saveFilter(input: SaveFilterInput!): ID!
|
|
|
|
"""
|
|
Place a ticket under an epic or another ticket of the same project (null: back to the top). Three levels at most: epic → ticket → subtask.
|
|
"""
|
|
setIssueParent(issueId: ID!, parentId: ID): CommandResult!
|
|
|
|
"""Put a ticket in a release (null removes it)"""
|
|
setIssueRelease(issueId: ID!, releaseId: ID): CommandResult!
|
|
|
|
"""Put a ticket in a sprint (null: back to the backlog)"""
|
|
setIssueSprint(issueId: ID!, sprintId: ID): CommandResult!
|
|
|
|
"""Start a planned sprint (only one under way per project)"""
|
|
startSprint(sprintId: ID!): CommandResult!
|
|
|
|
"""Send a ping now and tell how it went"""
|
|
testWebhook(webhookId: ID!): WebhookDelivery!
|
|
|
|
"""
|
|
To the trash (whoever opened it, or an owner/admin): hidden everywhere, deleted for good after 30 days
|
|
"""
|
|
trashIssue(issueId: ID!): CommandResult!
|
|
unlinkIssues(input: LinkIssuesInput!): CommandResult!
|
|
|
|
"""Stop following a ticket"""
|
|
unwatchIssue(issueId: ID!): CommandResult!
|
|
|
|
"""Rename, pause or resume"""
|
|
updateAutomation(active: Boolean, automationId: ID!, name: String): Automation!
|
|
|
|
"""Reword, tick or untick a checklist step"""
|
|
updateChecklistItem(input: UpdateChecklistItemInput!): CommandResult!
|
|
updateIssue(input: UpdateIssueInput!): CommandResult!
|
|
updateNotificationSettings(email: Boolean!): NotificationSettings!
|
|
updateProject(input: UpdateProjectInput!): CommandResult!
|
|
|
|
"""
|
|
Replace statuses, transitions, ticket types and areas (owners and admins). Values can be archived, not deleted.
|
|
"""
|
|
updateProjectSettings(projectId: ID!, settings: ProjectSettingsInput!): CommandResult!
|
|
updateRelease(input: UpdateReleaseInput!): CommandResult!
|
|
updateSprint(input: UpdateSprintInput!): CommandResult!
|
|
updateWebhook(input: UpdateWebhookInput!): Webhook!
|
|
|
|
"""
|
|
Follow a ticket: be told when it moves, is reassigned or gets a comment
|
|
"""
|
|
watchIssue(issueId: ID!): CommandResult!
|
|
|
|
"""
|
|
Write the release notes (Markdown; null removes them). Also after shipping.
|
|
"""
|
|
writeReleaseNotes(notes: String, releaseId: ID!): CommandResult!
|
|
}
|
|
|
|
type MyNotifications {
|
|
items: [Notification!]!
|
|
|
|
"""All my unread ones, not just these"""
|
|
unread: Int!
|
|
}
|
|
|
|
type Notification {
|
|
actor: UserRef!
|
|
createdAt: String!
|
|
id: ID!
|
|
issueId: ID
|
|
issueKey: String
|
|
kind: NotificationKind!
|
|
projectId: ID!
|
|
projectKey: String!
|
|
|
|
"""Null: unread"""
|
|
readAt: String
|
|
summary: String!
|
|
}
|
|
|
|
"""Why someone is told"""
|
|
enum NotificationKind {
|
|
ADDED_TO_PROJECT
|
|
ASSIGNED
|
|
COMMENTED
|
|
MENTIONED
|
|
QA_FAILED
|
|
REMINDER
|
|
REPLIED
|
|
STATUS_CHANGED
|
|
WATCHED
|
|
}
|
|
|
|
type NotificationSettings {
|
|
"""Copies by e-mail"""
|
|
email: Boolean!
|
|
|
|
"""Whether this installation can send e-mail at all"""
|
|
emailAvailable: Boolean!
|
|
}
|
|
|
|
type Project {
|
|
"""
|
|
Statistics of the last `days` days (7-365): created vs resolved, cumulative flow, cycle/lead time, throughput and QA
|
|
"""
|
|
analytics(days: Int! = 90): ProjectAnalytics!
|
|
|
|
"""Kanban board, one column per status"""
|
|
board(
|
|
area: String
|
|
assigneeId: ID
|
|
labels: [String!]
|
|
perColumn: Int! = 50
|
|
priorities: [IssuePriority!]
|
|
releaseId: ID
|
|
|
|
"""Matches key, title or description"""
|
|
search: String
|
|
sprintId: ID
|
|
types: [String!]
|
|
unassigned: Boolean
|
|
): [BoardColumn!]!
|
|
createdAt: String!
|
|
description: String
|
|
id: ID!
|
|
|
|
"""Anyone can read it, also without signing in"""
|
|
isPublic: Boolean!
|
|
key: String!
|
|
members: [ProjectMember!]!
|
|
name: String!
|
|
owner: UserRef!
|
|
releases: [Release!]!
|
|
settings: ProjectSettings!
|
|
|
|
"""Project tracking dashboard"""
|
|
stats: ProjectStats!
|
|
updatedAt: String!
|
|
version: Int!
|
|
}
|
|
|
|
type ProjectAnalytics {
|
|
createdVsResolved: [CreatedResolved!]!
|
|
|
|
"""Tickets in each status at the end of every day"""
|
|
cumulativeFlow: CumulativeFlow!
|
|
|
|
"""Start of work → done"""
|
|
cycleTime: DurationStats!
|
|
from: String!
|
|
|
|
"""Creation → done"""
|
|
leadTime: DurationStats!
|
|
qa: QaStats!
|
|
|
|
"""Finished per person and week"""
|
|
throughput: [Throughput!]!
|
|
to: String!
|
|
}
|
|
|
|
type ProjectChange {
|
|
action: String!
|
|
actorId: ID!
|
|
project: Project!
|
|
version: Int!
|
|
}
|
|
|
|
type ProjectMember {
|
|
role: ProjectRole!
|
|
user: UserRef!
|
|
}
|
|
|
|
input ProjectMemberInput {
|
|
projectId: ID!
|
|
role: ProjectRole! = MEMBER
|
|
|
|
"""Pireon user id"""
|
|
userId: ID!
|
|
}
|
|
|
|
enum ProjectRole {
|
|
ADMIN
|
|
MEMBER
|
|
OWNER
|
|
VIEWER
|
|
}
|
|
|
|
"""Statuses (board order), transitions, ticket types and areas"""
|
|
type ProjectSettings {
|
|
areas: [AreaOption!]!
|
|
issueTypes: [IssueTypeOption!]!
|
|
statuses: [WorkflowStatus!]!
|
|
transitions: [StatusTransitions!]!
|
|
}
|
|
|
|
"""
|
|
The whole configuration (replaces the previous one). Statuses go in board order.
|
|
"""
|
|
input ProjectSettingsInput {
|
|
areas: [AreaOptionInput!]!
|
|
issueTypes: [IssueTypeOptionInput!]!
|
|
statuses: [WorkflowStatusInput!]!
|
|
transitions: [StatusTransitionsInput!]!
|
|
}
|
|
|
|
type ProjectStats {
|
|
byArea: [CountByKey!]!
|
|
|
|
"""Open tickets per person"""
|
|
byAssignee: [CountByAssignee!]!
|
|
byPriority: [CountByKey!]!
|
|
byStatus: [CountByStatus!]!
|
|
byType: [CountByKey!]!
|
|
open: Int!
|
|
total: Int!
|
|
}
|
|
|
|
type QaStats {
|
|
failed: Int!
|
|
failureRate: Float
|
|
passed: Int!
|
|
}
|
|
|
|
type Query {
|
|
"""Project activity feed (newest first)"""
|
|
activity(
|
|
"""ISO date cursor"""
|
|
before: String
|
|
issueId: ID
|
|
limit: Int! = 50
|
|
projectId: ID!
|
|
): [Activity!]!
|
|
automations(projectId: ID!): [Automation!]!
|
|
|
|
"""
|
|
A project's epics: top-level tickets that group others, with the progress of those
|
|
"""
|
|
epics(projectId: ID!): [Epic!]!
|
|
gitIntegration(projectId: ID!): GitIntegration!
|
|
issue(
|
|
"""Issue id or key (e.g. "TS-42")"""
|
|
idOrKey: String!
|
|
): Issue!
|
|
issues(filter: IssueFilterInput!, limit: Int! = 50, offset: Int! = 0): IssuePage!
|
|
|
|
"""The authenticated user"""
|
|
me: Me!
|
|
|
|
"""
|
|
Tickets across all my projects: assigned to me (default) or any (e.g. categories [QA])
|
|
"""
|
|
myIssues(
|
|
assignedToMe: Boolean! = true
|
|
categories: [StatusCategory!]
|
|
limit: Int! = 50
|
|
offset: Int! = 0
|
|
|
|
"""Matches key, title or description (global search)"""
|
|
search: String
|
|
statuses: [String!]
|
|
|
|
"""Only the tickets I follow"""
|
|
watching: Boolean! = false
|
|
): IssuePage!
|
|
|
|
"""My notifications, newest first, and how many are unread"""
|
|
myNotifications(limit: Int! = 30, unreadOnly: Boolean! = false): MyNotifications!
|
|
|
|
"""Projects where I am a member"""
|
|
myProjects: [Project!]!
|
|
notificationSettings: NotificationSettings!
|
|
|
|
"""A project of mine, or any public one (no sign-in needed)"""
|
|
project(
|
|
"""Project id or key (e.g. "TS")"""
|
|
idOrKey: String!
|
|
): Project!
|
|
|
|
"""Projects anyone can read, also without signing in"""
|
|
publicProjects: [Project!]!
|
|
release(id: ID!): Release!
|
|
|
|
"""My views of the project's board, then the shared ones"""
|
|
savedFilters(projectId: ID!): [SavedFilter!]!
|
|
sprint(id: ID!): Sprint!
|
|
|
|
"""
|
|
A project's sprints: the one under way, the planned ones, then the closed ones
|
|
"""
|
|
sprints(projectId: ID!): [Sprint!]!
|
|
|
|
"""A project's tickets in the trash, newest first"""
|
|
trash(projectId: ID!): [Issue!]!
|
|
|
|
"""Planned releases of all my projects, soonest target date first"""
|
|
upcomingReleases(limit: Int! = 10): [Release!]!
|
|
user(id: String!): User
|
|
|
|
"""Search users by name or email (to assign / add members)"""
|
|
users(limit: Int! = 20, search: String! = ""): [User!]!
|
|
|
|
"""Event names a webhook can subscribe to (also family.* and *)"""
|
|
webhookEvents: [String!]!
|
|
webhooks(projectId: ID!): [Webhook!]!
|
|
}
|
|
|
|
input RankIssueInput {
|
|
"""The ticket that ends up right above (null: the top)"""
|
|
aboveIssueId: ID
|
|
|
|
"""The ticket that ends up right below (null: the bottom)"""
|
|
belowIssueId: ID
|
|
issueId: ID!
|
|
}
|
|
|
|
type Release {
|
|
"""Scope vs finished tickets, day by day"""
|
|
burnup: ReleaseBurnup!
|
|
createdAt: String!
|
|
description: String
|
|
id: ID!
|
|
|
|
"""Tickets included in this release"""
|
|
issues(limit: Int! = 100, offset: Int! = 0): IssuePage!
|
|
name: String!
|
|
|
|
"""What shipped, told for people (Markdown)"""
|
|
notes: String
|
|
|
|
"""
|
|
A Markdown draft of the notes from its finished tickets, by type (not saved)
|
|
"""
|
|
notesDraft: String!
|
|
progress: ReleaseProgress!
|
|
projectId: ID!
|
|
releasedAt: String
|
|
status: ReleaseStatus!
|
|
targetDate: String
|
|
version: Int!
|
|
}
|
|
|
|
type ReleaseBurnup {
|
|
dates: [String!]!
|
|
done: [Int!]!
|
|
releaseId: ID!
|
|
|
|
"""Tickets in the release (not cancelled)"""
|
|
scope: [Int!]!
|
|
targetDate: String
|
|
}
|
|
|
|
type ReleaseChange {
|
|
action: String!
|
|
actorId: ID!
|
|
release: Release!
|
|
version: Int!
|
|
}
|
|
|
|
type ReleaseProgress {
|
|
byStatus: [CountByStatus!]!
|
|
finished: Int!
|
|
percent: Int!
|
|
total: Int!
|
|
}
|
|
|
|
type ReleaseRef {
|
|
id: ID!
|
|
name: String!
|
|
}
|
|
|
|
enum ReleaseStatus {
|
|
ARCHIVED
|
|
PLANNED
|
|
RELEASED
|
|
}
|
|
|
|
input SaveFilterInput {
|
|
criteria: SavedFilterCriteriaInput!
|
|
name: String!
|
|
projectId: ID!
|
|
|
|
"""Visible to the whole project (members, not viewers, share)"""
|
|
shared: Boolean! = false
|
|
}
|
|
|
|
"""
|
|
A named view of the board: private to whoever saved it, or shared with the project
|
|
"""
|
|
type SavedFilter {
|
|
createdAt: String!
|
|
criteria: SavedFilterCriteria!
|
|
id: ID!
|
|
name: String!
|
|
owner: UserRef!
|
|
projectId: ID!
|
|
shared: Boolean!
|
|
}
|
|
|
|
"""What a saved view narrows the board to; empty: everything"""
|
|
type SavedFilterCriteria {
|
|
areas: [String!]
|
|
assigneeId: ID
|
|
labels: [String!]
|
|
priorities: [IssuePriority!]
|
|
releaseId: ID
|
|
search: String
|
|
types: [String!]
|
|
unassigned: Boolean
|
|
}
|
|
|
|
input SavedFilterCriteriaInput {
|
|
areas: [String!]
|
|
assigneeId: ID
|
|
labels: [String!]
|
|
priorities: [IssuePriority!]
|
|
releaseId: ID
|
|
search: String
|
|
types: [String!]
|
|
unassigned: Boolean
|
|
}
|
|
|
|
"""A time-boxed iteration: the tickets the team commits to"""
|
|
type Sprint {
|
|
burndown: SprintBurndown!
|
|
closedAt: String
|
|
createdAt: String!
|
|
|
|
"""Last day (included), YYYY-MM-DD"""
|
|
endDate: String!
|
|
goal: String
|
|
id: ID!
|
|
|
|
"""Tickets in this sprint, in backlog order"""
|
|
issues(limit: Int! = 100, offset: Int! = 0): IssuePage!
|
|
name: String!
|
|
progress: SprintProgress!
|
|
projectId: ID!
|
|
|
|
"""First day, YYYY-MM-DD"""
|
|
startDate: String!
|
|
startedAt: String
|
|
status: SprintStatus!
|
|
version: Int!
|
|
}
|
|
|
|
"""
|
|
Per day of the sprint: tickets in it, still open, and their points (null: days to come). `ideal` falls from the first day to zero.
|
|
"""
|
|
type SprintBurndown {
|
|
dates: [String!]!
|
|
ideal: [Float!]!
|
|
remaining: [Int]!
|
|
remainingPoints: [Int]!
|
|
scope: [Int]!
|
|
sprintId: ID!
|
|
}
|
|
|
|
type SprintChange {
|
|
action: String!
|
|
actorId: ID!
|
|
|
|
"""Null: deleted"""
|
|
sprint: Sprint
|
|
sprintId: ID!
|
|
version: Int!
|
|
}
|
|
|
|
type SprintProgress {
|
|
"""Done or cancelled"""
|
|
finished: Int!
|
|
finishedStoryPoints: Int!
|
|
percent: Int!
|
|
storyPoints: Int!
|
|
total: Int!
|
|
}
|
|
|
|
type SprintRef {
|
|
id: ID!
|
|
name: String!
|
|
}
|
|
|
|
"""PLANNED, ACTIVE (one per project at a time) or CLOSED"""
|
|
enum SprintStatus {
|
|
ACTIVE
|
|
CLOSED
|
|
PLANNED
|
|
}
|
|
|
|
"""
|
|
What a status means, whatever each project calls it. DONE and CANCELLED are finished.
|
|
"""
|
|
enum StatusCategory {
|
|
CANCELLED
|
|
DONE
|
|
IN_PROGRESS
|
|
QA
|
|
TODO
|
|
}
|
|
|
|
type StatusTransitions {
|
|
from: String!
|
|
to: [String!]!
|
|
}
|
|
|
|
input StatusTransitionsInput {
|
|
from: String!
|
|
to: [String!]!
|
|
}
|
|
|
|
type Subscription {
|
|
"""Live activity feed"""
|
|
activityAdded(projectId: ID!): Activity!
|
|
commentChanged(issueId: ID!): CommentChange!
|
|
|
|
"""Tickets created/updated/moved in a project (board in realtime)"""
|
|
issueChanged(projectId: ID!): IssueChange!
|
|
|
|
"""Projects I am added to / removed from"""
|
|
myProjectsChanged: ProjectChange!
|
|
|
|
"""My notifications, as they happen"""
|
|
notificationAdded: Notification!
|
|
projectChanged(projectId: ID!): ProjectChange!
|
|
releaseChanged(projectId: ID!): ReleaseChange!
|
|
sprintChanged(projectId: ID!): SprintChange!
|
|
}
|
|
|
|
type Throughput {
|
|
count: Int!
|
|
user: UserRef
|
|
week: String!
|
|
}
|
|
|
|
input UpdateChecklistItemInput {
|
|
done: Boolean
|
|
issueId: ID!
|
|
itemId: ID!
|
|
text: String
|
|
}
|
|
|
|
input UpdateIssueInput {
|
|
"""An area id"""
|
|
area: String
|
|
description: String
|
|
dueDate: String
|
|
|
|
"""Figma frame for UI changes"""
|
|
figmaUrl: String
|
|
issueId: ID!
|
|
labels: [String!]
|
|
priority: IssuePriority
|
|
|
|
"""When work should start (roadmap), YYYY-MM-DD"""
|
|
startDate: String
|
|
storyPoints: Int
|
|
title: String
|
|
type: String
|
|
}
|
|
|
|
input UpdateProjectInput {
|
|
description: String
|
|
isPublic: Boolean
|
|
name: String
|
|
projectId: ID!
|
|
}
|
|
|
|
input UpdateReleaseInput {
|
|
description: String
|
|
name: String
|
|
releaseId: ID!
|
|
targetDate: String
|
|
}
|
|
|
|
input UpdateSprintInput {
|
|
endDate: String
|
|
goal: String
|
|
name: String
|
|
sprintId: ID!
|
|
startDate: String
|
|
}
|
|
|
|
input UpdateWebhookInput {
|
|
active: Boolean
|
|
events: [String!]
|
|
url: String
|
|
webhookId: ID!
|
|
}
|
|
|
|
"""User managed by the Pireon identity server"""
|
|
type User {
|
|
email: String!
|
|
id: ID!
|
|
isActive: Boolean!
|
|
name: String!
|
|
}
|
|
|
|
type UserRef {
|
|
id: ID!
|
|
name: String!
|
|
}
|
|
|
|
"""
|
|
Where the project tells another system what happened (signed POST, HMAC-SHA256)
|
|
"""
|
|
type Webhook {
|
|
active: Boolean!
|
|
createdAt: String!
|
|
createdBy: UserRef!
|
|
|
|
"""Event names, family.* or *"""
|
|
events: [String!]!
|
|
id: ID!
|
|
lastDelivery: WebhookDelivery
|
|
projectId: ID!
|
|
url: String!
|
|
}
|
|
|
|
type WebhookCreated {
|
|
id: ID!
|
|
|
|
"""Signs every delivery. Shown only now: keep it."""
|
|
secret: String!
|
|
}
|
|
|
|
type WebhookDelivery {
|
|
at: String!
|
|
error: String
|
|
event: String!
|
|
ok: Boolean!
|
|
|
|
"""HTTP status"""
|
|
status: Int
|
|
}
|
|
|
|
type WorkflowStatus {
|
|
"""No new tickets or transitions into it"""
|
|
archived: Boolean!
|
|
category: StatusCategory!
|
|
|
|
"""Colour token: slate, violet, green…"""
|
|
color: String!
|
|
|
|
"""Stable id stored on tickets, e.g. IN_REVIEW"""
|
|
id: String!
|
|
name: String!
|
|
|
|
"""Entering it needs a reason"""
|
|
requiresReason: Boolean!
|
|
|
|
"""
|
|
Work-in-progress limit: most tickets the column should hold (a warning, not a lock)
|
|
"""
|
|
wipLimit: Int
|
|
}
|
|
|
|
input WorkflowStatusInput {
|
|
archived: Boolean! = false
|
|
category: StatusCategory!
|
|
color: String!
|
|
id: String!
|
|
name: String!
|
|
requiresReason: Boolean! = false
|
|
|
|
"""Work-in-progress limit (null: none)"""
|
|
wipLimit: Int
|
|
} |