API reference
Every query and mutation an API key can call, with an example call and answer, straight from the schema. Settings, people, keys and connections are changed signed in to the app and aren't listed here.
Address and signing in
Every call is a POST to your workspace's /graphql, with your API key in the Authorization header and the query as JSON. A key sees and may do what its person's role may in the app.
Who may what
A key may what its person's role may. Each query, mutation and field shows the four roles on the right; "View as" on the left leaves out what a role can't. Where it depends on the record (their own time entries, projects they are assigned to, a draft), the box under the description says how.
- may
- depends on the record
- may not
More
Request
curl https://yourworkspace.docket.rocks/graphql \
-H "Authorization: Bearer dkt_…" \
-H "Content-Type: application/json" \
-d '{ "query": "{ viewer { id firstname role } }" }'
Response
{
"data": {
"viewer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"role": "PM"
}
}
}
Queries
Query
account
The workspace itself: its settings and company data.
Who may Only the caller's own workspace is returned; any other id gives null.
Arguments
idID!required
Returns: Account
Example
query Account($id: ID!) {
account(id: $id) {
id
name
createdAt
accountingFont
accountingFooterManagingDirector
accountingFooterOffice
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"account": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingFont": "text",
"accountingFooterManagingDirector": "text",
"accountingFooterOffice": "text"
}
}
}
Query
accountantAccesses
The tax office's accesses to the export for the bookkeeping: those in force first, then the revoked ones, newest first.
Who may Admins only; anyone else gets an error.
Returns: [AccountantAccess!]!
Example
query {
accountantAccesses {
id
name
email
createdAt
lastSignedInAt
revokedAt
}
}
Response
{
"data": {
"accountantAccesses": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"lastSignedInAt": "2026-11-13T09:30:00+01:00",
"revokedAt": "2026-11-13T09:30:00+01:00"
}
]
}
}
Query
accountantPortalUrl
Where the workspace's tax office signs in and downloads the export for the bookkeeping.
Who may Admins only; anyone else gets an error.
Returns: String!
Example
query {
accountantPortalUrl
}
Response
{
"data": {
"accountantPortalUrl": "text"
}
}
Query
accounting
A billing cycle of a project by id: the container of its quotation, order confirmations, delivery notes and invoices.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: Accounting
Example
query Accounting($id: ID!) {
accounting(id: $id) {
id
createdAt
accountId
invoicesTypesThatCanBeCreated
serviceRatesUpdatable
updatedAt
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"accounting": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"invoicesTypesThatCanBeCreated": [
"ADVANCE_PAYMENT"
],
"serviceRatesUpdatable": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
aiConnectionsEnabled
Whether the workspace allows connecting AI apps over MCP.
Returns: Boolean!
Example
query {
aiConnectionsEnabled
}
Response
{
"data": {
"aiConnectionsEnabled": true
}
}
Query
apiTokens
The signed-in person's own API keys, newest first
Returns: [ApiToken!]!
Example
query {
apiTokens {
id
name
createdAt
expiresAt
lastFour
lastUsedAt
}
}
Response
{
"data": {
"apiTokens": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"expiresAt": "2026-11-13T09:30:00+01:00",
"lastFour": "text",
"lastUsedAt": "2026-11-13T09:30:00+01:00"
}
]
}
}
Query
bookkeepingPeriod
What an export for the bookkeeping would hold for a period, and the latest exports. The period must not end before it starts and spans at most 366 days.
Who may Admins only; anyone else gets an error.
Arguments
fromISO8601Date!required- First day of the period
toISO8601Date!required- Last day of the period, included
Returns: BookkeepingPeriod!
Example
query BookkeepingPeriod($from: ISO8601Date!, $to: ISO8601Date!) {
bookkeepingPeriod(from: $from, to: $to) {
exportedBeforeCount
externalCostsCount
invoicesCount
withBookings
}
}
Variables
{
"from": "2026-11-13",
"to": "2026-11-13"
}
Response
{
"data": {
"bookkeepingPeriod": {
"exportedBeforeCount": 42,
"externalCostsCount": 42,
"invoicesCount": 42,
"withBookings": true
}
}
}
Query
contact
A customer's contact person by id.
Who may Null when not found or not visible: timetrackers only see contacts of customers they are assigned to.
Arguments
idID!required
Returns: Contact
Example
query Contact($id: ID!) {
contact(id: $id) {
id
title
firstname
lastname
email
createdAt
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"contact": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
contacts
Contact persons of customers.
Who may Admins, project managers and basic users see all of them, timetrackers only those of customers they are assigned to, directly or through a project.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterContactFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ContactEdge!]!- A list of edges.
maxFloatminFloatnodes[Contact!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
contacts(perPage: 25) {
totalCount
edges {
node {
id
title
firstname
lastname
email
createdAt
}
}
}
}
Response
{
"data": {
"contacts": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
]
}
}
}
Query
countries
The countries an address can be in, with their ISO code and English name, sorted by name.
Returns: [Country!]!
Example
query {
countries {
name
code
}
}
Response
{
"data": {
"countries": [
{
"name": "Website relaunch",
"code": "text"
}
]
}
}
Query
customField
A custom field defined for a customer by id.
Who may Basic users, project managers and admins; null for timetrackers.
Arguments
idID!required
Returns: CustomField
Example
query CustomField($id: ID!) {
customField(id: $id) {
id
name
createdAt
archived
defaultValue
fieldType
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"customField": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
}
}
}
Query
customFields
The custom fields defined for customers.
Who may Basic users, project managers and admins; an empty list for timetrackers.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterCustomFieldFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[CustomFieldEdge!]!- A list of edges.
maxFloatminFloatnodes[CustomField!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
customFields(perPage: 25) {
totalCount
edges {
node {
id
name
createdAt
archived
defaultValue
fieldType
}
}
}
}
Response
{
"data": {
"customFields": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
}
}
]
}
}
}
Query
customer
A customer by id.
Who may Admins, project managers and basic users see every customer, timetrackers only customers they are assigned to, directly or through a project; null otherwise.
Arguments
idID!required
Returns: Customer
Example
query Customer($id: ID!) {
customer(id: $id) {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"customer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
}
}
}
Query
customerAddress
A customer's address by id.
Who may Null when the caller cannot see the customer (see customer).
Arguments
idID!required
Returns: CustomerAddress
Example
query CustomerAddress($id: ID!) {
customerAddress(id: $id) {
id
number
createdAt
address1
address2
buyerReference
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"customerAddress": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
}
}
}
Query
customerAddresses
Addresses of customers, limited to the customers the caller can see (see customers).
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterCustomerAddressFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[CustomerAddressEdge!]!- A list of edges.
maxFloatminFloatnodes[CustomerAddress!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
customerAddresses(perPage: 25) {
totalCount
edges {
node {
id
number
createdAt
address1
address2
buyerReference
}
}
}
}
Response
{
"data": {
"customerAddresses": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
}
}
]
}
}
}
Query
customerBySlug
A customer by its slug, the name in its URL.
Who may Visibility as for customer.
Arguments
slugString!required
Returns: Customer
Example
query CustomerBySlug($slug: String!) {
customerBySlug(slug: $slug) {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"customerBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
}
}
}
Query
customers
The workspace's customers, archived ones included unless filtered.
Who may Admins, project managers and basic users see every customer, timetrackers only customers they are assigned to, directly or through a project.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterCustomerFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[CustomerEdge!]!- A list of edges.
maxFloatminFloatnodes[Customer!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
customers(perPage: 25) {
totalCount
edges {
node {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
}
}
}
Response
{
"data": {
"customers": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
}
}
]
}
}
}
Query
deliveryNote
A delivery note by id.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: DeliveryNote
Example
query DeliveryNote($id: ID!) {
deliveryNote(id: $id) {
id
number
title
name
status
date
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
deliveryNoteByNumber
A delivery note by its number and the project it belongs to.
Who may Visibility as for deliveryNote.
Arguments
numberInt!requiredprojectIdID!required
Returns: DeliveryNote
Example
query DeliveryNoteByNumber($number: Int!, $projectId: ID!) {
deliveryNoteByNumber(number: $number, projectId: $projectId) {
id
number
title
name
status
date
}
}
Variables
{
"number": 1017,
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"deliveryNoteByNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
deliveryNotes
Delivery notes.
Who may Project managers and admins only; an empty list for everyone else.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterDeliveryNoteFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[DeliveryNoteEdge!]!- A list of edges.
maxFloatminFloatnodes[DeliveryNote!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
deliveryNotes(perPage: 25) {
totalCount
edges {
node {
id
number
title
name
status
date
}
}
}
}
Response
{
"data": {
"deliveryNotes": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
]
}
}
}
Query
documentTemplates
Templates for quotations and invoices, sorted by name.
Who may Project managers and admins only; an empty list for everyone else.
Arguments
customerIdID- Only the templates offered for this customer's documents: its own and those for every customer
kindString- quotation or invoice; omit for both
Returns: [DocumentTemplate!]!
Example
query {
documentTemplates {
id
name
createdAt
blockTitles
kind
missingServiceCount
}
}
Response
{
"data": {
"documentTemplates": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"blockTitles": [
"text"
],
"kind": "text",
"missingServiceCount": 42
}
]
}
}
Query
externalCost
An external cost (a supplier's invoice) by id.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: ExternalCost
Example
query ExternalCost($id: ID!) {
externalCost(id: $id) {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"externalCost": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
}
Query
externalCostFigures
Works out the figures of an external cost that were not given, exactly as saving it would: the amount converted at the ECB rate of the invoice date, the tax at the VAT rate, and whether the VAT is deductible. Saves nothing. Pass what is known and leave out the rest.
Arguments
currencyCurrency!required- The currency of the supplier's invoice
amountFloat- Net amount in the workspace's currency; leave out to have it converted from originalAmount
invoiceDateISO8601Date- Decides which day's ECB rate applies
originalAmountFloat- Net amount in the invoice's currency, when that is not the workspace's currency
taxRateFloat- VAT rate in percent; the workspace's default when left out
Returns: ExternalCostFigures!
Example
query ExternalCostFigures($currency: Currency!) {
externalCostFigures(currency: $currency) {
convertedAmount
inputTaxDeductible
taxAtRate
}
}
Variables
{
"currency": "EUR"
}
Response
{
"data": {
"externalCostFigures": {
"convertedAmount": 120.5,
"inputTaxDeductible": true,
"taxAtRate": 120.5
}
}
}
Query
externalCosts
External costs (suppliers' invoices).
Who may Project managers and admins only; an empty list for everyone else.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterExternalCostFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ExternalCostEdge!]!- A list of edges.
maxFloatminFloatnodes[ExternalCost!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
externalCosts(perPage: 25) {
totalCount
edges {
node {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
}
}
Response
{
"data": {
"externalCosts": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
]
}
}
}
Query
financialSummary
The finance dashboard's figures for a year (the current one when left out): open, paid and overdue invoices, the pipeline of quotations, revenue per month.
Who may Admins only; anyone else gets an error.
Arguments
yearInt- Defaults to the current year
Returns: FinancialSummary!
Example
query {
financialSummary {
awaitingOrderConfirmationCount
awaitingOrderConfirmationTotal
carriedOverCount
carriedOverTotal
openInvoicesCount
openInvoicesTotal
}
}
Response
{
"data": {
"financialSummary": {
"awaitingOrderConfirmationCount": 42,
"awaitingOrderConfirmationTotal": 120.5,
"carriedOverCount": 42,
"carriedOverTotal": 120.5,
"openInvoicesCount": 42,
"openInvoicesTotal": 120.5
}
}
}
Query
forecast
The revenue forecast of a year: the year's quotations and the invoices written for them.
Who may Admins only, and only while the workspace has the forecast feature; anyone else gets an error.
Arguments
yearInt!requiredfilterQuotationFilter- Narrows the quotations
invoiceFilterInvoiceFilter- Narrows the invoices counted for those quotations
Returns: ForecastReport!
Example
query Forecast($year: Int!) {
forecast(year: $year) {
invoiceCount
quotationCount
year
years
}
}
Variables
{
"year": 42
}
Response
{
"data": {
"forecast": {
"invoiceCount": 42,
"quotationCount": 42,
"year": 42,
"years": [
42
]
}
}
}
Query
frequentReactions
The emojis the workspace reacts to comments with most, most used first (at most nine).
Returns: [String!]!
Example
query {
frequentReactions
}
Response
{
"data": {
"frequentReactions": [
"text"
]
}
}
Query
invoice
An invoice by id.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: Invoice
Example
query Invoice($id: ID!) {
invoice(id: $id) {
id
number
inr
title
name
status
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
Query
invoiceByNumber
An invoice by its invoice number.
Who may Visibility as for invoice.
Arguments
numberInt!required
Returns: Invoice
Example
query InvoiceByNumber($number: Int!) {
invoiceByNumber(number: $number) {
id
number
inr
title
name
status
}
}
Variables
{
"number": 1017
}
Response
{
"data": {
"invoiceByNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
Query
invoices
Invoices of every type and status, drafts and cancellations included unless filtered.
Who may Project managers and admins only; an empty list for everyone else.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterInvoiceFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[InvoiceEdge!]!- A list of edges.
maxFloatminFloatnodes[Invoice!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
invoices(perPage: 25) {
totalCount
edges {
node {
id
number
inr
title
name
status
}
}
}
}
Response
{
"data": {
"invoices": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
]
}
}
}
Query
jiraConnection
A connected Jira site by id.
Who may Admins only.
Arguments
idID!required
Returns: JiraSite
Example
query JiraConnection($id: ID!) {
jiraConnection(id: $id) {
id
name
status
createdAt
authKind
cloudId
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"jiraConnection": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"status": "ACTIVE",
"createdAt": "2026-11-13T09:30:00+01:00",
"authKind": "text",
"cloudId": "text"
}
}
}
Query
jiraConnections
The Jira sites connected to the workspace, with their sync settings.
Who may Admins only; an empty list for everyone else.
Returns: [JiraSite!]!
Example
query {
jiraConnections {
id
name
status
createdAt
authKind
cloudId
}
}
Response
{
"data": {
"jiraConnections": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"status": "ACTIVE",
"createdAt": "2026-11-13T09:30:00+01:00",
"authKind": "text",
"cloudId": "text"
}
]
}
}
Query
jiraEpics
The epics of a Jira project, newest first, at most 50, asked from Jira live.
Who may Project managers and admins; anyone else gets an error.
Arguments
jiraConnectionIdID!requiredjiraProjectKeyString!required- The Jira project's key, e.g. "WEB"
queryString- Only epics whose summary starts with this text
Returns: [JiraEpicRef!]!
Example
query JiraEpics($jiraConnectionId: ID!, $jiraProjectKey: String!) {
jiraEpics(jiraConnectionId: $jiraConnectionId, jiraProjectKey: $jiraProjectKey) {
id
status
key
summary
}
}
Variables
{
"jiraConnectionId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"jiraProjectKey": "text"
}
Response
{
"data": {
"jiraEpics": [
{
"id": "text",
"status": "text",
"key": "text",
"summary": "text"
}
]
}
}
Query
jiraMirrorConflicts
Tickets mirrored from this Jira project that live in other docket projects and have time booked on them. Linking the Jira project elsewhere would not move them.
Who may Project managers and admins; anyone else gets an error.
Arguments
jiraConnectionIdID!requiredjiraProjectKeyString!required- The Jira project's key, e.g. "WEB"
excludeProjectIdID- A docket project whose own mirrored tickets are not conflicts (the one being linked)
Returns: [JiraMirrorConflict!]!
Example
query JiraMirrorConflicts($jiraConnectionId: ID!, $jiraProjectKey: String!) {
jiraMirrorConflicts(jiraConnectionId: $jiraConnectionId, jiraProjectKey: $jiraProjectKey) {
bookedMinutes
ticketCount
}
}
Variables
{
"jiraConnectionId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"jiraProjectKey": "text"
}
Response
{
"data": {
"jiraMirrorConflicts": [
{
"bookedMinutes": 120.5,
"ticketCount": 42
}
]
}
}
Query
jiraOauthAvailable
Whether signing in to Jira with an Atlassian account (OAuth) is set up on this server; if not, a Jira account is connected with an API token.
Returns: Boolean!
Example
query {
jiraOauthAvailable
}
Response
{
"data": {
"jiraOauthAvailable": true
}
}
Query
jiraProjects
The Jira projects the connection's service account can see, asked from Jira live.
Who may Project managers and admins; anyone else gets an error.
Arguments
jiraConnectionIdID!requiredqueryString- Only Jira projects matching this text
Returns: [JiraProjectRef!]!
Example
query JiraProjects($jiraConnectionId: ID!) {
jiraProjects(jiraConnectionId: $jiraConnectionId) {
name
jiraProjectId
key
}
}
Variables
{
"jiraConnectionId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"jiraProjects": [
{
"name": "Website relaunch",
"jiraProjectId": "text",
"key": "text"
}
]
}
}
Query
jiraUsers
Jira users matching a text, asked from Jira live, for mapping a docket user to a Jira account.
Who may Admins only; anyone else gets an error.
Arguments
jiraConnectionIdID!requiredqueryString!required- The text to look for; an empty text finds nobody
Returns: [JiraUserRef!]!
Example
query JiraUsers($jiraConnectionId: ID!, $query: String!) {
jiraUsers(jiraConnectionId: $jiraConnectionId, query: $query) {
accountId
avatarUrl
displayName
emailAddress
}
}
Variables
{
"jiraConnectionId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"query": "text"
}
Response
{
"data": {
"jiraUsers": [
{
"accountId": "text",
"avatarUrl": "text",
"displayName": "text",
"emailAddress": "text"
}
]
}
}
Query
mcpUrl
The MCP server address to enter in an AI app. The same for every workspace.
Returns: String!
Example
query {
mcpUrl
}
Response
{
"data": {
"mcpUrl": "text"
}
}
Query
myAiConnections
The AI apps (MCP clients) the caller has connected to docket.
Who may Never anyone else's.
Returns: [ConnectedAiApp!]!
Example
query {
myAiConnections {
id
name
connectedAt
lastUsedAt
scopes
}
}
Response
{
"data": {
"myAiConnections": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"connectedAt": "2026-11-13T09:30:00+01:00",
"lastUsedAt": "2026-11-13T09:30:00+01:00",
"scopes": [
"text"
]
}
]
}
}
Query
myJiraCredentials
The caller's own connected Jira accounts.
Who may Never anyone else's.
Returns: [JiraUserCredential!]!
Example
query {
myJiraCredentials {
id
email
createdAt
authKind
displayName
tokenCheckedAt
}
}
Response
{
"data": {
"myJiraCredentials": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"authKind": "text",
"displayName": "text",
"tokenCheckedAt": "2026-11-13T09:30:00+01:00"
}
]
}
}
Query
myJiraSites
The workspace's active Jira sites by name, with just enough to connect one's own Jira account.
Who may Visible to everyone in the workspace.
Returns: [JiraSiteSummary!]!
Example
query {
myJiraSites {
id
name
siteUrl
}
}
Response
{
"data": {
"myJiraSites": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"siteUrl": "text"
}
]
}
}
Query
orderConfirmation
An order confirmation by id.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: OrderConfirmation
Example
query OrderConfirmation($id: ID!) {
orderConfirmation(id: $id) {
id
number
title
name
status
date
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
orderConfirmationByNumber
An order confirmation by its number and the project it belongs to.
Who may Visibility as for orderConfirmation.
Arguments
numberInt!requiredprojectIdID!required
Returns: OrderConfirmation
Example
query OrderConfirmationByNumber($number: Int!, $projectId: ID!) {
orderConfirmationByNumber(number: $number, projectId: $projectId) {
id
number
title
name
status
date
}
}
Variables
{
"number": 1017,
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"orderConfirmationByNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
orderConfirmations
Order confirmations.
Who may Project managers and admins only; an empty list for everyone else.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterOrderConfirmationFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[OrderConfirmationEdge!]!- A list of edges.
maxFloatminFloatnodes[OrderConfirmation!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
orderConfirmations(perPage: 25) {
totalCount
edges {
node {
id
number
title
name
status
date
}
}
}
}
Response
{
"data": {
"orderConfirmations": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
]
}
}
}
Query
phase
A project phase by id.
Who may Null when the caller cannot open its project.
Arguments
idID!required
Returns: Phase
Example
query Phase($id: ID!) {
phase(id: $id) {
id
title
createdAt
computedEndDate
computedStartDate
description
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
}
}
Query
phases
Project phases, limited to projects the caller can open (see projects).
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterPhaseFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
Example
query {
phases(perPage: 25) {
totalCount
edges {
node {
id
title
createdAt
computedEndDate
computedStartDate
description
}
}
}
}
Response
{
"data": {
"phases": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
}
]
}
}
}
Query
project
A project by id. Budgets and other money fields are restricted further on the type.
Who may Admins, project managers and basic users open every project, timetrackers only projects they are assigned to, directly or through the customer; null otherwise.
Arguments
idID!required
Returns: Project
Example
query Project($id: ID!) {
project(id: $id) {
id
number
pnr
title
status
createdAt
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
projectBySlug
A project by its slug, the name in its URL.
Who may Visibility as for project.
Arguments
slugString!required
Returns: Project
Example
query ProjectBySlug($slug: String!) {
projectBySlug(slug: $slug) {
id
number
pnr
title
status
createdAt
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"projectBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
projectLabel
A ticket label of a project by id.
Who may Null when the caller cannot open its project.
Arguments
idID!required
Returns: ProjectLabel
Example
query ProjectLabel($id: ID!) {
projectLabel(id: $id) {
id
title
createdAt
color
description
slug
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"projectLabel": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
}
}
Query
projectLabels
The ticket labels of projects, limited to projects the caller can open (see projects).
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterProjectLabelFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ProjectLabelEdge!]!- A list of edges.
maxFloatminFloatnodes[ProjectLabel!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
projectLabels(perPage: 25) {
totalCount
edges {
node {
id
title
createdAt
color
description
slug
}
}
}
}
Response
{
"data": {
"projectLabels": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
}
]
}
}
}
Query
projects
Projects, archived ones included unless filtered. Besides plain fields, orderBy accepts budgetUsed and progressRelative.
Who may Admins, project managers and basic users see every project, timetrackers only projects they are assigned to, directly or through the customer.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterProjectFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ProjectEdge!]!- A list of edges.
groupByProjectGroup!maxFloatminFloatnodes[Project!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
projects(perPage: 25) {
totalCount
edges {
node {
id
number
pnr
title
status
createdAt
}
}
}
}
Response
{
"data": {
"projects": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
]
}
}
}
Query
quotation
A quotation by id.
Who may Project managers and admins only; null for everyone else.
Arguments
idID!required
Returns: Quotation
Example
query Quotation($id: ID!) {
quotation(id: $id) {
id
number
title
name
status
date
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
quotationByNumber
A quotation by its number and the project it belongs to.
Who may Visibility as for quotation.
Arguments
numberInt!requiredprojectIdID!required
Returns: Quotation
Example
query QuotationByNumber($number: Int!, $projectId: ID!) {
quotationByNumber(number: $number, projectId: $projectId) {
id
number
title
name
status
date
}
}
Variables
{
"number": 1017,
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"quotationByNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
Query
quotations
Quotations of all projects that are not archived.
Who may Project managers and admins only; an empty list for everyone else.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterQuotationFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[QuotationEdge!]!- A list of edges.
maxFloatminFloatnodes[Quotation!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
quotations(perPage: 25) {
totalCount
edges {
node {
id
number
title
name
status
date
}
}
}
}
Response
{
"data": {
"quotations": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
]
}
}
}
Query
retainersDue
The months of the workspace's retainers that are over and have no invoice yet, by project.
Who may Project managers and admins; an empty list for everyone else.
Returns: [RetainerMonth!]!
Example
query {
retainersDue {
billsOverage
bookedMinutes
contingentMinutes
due
fee
from
}
}
Response
{
"data": {
"retainersDue": [
{
"billsOverage": true,
"bookedMinutes": 42,
"contingentMinutes": 42,
"due": true,
"fee": 120.5,
"from": "2026-11-13"
}
]
}
}
Query
savedViews
The saved views (stored list settings) of a list, sorted by name: those shared with the team and the caller's own. For a list inside a project, pass the project; views of projects the caller cannot open are left out.
Arguments
listSavedViewList!requiredprojectIdID- Required for a list inside a project (tickets, boards, controlling); ignored for the others
Returns: [SavedView!]!
Example
query SavedViews($list: SavedViewList!) {
savedViews(list: $list) {
id
name
createdAt
query
shared
updatedAt
}
}
Variables
{
"list": "TICKETS"
}
Response
{
"data": {
"savedViews": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"query": "text",
"shared": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
]
}
}
Query
search
The global search over projects, tickets and their comments, billing documents, external costs, the team, customers and contacts. Returns only what the caller may open. A project or customer slug the caller cannot see gives an empty list.
Arguments
queryString!required- The text to look for
customerSlugString- Only this customer's projects, what's in them, and its contacts
projectSlugString- Only this project and what's in it
scopes[SearchScope!]- Only these kinds (all when left out)
Returns: [SearchResult!]!
Example
query Search($query: String!) {
search(query: $query) {
id
title
meta
slug
type
url
}
}
Variables
{
"query": "text"
}
Response
{
"data": {
"search": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"meta": "text",
"slug": "website-relaunch",
"type": "PROJECT",
"url": "https://example.com"
}
]
}
}
Query
service
A service (a kind of work, with its daily rate) by id.
Who may Everyone in the workspace sees services; the rate is null unless the caller may see financial data (project managers and admins).
Arguments
idID!required
Returns: Service
Example
query Service($id: ID!) {
service(id: $id) {
id
title
createdAt
archived
billable
dailyRate
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"service": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
}
Query
serviceBySlug
A service by its slug, the name in its URL.
Who may Visibility as for service.
Arguments
slugString!required
Returns: Service
Example
query ServiceBySlug($slug: String!) {
serviceBySlug(slug: $slug) {
id
title
createdAt
archived
billable
dailyRate
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"serviceBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
}
Query
serviceCategories
The workspace's service categories (groups of services).
Who may Visible to everyone in the workspace.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterServiceCategoryFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ServiceCategoryEdge!]!- A list of edges.
maxFloatminFloatnodes[ServiceCategory!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
serviceCategories(perPage: 25) {
totalCount
edges {
node {
id
title
createdAt
slug
updatedAt
}
}
}
}
Response
{
"data": {
"serviceCategories": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
]
}
}
}
Query
serviceCategory
A service category (a group of services) by id.
Who may Visible to everyone in the workspace.
Arguments
idID!required
Returns: ServiceCategory
Example
query ServiceCategory($id: ID!) {
serviceCategory(id: $id) {
id
title
createdAt
slug
updatedAt
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"serviceCategory": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
serviceCategoryBySlug
A service category by its slug, the name in its URL.
Arguments
slugString!required
Returns: ServiceCategory
Example
query ServiceCategoryBySlug($slug: String!) {
serviceCategoryBySlug(slug: $slug) {
id
title
createdAt
slug
updatedAt
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"serviceCategoryBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
Query
services
The workspace's services (kinds of work, each with a daily rate), archived ones included unless filtered. Besides plain fields, orderBy accepts expertCount.
Who may Everyone sees them; rates only project managers and admins.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterServiceFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[ServiceEdge!]!- A list of edges.
maxFloatminFloatnodes[Service!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
services(perPage: 25) {
totalCount
edges {
node {
id
title
createdAt
archived
billable
dailyRate
}
}
}
}
Response
{
"data": {
"services": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
]
}
}
}
Query
stopwatches
The caller's own stopwatches, running and paused, oldest first.
Who may Nobody sees another person's stopwatches.
Returns: [Stopwatch!]!
Example
query {
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
Response
{
"data": {
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
Query
supplier
A supplier by id.
Who may Basic users, project managers and admins; null for timetrackers.
Arguments
idID!required
Returns: Supplier
Example
query Supplier($id: ID!) {
supplier(id: $id) {
id
title
createdAt
archived
datevAccount
ksk
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"supplier": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
}
Query
supplierBySlug
A supplier by its slug, the name in its URL.
Who may Visibility as for supplier.
Arguments
slugString!required
Returns: Supplier
Example
query SupplierBySlug($slug: String!) {
supplierBySlug(slug: $slug) {
id
title
createdAt
archived
datevAccount
ksk
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"supplierBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
}
Query
suppliers
The workspace's suppliers, archived ones included unless filtered.
Who may Basic users, project managers and admins; an empty list for timetrackers.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterSupplierFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[SupplierEdge!]!- A list of edges.
maxFloatminFloatnodes[Supplier!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
suppliers(perPage: 25) {
totalCount
edges {
node {
id
title
createdAt
archived
datevAccount
ksk
}
}
}
}
Response
{
"data": {
"suppliers": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
]
}
}
}
Query
ticket
A ticket by id.
Who may Null when not found or when the caller cannot open its project (timetrackers only open projects they are assigned to, directly or through the customer).
Arguments
idID!required
Returns: Ticket
Example
query Ticket($id: ID!) {
ticket(id: $id) {
id
number
title
status
createdAt
boardPosition
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
Query
ticketByNumber
A ticket by its number within a project.
Who may Visibility as for ticket.
Arguments
numberInt!required- The ticket's number within its project
projectIdID!required
Returns: Ticket
Example
query TicketByNumber($number: Int!, $projectId: ID!) {
ticketByNumber(number: $number, projectId: $projectId) {
id
number
title
status
createdAt
boardPosition
}
}
Variables
{
"number": 1017,
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"ticketByNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
Query
ticketByProjectSlugAndNumber
A ticket by its project's slug and its number within that project, as in the ticket's URL.
Who may Visibility as for ticket.
Arguments
numberInt!required- The ticket's number within its project
projectSlugString!required
Returns: Ticket
Example
query TicketByProjectSlugAndNumber($number: Int!, $projectSlug: String!) {
ticketByProjectSlugAndNumber(number: $number, projectSlug: $projectSlug) {
id
number
title
status
createdAt
boardPosition
}
}
Variables
{
"number": 1017,
"projectSlug": "text"
}
Response
{
"data": {
"ticketByProjectSlugAndNumber": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
Query
tickets
Closed tickets and tickets of archived projects are included unless filtered.
Who may Tickets, including those mirrored from Jira: timetrackers only in projects they are assigned to, directly or through the customer; everyone else in every project.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterTicketFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[TicketEdge!]!- A list of edges.
groupByTicketGroup!maxFloatminFloatnodes[Ticket!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
tickets(perPage: 25) {
totalCount
edges {
node {
id
number
title
status
createdAt
boardPosition
}
}
}
}
Response
{
"data": {
"tickets": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
]
}
}
}
Query
timeEntryDescriptionRefusal
Why no description can be suggested by AI for a time entry on this ticket and day, as a sentence to show; null when a suggestion is possible. Only checks, calls no AI. For a ticket the caller cannot open it returns the not-authorized message.
Arguments
dateISO8601Date!required- The day of the time entry
ticketIdID!required
Returns: String
Example
query TimeEntryDescriptionRefusal($ticketId: ID!, $date: ISO8601Date!) {
timeEntryDescriptionRefusal(ticketId: $ticketId, date: $date)
}
Variables
{
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13"
}
Response
{
"data": {
"timeEntryDescriptionRefusal": "text"
}
}
Query
timetracking
A time entry by id.
Who may Admins see every entry, timetrackers only their own, everyone else also colleagues' entries on projects they can open; null otherwise.
Arguments
idID!required
Returns: Timetracking
Example
query Timetracking($id: ID!) {
timetracking(id: $id) {
id
date
duration
createdAt
billed
dailyRate
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
Query
timetrackingAggregation
Figures computed over time entries: the average time booked per day.
Returns: TimetrackingAggregation!
Example
query {
timetrackingAggregation {
avgTimetrackingsPerDay {
from
to
}
}
}
Response
{
"data": {
"timetrackingAggregation": {
"avgTimetrackingsPerDay": {
"from": "2026-11-13",
"to": "2026-11-13"
}
}
}
}
Query
timetrackings
Time entries. Revenue and rates are null unless the caller may see financial data.
Who may Admins see everyone's, timetrackers only their own, project managers and basic users their own and those on every project they can open.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterTimetrackingFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
countInt!edges[TimetrackingEdge!]!- A list of edges.
groupByTimetrackingGroup!maxFloatminFloatnodes[Timetracking!]!- A list of nodes.
pageInfoPageInfo!- Information to aid in pagination.
sumFloattotalCountInt!
Example
query {
timetrackings(perPage: 25) {
totalCount
edges {
node {
id
date
duration
createdAt
billed
dailyRate
}
}
}
}
Response
{
"data": {
"timetrackings": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
]
}
}
}
Query
user
A person of the workspace by id, archived ones included.
Who may Visible to everyone in the workspace; private fields are restricted on the type.
Arguments
idID!required
Returns: User
Example
query User($id: ID!) {
user(id: $id) {
id
firstname
lastname
email
createdAt
archived
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"user": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
}
}
Query
userBySlug
A person of the workspace by their slug, the name in their profile's URL.
Arguments
slugString!required
Returns: User
Example
query UserBySlug($slug: String!) {
userBySlug(slug: $slug) {
id
firstname
lastname
email
createdAt
archived
}
}
Variables
{
"slug": "website-relaunch"
}
Response
{
"data": {
"userBySlug": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
}
}
Query
userWorkTime
A person's weekly working hours (hours per weekday, valid from a date) by id.
Who may Everyone sees their own; basic users, project managers and admins see everyone's; null otherwise.
Arguments
idID!required
Returns: UserWorkTime
Example
query UserWorkTime($id: ID!) {
userWorkTime(id: $id) {
id
createdAt
activeFrom
fri
mon
sat
}
}
Variables
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
Response
{
"data": {
"userWorkTime": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"activeFrom": "2026-11-13",
"fri": 120.5,
"mon": 120.5,
"sat": 120.5
}
}
}
Query
users
The people of the workspace, archived ones included unless filtered with archived: false. Placeholder users created for Jira authors are left out unless the filter asks for them.
Who may Visible to everyone in the workspace.
Arguments
afterString- Returns the elements in the list that come after the specified cursor.
beforeString- Returns the elements in the list that come before the specified cursor.
filterUserFilter- Narrows the list; every filter given must match. In a list of IDs or statuses, a value with a leading "!" excludes what it names, e.g. ["!<id>"].
firstInt- Returns the first _n_ elements from the list.
lastInt- Returns the last _n_ elements from the list.
orderBy[String!]- Sort order, applied in sequence: field names of the listed type, descending with a leading "-", e.g. ["-date", "title"]. A field of a record it belongs to is written "project.number". Text sorts case-insensitively. Unknown fields are ignored, as are money fields for callers who may not see financial data.
pageInt- Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPageInt- How many records a page holds. Without page: the first perPage records. On a paged list, count and sum only see the page: ask for totals in a second field without perPage.
Answer
Example
query {
users(perPage: 25) {
totalCount
edges {
node {
id
firstname
lastname
email
createdAt
archived
}
}
}
}
Response
{
"data": {
"users": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
}
]
}
}
}
Query
viewer
The signed-in person; with an API key, the key's owner.
Returns: Viewer!
Example
query {
viewer {
id
firstname
lastname
email
createdAt
archived
}
}
Response
{
"data": {
"viewer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
}
}
Query
webhookEndpoints
The workspace's webhooks.
Who may Admins only; anyone else gets an error.
Returns: [WebhookEndpoint!]!
Example
query {
webhookEndpoints {
id
createdAt
active
disabledAt
events
failureCount
}
}
Response
{
"data": {
"webhookEndpoints": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"active": true,
"disabledAt": "2026-11-13T09:30:00+01:00",
"events": [
"text"
],
"failureCount": 42
}
]
}
}
Query
webhookEvents
The events a webhook can ask for
Returns: [String!]!
Example
query {
webhookEvents
}
Response
{
"data": {
"webhookEvents": [
"text"
]
}
}
Query
workloadOverview
Open tickets counted per assignee (plus a row for unassigned ones) by when they are planned: overdue, this week, this month, next month, later, unplanned. Counts only tickets the caller can see (see tickets).
Arguments
excludeGeneralBoolean- Leave out ticket number 1 of each project
Returns: WorkloadOverview!
Example
query {
workloadOverview {
max
total
}
}
Response
{
"data": {
"workloadOverview": {
"max": 42,
"total": 42
}
}
}
Mutations
Accounting
Mutation
useLatestServiceRatesInAccounting
Switches a billing cycle to the service rates as they are now. A cycle otherwise prices its documents at the rates of the moment it was created, or of the last time this was called.
Who may Project managers and admins.
Arguments
idID!required- The billing cycle (accounting) of a project
Answer
accountingAccountingerrorsJson
Example
mutation UseLatestServiceRatesInAccounting($input: UseLatestServiceRatesInAccountingInput!) {
useLatestServiceRatesInAccounting(input: $input) {
accounting {
id
createdAt
accountId
invoicesTypesThatCanBeCreated
serviceRatesUpdatable
updatedAt
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"useLatestServiceRatesInAccounting": {
"accounting": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"invoicesTypesThatCanBeCreated": [
"ADVANCE_PAYMENT"
],
"serviceRatesUpdatable": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Block
Mutation
createBlock
Inserts a block into a draft quotation or invoice. A block is a section of the document that holds its positions: a phase, or a group of agency or external services. Returns the changed document under quotation or invoice, whichever it is. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewIndexInt- Where the block goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation CreateBlock($input: CreateBlockInput!) {
createBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"createBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
deleteBlock
Removes a block and its positions from a draft quotation or invoice. On an invoice, a block that comes from the job's quotation or an earlier invoice is only marked deleted; restoreBlock brings it back. Returns the changed document under quotation or invoice, whichever it is.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewIndexInt- Where the block goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation DeleteBlock($input: DeleteBlockInput!) {
deleteBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"deleteBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
duplicateBlock
Copies a phase with all its positions and inserts the copy at newIndex. Only blocks of type phase are copied; for any other block, or an index out of range, the document comes back unchanged. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
newIndexInt!required- Where the block goes, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDoptionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation DuplicateBlock($input: DuplicateBlockInput!) {
duplicateBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42,
"newIndex": 42
}
}
Response
{
"data": {
"duplicateBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
moveBlock
Moves a block to another place in a draft quotation or invoice. With an index out of range the document comes back unchanged. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
newIndexInt!required- Where the block goes, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDoptionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation MoveBlock($input: MoveBlockInput!) {
moveBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42,
"newIndex": 42
}
}
Response
{
"data": {
"moveBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
restoreBlock
Brings back a block that deleteBlock marked as deleted on a draft invoice. Returns the changed document under quotation or invoice, whichever it is.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewIndexInt- Where the block goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation RestoreBlock($input: RestoreBlockInput!) {
restoreBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"restoreBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
updateBlock
Changes a block's type, title, texts or optional flag; only the arguments you send change. Setting optional applies it to all of the block's positions and lines. Returns the changed document under quotation or invoice, whichever it is. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- The block's place in the document, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewIndexInt- Where the block goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
titleStringtypeBlockTypeEnum
Answer
Example
mutation UpdateBlock($input: UpdateBlockInput!) {
updateBlock(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"updateBlock": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Block Position
Mutation
createBlockPosition
Adds a position, a titled group of price lines, to a block of a draft quotation or invoice. On an invoice the new position comes ticked, so it is billed. Returns the changed document under quotation or invoice, whichever it is. Refused unless the document is a draft.
Who may Project managers and admins. docket prices service lines from the rates of the document's project.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
optionalBoolean!required- Offered as an option: printed, but not counted into the total
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
subpositions[BlockPositionSubpositionInput!]!required- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString!requireddescriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
newPositionIndexInt- Where in that block the position goes, counted from 0
selectedBoolean- Ticked: a partial or final invoice bills the position
Answer
Example
mutation CreateBlockPosition($input: CreateBlockPositionInput!) {
createBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42,
"title": "Website relaunch",
"optional": true,
"subpositions": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
]
}
}
Response
{
"data": {
"createBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
deleteBlockPosition
Removes a position from a draft quotation or invoice. On an invoice, a position that comes from the job's quotation or an earlier invoice is only marked deleted; restoreBlockPosition brings it back. Returns the changed document under quotation or invoice, whichever it is.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
newPositionIndexInt- Where in that block the position goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
selectedBoolean- Ticked: a partial or final invoice bills the position
subpositions[BlockPositionSubpositionInput!]- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString
Answer
Example
mutation DeleteBlockPosition($input: DeleteBlockPositionInput!) {
deleteBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42
}
}
Response
{
"data": {
"deleteBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
duplicateBlockPosition
Copies a position with its lines and inserts the copy at newPositionIndex of the same block. With an index out of range the document comes back unchanged. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
newPositionIndexInt!required- Where in that block the position goes, counted from 0
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
selectedBoolean- Ticked: a partial or final invoice bills the position
subpositions[BlockPositionSubpositionInput!]- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString
Answer
Example
mutation DuplicateBlockPosition($input: DuplicateBlockPositionInput!) {
duplicateBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42,
"newPositionIndex": 42
}
}
Response
{
"data": {
"duplicateBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
moveBlockPosition
Moves a position within its block or into another block of the same document. With an index out of range the document comes back unchanged. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
newBlockIndexInt!required- The block the position goes into, counted from 0
newPositionIndexInt!required- Where in that block the position goes, counted from 0
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDoptionalBoolean- Offered as an option: printed, but not counted into the total
selectedBoolean- Ticked: a partial or final invoice bills the position
subpositions[BlockPositionSubpositionInput!]- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString
Answer
Example
mutation MoveBlockPosition($input: MoveBlockPositionInput!) {
moveBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42,
"newBlockIndex": 42,
"newPositionIndex": 42
}
}
Response
{
"data": {
"moveBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
restoreBlockPosition
Brings back a position that deleteBlockPosition marked as deleted on a draft invoice. Returns the changed document under quotation or invoice, whichever it is.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
descriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
newPositionIndexInt- Where in that block the position goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
selectedBoolean- Ticked: a partial or final invoice bills the position
subpositions[BlockPositionSubpositionInput!]- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString
Answer
Example
mutation RestoreBlockPosition($input: RestoreBlockPositionInput!) {
restoreBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42
}
}
Response
{
"data": {
"restoreBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
selectBlockPosition
Ticks or unticks a position. A partial or final invoice bills only its ticked positions. Returns the changed document under quotation or invoice, whichever it is. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
selectedBoolean!required- Ticked: a partial or final invoice bills the position
descriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
newPositionIndexInt- Where in that block the position goes, counted from 0
optionalBoolean- Offered as an option: printed, but not counted into the total
subpositions[BlockPositionSubpositionInput!]- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString
Answer
Example
mutation SelectBlockPosition($input: SelectBlockPositionInput!) {
selectBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42,
"selected": true
}
}
Response
{
"data": {
"selectBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
updateBlockPosition
Changes a position's title, texts, optional flag and lines. Always send the whole list of subpositions: it replaces the position's lines. Returns the changed document under quotation or invoice, whichever it is. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
blockIndexInt!required- The place of the position's block in the document, counted from 0
optionalBoolean!required- Offered as an option: printed, but not counted into the total
positionIndexInt!required- The position's place in its block, counted from 0
recordIdID!required- The draft quotation or invoice to change
subpositions[BlockPositionSubpositionInput!]!required- The price lines, always the whole list: service (quantity, unit), custom (name, rate, quantity, unit) or flatrate (name, amount) lines
titleString!requireddescriptionStringfooterStringidIDnewBlockIndexInt- The block the position goes into, counted from 0
newPositionIndexInt- Where in that block the position goes, counted from 0
selectedBoolean- Ticked: a partial or final invoice bills the position
Answer
Example
mutation UpdateBlockPosition($input: UpdateBlockPositionInput!) {
updateBlockPosition(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"blockIndex": 42,
"positionIndex": 42,
"title": "Website relaunch",
"optional": true,
"subpositions": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
]
}
}
Response
{
"data": {
"updateBlockPosition": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Block Position Subposition
Mutation
validateBlockPositionSubposition
Checks one price line and returns it priced exactly as the document will price it, without changing anything. Use it to preview a line before sending it with createBlockPosition or updateBlockPosition. A line for a service that is not billable is refused.
Who may Project managers and admins.
Arguments
recordIdID!required- The quotation or invoice the line is meant for; its project's rates price the line
amountFloat- For a flatrate line: the net price
descriptionStringidStringnameString- The label of a custom or flatrate line
optionalBoolean- Offered as an option: printed, but not counted into the total
quantityFloat- How many units; for a service line, hours or days
rateFloat- For a custom line: the net price per unit
serviceBlockPositionSubpositionServiceEnum- Whether the line is the agency's own work or an external service
serviceIdString- For a service line: the service's id as the document's billing cycle lists its rates (a_<accounting id>_<service id>)
taxRateFloat- VAT rate in percent; omit for the document's rate
typeBlockPositionSubpositionTypeEnum- service: time of a service at the project's rate; custom: a free line with rate and quantity; flatrate: a fixed amount
unitString- For a service line hours or days (a day is 8 hours); for a custom line any unit to print
Answer
errorsJsonsubpositionBlockPositionSubposition
Example
mutation ValidateBlockPositionSubposition($input: ValidateBlockPositionSubpositionInput!) {
validateBlockPositionSubposition(input: $input) {
errors
subposition {
id
title
name
amount
billedQuantity
dailyRate
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"validateBlockPositionSubposition": {
"errors": null,
"subposition": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"name": "Website relaunch",
"amount": 120.5,
"billedQuantity": 120.5,
"dailyRate": 120.5
}
}
}
}
Board
Mutation
createBoard
Adds a column to a project's kanban board. projectId and title are required; the title is unique within the project.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
projectIdIDticketStatusTicketStatus- The status a ticket takes when it is put into this column
titleString
Answer
Example
mutation CreateBoard($input: CreateBoardInput!) {
createBoard(input: $input) {
board {
id
title
createdAt
position
preset
ticketStatus
}
errors
}
}
Variables
{
"input": {
"title": "Website relaunch",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createBoard": {
"board": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
},
"errors": null
}
}
}
Mutation
deleteBoard
Deletes a column of a project's kanban board; its open tickets go to Backlog, its closed ones to Done. The Backlog and Done columns themselves can't be deleted.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!required
Answer
Example
mutation DeleteBoard($input: DeleteBoardInput!) {
deleteBoard(input: $input) {
board {
id
title
createdAt
position
preset
ticketStatus
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteBoard": {
"board": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
},
"errors": null
}
}
}
Mutation
moveBoard
Moves a column to another place on its project's kanban board.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredtoPositionInt!required- The new position, counted from 1
Answer
Example
mutation MoveBoard($input: MoveBoardInput!) {
moveBoard(input: $input) {
board {
id
title
createdAt
position
preset
ticketStatus
}
errors
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toPosition": 42
}
}
Response
{
"data": {
"moveBoard": {
"board": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
},
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateBoard
Changes a column of a project's kanban board. The column stays in its project: projectId is ignored.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredprojectIdIDticketStatusTicketStatus- The status a ticket takes when it is put into this column
titleString
Answer
Example
mutation UpdateBoard($input: UpdateBoardInput!) {
updateBoard(input: $input) {
board {
id
title
createdAt
position
preset
ticketStatus
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateBoard": {
"board": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
},
"errors": null
}
}
}
Comment Reaction
Mutation
toggleCommentReaction
Adds the caller's reaction with an emoji to a comment, or takes it back when it is already there. The comment's author gets a notification that arrives as read, without a mail.
Who may Anyone who can see what the comment is on: a ticket's project or the billing document; comments on tickets mirrored from Jira included.
Arguments
commentIdID!requiredemojiString!required- A single emoji. A comment takes at most 20 different ones
kindCommentOn!required- What the comment is on
Answer
commentCommentUnionerrorsJson
Example
mutation ToggleCommentReaction($input: ToggleCommentReactionInput!) {
toggleCommentReaction(input: $input) {
comment {
__typename
... on TicketComment {
id
}
... on QuotationComment {
id
}
... on OrderConfirmationComment {
id
}
}
errors
}
}
Variables
{
"input": {
"commentId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"kind": "TICKET",
"emoji": "text"
}
}
Response
{
"data": {
"toggleCommentReaction": {
"comment": {
"__typename": "TicketComment",
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
},
"errors": null
}
}
}
Contact
Mutation
createContact
Adds a contact person and links them to customers.
Who may Admins only.
Arguments
archivedBooleancustomerIds[ID!]- The customers this person is a contact of; replaces the whole list
departmentStringemailStringfirstnameStringlastnameStringphoneStringsalutationStringtitleString
Answer
Example
mutation CreateContact($input: CreateContactInput!) {
createContact(input: $input) {
contact {
id
title
firstname
lastname
email
createdAt
}
errors
}
}
Variables
{
"input": {
"title": "Website relaunch"
}
}
Response
{
"data": {
"createContact": {
"contact": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Mutation
deleteContact
Deletes a contact person; quotations and invoices that named them keep existing without a contact.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation DeleteContact($input: DeleteContactInput!) {
deleteContact(input: $input) {
contact {
id
title
firstname
lastname
email
createdAt
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteContact": {
"contact": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Mutation
updateContact
Changes a contact person. Only the arguments sent are changed.
Who may Admins only.
Arguments
idID!requiredarchivedBooleancustomerIds[ID!]- The customers this person is a contact of; replaces the whole list
departmentStringemailStringfirstnameStringlastnameStringphoneStringsalutationStringtitleString
Answer
Example
mutation UpdateContact($input: UpdateContactInput!) {
updateContact(input: $input) {
contact {
id
title
firstname
lastname
email
createdAt
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateContact": {
"contact": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Custom Field
Mutation
createCustomField
Defines a custom field for one customer; the field is then filled in on that customer's billing documents. name, fieldType and customerId are required.
Who may Admins only.
Arguments
archivedBooleancustomerIdID- The customer whose documents carry the field
defaultValueStringfieldTypeStringtextorcontactlabelStringnameString
Answer
customFieldCustomFielderrorsJson
Example
mutation CreateCustomField($input: CreateCustomFieldInput!) {
createCustomField(input: $input) {
customField {
id
name
createdAt
archived
defaultValue
fieldType
}
errors
}
}
Variables
{
"input": {
"name": "Website relaunch",
"customerId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createCustomField": {
"customField": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
},
"errors": null
}
}
}
Mutation
deleteCustomField
Deletes a customer's custom field together with the values documents hold for it. To keep them, set archived with updateCustomField instead.
Who may Admins only.
Arguments
idID!required
Answer
customFieldCustomFielderrorsJson
Example
mutation DeleteCustomField($input: DeleteCustomFieldInput!) {
deleteCustomField(input: $input) {
customField {
id
name
createdAt
archived
defaultValue
fieldType
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteCustomField": {
"customField": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
},
"errors": null
}
}
}
Mutation
updateCustomField
Changes a customer's custom field. Only the arguments sent are changed.
Who may Admins only.
Arguments
idID!requiredarchivedBooleancustomerIdID- The customer whose documents carry the field
defaultValueStringfieldTypeStringtextorcontactlabelStringnameString
Answer
customFieldCustomFielderrorsJson
Example
mutation UpdateCustomField($input: UpdateCustomFieldInput!) {
updateCustomField(input: $input) {
customField {
id
name
createdAt
archived
defaultValue
fieldType
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateCustomField": {
"customField": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
},
"errors": null
}
}
}
Customer
Mutation
createCustomer
Adds a customer. Its addresses (which carry the customer number) are added with createCustomerAddress.
Who may Admins only.
Arguments
accountingCommissionPercentFloat- Commission in percent on the external costs billed in a document
accountingCommissionThresholdFloat- Net total of external costs in a document from which the commission applies
archivedBooleancompanyStringdatevAccountString- The customer's own account (debtor number) in DATEV; empty = the collective account
descriptionStringemailStringinitialStringinvoiceFooterDeStringinvoiceFooterEnStringmasterAgreementBoolean- The customer has a master agreement; advance-payment invoices then name it
paymentTermDaysInt- This customer's payment term in days, 0 to 365; null = the workspace's
phoneStringquotationFooterDeStringquotationFooterEnStringserviceRates[ServiceRateInput!]- The customer's own daily rates;
idis a ServiceRate id as Customer.serviceRates returns it webString
Answer
Example
mutation CreateCustomer($input: CreateCustomerInput!) {
createCustomer(input: $input) {
customer {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
errors
}
}
Variables
{
"input": {
"company": "Alpine Coffee Roasters GmbH",
"initial": "text"
}
}
Response
{
"data": {
"createCustomer": {
"customer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
},
"errors": null
}
}
}
Mutation
deleteCustomer
Deletes a customer together with its addresses, custom fields and projects. To keep the history, set archived with updateCustomer instead.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation DeleteCustomer($input: DeleteCustomerInput!) {
deleteCustomer(input: $input) {
customer {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteCustomer": {
"customer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
},
"errors": null
}
}
}
Mutation
updateCustomer
Changes a customer's master data, its own daily rates and its accounting defaults. Only the arguments sent are changed.
Who may Admins only.
Arguments
idID!requiredaccountingCommissionPercentFloat- Commission in percent on the external costs billed in a document
accountingCommissionThresholdFloat- Net total of external costs in a document from which the commission applies
archivedBooleancompanyStringdatevAccountString- The customer's own account (debtor number) in DATEV; empty = the collective account
descriptionStringemailStringinitialStringinvoiceFooterDeStringinvoiceFooterEnStringmasterAgreementBoolean- The customer has a master agreement; advance-payment invoices then name it
paymentTermDaysInt- This customer's payment term in days, 0 to 365; null = the workspace's
phoneStringquotationFooterDeStringquotationFooterEnStringserviceRates[ServiceRateInput!]- The customer's own daily rates;
idis a ServiceRate id as Customer.serviceRates returns it updateTimetrackingsBoolean- true: time already booked for this customer is repriced where a service's rate changed, in the background
webString
Answer
Example
mutation UpdateCustomer($input: UpdateCustomerInput!) {
updateCustomer(input: $input) {
customer {
id
company
email
createdAt
accountingCommissionPercent
accountingCommissionThreshold
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateCustomer": {
"customer": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
},
"errors": null
}
}
}
Customer Address
Mutation
createCustomerAddress
Adds an address to a customer; documents are written to an address. Unless the workspace numbers its customers itself, docket assigns the next customer number.
Who may Admins only.
Arguments
customerIdID!requiredaddress1Stringaddress2StringbuyerReferenceString- The e-invoice's buyer reference (BT-10), e.g. a Leitweg-ID
cityStringcountryString- Free text, from before the list; prefer countryCode
countryCodeString- ISO 3166-1 alpha-2
departmentStringinvoiceEmailString- Where this customer receives e-invoices (BT-49)
numberInt- The customer number; typed where the workspace numbers its customers itself, else docket's
recipientStringtaxTreatmentTaxTreatmentvatNoStringzipString
Answer
customerAddressCustomerAddresserrorsJson
Example
mutation CreateCustomerAddress($input: CreateCustomerAddressInput!) {
createCustomerAddress(input: $input) {
customerAddress {
id
number
createdAt
address1
address2
buyerReference
}
errors
}
}
Variables
{
"input": {
"customerId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createCustomerAddress": {
"customerAddress": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
},
"errors": null
}
}
}
Mutation
deleteCustomerAddress
Removes an address of a customer. Refused for an address that documents were written to.
Who may Admins only.
Arguments
idID!required
Answer
customerAddressCustomerAddresserrorsJson
Example
mutation DeleteCustomerAddress($input: DeleteCustomerAddressInput!) {
deleteCustomerAddress(input: $input) {
customerAddress {
id
number
createdAt
address1
address2
buyerReference
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteCustomerAddress": {
"customerAddress": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
},
"errors": null
}
}
}
Mutation
updateCustomerAddress
Changes an address of a customer. Only the arguments sent are changed.
Who may Admins only.
Arguments
idID!requiredaddress1Stringaddress2StringbuyerReferenceString- The e-invoice's buyer reference (BT-10), e.g. a Leitweg-ID
cityStringcountryString- Free text, from before the list; prefer countryCode
countryCodeString- ISO 3166-1 alpha-2
departmentStringinvoiceEmailString- Where this customer receives e-invoices (BT-49)
numberInt- The customer number; typed where the workspace numbers its customers itself, else docket's
recipientStringtaxTreatmentTaxTreatmentvatNoStringzipString
Answer
customerAddressCustomerAddresserrorsJson
Example
mutation UpdateCustomerAddress($input: UpdateCustomerAddressInput!) {
updateCustomerAddress(input: $input) {
customerAddress {
id
number
createdAt
address1
address2
buyerReference
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateCustomerAddress": {
"customerAddress": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
},
"errors": null
}
}
}
Delivery Note
Mutation
createDeliveryNote
Creates a draft delivery note from an order confirmation or an invoice, in the same billing cycle and with that document's content. One of orderConfirmationId and invoiceId is needed. A cycle can have as many delivery notes as you deliver in parts.
Who may Project managers and admins.
Arguments
authorIdIDcontactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringfooterStringinvoiceIdIDlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The delivery note's running number within its project; the next free one when omitted
orderConfirmationIdIDshowPositionSubtotalBooleanstatusDeliveryNoteStatus
Answer
deliveryNoteDeliveryNoteerrorsJson
Example
mutation CreateDeliveryNote($input: CreateDeliveryNoteInput!) {
createDeliveryNote(input: $input) {
deliveryNote {
id
number
title
name
status
date
}
errors
}
}
Variables
{
"input": {
"customerAddressId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"orderConfirmationId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createDeliveryNote": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
},
"errors": null
}
}
}
Mutation
deleteDeliveryNote
Deletes a delivery note.
Who may Admins only.
Arguments
idID!required
Answer
deliveryNoteDeliveryNoteerrorsJson
Example
mutation DeleteDeliveryNote($input: DeleteDeliveryNoteInput!) {
deleteDeliveryNote(input: $input) {
deliveryNote {
id
number
title
name
status
date
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteDeliveryNote": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
},
"errors": null
}
}
}
Mutation
draftDeliveryNote
Takes a published delivery note back to draft. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!required
Answer
deliveryNoteDeliveryNoteerrorsJson
Example
mutation DraftDeliveryNote($input: DraftDeliveryNoteInput!) {
draftDeliveryNote(input: $input) {
deliveryNote {
id
number
title
name
status
date
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"draftDeliveryNote": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
},
"errors": null
}
}
}
Mutation
publishDeliveryNote
Publishes a delivery note. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins. docket sends nothing to the customer; send the PDF yourself.
Arguments
idID!required
Answer
deliveryNoteDeliveryNoteerrorsJson
Example
mutation PublishDeliveryNote($input: PublishDeliveryNoteInput!) {
publishDeliveryNote(input: $input) {
deliveryNote {
id
number
title
name
status
date
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"publishDeliveryNote": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
},
"errors": null
}
}
}
Mutation
updateDeliveryNote
Changes a delivery note's header: name, date, texts, address, contacts, custom fields. Only the arguments you send change. The status has its own mutations.
Who may Project managers and admins.
Arguments
idID!requiredauthorIdIDcontactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringfooterStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The delivery note's running number within its project; the next free one when omitted
showPositionSubtotalBooleanstatusDeliveryNoteStatus
Answer
deliveryNoteDeliveryNoteerrorsJson
Example
mutation UpdateDeliveryNote($input: UpdateDeliveryNoteInput!) {
updateDeliveryNote(input: $input) {
deliveryNote {
id
number
title
name
status
date
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateDeliveryNote": {
"deliveryNote": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
},
"errors": null
}
}
}
Delivery Note Comment
Mutation
createDeliveryNoteComment
Adds a comment to a delivery note, as the caller. The caller starts following the delivery note; its other followers and the people mentioned are notified.
Who may Project managers and admins.
Arguments
authorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
deliveryNoteIdID- The delivery note to comment on; needed when creating, ignored when updating
Answer
deliveryNoteCommentDeliveryNoteCommenterrorsJson
Example
mutation CreateDeliveryNoteComment($input: CreateDeliveryNoteCommentInput!) {
createDeliveryNoteComment(input: $input) {
deliveryNoteComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
errors
}
}
Variables
{
"input": {
"deliveryNoteId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createDeliveryNoteComment": {
"deliveryNoteComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Mutation
deleteDeliveryNoteComment
Deletes a comment on a delivery note.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!required
Answer
deliveryNoteCommentDeliveryNoteCommenterrorsJson
Example
mutation DeleteDeliveryNoteComment($input: DeleteDeliveryNoteCommentInput!) {
deleteDeliveryNoteComment(input: $input) {
deliveryNoteComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteDeliveryNoteComment": {
"deliveryNoteComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Mutation
updateDeliveryNoteComment
Changes the text of a comment on a delivery note. The note docket writes when the AI assistant added positions cannot be changed.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!requiredauthorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
deliveryNoteIdID- The delivery note to comment on; needed when creating, ignored when updating
Answer
deliveryNoteCommentDeliveryNoteCommenterrorsJson
Example
mutation UpdateDeliveryNoteComment($input: UpdateDeliveryNoteCommentInput!) {
updateDeliveryNoteComment(input: $input) {
deliveryNoteComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateDeliveryNoteComment": {
"deliveryNoteComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
},
"errors": null
}
}
}
Discount Surcharge
Mutation
createDiscountSurcharge
Adds a discount or a surcharge to a draft quotation or invoice: a net amount taken off or added to the total of the positions. Returns the document's whole list of discounts and surcharges. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- Its place in the document's list of discounts and surcharges, counted from 0
recordIdID!required- The draft quotation or invoice to change
typeDiscountSurchargeTypeEnum!requiredamountFloat- The net amount as a positive number; a discount is subtracted, a surcharge added
titleString
Answer
Example
mutation CreateDiscountSurcharge($input: CreateDiscountSurchargeInput!) {
createDiscountSurcharge(input: $input) {
discountSurcharge
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42,
"type": "discount"
}
}
Response
{
"data": {
"createDiscountSurcharge": {
"discountSurcharge": {},
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
deleteDiscountSurcharge
Removes a discount or surcharge from a draft quotation or invoice. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- Its place in the document's list of discounts and surcharges, counted from 0
recordIdID!required- The draft quotation or invoice to change
amountFloat- The net amount as a positive number; a discount is subtracted, a surcharge added
titleString
Answer
Example
mutation DeleteDiscountSurcharge($input: DeleteDiscountSurchargeInput!) {
deleteDiscountSurcharge(input: $input) {
discountSurcharge
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"deleteDiscountSurcharge": {
"discountSurcharge": {},
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
updateDiscountSurcharge
Changes a discount or surcharge of a draft quotation or invoice; only the arguments you send change. Refused unless the document is a draft.
Who may Project managers and admins.
Arguments
indexInt!required- Its place in the document's list of discounts and surcharges, counted from 0
recordIdID!required- The draft quotation or invoice to change
amountFloat- The net amount as a positive number; a discount is subtracted, a surcharge added
titleString
Answer
Example
mutation UpdateDiscountSurcharge($input: UpdateDiscountSurchargeInput!) {
updateDiscountSurcharge(input: $input) {
discountSurcharge
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"index": 42
}
}
Response
{
"data": {
"updateDiscountSurcharge": {
"discountSurcharge": {},
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Document Assistant
Mutation
applyDocumentPlan
Adds the plan askDocumentAssistant answered to the draft quotation or invoice and notes what was added in a comment on it. The plan is checked again and refused when it no longer fits the document. Returns the changed document under quotation or invoice, whichever it is.
Who may Project managers and admins.
Arguments
planJson!required- As askDocumentAssistant answered it
recordIdID!required- The draft quotation or invoice
uploadKeyString- The file it came from, attached to the comment
Answer
Example
mutation ApplyDocumentPlan($input: ApplyDocumentPlanInput!) {
applyDocumentPlan(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"plan": {}
}
}
Response
{
"data": {
"applyDocumentPlan": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
askDocumentAssistant
One turn with the AI assistant of a draft quotation or invoice: describe what the document should get, optionally with a spreadsheet of hours, and get either questions back or a plan with a priced preview. Changes nothing; applyDocumentPlan adds the plan. Every call counts against the workspace's AI quota. The conversation is not stored: send what came before in history.
Who may Project managers and admins.
Arguments
messageString!required- What the document should get, in plain words; at most 4,000 characters
recordIdID!required- The quotation's or invoice's id
history[DocumentAssistantTurnInput!]- The conversation so far, oldest first
uploadKeyString- An XLSX or CSV from /api/upload
Answer
errorsJsonnoticeString- Why nothing came of it
planJson- To hand to applyDocumentPlan as it is
previewDocumentPlanPreviewquestions[DocumentAssistantQuestion!]!skippedDocumentAssistantSkippedsummaryString
Example
mutation AskDocumentAssistant($input: AskDocumentAssistantInput!) {
askDocumentAssistant(input: $input) {
errors
notice
plan
preview {
net
}
questions {
multiple
options
question
}
skipped {
noQuantity
noService
}
summary
}
}
Variables
{
"input": {
"recordId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"message": "text"
}
}
Response
{
"data": {
"askDocumentAssistant": {
"errors": null,
"notice": "text",
"plan": {},
"preview": {
"net": 120.5
},
"questions": [
{
"multiple": true,
"options": [
"text"
],
"question": "text"
}
],
"skipped": {
"noQuantity": 42,
"noService": 42
},
"summary": "text"
}
}
}
Document Template
Mutation
applyDocumentTemplate
Fills an empty draft quotation or invoice with a template of its kind: content, texts and footer. Service lines are priced from the rates of the document's project. Refused when the document already has content or is not a draft, and for an invoice that belongs to a quotation or order confirmation.
Who may Project managers and admins.
Arguments
documentIdID!required- The empty quotation or invoice to fill
idID!required
Answer
Example
mutation ApplyDocumentTemplate($input: ApplyDocumentTemplateInput!) {
applyDocumentTemplate(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"documentId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"applyDocumentTemplate": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
createDocumentTemplate
Saves the content of a quotation or an invoice as a new template for that kind of document. The document itself is not changed.
Who may Project managers and admins.
Arguments
documentIdID!required- The quotation or invoice to save
nameString!requiredcustomerIdID- Offer it only for this customer; omit for every customer
noteString- An internal note on what the template is for
Answer
documentTemplateDocumentTemplateerrorsJson
Example
mutation CreateDocumentTemplate($input: CreateDocumentTemplateInput!) {
createDocumentTemplate(input: $input) {
documentTemplate {
id
name
createdAt
blockTitles
kind
missingServiceCount
}
errors
}
}
Variables
{
"input": {
"documentId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch"
}
}
Response
{
"data": {
"createDocumentTemplate": {
"documentTemplate": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"blockTitles": [
"text"
],
"kind": "text",
"missingServiceCount": 42
},
"errors": null
}
}
}
Mutation
deleteDocumentTemplate
Deletes a template. Documents started from it keep their content.
Who may Project managers and admins.
Arguments
idID!required
Answer
documentTemplateDocumentTemplateerrorsJson
Example
mutation DeleteDocumentTemplate($input: DeleteDocumentTemplateInput!) {
deleteDocumentTemplate(input: $input) {
documentTemplate {
id
name
createdAt
blockTitles
kind
missingServiceCount
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteDocumentTemplate": {
"documentTemplate": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"blockTitles": [
"text"
],
"kind": "text",
"missingServiceCount": 42
},
"errors": null
}
}
}
Mutation
updateDocumentTemplate
Renames a template, changes its note or its customer and, with documentId, replaces its content with that document's. The document must be of the template's kind.
Who may Project managers and admins.
Arguments
idID!requiredcustomerIdID- null: offer it for every customer
documentIdID- Replace the template's content with this quotation's or invoice's
nameStringnoteString- An internal note on what the template is for
Answer
documentTemplateDocumentTemplateerrorsJson
Example
mutation UpdateDocumentTemplate($input: UpdateDocumentTemplateInput!) {
updateDocumentTemplate(input: $input) {
documentTemplate {
id
name
createdAt
blockTitles
kind
missingServiceCount
}
errors
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateDocumentTemplate": {
"documentTemplate": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"blockTitles": [
"text"
],
"kind": "text",
"missingServiceCount": 42
},
"errors": null
}
}
}
Mutation
useDocumentTemplate
Starts a new draft from a template in a project: a quotation, or an invoice that is a billing cycle of its own. A template saved for one customer is refused in another customer's project.
Who may Project managers and admins.
Arguments
idID!requiredprojectIdID!required
Answer
Example
mutation UseDocumentTemplate($input: UseDocumentTemplateInput!) {
useDocumentTemplate(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"useDocumentTemplate": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
},
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
External Cost
Mutation
bulkUpdateExternalCost
Sets the same values, typically the status or the responsible person, on several external costs at once. Assignments are not changed here.
Who may Project managers and admins.
Arguments
ids[ID!]!required- The external costs to change; at least one
amountFloat- Net, in the workspace's currency
assignmentsAttributes[ExternalCostAssignmentInput!]- Always send all positions, since using this argument will replace the whole collection
blobIdID- The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currencyCurrency- The invoice's currency, where it is not the workspace's
inputTaxDeductibleBoolean- Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDateISO8601DateinvoiceNumberStringoriginalAmountFloat- Net in the invoice's currency;
amountis then the net in the workspace's (omitted: at the ECB rate of the invoice date) partialAmountBoolean- true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBillBoolean- One of several invoices from the supplier for the same job
relatedCostIdString- Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
statusExternalCostStatussupplierIdIDtaxFloat- The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRateFloat- In percent
userIdID- The responsible person; they get an email when it is set or changed
Answer
errorsJsonexternalCostsExternalCostConnection
Example
mutation BulkUpdateExternalCost($input: BulkUpdateExternalCostInput!) {
bulkUpdateExternalCost(input: $input) {
errors
externalCosts {
totalCount
edges {
node {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
}
}
}
Variables
{
"input": {
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
}
Response
{
"data": {
"bulkUpdateExternalCost": {
"errors": null,
"externalCosts": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
]
}
}
}
}
Mutation
createExternalCost
Enters a supplier invoice as an external cost. Needs the supplier, the invoice number (unique per supplier and VAT rate), the invoice date, the net amount and the invoice file (blobId); any status but DRAFT also needs at least one assignment. The responsible person (userId) gets an email.
Who may Project managers and admins.
Arguments
amountFloat- Net, in the workspace's currency
assignmentsAttributes[ExternalCostAssignmentInput!]- Always send all positions, since using this argument will replace the whole collection
blobIdID- The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currencyCurrency- The invoice's currency, where it is not the workspace's
inputTaxDeductibleBoolean- Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDateISO8601DateinvoiceNumberStringoriginalAmountFloat- Net in the invoice's currency;
amountis then the net in the workspace's (omitted: at the ECB rate of the invoice date) partialAmountBoolean- true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBillBoolean- One of several invoices from the supplier for the same job
relatedCostIdString- Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
statusExternalCostStatussupplierIdIDtaxFloat- The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRateFloat- In percent
userIdID- The responsible person; they get an email when it is set or changed
Answer
errorsJsonexternalCostExternalCost
Example
mutation CreateExternalCost($input: CreateExternalCostInput!) {
createExternalCost(input: $input) {
errors
externalCost {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
}
Variables
{
"input": {
"blobId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"supplierId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"relatedCostId": "text"
}
}
Response
{
"data": {
"createExternalCost": {
"errors": null,
"externalCost": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
}
}
Mutation
deleteExternalCost
Deletes an external cost together with its assignments to projects and quotations.
Who may Project managers and admins.
Arguments
idID!required
Answer
errorsJsonexternalCostExternalCost
Example
mutation DeleteExternalCost($input: DeleteExternalCostInput!) {
deleteExternalCost(input: $input) {
errors
externalCost {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteExternalCost": {
"errors": null,
"externalCost": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
}
}
Mutation
readExternalCostReceipt
Reads an uploaded supplier invoice and returns what it found, to fill in an external cost; nothing is saved. An e-invoice (ZUGFeRD, Factur-X, XRechnung) is read directly; any other file only with AI, where the workspace switched that on, and such a reading counts against the workspace's monthly AI quota.
Who may Project managers and admins.
Arguments
blobIdID!required- A file uploaded through /api/upload, or the invoice file of an existing external cost
withAiBoolean- Read with AI if there's no e-invoice (the wand); else only when the workspace reads every upload
Answer
amountFloat- Net
currencyString- As the invoice says; amount and tax are in it
errorsJsonexchangeRateExchangeRate- The ECB rate of the invoice date, for an invoice in another currency docket can convert
invoiceDateISO8601DateinvoiceNumberStringmixedTaxRatesBooleannoticeString- Why nothing was read, when it says
sourceReceiptSourcesupplierSupplier- The workspace's supplier of that name
supplierNameStringtaxFloat- The VAT amount the invoice states
taxRateFloat
Example
mutation ReadExternalCostReceipt($input: ReadExternalCostReceiptInput!) {
readExternalCostReceipt(input: $input) {
amount
currency
errors
exchangeRate {
on
rate
}
invoiceDate
invoiceNumber
mixedTaxRates
notice
source
supplier {
id
title
createdAt
archived
datevAccount
ksk
}
supplierName
tax
taxRate
}
}
Variables
{
"input": {
"blobId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"readExternalCostReceipt": {
"amount": 120.5,
"currency": "text",
"errors": null,
"exchangeRate": {
"on": "2026-11-13",
"rate": 120.5
},
"invoiceDate": "2026-11-13",
"invoiceNumber": "text",
"mixedTaxRates": true,
"notice": "text",
"source": "E_INVOICE",
"supplier": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
},
"supplierName": "text",
"tax": 120.5,
"taxRate": 120.5
}
}
}
Mutation
updateExternalCost
Changes an external cost. Only the arguments sent are changed, but assignmentsAttributes replaces all assignments and blobId replaces the invoice file. A new responsible person (userId) gets an email.
Who may Project managers and admins.
Arguments
idID!requiredamountFloat- Net, in the workspace's currency
assignmentsAttributes[ExternalCostAssignmentInput!]- Always send all positions, since using this argument will replace the whole collection
blobIdID- The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currencyCurrency- The invoice's currency, where it is not the workspace's
inputTaxDeductibleBoolean- Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDateISO8601DateinvoiceNumberStringoriginalAmountFloat- Net in the invoice's currency;
amountis then the net in the workspace's (omitted: at the ECB rate of the invoice date) partialAmountBoolean- true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBillBoolean- One of several invoices from the supplier for the same job
relatedCostIdString- Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
statusExternalCostStatussupplierIdIDtaxFloat- The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRateFloat- In percent
userIdID- The responsible person; they get an email when it is set or changed
Answer
errorsJsonexternalCostExternalCost
Example
mutation UpdateExternalCost($input: UpdateExternalCostInput!) {
updateExternalCost(input: $input) {
errors
externalCost {
id
status
amount
createdAt
assignmentsDifference
currency
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateExternalCost": {
"errors": null,
"externalCost": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
}
}
}
Follow
Mutation
setFollow
Follows or unfollows a ticket, a project or a billing document (quotation, order confirmation, delivery note, invoice) for the caller. Followers are notified of what happens there.
Who may Anyone who can open the record; it only ever changes the caller's own notifications.
Arguments
followingBoolean!required- true follows, false unfollows
idID!required- ID of a ticket, a project, a quotation, an order confirmation, a delivery note or an invoice
Answer
errorsJsonfollowableIdIDviewerIsFollowingBoolean
Example
mutation SetFollow($input: SetFollowInput!) {
setFollow(input: $input) {
errors
followableId
viewerIsFollowing
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"following": true
}
}
Response
{
"data": {
"setFollow": {
"errors": null,
"followableId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"viewerIsFollowing": true
}
}
}
Invoice
Mutation
cancelInvoice
Cancels a published invoice. docket creates a cancellation invoice that reverses it figure for figure (a draft that gets its own number when published) and marks the invoice canceled. Refused for an invoice that is not published, for a cancellation invoice, and for one an issued final invoice has settled: cancel the final invoice first.
Who may Project managers and admins.
Arguments
idID!requiredcanceledNoteString- Why it was canceled; kept with the canceled invoice
Answer
Example
mutation CancelInvoice($input: CancelInvoiceInput!) {
cancelInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"cancelInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
correctInvoice
Corrects a published invoice the customer already has: it is canceled with a cancellation invoice, and a copy starts as a new draft in the same billing cycle. Returns the new draft. Refused where cancelInvoice is refused. Publish the cancellation invoice and the corrected invoice afterwards; each gets its own number.
Who may Project managers and admins.
Arguments
idID!requirednoteString- Why it is corrected — kept as the canceled invoice's note
Answer
Example
mutation CorrectInvoice($input: CorrectInvoiceInput!) {
correctInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"correctInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
createInvoice
Starts a draft invoice. With orderConfirmationId or quotationId it joins that billing cycle as an advance payment, a partial invoice or the final invoice; with only projectId it is a billing cycle of its own and must be a FINAL_INVOICE. Advance payments and partial invoices cannot be mixed in one cycle. The invoice gets its number when an admin publishes it.
Who may Project managers and admins.
Arguments
invoiceTypeInvoiceTypeEnum!requiredauthorIdIDblocksJson- The content: the whole list of blocks, each with its positions and their lines. Replaces what is there; only in a draft
contactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedeductionTypeString- How to read deductionValue: percentage_amount or fixed_amount. Advance payments only
deductionValueFloat- An advance payment's share of the job: a percentage (above 0, up to 100) or a net amount, as deductionType says
deliveryDateISO8601Date- The date of delivery or service printed on the invoice; today when omitted on creation
descriptionStringdiscountSurchargeJson- The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footerStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The invoice number. Leave it out: publishing assigns the next one in the workspace's sequence
orderConfirmationIdID- The order confirmation whose billing cycle the invoice joins
projectIdID- The project to bill, for an invoice without a quotation or order confirmation
quotationIdID- The quotation whose billing cycle the invoice joins
showPositionSubtotalBooleanstatusInvoiceStatus- Only PUBLISHED can be set, in updateInvoice and by admins; every other status change has its own mutation
taxRateFloat- The VAT rate lines use unless they set their own; fixed once the document leaves draft
timetrackingsAsPositionBoolean- Take the project's time entries that are still open (billable, on no other invoice) as lines
timetrackingsFromISO8601Date- Only entries from this day on
timetrackingsUntilISO8601Date- Only entries up to this day
Answer
Example
mutation CreateInvoice($input: CreateInvoiceInput!) {
createInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"invoiceType": "ADVANCE_PAYMENT"
}
}
Response
{
"data": {
"createInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
createRetainerInvoice
Starts the invoice of a retainer's month as a draft: the monthly fee as one line and, with a contingent whose overage is billed, the hours beyond it at the project's rates. The month's open time entries are held by the invoice, so they aren't billed again. Refused for a project without a retainer, a month outside its term, and a month that has an invoice.
Who may Project managers and admins.
Arguments
monthISO8601Date!required- Any day of the month to invoice
projectIdID!required
Answer
Example
mutation CreateRetainerInvoice($input: CreateRetainerInvoiceInput!) {
createRetainerInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"month": "2026-11-13"
}
}
Response
{
"data": {
"createRetainerInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
deleteInvoice
Deletes a draft invoice. An invoice that was published stays (cancel it instead), and so does one reopened for correction, which keeps its number. Time entries the draft held are free to be billed again.
Who may Project managers and admins.
Arguments
idID!required
Answer
Example
mutation DeleteInvoice($input: DeleteInvoiceInput!) {
deleteInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
draftInvoice
Takes an invoice that has no number yet back to draft. This only applies to invoices in the former approved status. For a published invoice use reopenInvoiceForCorrection or correctInvoice.
Who may Project managers and admins.
Arguments
idID!required
Answer
Example
mutation DraftInvoice($input: DraftInvoiceInput!) {
draftInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"draftInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
duplicateInvoice
Copies an invoice's name, description, content and discounts and surcharges into a new draft invoice in the given project. The copy is a billing cycle of its own and therefore always a final invoice, whatever the original was.
Who may Project managers and admins.
Arguments
idID!requiredprojectIdID!required- The project the copy goes into
Answer
Example
mutation DuplicateInvoice($input: DuplicateInvoiceInput!) {
duplicateInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"duplicateInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
markInvoiceAsPaid
Marks a published invoice as paid. Only reverseInvoicePayment takes this back. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!requiredpaidAtISO8601DateTime- When the payment arrived; now when omitted
Answer
Example
mutation MarkInvoiceAsPaid($input: MarkInvoiceAsPaidInput!) {
markInvoiceAsPaid(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"markInvoiceAsPaid": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
publishInvoice
Publishes a draft invoice and makes it final: it gets its number (the next in the workspace's sequence, unless it has one), its due date from the payment term, and its figures and PDF are fixed. Refused when it bills nothing, has no customer address, lacks tax details the invoice must carry, or when an issued final invoice of its billing cycle has settled it. Followers of the document and of its project get a mail and an inbox entry.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation PublishInvoice($input: PublishInvoiceInput!) {
publishInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"publishInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
reopenInvoiceForCorrection
Takes a published invoice that has not reached the customer back to draft. It keeps its number; the reason and the PDF as it was are kept with it. Fix it and publish it again. Refused for a cancellation invoice and for an invoice an issued final invoice has settled. If the customer already has the invoice, use correctInvoice.
Who may Admins only.
Arguments
idID!requirednotSentToCustomerBoolean!required- The customer hasn't received this invoice
reasonString!required- What is wrong — kept with the correction
Answer
Example
mutation ReopenInvoiceForCorrection($input: ReopenInvoiceForCorrectionInput!) {
reopenInvoiceForCorrection(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"reason": "text",
"notSentToCustomer": true
}
}
Response
{
"data": {
"reopenInvoiceForCorrection": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
reverseInvoicePayment
Takes back the payment of a paid invoice, marked by mistake or returned by the bank: the invoice is published and unpaid again. Its number, PDF and figures stay as they went out, and nobody is notified.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation ReverseInvoicePayment($input: ReverseInvoicePaymentInput!) {
reverseInvoicePayment(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"reverseInvoicePayment": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Mutation
updateInvoice
Changes an invoice. Only the arguments you send change; blocks, discountSurcharge and the contact lists each replace the whole list. Content can only be changed in a draft. Sending status PUBLISHED publishes it as publishInvoice does (admins only); every other status change has its own mutation.
Who may Project managers and admins.
Arguments
idID!requiredauthorIdIDblocksJson- The content: the whole list of blocks, each with its positions and their lines. Replaces what is there; only in a draft
contactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedeductionTypeString- How to read deductionValue: percentage_amount or fixed_amount. Advance payments only
deductionValueFloat- An advance payment's share of the job: a percentage (above 0, up to 100) or a net amount, as deductionType says
deliveryDateISO8601Date- The date of delivery or service printed on the invoice; today when omitted on creation
descriptionStringdiscountSurchargeJson- The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footerStringinvoiceTypeInvoiceTypeEnumlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The invoice number. Leave it out: publishing assigns the next one in the workspace's sequence
showPositionSubtotalBooleanstatusInvoiceStatus- Only PUBLISHED can be set, in updateInvoice and by admins; every other status change has its own mutation
taxRateFloat- The VAT rate lines use unless they set their own; fixed once the document leaves draft
Answer
Example
mutation UpdateInvoice($input: UpdateInvoiceInput!) {
updateInvoice(input: $input) {
errors
invoice {
id
number
inr
title
name
status
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateInvoice": {
"errors": null,
"invoice": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
}
}
}
Invoice Comment
Mutation
createInvoiceComment
Adds a comment to an invoice, as the caller. The caller starts following the invoice; its other followers and the people mentioned are notified.
Who may Project managers and admins.
Arguments
authorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
invoiceIdID- The invoice to comment on; needed when creating, ignored when updating
Answer
errorsJsoninvoiceCommentInvoiceComment
Example
mutation CreateInvoiceComment($input: CreateInvoiceCommentInput!) {
createInvoiceComment(input: $input) {
errors
invoiceComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"invoiceId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createInvoiceComment": {
"errors": null,
"invoiceComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteInvoiceComment
Deletes a comment on an invoice.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!required
Answer
errorsJsoninvoiceCommentInvoiceComment
Example
mutation DeleteInvoiceComment($input: DeleteInvoiceCommentInput!) {
deleteInvoiceComment(input: $input) {
errors
invoiceComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteInvoiceComment": {
"errors": null,
"invoiceComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateInvoiceComment
Changes the text of a comment on an invoice. The note docket writes when the AI assistant added positions cannot be changed.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!requiredauthorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
invoiceIdID- The invoice to comment on; needed when creating, ignored when updating
Answer
errorsJsoninvoiceCommentInvoiceComment
Example
mutation UpdateInvoiceComment($input: UpdateInvoiceCommentInput!) {
updateInvoiceComment(input: $input) {
errors
invoiceComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateInvoiceComment": {
"errors": null,
"invoiceComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Notification
Mutation
markAllNotificationsAsRead
Marks all of the caller's unread notifications as read and answers with the ones it changed.
Who may Anyone, for their own notifications.
Arguments
userIdID!required- The caller's own user id
Answer
errorsJsonnotifications[Notification!]!
Example
mutation MarkAllNotificationsAsRead($input: MarkAllNotificationsAsReadInput!) {
markAllNotificationsAsRead(input: $input) {
errors
notifications {
id
createdAt
action
actorCount
count
countArchived
}
}
}
Variables
{
"input": {
"userId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"markAllNotificationsAsRead": {
"errors": null,
"notifications": [
{
"id": "text",
"createdAt": "2026-11-13T09:30:00+01:00",
"action": "TICKET_CREATED",
"actorCount": 42,
"count": 42,
"countArchived": 42
}
]
}
}
}
Mutation
markNotificationAsRead
Marks one notification as read.
Who may Only the person it was sent to.
Arguments
idID!required
Answer
errorsJsonnotificationNotification
Example
mutation MarkNotificationAsRead($input: MarkNotificationAsReadInput!) {
markNotificationAsRead(input: $input) {
errors
notification {
id
createdAt
action
actorCount
count
countArchived
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"markNotificationAsRead": {
"errors": null,
"notification": {
"id": "text",
"createdAt": "2026-11-13T09:30:00+01:00",
"action": "TICKET_CREATED",
"actorCount": 42,
"count": 42,
"countArchived": 42
}
}
}
}
Mutation
updateNotificationsByRecords
Sets the read and the archived state of all of the caller's notifications about the given records: the inbox shows one entry per record and event. Both states are always set.
Who may Only ever the caller's own notifications.
Arguments
archivedBoolean!requiredisNewBoolean!required- false marks them as read, true as unread
records[NotificationRecordInput!]!required
Answer
errorsJsonnotifications[Notification!]!
Example
mutation UpdateNotificationsByRecords($input: UpdateNotificationByRecordsInput!) {
updateNotificationsByRecords(input: $input) {
errors
notifications {
id
createdAt
action
actorCount
count
countArchived
}
}
}
Variables
{
"input": {
"records": [
{
"type": "TICKET",
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
],
"isNew": true,
"archived": true
}
}
Response
{
"data": {
"updateNotificationsByRecords": {
"errors": null,
"notifications": [
{
"id": "text",
"createdAt": "2026-11-13T09:30:00+01:00",
"action": "TICKET_CREATED",
"actorCount": 42,
"count": 42,
"countArchived": 42
}
]
}
}
}
Order Confirmation
Mutation
createOrderConfirmation
Creates the order confirmation of a quotation's billing cycle, as a draft with the quotation's content.
Who may Project managers and admins. confirmQuotation does this by itself, so you rarely need it.
Arguments
quotationIdID!required- The quotation it confirms
authorIdIDcontactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringfooterStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The order confirmation's running number within its project; the next free one when omitted
showPositionSubtotalBooleanstatusOrderConfirmationStatus
Answer
errorsJsonorderConfirmationOrderConfirmation
Example
mutation CreateOrderConfirmation($input: CreateOrderConfirmationInput!) {
createOrderConfirmation(input: $input) {
errors
orderConfirmation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"quotationId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createOrderConfirmation": {
"errors": null,
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
deleteOrderConfirmation
Deletes an order confirmation.
Who may Admins only.
Arguments
idID!required
Answer
errorsJsonorderConfirmationOrderConfirmation
Example
mutation DeleteOrderConfirmation($input: DeleteOrderConfirmationInput!) {
deleteOrderConfirmation(input: $input) {
errors
orderConfirmation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteOrderConfirmation": {
"errors": null,
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
draftOrderConfirmation
Takes a published order confirmation back to draft. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!required
Answer
errorsJsonorderConfirmationOrderConfirmation
Example
mutation DraftOrderConfirmation($input: DraftOrderConfirmationInput!) {
draftOrderConfirmation(input: $input) {
errors
orderConfirmation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"draftOrderConfirmation": {
"errors": null,
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
publishOrderConfirmation
Publishes an order confirmation. While it is published its quotation cannot be confirmed again, as that would change it. docket sends nothing to the customer; send the PDF yourself. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!required
Answer
errorsJsonorderConfirmationOrderConfirmation
Example
mutation PublishOrderConfirmation($input: PublishOrderConfirmationInput!) {
publishOrderConfirmation(input: $input) {
errors
orderConfirmation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"publishOrderConfirmation": {
"errors": null,
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
updateOrderConfirmation
Changes an order confirmation's header: name, date, texts, address, contacts, custom fields. Only the arguments you send change. Its positions are the quotation's: change the quotation and confirm it again. The status has its own mutations.
Who may Project managers and admins.
Arguments
idID!requiredauthorIdIDcontactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringfooterStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The order confirmation's running number within its project; the next free one when omitted
showPositionSubtotalBooleanstatusOrderConfirmationStatus
Answer
errorsJsonorderConfirmationOrderConfirmation
Example
mutation UpdateOrderConfirmation($input: UpdateOrderConfirmationInput!) {
updateOrderConfirmation(input: $input) {
errors
orderConfirmation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateOrderConfirmation": {
"errors": null,
"orderConfirmation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Order Confirmation Comment
Mutation
createOrderConfirmationComment
Adds a comment to an order confirmation, as the caller. The caller starts following the order confirmation; its other followers and the people mentioned are notified.
Who may Project managers and admins.
Arguments
authorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
orderConfirmationIdID- The order confirmation to comment on; needed when creating, ignored when updating
Answer
errorsJsonorderConfirmationCommentOrderConfirmationComment
Example
mutation CreateOrderConfirmationComment($input: CreateOrderConfirmationCommentInput!) {
createOrderConfirmationComment(input: $input) {
errors
orderConfirmationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"orderConfirmationId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createOrderConfirmationComment": {
"errors": null,
"orderConfirmationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteOrderConfirmationComment
Deletes a comment on an order confirmation.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!required
Answer
errorsJsonorderConfirmationCommentOrderConfirmationComment
Example
mutation DeleteOrderConfirmationComment($input: DeleteOrderConfirmationCommentInput!) {
deleteOrderConfirmationComment(input: $input) {
errors
orderConfirmationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteOrderConfirmationComment": {
"errors": null,
"orderConfirmationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateOrderConfirmationComment
Changes the text of a comment on an order confirmation. The note docket writes when the AI assistant added positions cannot be changed.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!requiredauthorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
orderConfirmationIdID- The order confirmation to comment on; needed when creating, ignored when updating
Answer
errorsJsonorderConfirmationCommentOrderConfirmationComment
Example
mutation UpdateOrderConfirmationComment($input: UpdateOrderConfirmationCommentInput!) {
updateOrderConfirmationComment(input: $input) {
errors
orderConfirmationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateOrderConfirmationComment": {
"errors": null,
"orderConfirmationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Phase
Mutation
createPhase
Adds a phase to a project's roadmap. projectId and title are required; the title is unique within the project.
Who may Project managers and admins.
Arguments
descriptionStringendDateString- ISO 8601 date (YYYY-MM-DD)
projectIdIDstartDateString- ISO 8601 date (YYYY-MM-DD)
titleString
Answer
Example
mutation CreatePhase($input: CreatePhaseInput!) {
createPhase(input: $input) {
errors
phase {
id
title
createdAt
computedEndDate
computedStartDate
description
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createPhase": {
"errors": null,
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
}
}
}
Mutation
deletePhase
Deletes a phase. Its tickets stay in the project, without a phase.
Who may Project managers and admins.
Arguments
idID!required
Answer
Example
mutation DeletePhase($input: DeletePhaseInput!) {
deletePhase(input: $input) {
errors
phase {
id
title
createdAt
computedEndDate
computedStartDate
description
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deletePhase": {
"errors": null,
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
}
}
}
Mutation
movePhase
Moves a phase to another place in the order of its project's phases.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredtoPositionInt!required- The new position, counted from 1
Answer
Example
mutation MovePhase($input: MovePhaseInput!) {
movePhase(input: $input) {
errors
phase {
id
title
createdAt
computedEndDate
computedStartDate
description
}
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toPosition": 42
}
}
Response
{
"data": {
"movePhase": {
"errors": null,
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
},
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updatePhase
Changes a phase's title, description or dates. The phase stays in its project: projectId is ignored.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requireddescriptionStringendDateString- ISO 8601 date (YYYY-MM-DD)
projectIdIDstartDateString- ISO 8601 date (YYYY-MM-DD)
titleString
Answer
Example
mutation UpdatePhase($input: UpdatePhaseInput!) {
updatePhase(input: $input) {
errors
phase {
id
title
createdAt
computedEndDate
computedStartDate
description
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updatePhase": {
"errors": null,
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
}
}
}
Project
Mutation
createProject
Creates a project for a customer. title, customerId and at least one of supervisorIds are required. The project starts with a Backlog and a Done board and a first general ticket, and the project.created webhook fires.
Who may Project managers and admins.
Arguments
archivedBooleanbudgetRateFloat- The budget in the unit of
budgetType: minutes, or an amount in the workspace's currency budgetTypeProjectBudgetcustomerIdIDdeadlineISO8601DatedescriptionStringnumberInt- Project number, unique in the workspace. Default: the next free number
retainerBillsOverageBoolean- Whether hours beyond the contingent (a budget of hours per month) are billed on top of the fee. Default: true
retainerContingentMinutesInt- The hours one fee covers, in minutes per period (month or quarter). Null: the budget stands in when it is hours per month
retainerEndsOnISO8601Date- The last day of the retainer; null for an open-ended one
retainerFeeFloat- The retainer's fee per period (month or quarter), net, in the workspace's currency
retainerIntervalMonthsInt- 1: billed monthly (default); 3: billed quarterly, counted from the month it starts in
retainerNoticeMonthsInt- The notice period in months
retainerStartsOnISO8601Date- The first day of the retainer. A project with a start is a retainer; null ends it (invoices written stay)
serviceRates[ServiceRateInput!]- The project's own daily rates, replacing all it had.
idis a rate's id asserviceRatesreturns it (it ends in the service's id) statusProjectStatusstatusDateISO8601Date- Since when the project has its status. Set to today whenever the status changes
supervisorIds[ID!]- The users who manage the project; at least one. On update: the whole list, users left out are removed
titleString
Answer
Example
mutation CreateProject($input: CreateProjectInput!) {
createProject(input: $input) {
errors
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"customerId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createProject": {
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteProject
Deletes a project with everything in it: its tickets, time entries, boards, phases and billing documents. Fails while external costs are assigned to the project.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation DeleteProject($input: DeleteProjectInput!) {
deleteProject(input: $input) {
errors
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteProject": {
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateProject
Changes a project; only the arguments sent are changed. Time already booked keeps its rates unless updateTimetrackings is true.
Who may Project managers and admins.
Arguments
idID!requiredarchivedBooleanbudgetRateFloat- The budget in the unit of
budgetType: minutes, or an amount in the workspace's currency budgetTypeProjectBudgetcustomerIdIDdeadlineISO8601DatedescriptionStringnumberInt- Project number, unique in the workspace. Default: the next free number
retainerBillsOverageBoolean- Whether hours beyond the contingent (a budget of hours per month) are billed on top of the fee. Default: true
retainerContingentMinutesInt- The hours one fee covers, in minutes per period (month or quarter). Null: the budget stands in when it is hours per month
retainerEndsOnISO8601Date- The last day of the retainer; null for an open-ended one
retainerFeeFloat- The retainer's fee per period (month or quarter), net, in the workspace's currency
retainerIntervalMonthsInt- 1: billed monthly (default); 3: billed quarterly, counted from the month it starts in
retainerNoticeMonthsInt- The notice period in months
retainerStartsOnISO8601Date- The first day of the retainer. A project with a start is a retainer; null ends it (invoices written stay)
serviceRates[ServiceRateInput!]- The project's own daily rates, replacing all it had.
idis a rate's id asserviceRatesreturns it (it ends in the service's id) statusProjectStatusstatusDateISO8601Date- Since when the project has its status. Set to today whenever the status changes
supervisorIds[ID!]- The users who manage the project; at least one. On update: the whole list, users left out are removed
titleStringupdateTimetrackingsBoolean- true: time already booked on services whose rate changed is repriced at the new rate
Answer
Example
mutation UpdateProject($input: UpdateProjectInput!) {
updateProject(input: $input) {
errors
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateProject": {
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Project Label
Mutation
createProjectLabel
Adds a label to a project, to tag its tickets with. projectId, title and color are required.
Who may Project managers and admins.
Arguments
colorString- Hex colour code: #rgb or #rrggbb
descriptionStringprojectIdIDtitleString
Answer
errorsJsonprojectLabelProjectLabel
Example
mutation CreateProjectLabel($input: CreateProjectLabelInput!) {
createProjectLabel(input: $input) {
errors
projectLabel {
id
title
createdAt
color
description
slug
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createProjectLabel": {
"errors": null,
"projectLabel": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
}
}
}
Mutation
deleteProjectLabel
Deletes a label and takes it off every ticket that carries it.
Who may Project managers and admins.
Arguments
idID!required
Answer
errorsJsonprojectLabelProjectLabel
Example
mutation DeleteProjectLabel($input: DeleteProjectLabelInput!) {
deleteProjectLabel(input: $input) {
errors
projectLabel {
id
title
createdAt
color
description
slug
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteProjectLabel": {
"errors": null,
"projectLabel": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
}
}
}
Mutation
updateProjectLabel
Changes a label's title, description or colour. The label stays in its project: projectId is ignored.
Who may Project managers and admins.
Arguments
idID!requiredcolorString- Hex colour code: #rgb or #rrggbb
descriptionStringprojectIdIDtitleString
Answer
errorsJsonprojectLabelProjectLabel
Example
mutation UpdateProjectLabel($input: UpdateProjectLabelInput!) {
updateProjectLabel(input: $input) {
errors
projectLabel {
id
title
createdAt
color
description
slug
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateProjectLabel": {
"errors": null,
"projectLabel": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
}
}
}
Quotation
Mutation
applyQuotationToProjectBudget
Takes what a confirmed quotation sold into its project's budget: its hours or its net total, whichever the budget counts. The figure comes from the quotation, never from the caller. A quotation goes into the budget only once; a second call is refused.
Who may Project managers and admins who may also change the project and see its budget.
Arguments
idID!requiredmodeBudgetHandoffMode!required
Answer
Example
mutation ApplyQuotationToProjectBudget($input: ApplyQuotationToProjectBudgetInput!) {
applyQuotationToProjectBudget(input: $input) {
errors
project {
id
number
pnr
title
status
createdAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"mode": "SET"
}
}
Response
{
"data": {
"applyQuotationToProjectBudget": {
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
cancelQuotation
Marks a published or confirmed quotation as canceled, with an optional note. A draft cannot be canceled: delete it instead. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!requiredcanceledNoteString- Why it was canceled; shown with the quotation
Answer
Example
mutation CancelQuotation($input: CancelQuotationInput!) {
cancelQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"cancelQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
confirmQuotation
Records that the customer accepted the quotation. docket then creates the order confirmation with the quotation's content, or updates the existing one when the quotation is confirmed again. Refused without a customer address, and while the order confirmation is published (take that back to draft first). Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!requiredconfirmationFileString- The customer's signed confirmation as a data URL (data:application/pdf;base64,...): a PDF of at most 2 MB
confirmationFilenameString- The file name to store the confirmation under
confirmedNoteString- A note on the confirmation, e.g. how the customer accepted
Answer
Example
mutation ConfirmQuotation($input: ConfirmQuotationInput!) {
confirmQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"confirmQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
createQuotation
Starts a draft quotation in a project, and with it a new billing cycle. The number is the next one in the project unless you send one, and the address starts as the customer's first. Add the content with blocks here, or with createBlock and createBlockPosition afterwards.
Who may Project managers and admins.
Arguments
projectIdID!requiredauthorIdIDblocksJson- The content: the whole list of blocks, each with its positions and their lines. Replaces what is there; only in a draft
contactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringdiscountSurchargeJson- The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footerStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The quotation's running number within its project; the next free one when omitted
showPositionSubtotalBooleanstatusQuotationStatustaxRateFloat- The VAT rate lines use unless they set their own; fixed once the document leaves draft
Answer
Example
mutation CreateQuotation($input: CreateQuotationInput!) {
createQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
deleteQuotation
Deletes a draft or a canceled quotation; a published or confirmed one stays. A quotation with external costs on it is refused unless you say where they go: moveExternalCostsToId or unassignExternalCosts.
Who may Project managers and admins.
Arguments
idID!requiredmoveExternalCostsToIdID- Another quotation of the same project that takes over this one's external costs
unassignExternalCostsBoolean- Take the external costs off the quotation and set them back to draft
Answer
Example
mutation DeleteQuotation($input: DeleteQuotationInput!) {
deleteQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
draftQuotation
Takes a published, confirmed or canceled quotation back to draft, so its content can be changed again. Its date is set to today. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!required
Answer
Example
mutation DraftQuotation($input: DraftQuotationInput!) {
draftQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"draftQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
duplicateQuotation
Copies a quotation into a new draft quotation in the given project, as a billing cycle of its own: name, description, content, discounts and surcharges, internal contacts and language. The address is kept only when the project belongs to the same customer; otherwise the copy starts at that customer's first address.
Who may Project managers and admins.
Arguments
idID!requiredprojectIdID!required- The project the copy goes into
Answer
Example
mutation DuplicateQuotation($input: DuplicateQuotationInput!) {
duplicateQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"duplicateQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
publishQuotation
Publishes a quotation: its content is locked until it is taken back to draft. Refused without a customer address. docket sends nothing to the customer; send the PDF yourself. Followers of the document and of its project get a mail and an inbox entry.
Who may Project managers and admins.
Arguments
idID!required
Answer
Example
mutation PublishQuotation($input: PublishQuotationInput!) {
publishQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"publishQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
updateQuotation
Changes a quotation. Only the arguments you send change; blocks, discountSurcharge and the contact lists each replace the whole list. Content (blocks, discountSurcharge) can only be changed in a draft, and the status only through its own mutations (publishQuotation, confirmQuotation, cancelQuotation, draftQuotation).
Who may Project managers and admins.
Arguments
idID!requiredauthorIdIDblocksJson- The content: the whole list of blocks, each with its positions and their lines. Replaces what is there; only in a draft
contactCustomerIds[ID!]- The customer's contacts the document names; replaces the whole list
contactInternalIds[ID!]- The workspace's users named as contacts on the document; replaces the whole list
customFields[AccountingCustomFieldInput!]- Values for the workspace's custom fields; they are shared by all documents of the billing cycle
customerAddressIdID- One of the customer's addresses; the document is made out to it
dateISO8601DatedescriptionStringdiscountSurchargeJson- The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footerStringlanguageString- The language the document is printed in, as a locale code: de (the default) or en
nameStringnumberInt- The quotation's running number within its project; the next free one when omitted
showPositionSubtotalBooleanstatusQuotationStatustaxRateFloat- The VAT rate lines use unless they set their own; fixed once the document leaves draft
Answer
Example
mutation UpdateQuotation($input: UpdateQuotationInput!) {
updateQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Mutation
uploadConfirmationFileToQuotation
Attaches the customer's signed confirmation to a quotation, replacing an earlier one. The file must be a PDF of at most 2 MB.
Who may Project managers and admins.
Arguments
idID!requiredconfirmationFileString- The customer's signed confirmation as a data URL (data:application/pdf;base64,...): a PDF of at most 2 MB
confirmationFilenameString- The file name to store the confirmation under
Answer
Example
mutation UploadConfirmationFileToQuotation($input: UploadConfirmationFileToQuotationInput!) {
uploadConfirmationFileToQuotation(input: $input) {
errors
quotation {
id
number
title
name
status
date
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"uploadConfirmationFileToQuotation": {
"errors": null,
"quotation": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
}
}
}
Quotation Comment
Mutation
createQuotationComment
Adds a comment to a quotation, as the caller. The caller starts following the quotation; its other followers and the people mentioned are notified.
Who may Project managers and admins.
Arguments
authorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
quotationIdID- The quotation to comment on; needed when creating, ignored when updating
Answer
errorsJsonquotationCommentQuotationComment
Example
mutation CreateQuotationComment($input: CreateQuotationCommentInput!) {
createQuotationComment(input: $input) {
errors
quotationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"quotationId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createQuotationComment": {
"errors": null,
"quotationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteQuotationComment
Deletes a comment on a quotation.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!required
Answer
errorsJsonquotationCommentQuotationComment
Example
mutation DeleteQuotationComment($input: DeleteQuotationCommentInput!) {
deleteQuotationComment(input: $input) {
errors
quotationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteQuotationComment": {
"errors": null,
"quotationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateQuotationComment
Changes the text of a comment on a quotation. The note docket writes when the AI assistant added positions cannot be changed.
Who may Only its author, as long as they are a project manager or admin.
Arguments
idID!requiredauthorIdIDbodyJson- The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
quotationIdID- The quotation to comment on; needed when creating, ignored when updating
Answer
errorsJsonquotationCommentQuotationComment
Example
mutation UpdateQuotationComment($input: UpdateQuotationCommentInput!) {
updateQuotationComment(input: $input) {
errors
quotationComment {
id
createdAt
body
bodyHtml
byAi
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateQuotationComment": {
"errors": null,
"quotationComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Saved View
Mutation
createSavedView
Saves a list's filters under a name, as the caller's own view or one shared with everyone. At most 50 views per list, project and owner.
Who may Own views: anyone who can open the list (a project's lists: the project). Shared views: project managers and admins.
Arguments
listSavedViewList!requirednameString!requiredqueryString!required- The list's URL query string (its filters), at most 2000 characters
projectIdID- For a project's lists (its tickets, its controlling)
sharedBoolean- For everyone in the project or workspace (PMs and admins)
Answer
Example
mutation CreateSavedView($input: CreateSavedViewInput!) {
createSavedView(input: $input) {
errors
savedView {
id
name
createdAt
query
shared
updatedAt
}
}
}
Variables
{
"input": {
"list": "TICKETS",
"name": "Website relaunch",
"query": "text"
}
}
Response
{
"data": {
"createSavedView": {
"errors": null,
"savedView": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"query": "text",
"shared": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteSavedView
Deletes a saved view.
Who may Own views: their owner. Shared views: project managers and admins.
Arguments
idID!required
Answer
Example
mutation DeleteSavedView($input: DeleteSavedViewInput!) {
deleteSavedView(input: $input) {
errors
savedView {
id
name
createdAt
query
shared
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteSavedView": {
"errors": null,
"savedView": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"query": "text",
"shared": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Service
Mutation
createService
Adds a service: a kind of work with a daily rate, which time is booked on and which document lines are priced with.
Who may Admins only.
Arguments
archivedBooleanbillableBoolean- Whether time booked on this service is billed to the customer
dailyRateFloat- Net, in the workspace's currency
defaultTaxRateFloat- The VAT rate in percent a document line of this service starts with; null = the document's
descriptionStringserviceCategoryIdIDtitleString
Answer
Example
mutation CreateService($input: CreateServiceInput!) {
createService(input: $input) {
errors
service {
id
title
createdAt
archived
billable
dailyRate
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"serviceCategoryId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createService": {
"errors": null,
"service": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
}
}
Mutation
deleteService
Deletes a service. Fails for a service that time was booked on; set archived with updateService instead.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation DeleteService($input: DeleteServiceInput!) {
deleteService(input: $input) {
errors
service {
id
title
createdAt
archived
billable
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteService": {
"errors": null,
"service": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
}
}
Mutation
updateService
Changes a service. Send updateTimetrackings: true to reprice the time already booked on it with the new rate.
Who may Admins only.
Arguments
idID!requiredarchivedBooleanbillableBoolean- Whether time booked on this service is billed to the customer
dailyRateFloat- Net, in the workspace's currency
defaultTaxRateFloat- The VAT rate in percent a document line of this service starts with; null = the document's
descriptionStringserviceCategoryIdIDtitleStringupdateTimetrackingsBoolean- true: time already booked on this service is repriced with the new rate, in the background
Answer
Example
mutation UpdateService($input: UpdateServiceInput!) {
updateService(input: $input) {
errors
service {
id
title
createdAt
archived
billable
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateService": {
"errors": null,
"service": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
}
}
}
Service Category
Mutation
createServiceCategory
Adds a category that groups services.
Who may Admins only.
Arguments
titleString
Answer
errorsJsonserviceCategoryServiceCategory
Example
mutation CreateServiceCategory($input: CreateServiceCategoryInput!) {
createServiceCategory(input: $input) {
errors
serviceCategory {
id
title
createdAt
slug
updatedAt
}
}
}
Variables
{
"input": {
"title": "Website relaunch"
}
}
Response
{
"data": {
"createServiceCategory": {
"errors": null,
"serviceCategory": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
deleteServiceCategory
Deletes a service category. Fails while services or tickets still use it.
Who may Admins only.
Arguments
idID!required
Answer
errorsJsonserviceCategoryServiceCategory
Example
mutation DeleteServiceCategory($input: DeleteServiceCategoryInput!) {
deleteServiceCategory(input: $input) {
errors
serviceCategory {
id
title
createdAt
slug
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteServiceCategory": {
"errors": null,
"serviceCategory": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Mutation
updateServiceCategory
Renames a service category.
Who may Admins only.
Arguments
idID!requiredtitleString
Answer
errorsJsonserviceCategoryServiceCategory
Example
mutation UpdateServiceCategory($input: UpdateServiceCategoryInput!) {
updateServiceCategory(input: $input) {
errors
serviceCategory {
id
title
createdAt
slug
updatedAt
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateServiceCategory": {
"errors": null,
"serviceCategory": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Shared Project Report
Stopwatch
Mutation
createStopwatch
Creates a stopwatch for the caller, running unless start is false. At most 20 per person. Book one with createTimetracking(stopwatchId: …). Like every stopwatch mutation, it answers with the stopwatch and the caller's full list.
Who may Stopwatches are private: only their owner sees and uses them.
Arguments
startBoolean- Start it right away
ticketIdID- A ticket the caller can open; it can be set later
titleString- Default: Stopwatch 1, 2, …
Answer
Example
mutation CreateStopwatch($input: CreateStopwatchInput!) {
createStopwatch(input: $input) {
errors
stopwatch {
id
title
createdAt
roundedMinutes
running
seconds
}
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createStopwatch": {
"errors": null,
"stopwatch": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
},
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
}
Mutation
deleteStopwatch
Discards a stopwatch without booking its time.
Who may Only the stopwatch's owner.
Arguments
idID!required
Answer
Example
mutation DeleteStopwatch($input: DeleteStopwatchInput!) {
deleteStopwatch(input: $input) {
errors
stopwatch {
id
title
createdAt
roundedMinutes
running
seconds
}
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteStopwatch": {
"errors": null,
"stopwatch": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
},
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
}
Mutation
pauseStopwatch
Pauses a running stopwatch; the time counted so far stays.
Who may Only the stopwatch's owner.
Arguments
idID!required
Answer
Example
mutation PauseStopwatch($input: PauseStopwatchInput!) {
pauseStopwatch(input: $input) {
errors
stopwatch {
id
title
createdAt
roundedMinutes
running
seconds
}
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"pauseStopwatch": {
"errors": null,
"stopwatch": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
},
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
}
Mutation
startStopwatch
Starts a stopwatch or resumes a paused one; does nothing to one that is running.
Who may Only the stopwatch's owner.
Arguments
idID!required
Answer
Example
mutation StartStopwatch($input: StartStopwatchInput!) {
startStopwatch(input: $input) {
errors
stopwatch {
id
title
createdAt
roundedMinutes
running
seconds
}
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"startStopwatch": {
"errors": null,
"stopwatch": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
},
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
}
Mutation
updateStopwatch
Renames a stopwatch, attaches it to a ticket or detaches it, or sets its clock by hand.
Who may Only the stopwatch's owner.
Arguments
idID!requiredsecondsInt- Sets the clock, in seconds (at most 7 days). A running stopwatch keeps running from there
ticketIdID- null detaches the ticket
titleString
Answer
Example
mutation UpdateStopwatch($input: UpdateStopwatchInput!) {
updateStopwatch(input: $input) {
errors
stopwatch {
id
title
createdAt
roundedMinutes
running
seconds
}
stopwatches {
id
title
createdAt
roundedMinutes
running
seconds
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateStopwatch": {
"errors": null,
"stopwatch": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
},
"stopwatches": [
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
]
}
}
}
Supplier
Mutation
createSupplier
Adds a supplier, whose invoices are entered as external costs.
Who may Project managers and admins.
Arguments
archivedBooleandatevAccountString- The supplier's own account (creditor number) in DATEV; empty = the collective account
kskBoolean- Subject to the German artists' social insurance levy (KSK), which is then shown on each of their invoices
taxTreatmentSupplierTaxTreatmenttitleString
Answer
Example
mutation CreateSupplier($input: CreateSupplierInput!) {
createSupplier(input: $input) {
errors
supplier {
id
title
createdAt
archived
datevAccount
ksk
}
}
}
Variables
{
"input": {
"title": "Website relaunch"
}
}
Response
{
"data": {
"createSupplier": {
"errors": null,
"supplier": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
}
}
Mutation
deleteSupplier
Deletes a supplier. Fails while external costs of this supplier exist; set archived with updateSupplier instead.
Who may Admins only.
Arguments
idID!required
Answer
Example
mutation DeleteSupplier($input: DeleteSupplierInput!) {
deleteSupplier(input: $input) {
errors
supplier {
id
title
createdAt
archived
datevAccount
ksk
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteSupplier": {
"errors": null,
"supplier": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
}
}
Mutation
updateSupplier
Changes a supplier. Only the arguments sent are changed.
Who may Admins only.
Arguments
idID!requiredarchivedBooleandatevAccountString- The supplier's own account (creditor number) in DATEV; empty = the collective account
kskBoolean- Subject to the German artists' social insurance levy (KSK), which is then shown on each of their invoices
taxTreatmentSupplierTaxTreatmenttitleString
Answer
Example
mutation UpdateSupplier($input: UpdateSupplierInput!) {
updateSupplier(input: $input) {
errors
supplier {
id
title
createdAt
archived
datevAccount
ksk
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateSupplier": {
"errors": null,
"supplier": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
}
}
}
Ticket
Mutation
closeTicket
Closes a ticket and moves it to its project's Done column. The ticket's followers are notified by mail. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!required
Answer
Example
mutation CloseTicket($input: CloseTicketInput!) {
closeTicket(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"closeTicket": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
createTicket
Creates a ticket in a project. projectId, title and a description (body, or text as plain text) are required; the caller becomes the author. Assignees get a mail and follow the ticket, the project's followers are notified, and the ticket.created webhook fires.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
assigneeIds[ID!]- Users who can open the project. On update: the whole list, users left out are unassigned
authorIdIDboardIdID- The column of the project's kanban board. Default: Backlog for an open ticket, Done for a closed one
bodyJson- The ticket's description. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
budgetRateFloat- The budget in the unit of
budgetType: minutes, or an amount in the workspace's currency budgetTypeTicketBudget- Ignored, like
budgetRate, unless the caller sees financial data (project managers and admins) endDateISO8601DatelabelIds[ID!]- Labels of the ticket's project. On update: the whole list, labels left out are removed
numberInt- Ignored on create: a new ticket gets the next number in its project
phaseIdIDpriorityTicketPriorityprojectIdIDserviceCategoryIdIDstartDateISO8601DatestatusTicketStatus- Default: OPEN. A ticket created with
boardIdtakes that column's status instead textString- Plain text instead of
body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored whenbodyis sent titleString
Answer
Example
mutation CreateTicket($input: CreateTicketInput!) {
createTicket(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"title": "Website relaunch",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"boardId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createTicket": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
deleteTicket
Deletes a ticket together with its comments and the time booked on it. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!required
Answer
Example
mutation DeleteTicket($input: DeleteTicketInput!) {
deleteTicket(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteTicket": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
moveTicketInBoard
Puts a ticket into a column of its project's kanban board, at a position. A column with another ticket status closes or reopens the ticket, and its followers are notified by mail. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredtoBoardID!required- ID of the column (board) of the same project to put the ticket into
toPositionInt!required- The position in that column, counted from 1
Answer
Example
mutation MoveTicketInBoard($input: MoveTicketInBoardInput!) {
moveTicketInBoard(input: $input) {
board {
id
title
createdAt
position
preset
ticketStatus
}
errors
project {
id
number
pnr
title
status
createdAt
}
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toBoard": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toPosition": 42
}
}
Response
{
"data": {
"moveTicketInBoard": {
"board": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
},
"errors": null,
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
},
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
moveTicketInPhase
Puts a ticket into a phase of its project (or takes it out of its phase), at a position within the phase. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredtoPhaseID!required- ID of a phase of the same project, or
__NO__PHASE__for no phase toPositionInt!required- The position in that phase, counted from 1
Answer
Example
mutation MoveTicketInPhase($input: MoveTicketInPhaseInput!) {
moveTicketInPhase(input: $input) {
errors
phase {
id
title
createdAt
computedEndDate
computedStartDate
description
}
project {
id
number
pnr
title
status
createdAt
}
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toPhase": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"toPosition": 42
}
}
Response
{
"data": {
"moveTicketInPhase": {
"errors": null,
"phase": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
},
"project": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
},
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
openTicket
Reopens a closed ticket and moves it to its project's Backlog column. The ticket's followers are notified by mail. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!required
Answer
Example
mutation OpenTicket($input: OpenTicketInput!) {
openTicket(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"openTicket": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
toggleTicketSticky
Pins a ticket, or unpins a pinned one. Pinned (sticky) tickets are marked with a pin in the lists. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!required
Answer
Example
mutation ToggleTicketSticky($input: ToggleTicketStickyInput!) {
toggleTicketSticky(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"toggleTicketSticky": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
toggleTicketTodo
Ticks or unticks one checklist item in a ticket's description. Refused for a ticket mirrored from Jira: those are changed in Jira.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredtodoIdString!required- The
idattribute of the checklist item in the body's JSON
Answer
Example
mutation ToggleTicketTodo($input: ToggleTicketTodoInput!) {
toggleTicketTodo(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"todoId": "text"
}
}
Response
{
"data": {
"toggleTicketTodo": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Mutation
updateTicket
Changes a ticket; only the arguments sent are changed. Refused for a ticket mirrored from Jira: those are changed in Jira. A change of status notifies the ticket's followers by mail, a new assignee gets a mail. projectId moves the ticket into another project the caller can open; it then loses its phase and lands in that project's Backlog or Done.
Who may Anyone who can open the project (timetrackers: only the projects and customers they are assigned to).
Arguments
idID!requiredassigneeIds[ID!]- Users who can open the project. On update: the whole list, users left out are unassigned
authorIdIDboardIdID- The column of the project's kanban board. Default: Backlog for an open ticket, Done for a closed one
bodyJson- The ticket's description. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
budgetRateFloat- The budget in the unit of
budgetType: minutes, or an amount in the workspace's currency budgetTypeTicketBudget- Ignored, like
budgetRate, unless the caller sees financial data (project managers and admins) endDateISO8601DatelabelIds[ID!]- Labels of the ticket's project. On update: the whole list, labels left out are removed
numberInt- Ignored on create: a new ticket gets the next number in its project
phaseIdIDpriorityTicketPriorityprojectIdIDserviceCategoryIdIDstartDateISO8601DatestatusTicketStatus- Default: OPEN. A ticket created with
boardIdtakes that column's status instead textString- Plain text instead of
body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored whenbodyis sent titleString
Answer
Example
mutation UpdateTicket($input: UpdateTicketInput!) {
updateTicket(input: $input) {
errors
ticket {
id
number
title
status
createdAt
boardPosition
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateTicket": {
"errors": null,
"ticket": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
}
}
}
Ticket Assignment
Mutation
createTicketAssignment
Assigns a user to a ticket. The user starts following the ticket and gets a mail, unless they assign themselves. Refused for a ticket mirrored from Jira: its assignees come from Jira.
Who may Anyone who can open the ticket's project; the assigned user must be able to open it too.
Arguments
projectIdID- Ignored: the project is the ticket's
ticketIdIDuserIdID
Answer
errorsJsonticketAssignmentTicketAssignment
Example
mutation CreateTicketAssignment($input: CreateTicketAssignmentInput!) {
createTicketAssignment(input: $input) {
errors
ticketAssignment {
id
createdAt
updatedAt
}
}
}
Variables
{
"input": {
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createTicketAssignment": {
"errors": null,
"ticketAssignment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
}
}
}
Ticket Comment
Mutation
createTicketComment
Comments on a ticket. The ticket's followers and anyone mentioned are notified by mail. Refused for a ticket mirrored from Jira: it is discussed in Jira.
Who may Anyone who can open the ticket's project; the caller becomes the author and starts following the ticket.
Arguments
authorIdIDbodyJson- The comment's text. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
textString- Plain text instead of
body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored whenbodyis sent ticketIdID
Answer
errorsJsonticketCommentTicketComment
Example
mutation CreateTicketComment($input: CreateTicketCommentInput!) {
createTicketComment(input: $input) {
errors
ticketComment {
id
createdAt
body
bodyHtml
todosClosed
todosOpen
}
}
}
Variables
{
"input": {
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createTicketComment": {
"errors": null,
"ticketComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"todosClosed": 42,
"todosOpen": 42
}
}
}
}
Mutation
deleteTicketComment
Deletes a ticket comment.
Who may Only its author, while they can still open the ticket's project.
Arguments
idID!required
Answer
errorsJsonticketCommentTicketComment
Example
mutation DeleteTicketComment($input: DeleteTicketCommentInput!) {
deleteTicketComment(input: $input) {
errors
ticketComment {
id
createdAt
body
bodyHtml
todosClosed
todosOpen
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteTicketComment": {
"errors": null,
"ticketComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"todosClosed": 42,
"todosOpen": 42
}
}
}
}
Mutation
toggleTicketCommentTodo
Ticks or unticks one checklist item in a ticket comment.
Who may Anyone who can open the ticket's project, not only the comment's author.
Arguments
idID!requiredtodoIdString!required- The
idattribute of the checklist item in the body's JSON
Answer
errorsJsonticketCommentTicketComment
Example
mutation ToggleTicketCommentTodo($input: ToggleTicketCommentTodoInput!) {
toggleTicketCommentTodo(input: $input) {
errors
ticketComment {
id
createdAt
body
bodyHtml
todosClosed
todosOpen
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"todoId": "text"
}
}
Response
{
"data": {
"toggleTicketCommentTodo": {
"errors": null,
"ticketComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"todosClosed": 42,
"todosOpen": 42
}
}
}
}
Mutation
updateTicketComment
Changes the text of a ticket comment. Only body is used.
Who may Only its author, while they can still open the ticket's project.
Arguments
idID!requiredauthorIdIDbodyJson- The comment's text. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
textString- Plain text instead of
body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored whenbodyis sent ticketIdID
Answer
errorsJsonticketCommentTicketComment
Example
mutation UpdateTicketComment($input: UpdateTicketCommentInput!) {
updateTicketComment(input: $input) {
errors
ticketComment {
id
createdAt
body
bodyHtml
todosClosed
todosOpen
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateTicketComment": {
"errors": null,
"ticketComment": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"todosClosed": 42,
"todosOpen": 42
}
}
}
}
Timetracking
Mutation
bulkUpdateTimetracking
Makes the same change to several time entries at once: every argument sent is set on each of them.
Who may The caller must be allowed to change every one of them (their own entries, on projects they can open; admins any entry), or nothing is changed.
Arguments
ids[ID!]!requireddateISO8601DatedescriptionStringdurationFloat- In minutes, in steps of 15
projectIdIDserviceIdID- The kind of work; the entry is priced at the project's rate for it
ticketIdID- A ticket of the project in
projectId userIdID- Whose time it is. Default on create: the caller. Only admins may name someone else
Answer
errorsJsontimetrackingsTimetrackingConnection
Example
mutation BulkUpdateTimetracking($input: BulkUpdateTimetrackingInput!) {
bulkUpdateTimetracking(input: $input) {
errors
timetrackings {
totalCount
edges {
node {
id
date
duration
createdAt
billed
dailyRate
}
}
}
}
}
Variables
{
"input": {
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
}
Response
{
"data": {
"bulkUpdateTimetracking": {
"errors": null,
"timetrackings": {
"totalCount": 1,
"edges": [
{
"node": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
]
}
}
}
}
Mutation
copyTimetracking
Books a copy of a time entry: same project, ticket, service, person, description and duration, priced at the current rate.
Who may Everyone their own entries, on projects they can open; admins any entry.
Arguments
idID!requireddateISO8601Date- The day of the copy. Default: the day of the original
Answer
errorsJsontimetrackingTimetracking
Example
mutation CopyTimetracking($input: CopyTimetrackingInput!) {
copyTimetracking(input: $input) {
errors
timetracking {
id
date
duration
createdAt
billed
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"copyTimetracking": {
"errors": null,
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
}
Mutation
createTimetracking
Books time on a ticket. date, duration, projectId, ticketId and serviceId are required, and the ticket must belong to the project. The entry is priced at the project's rate for the service and the time_entry.created webhook fires; time on a ticket mirrored from Jira is sent to Jira as a worklog when the project's Jira link does that.
Who may Everyone books their own time, on projects they can open; admins may book for anyone (userId).
Arguments
dateISO8601DatedescriptionStringdurationFloat- In minutes, in steps of 15
projectIdIDserviceIdID- The kind of work; the entry is priced at the project's rate for it
stopwatchIdID- Books this stopwatch of yours: it is removed together with creating the entry
ticketIdID- A ticket of the project in
projectId userIdID- Whose time it is. Default on create: the caller. Only admins may name someone else
Answer
errorsJsontimetrackingTimetracking
Example
mutation CreateTimetracking($input: CreateTimetrackingInput!) {
createTimetracking(input: $input) {
errors
timetracking {
id
date
duration
createdAt
billed
dailyRate
}
}
}
Variables
{
"input": {
"serviceId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createTimetracking": {
"errors": null,
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
}
Mutation
deleteTimetracking
Deletes a time entry. A worklog that was sent to Jira for it is deleted there too.
Who may Everyone their own entries; admins any entry.
Arguments
idID!required
Answer
errorsJsontimetrackingTimetracking
Example
mutation DeleteTimetracking($input: DeleteTimetrackingInput!) {
deleteTimetracking(input: $input) {
errors
timetracking {
id
date
duration
createdAt
billed
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteTimetracking": {
"errors": null,
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
}
Mutation
moveTimetracking
Moves a time entry to another day.
Who may Everyone their own entries, on projects they can open; admins any entry.
Arguments
idID!requireddateISO8601Date- The day to move the entry to
Answer
errorsJsontimetrackingTimetracking
Example
mutation MoveTimetracking($input: MoveTimetrackingInput!) {
moveTimetracking(input: $input) {
errors
timetracking {
id
date
duration
createdAt
billed
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"moveTimetracking": {
"errors": null,
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
}
Mutation
suggestTimeEntries
Turns a note in free text ("2h checkout bug, 30 min call") into suggested time entries, read by AI; a note that asks what is not booked yet gets the tickets the caller worked in without booking time. Books nothing: book what fits with createTimetracking.
Who may Anyone; only tickets the caller can open are suggested. Only in a workspace whose admin switched AI for time entries on; each call counts against the monthly AI quota unless the workspace uses its own key.
Arguments
dateISO8601Date!required- The day the note is about, unless it names another
noteString!required
Answer
entries[TimeEntrySuggestion!]!errorsJsonheadingString- What the suggestions are, when it isn't obvious: the period of work found without booked time
noticeString- Why there are no suggestions, when there are none
Example
mutation SuggestTimeEntries($input: SuggestTimeEntriesInput!) {
suggestTimeEntries(input: $input) {
entries {
date
description
found
minutes
}
errors
heading
notice
}
}
Variables
{
"input": {
"note": "text",
"date": "2026-11-13"
}
}
Response
{
"data": {
"suggestTimeEntries": {
"entries": [
{
"date": "2026-11-13",
"description": "text",
"found": "text",
"minutes": 42
}
],
"errors": null,
"heading": "text",
"notice": "text"
}
}
}
Mutation
suggestTimeEntryDescription
Suggests a description for a time entry, written by AI from what the caller did in the ticket that day (their comments and changes). Saves nothing.
Who may Anyone who can open the ticket's project. Only in a workspace whose admin switched AI for time entries on; each call counts against the monthly AI quota unless the workspace uses its own key.
Arguments
dateISO8601Date!requiredticketIdID!required
Answer
descriptionStringerrorsJsonnoticeString- Why there is no suggestion, when there is none
Example
mutation SuggestTimeEntryDescription($input: SuggestTimeEntryDescriptionInput!) {
suggestTimeEntryDescription(input: $input) {
description
errors
notice
}
}
Variables
{
"input": {
"ticketId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13"
}
}
Response
{
"data": {
"suggestTimeEntryDescription": {
"description": "text",
"errors": null,
"notice": "text"
}
}
}
Mutation
updateTimetracking
Changes a time entry; only the arguments sent are changed. The entry keeps the rate it was booked at unless its project or service changes.
Who may Everyone their own entries, on projects they can open; admins any entry.
Arguments
idID!requireddateISO8601DatedescriptionStringdurationFloat- In minutes, in steps of 15
projectIdIDserviceIdID- The kind of work; the entry is priced at the project's rate for it
ticketIdID- A ticket of the project in
projectId userIdID- Whose time it is. Default on create: the caller. Only admins may name someone else
Answer
errorsJsontimetrackingTimetracking
Example
mutation UpdateTimetracking($input: UpdateTimetrackingInput!) {
updateTimetracking(input: $input) {
errors
timetracking {
id
date
duration
createdAt
billed
dailyRate
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateTimetracking": {
"errors": null,
"timetracking": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
}
}
}
User
Mutation
completeUserOnboarding
Marks the product tour as seen for the caller, so it is not shown again.
Who may Anyone, for themselves.
Answer
errorsJsononboardedBoolean!
Example
mutation CompleteUserOnboarding($input: CompleteUserOnboardingInput!) {
completeUserOnboarding(input: $input) {
errors
onboarded
}
}
Variables
{
"input": {}
}
Response
{
"data": {
"completeUserOnboarding": {
"errors": null,
"onboarded": true
}
}
}
Mutation
updatePinnedPages
Sets the caller's pinned pages. Always send the whole list: it replaces the current one.
Who may Anyone, for themselves.
Arguments
pages[PinnedPageInput!]!required
Answer
errorsJsonpinnedPages[PinnedPage!]
Example
mutation UpdatePinnedPages($input: UpdatePinnedPagesInput!) {
updatePinnedPages(input: $input) {
errors
pinnedPages {
title
path
}
}
}
Variables
{
"input": {
"pages": [
{
"title": "Website relaunch",
"path": "text"
}
]
}
}
Response
{
"data": {
"updatePinnedPages": {
"errors": null,
"pinnedPages": [
{
"title": "Website relaunch",
"path": "text"
}
]
}
}
}
User Work Time
Mutation
createUserWorkTime
Adds a working-hours profile for a user: the target hours per weekday from activeFrom on, until the user's next profile starts. A user has one profile per start date.
Who may Admins only.
Arguments
activeFromISO8601Date- The first day the profile applies; required, one profile per user and day
friFloat- Target working hours on Fridays
monFloat- Target working hours on Mondays
satFloat- Target working hours on Saturdays
sunFloat- Target working hours on Sundays
thuFloat- Target working hours on Thursdays
tueFloat- Target working hours on Tuesdays
userIdIDwedFloat- Target working hours on Wednesdays
Answer
errorsJsonuserWorkTimeUserWorkTime
Example
mutation CreateUserWorkTime($input: CreateUserWorkTimeInput!) {
createUserWorkTime(input: $input) {
errors
userWorkTime {
id
createdAt
activeFrom
fri
mon
sat
}
}
}
Variables
{
"input": {
"activeFrom": "2026-11-13",
"userId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"createUserWorkTime": {
"errors": null,
"userWorkTime": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"activeFrom": "2026-11-13",
"fri": 120.5,
"mon": 120.5,
"sat": 120.5
}
}
}
}
Mutation
deleteUserWorkTime
Removes a working-hours profile of a user.
Who may Admins only.
Arguments
idID!required
Answer
errorsJsonuserWorkTimeUserWorkTime
Example
mutation DeleteUserWorkTime($input: DeleteUserWorkTimeInput!) {
deleteUserWorkTime(input: $input) {
errors
userWorkTime {
id
createdAt
activeFrom
fri
mon
sat
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"deleteUserWorkTime": {
"errors": null,
"userWorkTime": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"activeFrom": "2026-11-13",
"fri": 120.5,
"mon": 120.5,
"sat": 120.5
}
}
}
}
Mutation
updateUserWorkTime
Changes a working-hours profile of a user.
Who may Admins only.
Arguments
idID!requiredactiveFromISO8601Date- The first day the profile applies; required, one profile per user and day
friFloat- Target working hours on Fridays
monFloat- Target working hours on Mondays
satFloat- Target working hours on Saturdays
sunFloat- Target working hours on Sundays
thuFloat- Target working hours on Thursdays
tueFloat- Target working hours on Tuesdays
userIdIDwedFloat- Target working hours on Wednesdays
Answer
errorsJsonuserWorkTimeUserWorkTime
Example
mutation UpdateUserWorkTime($input: UpdateUserWorkTimeInput!) {
updateUserWorkTime(input: $input) {
errors
userWorkTime {
id
createdAt
activeFrom
fri
mon
sat
}
}
}
Variables
{
"input": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
}
Response
{
"data": {
"updateUserWorkTime": {
"errors": null,
"userWorkTime": {
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"activeFrom": "2026-11-13",
"fri": 120.5,
"mon": 120.5,
"sat": 120.5
}
}
}
}
Objects
Account
AdminPMBasicTracker
Fields
accountingFontStringaccountingFooterManagingDirectorStringaccountingFooterOfficeStringaccountingHeaderStringaccountingTaxNumberStringaccountingVatIdStringadvancePaymentTitleDeStringadvancePaymentTitleEnStringaiApiKeyHintStringaiBaseUrlStringaiConnectionsEnabledBoolean!aiDocumentRulesStringaiDocumentsBoolean!aiModelStringaiProviderAiProvider!aiQuotaShareFloataiReceiptReadingBoolean!aiReceiptReadingAutomaticBoolean!aiTimeEntryBoolean!apiAccessEnabledBoolean!- Whether members may make personal API keys for the GraphQL API
bicStringcancellationInvoiceTitleDeStringcancellationInvoiceTitleEnStringcompanyCityStringcompanyNameStringcompanyPostalCodeStringcompanyStreetStringcountryString!countryAndCurrencyLockedBoolean!createdAtISO8601DateTime!currencyString!customCustomerNumberBoolean!- Whether customer numbers are typed on the address instead of given by docket
customInvoiceNumberBoolean!customerNumberStartInt!- Where docket's customer numbers start
customerNumberStepInt!- How far apart docket's customer numbers are
datevAccountKeys[String!]!- The cases an account can be set for: domestic_<rate> per VAT rate, the other tax treatments, expense, expense_reverse_charge_eu, expense_reverse_charge_third_country, debtors, creditors
datevAccountsJSON- The account per case, by the keys of datevAccountKeys
datevAvailableBoolean!- Whether the workspace can have the DATEV booking batch (a German one)
datevBookingsBooleandatevClientNumberIntdatevConsultantNumberIntdatevFiscalYearStartInt- The month the fiscal year starts in
datevStandardAccountsJSON!- What the form starts with, per chart (skr03, skr04)
defaultTaxRateFloat!documentFontConfirmedAtISO8601DateTimedocumentFontFiles[DocumentFontFile!]!domainString!finalInvoiceTitleDeStringfinalInvoiceTitleEnStringibanStringidID!invoiceContactEmailStringinvoiceContactNameStringinvoiceContactPhoneStringinvoiceFooterDeStringinvoiceFooterEnStringinvoiceNumberPrefixStringinvoiceTitleDeStringinvoiceTitleEnStringlatestExportWorkspaceExport- The most recent full workspace export (admins only)
letterheadLinesStringlocaleLocalelogoStringlogoSizeIntnameString!nextCustomerNumberInt!- The number docket gives the next customer address (Account#next_customer_number)
onboardingCompletedBoolean!partialInvoiceTitleDeStringpartialInvoiceTitleEnStringpaymentTermDaysInt!- Days from the invoice date to the due date, unless the customer has its own term
quotationFooterDeStringquotationFooterEnStringrequireTwoFactorBoolean!smallBusinessBoolean!- Whether the workspace is a small business today
taxRates[Float!]!updatedAtISO8601DateTime!vatStatuses[VatStatus!]!- The VAT status history, oldest first
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingFont": "text",
"accountingFooterManagingDirector": "text",
"accountingFooterOffice": "text"
}
AccountantAccess
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!emailString!- The address the sign-in links go to
idID!invitedByUser- The member who gave the access; null once they are gone
lastSignedInAtISO8601DateTime- Null until the tax office first signs in
nameString- The tax office's name, if one was given
revokedAtISO8601DateTime- Null while the access is good
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"lastSignedInAt": "2026-11-13T09:30:00+01:00",
"revokedAt": "2026-11-13T09:30:00+01:00"
}
Accounting
AdminPMBasicTracker
A billing cycle of a project: a quotation with its order confirmation, delivery notes and invoices, or an invoice on its own. Only project managers and admins can read it.
Fields
accountIdID!accountingCustomFieldsAccountingCustomFieldConnection!createdAtISO8601DateTime!customFields[AccountingCustomFieldValue!]!- The values of the workspace's custom fields for this cycle
idID!invoicesInvoiceConnection!invoicesTypesThatCanBeCreated[InvoiceTypeEnum!]- The invoice types the cycle still takes: advance payments or partial invoices (never both), then one final invoice, after which none. Canceled invoices do not count.
quotationQuotation- The cycle's quotation; null for an invoice on its own
serviceRates[ServiceRate!]!- Every service with the daily rate this cycle's documents are priced with, as the rates stood when the cycle last took them over
serviceRatesUpdatableBoolean!- Whether a rate of a service, the customer or the project changed since, so the cycle could take over the new rates
updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"invoicesTypesThatCanBeCreated": [
"ADVANCE_PAYMENT"
],
"serviceRatesUpdatable": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
AccountingCustomField
AdminPMBasicTracker
Fields
accountingAccounting!createdAtISO8601DateTime!customFieldCustomField!customFieldValueStringidID!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"customFieldValue": "text",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
AccountingCustomFieldValue
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!idID!nameString!typeString!updatedAtISO8601DateTime!valueString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"type": "text",
"updatedAt": "2026-11-13T09:30:00+01:00",
"value": "text"
}
AccountingCycle
AdminPMBasicTracker
Where a billing cycle's money stands: the quotation total and how much of it the issued invoices made paid, open or overdue. Net amounts in the workspace's currency. Cycles of which nothing has gone out yet are not listed.
Fields
invoiceCountInt!- Issued invoices (published or paid); cancellation invoices are not counted
openFloat!- What published invoices that are not overdue ask for
overdueFloat!- What published invoices past their due date ask for
overdueDaysInt- How many days the longest-overdue invoice is past its due date; null when none is overdue
paidFloat!- What the paid invoices asked for
quotationNumberString- The quotation's number as printed (Quotation.qnr); null for a cycle without a quotation
quotationStatusQuotationStatus- PUBLISHED (sent, not confirmed yet), CONFIRMED, or CANCELED while invoices still stand; null for a cycle without a quotation
totalFloat!- The quotation's net total; without a standing quotation, what the issued invoices ask for
Example
{
"invoiceCount": 42,
"open": 120.5,
"overdue": 120.5,
"overdueDays": 42,
"paid": 120.5,
"quotationNumber": "text"
}
ApiToken
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!expiresAtISO8601DateTime- From when the key is refused; null: it never expires
idID!lastFourString!- The key's last four characters, to tell keys apart
lastUsedAtISO8601DateTimenameString!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"expiresAt": "2026-11-13T09:30:00+01:00",
"lastFour": "text",
"lastUsedAt": "2026-11-13T09:30:00+01:00"
}
Attachment
AdminPMBasicTracker
Fields
blobIdID!byteSizeInt!contentTypeString!createdAtISO8601DateTime!downloadUrlString!- The file's path on the workspace. Fetch it signed in, or with the API key in the Authorization header
filenameString!idID!previewImageStringupdatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"blobId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"byteSize": 42,
"contentType": "text",
"downloadUrl": "text"
}
AvgTimetrackingPerDay
AdminPMBasicTracker
Fields
fromISO8601Date!nodes[AvgTimetrackingPerDayNode!]!toISO8601Date!
Example
{
"from": "2026-11-13",
"to": "2026-11-13"
}
Example
{
"date": "2026-11-13",
"duration": 120.5
}
BilledBefore
AdminPMBasicTracker
Fields
invoiceIdID!netFloat!
Example
{
"invoiceId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"net": 120.5
}
Block
AdminPMBasicTracker
Fields
deletedBooleandescriptionStringfooterStringidID!modifiedBooleannewBooleanoptionalBoolean!positions[BlockPosition!]!titleStringtotalFloat!typeBlockTypeEnum!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"deleted": true,
"description": "text",
"footer": "text",
"modified": true
}
BlockPosition
AdminPMBasicTracker
Fields
alreadySelectedBooleandeletedBooleandescriptionStringfooterStringidID!modifiedBooleannewBooleanoptionalBoolean!selectedBooleansubpositions[BlockPositionSubposition!]!titleString!totalFloat!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"alreadySelected": true,
"deleted": true,
"description": "text",
"footer": "text"
}
BlockPositionSubposition
AdminPMBasicTracker
Fields
amountFloatbilledQuantityFloatdailyRateFloatdeletedBooleandescriptionStringexistsBooleanidID!modifiedBooleannameStringnewBooleanoptionalBoolean!quantityFloatrateFloatserviceIdStringtaxRateFloat- This line's VAT rate in percent (the document's unless set on the line)
titleStringtotalFloat!unitStringunitLabelString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"name": "Website relaunch",
"amount": 120.5,
"billedQuantity": 120.5,
"dailyRate": 120.5
}
Board
AdminPMBasicTracker
A column of a project's kanban board. Every project starts with a backlog and a done column.
Fields
createdAtISO8601DateTime!idID!positionInt!- Rank among the project's columns, for ordering (not consecutive)
presetBoardPreset!- BACKLOG and DONE are the two columns every project has, where tickets land by their status; they cannot be deleted. CUSTOM is any other.
projectProject!ticketStatusTicketStatus!- The ticket status this column stands for
ticketsTicketConnection!titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"position": 42,
"preset": "backlog",
"ticketStatus": "OPEN"
}
BookkeepingExport
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!exportedByString- Who made it: the member's name, or the tax office's name (else its e-mail address) for an export from its portal. Null once they are gone
externalCostsCountInt!idID!invoicesCountInt!periodFromISO8601Date!periodToISO8601Date!userNameString- The member who made it in the app; null for the tax office's own exports
withBookingsBoolean!- Whether the ZIP held the DATEV booking batch
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"exportedBy": "text",
"externalCostsCount": 42,
"invoicesCount": 42,
"periodFrom": "2026-11-13"
}
BookkeepingPeriod
AdminPMBasicTracker
Fields
exportedBeforeCountInt!- How many of these documents an earlier export already held
exports[BookkeepingExport!]!- The latest exports, newest first
externalCostsCountInt!- External costs of the period that are ok or processed
invoicesCountInt!- Invoices issued in the period, cancellations included
withBookingsBoolean!- Whether the ZIP will hold the DATEV booking batch (the workspace has set its accounts)
Example
{
"exportedBeforeCount": 42,
"externalCostsCount": 42,
"invoicesCount": 42,
"withBookings": true
}
ConnectedAiApp
AdminPMBasicTracker
Fields
connectedAtISO8601DateTime!idID!lastUsedAtISO8601DateTimenameString!scopes[String!]!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"connectedAt": "2026-11-13T09:30:00+01:00",
"lastUsedAt": "2026-11-13T09:30:00+01:00",
"scopes": [
"text"
]
}
Contact
AdminPMBasicTracker
A person at a customer, who quotations, invoices and the other documents can be addressed to. Lists return the contacts of customers the caller can see.
Fields
archivedBoolean!createdAtISO8601DateTime!customersCustomerConnection!- The customers this person is a contact of
departmentStringemailString!firstnameString!idID!lastnameString!phoneStringsalutationString!titleString- Academic or professional title, e.g. Dr.
updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00"
}
Country
AdminPMBasicTracker
Fields
codeString!nameString!
Example
{
"name": "Website relaunch",
"code": "text"
}
CustomField
AdminPMBasicTracker
Fields
archivedBoolean!createdAtISO8601DateTime!customerCustomer!defaultValueStringfieldTypeString!idID!nameString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"defaultValue": "text",
"fieldType": "text"
}
Customer
AdminPMBasicTracker
A customer of the agency: the company projects are run for and documents are written to. Admins, project managers and basic users read every customer; a timetracker only those they are assigned to, directly or through a project.
Fields
accountingCommissionPercentFloat- Agency commission in percent, charged on the external services a document bills; null = none.
- Who sees Null unless you may see financial data (project managers and admins).
accountingCommissionThresholdFloat- The agency commission applies once a document's external services reach this net amount (workspace currency).
- Who sees Null unless you may see financial data (project managers and admins).
addressesCustomerAddressConnection!archivedBoolean!companyString!- The customer's name
contactsContactConnection!createdAtISO8601DateTime!customFieldsCustomFieldConnection!datevAccountString- The customer's own account (debtor number) in the tax office's DATEV; null = the collective account
descriptionStringemailStringidID!initialString!- Short code, unique in the workspace; it starts the numbers of the customer's projects (Project.pnr)
invoiceFooterDeString- Footer text for this customer's invoices in German
invoiceFooterEnString- Footer text for this customer's invoices in English
masterAgreementBoolean- Whether there is a master agreement with the customer; advance-payment invoices then name it.
- Who sees Null unless you may see financial data (project managers and admins).
paymentTermDaysInt- This customer's payment term in days; null = the workspace's
phoneStringprojectsProjectConnection!quotationFooterDeString- Footer text for this customer's quotations in German
quotationFooterEnString- Footer text for this customer's quotations in English
serviceRates[ServiceRate!]- Every service with the daily rate that applies to this customer (the customer's own, else the service's).
- Who sees Null unless you may see financial data (project managers and admins).
slugString!updatedAtISO8601DateTime!webString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"company": "Alpine Coffee Roasters GmbH",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"accountingCommissionPercent": 120.5,
"accountingCommissionThreshold": 120.5
}
CustomerAddress
AdminPMBasicTracker
One of a customer's addresses, with what a document sent to it needs: the customer number, the VAT ID and how the customer is taxed. Lists return the addresses of customers the caller can see.
Fields
address1Stringaddress2StringbuyerReferenceString- The e-invoice's buyer reference (BT-10) for this address, e.g. a Leitweg-ID; none: the invoice's PO number, else the customer number
cityStringcountryString- What was typed as the country before the list, where it names none docket knows
countryCodeString- ISO 3166-1 alpha-2; none for a customer in the workspace's own country
countryNameString- The country as the app shows it (English)
createdAtISO8601DateTime!deletionRefusalString- Why this address can't be deleted, or null when it can
departmentStringdocumentsCountInt!- Quotations, order confirmations, delivery notes and invoices written to this address
idID!invoiceEmailString- Where this customer receives e-invoices (BT-49); none: the customer's e-mail
numberInt!- The customer number, unique in the workspace
recipientStringtaxTreatmentTaxTreatment!- How documents to this address are taxed
updatedAtISO8601DateTime!vatEnabledBoolean!- Whether VAT is charged (tax treatment is domestic)
vatNoString- The customer's VAT identification number; needed for reverse charge
zipString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"createdAt": "2026-11-13T09:30:00+01:00",
"address1": "text",
"address2": "text",
"buyerReference": "text"
}
DeliveryNote
AdminPMBasicTracker
A delivery note, created from the order confirmation with its content. Optional, as many per billing cycle as there are deliveries. Only project managers and admins can read it.
Fields
accountingAccounting!- The billing cycle it belongs to
authorUser!- Who created it
commentsDeliveryNoteCommentConnection!contactCustomersContactConnection!- The customer's contacts the document is addressed to
contactInternalsUserConnection!- The agency's contact persons named on the document
createdAtISO8601DateTime!customerCustomer!- The customer of the document's project
customerAddressCustomerAddress- The customer address it is written to; needed before it can go out
dateISO8601DatedeletedBoolean!- Soft-delete flag; deleted documents are not listed
descriptionString- Introductory text (HTML)
filenameString!- File name of its PDF
footerString- Footer text (HTML)
idID!languageString- Language of the document and its PDF: de or en
nameString- Free name beside the number; the project's title unless given
noString!- The number as printed: project number, a dot and the two-digit number
notificationRecipients[User!]!numberInt!- Running number within the project
projectProject!showPositionSubtotalBoolean!- Whether the PDF shows a subtotal under each position
statusDeliveryNoteStatus!streamDeliveryNoteStreamConnection!- Its comments and events (status changes, edits), oldest first
summarySummary!- The document's computed totals: net, discounts and surcharges, VAT, gross
taxNoteString- Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRateFloat!- The VAT rate in percent its lines use unless a line has its own
taxTreatmentTaxTreatment!- How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
titleString!- no followed by the name
updatedAtISO8601DateTime!viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
DeliveryNoteComment
AdminPMBasicTracker
Fields
authorUser!bodyJson!bodyHtmlString!byAiBoolean!- Written by docket when the AI added positions (shown as docket's); the author applied them
createdAtISO8601DateTime!deliveryNoteDeliveryNote!idID!reactions[Reaction!]!- Its reactions by emoji, in the order they were first given
updatedAtISO8601DateTime!viewerCanEditBoolean!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
DiscountSurcharge
AdminPMBasicTracker
Fields
amountFloat!titleString!
Example
{
"title": "Website relaunch",
"amount": 120.5,
"type": "discount"
}
DocumentAssistantMapping
AdminPMBasicTracker
A value of the file and the service the AI suggests billing it as, for the person to change
Fields
serviceString- The service's title; null when none fits
valueString!
Example
{
"service": "text",
"value": "text"
}
DocumentAssistantQuestion
AdminPMBasicTracker
A question the AI asks back, with answers to pick from
Fields
mapping[DocumentAssistantMapping!]!- A file's values with the suggested service each, to change
multipleBoolean!- Several answers may be picked
options[String!]!questionString!
Example
{
"multiple": true,
"options": [
"text"
],
"question": "text"
}
DocumentAssistantSkipped
AdminPMBasicTracker
Rows of the file that didn't count
Fields
noQuantityInt!- Without hours or days to read
noServiceInt!- Without a service to bill
Example
{
"noQuantity": 42,
"noService": 42
}
Example
{
"filename": "text",
"style": "REGULAR"
}
DocumentPlanLine
AdminPMBasicTracker
A service line of the plan, priced from the project's rates
Fields
descriptionString!quantityFloat!serviceString!- The service's title
totalFloat- What the line comes to; null for a service the document's rates lack
unitString!- hours or days
Example
{
"description": "text",
"quantity": 120.5,
"service": "text",
"total": 120.5,
"unit": "text"
}
Example
{
"title": "Website relaunch"
}
Example
{
"title": "Website relaunch"
}
DocumentPlanPreview
AdminPMBasicTracker
What a plan adds to a document and what it comes to, net
Fields
netFloat!phases[DocumentPlanPhase!]!positions[DocumentPlanPosition!]!
Example
{
"net": 120.5
}
DocumentTemplate
AdminPMBasicTracker
Fields
authorUserblockTitles[String!]!- Its phase or block titles, for a preview
createdAtISO8601DateTime!customerCustomer- The one customer it's offered for; null: every customer
idID!kindString!- quotation or invoice: the documents it's for
missingServiceCountInt!- Services in it the workspace no longer has: their lines would be priced at nothing
nameString!noteString- What the template is for
structureString!- phases or agency (agency and external services)
updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"blockTitles": [
"text"
],
"kind": "text",
"missingServiceCount": 42
}
ExchangeRate
AdminPMBasicTracker
Fields
onISO8601Date!- The day the rate is from: the date asked for, or the last working day before it
rateFloat!
Example
{
"on": "2026-11-13",
"rate": 120.5
}
ExternalCost
AdminPMBasicTracker
An external cost: a supplier's invoice for something bought for a project, assigned to projects and quotations so it counts in their budget and controlling. Only project managers and admins can read it.
Fields
amountFloat!- Net amount in the workspace's currency
assignments[ExternalCostAssignment!]!- The projects and quotations it is assigned to, each with its amount and whether it is passed on to the customer
assignmentsDifferenceFloat!- With partial amounts: the net amount not assigned yet; otherwise 0
createdAtISO8601DateTime!currencyCurrency!- The currency of the supplier's invoice
exchangeRateFloat- Units of the currency per euro (ECB)
exchangeRateOnISO8601Date- The day the exchange rate is from
idID!inputTaxDeductibleBoolean!- false when the workspace could not reclaim the VAT (a small business): the cost then counts with its VAT
invoiceAttachment!- The invoice file (PDF)
invoiceDateISO8601Date!invoiceNumberString!- The supplier's invoice number; unique per supplier and VAT rate
kskFloat!- The KSK levy (German artists' social insurance) on the net amount at the invoice year's rate; 0 unless the supplier is subject to it
originalAmountFloat- Net amount in the invoice's currency, for an invoice in another currency than the workspace's
partialAmountBoolean!- Whether the invoice is split: each assignment takes a part of the amount. Otherwise it has one assignment for all of it.
partialBillBoolean!- Marks an invoice that is one of several from the supplier for the same job
projectsProjectConnection!- The projects it is assigned to
quotationsQuotationConnection!- The quotations it is assigned to
relatedCosts[ExternalCost!]!- The supplier's other invoices for the same job, linked to this one; oldest first
relatedTotalFloat!- What the linked invoices come to, this one included (net, in the workspace's currency)
statusExternalCostStatus!statusChangedAtISO8601DateTime!- When the status last changed
supplierSupplier!taxFloat!- The VAT amount, as the supplier's invoice states it
taxRateFloat!- The VAT rate in percent, e.g. 19.0
updatedAtISO8601DateTime!userUser- The person responsible for it, if one is set
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "DRAFT",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"assignmentsDifference": 120.5,
"currency": "EUR"
}
ExternalCostAssignment
AdminPMBasicTracker
Fields
amountFloatboundsExtended[ExternalCostAssignmentExtended!]boundsHeightFloatboundsLeftFloatboundsTopFloatboundsWidthFloatchargeableBoolean!createdAtISO8601DateTime!idID!pageIntprojectProject!quotationQuotation!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"amount": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"boundsHeight": 120.5,
"boundsLeft": 120.5,
"boundsTop": 120.5
}
ExternalCostAssignmentExtended
AdminPMBasicTracker
Fields
boundsHeightFloat!boundsLeftFloat!boundsTopFloat!boundsWidthFloat!pageInt!
Example
{
"boundsHeight": 120.5,
"boundsLeft": 120.5,
"boundsTop": 120.5,
"boundsWidth": 120.5,
"page": 42
}
ExternalCostFigures
AdminPMBasicTracker
Fields
convertedAmountFloat- The net amount at that rate, in the workspace's currency
exchangeRateExchangeRate- The ECB rate of the invoice date, for an invoice in another currency
inputTaxDeductibleBoolean!- Whether the VAT comes back as input tax: not while the workspace was a small business
taxAtRateFloat- The net amount given (or the converted one) at the VAT rate
Example
{
"convertedAmount": 120.5,
"inputTaxDeductible": true,
"taxAtRate": 120.5
}
ExternalCostsCheck
AdminPMBasicTracker
Fields
bookedFloat!- Supplier invoices assigned to the quote, passed on or not, net, drafts left out
notChargedFloat!- The part of booked that isn't passed on to the customer
overBoolean!- Booked above quoted
percentFloat- Booked as a percentage of quoted; null when nothing was quoted
quotedFloat!- The external services the confirmed quote sold
Example
{
"booked": 120.5,
"notCharged": 120.5,
"over": true,
"percent": 120.5,
"quoted": 120.5
}
FinancialSummary
AdminPMBasicTracker
Fields
awaitingOrderConfirmation[Quotation!]!awaitingOrderConfirmationCountInt!- The year's confirmed quotations whose order confirmation isn't published yet
awaitingOrderConfirmationTotalFloat!carriedOverCountInt!- Unpaid invoices from earlier years
carriedOverInvoices[Invoice!]!carriedOverTotalFloat!externalCostsOverruns[ExternalCostsOverrun!]!- The running jobs (confirmed quotations without an issued final invoice, any year) whose booked external costs are over what they sold, the furthest over first
monthlyRevenue[MonthlyRevenue!]!openInvoicesCountInt!openInvoicesTotalFloat!orderConfirmationsCountInt!orderConfirmationsTotalFloat!overdueCountInt!overdueInvoices[Invoice!]!overdueTotalFloat!paidCountInt!paidTotalFloat!pipelineCountInt!pipelineTotalFloat!quotationStatusBreakdown[StatusBreakdown!]!years[Int!]!- The years that have a quotation or an invoice, newest first — empty while the workspace has no document
Example
{
"awaitingOrderConfirmationCount": 42,
"awaitingOrderConfirmationTotal": 120.5,
"carriedOverCount": 42,
"carriedOverTotal": 120.5,
"openInvoicesCount": 42,
"openInvoicesTotal": 120.5
}
ForecastMonth
AdminPMBasicTracker
Fields
expectedFloat!monthInt!paidFloat!
Example
{
"expected": 120.5,
"month": 42,
"paid": 120.5
}
ForecastReport
AdminPMBasicTracker
Fields
invoiceCountInt!months[ForecastMonth!]!quotationCountInt!rows[ForecastRow!]!totalsForecastTotals!yearInt!years[Int!]!- The years that have a quotation or an invoice, newest first — empty while the workspace has no document
Example
{
"invoiceCount": 42,
"quotationCount": 42,
"year": 42,
"years": [
42
]
}
ForecastRow
AdminPMBasicTracker
Fields
allocationMonthIntbookedExternalCostsFloatdeltaToQuotationFloat!externalCostsFloat!externalCostsOverBooleanidID!invoiceDateISO8601DateinvoiceNumberStringinvoicePaidDateISO8601DateTimeinvoiceStatusStringinvoiceTotalFloat!isPaidBoolean!kvNumberStringmonthlyAmountFloat!poNumberStringprojectManagerStringprojectSlugString!projectTitleStringquotationBudgetFloat!quotationDateISO8601DatequotationNumberIntquotationStatusString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"allocationMonth": 42,
"bookedExternalCosts": 120.5,
"deltaToQuotation": 120.5,
"externalCosts": 120.5,
"externalCostsOver": true
}
ForecastTotals
AdminPMBasicTracker
Fields
bookedExternalCostsFloat!- The confirmed quotations' booked external costs
deltaToQuotationFloat!externalCostsFloat!invoiceTotalFloat!quotationBudgetFloat!- Net total of the confirmed quotations
Example
{
"bookedExternalCosts": 120.5,
"deltaToQuotation": 120.5,
"externalCosts": 120.5,
"invoiceTotal": 120.5,
"quotationBudget": 120.5
}
Invoice
AdminPMBasicTracker
An invoice. A draft has no number; publishing (admins only) gives it its number and makes it final. Only project managers and admins can read it.
Fields
accountingAccounting!- The billing cycle it belongs to
authorUser!- Who created it
canceledNoteString- The note given when it was canceled
commentsInvoiceCommentConnection!contactCustomersContactConnection!- The customer's contacts the document is addressed to
contactInternalsUserConnection!- The agency's contact persons named on the document
corrections[InvoiceCorrection!]!- Each time it was reopened for correction before it went out, oldest first
createdAtISO8601DateTime!customerCustomer!- The customer of the document's project
customerAddressCustomerAddress- The customer address it is written to; needed before it can go out
dateISO8601Date- The invoice date
daysOverdueInt- Days past the due date of a published, unpaid invoice; null otherwise
deletedBoolean!- Soft-delete flag; deleted documents are not listed
deliveryDateISO8601Date- The date of delivery or performance printed on the invoice
descriptionString- Introductory text (HTML)
documentTemplateDocumentTemplate- The template it was started from, if any
dueDateISO8601Date- The invoice date plus the payment term (the customer's, else the workspace's), fixed when it is published; null for a cancellation invoice
dueNetFloat!- What the invoice asks the customer for, net: a final invoice's total minus what was invoiced before, any other invoice's total
eInvoiceAvailableBoolean!- Whether the e-invoice (XRechnung XML) archived at publish can be downloaded, at /api/invoices/xml/:id
externalServiceTotalFloat- Net total of its external-service lines, in the workspace's currency
filenameString!- File name of its PDF
footerString- Footer text (HTML)
idID!inCorrectionBoolean!- Reopened for correction and not published again yet — a draft that keeps its number
inrString!- The invoice number as printed: project number, a dot, the workspace's number prefix if any, and the number (a placeholder while a draft)
inrWithNameString!- inr followed by the name
invoiceTypeInvoiceTypeEnum- Advance payment, partial, final or cancellation invoice
languageString- Language of the document and its PDF: de or en
nameString- Free name beside the number; the project's title unless given
notificationRecipients[User!]!numberInt- Assigned when it is published; null for a draft
orderConfirmationOrderConfirmation- The cycle's order confirmation, if its quotation was confirmed
originalInvoiceInvoice- For a cancellation invoice: the invoice it reverses
paidBoolean!- Whether its status is PAID
paidAtISO8601DateTime- When it was marked as paid
paidByUser- Who marked it as paid
partialInvoices[Invoice!]- For a final invoice and its cancellation: the cycle's earlier invoices it deducts, oldest first. Null for the other types.
projectProject!quotationQuotation- The quotation of its billing cycle; null for an invoice without one
retainerMonthISO8601Date- The month of a retainer this invoice bills (its first day); null for any other invoice
selectsPositionsBoolean!- Whether someone picks the positions it bills: a partial invoice, and a job's final invoice; one on its own bills all
showPositionSubtotalBoolean!- Whether the PDF shows a subtotal under each position
statusInvoiceStatus!streamInvoiceStreamConnection!- Its comments and events (status changes, edits), oldest first
summarySummary!- The document's computed totals: net, discounts and surcharges, VAT, gross
taxNoteString- Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRateFloat!- The VAT rate in percent its lines use unless a line has its own
taxTreatmentTaxTreatment!- How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
templateCanFillBoolean!- Whether a document template can still fill it, which needs an empty draft
titleString!- What the app calls it, in the caller's language: its kind, its number and the quotation or invoice it refers to
totalNetFloat- Net total in the workspace's currency; for a final invoice the whole job, before what was invoiced earlier is deducted
updatedAtISO8601DateTime!viewerCanCorrectBoolean!- Whether the caller may correct it, which cancels it and opens a copy as a new draft: project managers and admins, for an invoice that can be canceled
viewerCanReopenForCorrectionBoolean!- Whether the caller may take the published invoice back to draft with its number: admins, while it is neither paid, canceled nor settled by a final invoice
viewerCanReturnToDraftBoolean!- Whether the caller may take it back to draft: an invoice without a number that is not a draft
viewerCanReversePaymentBoolean!- Whether the caller may make a paid invoice unpaid again: admins
viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"inr": "20017",
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT"
}
InvoiceComment
AdminPMBasicTracker
Fields
authorUser!bodyJson!bodyHtmlString!byAiBoolean!- Written by docket when the AI added positions (shown as docket's); the author applied them
createdAtISO8601DateTime!idID!invoiceInvoice!reactions[Reaction!]!- Its reactions by emoji, in the order they were first given
updatedAtISO8601DateTime!viewerCanEditBoolean!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
InvoiceCorrection
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!- When it was reopened
idID!previousDateISO8601Date- The invoice date before the correction
reasonString!republishedAtISO8601DateTime- When it was published again; null while it is being corrected
supersededPdfUrlString- The PDF as it was archived before the correction
userUser!- Who reopened it and confirmed the customer hadn't received it
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"previousDate": "2026-11-13",
"reason": "text",
"republishedAt": "2026-11-13T09:30:00+01:00",
"supersededPdfUrl": "text"
}
JiraEpicRef
AdminPMBasicTracker
Fields
idString!keyString!statusStringsummaryString
Example
{
"id": "text",
"status": "text",
"key": "text",
"summary": "text"
}
JiraMirrorConflict
AdminPMBasicTracker
Fields
bookedMinutesFloat!projectProject!ticketCountInt!
Example
{
"bookedMinutes": 120.5,
"ticketCount": 42
}
JiraProjectLink
AdminPMBasicTracker
Fields
convertWorklogsBoolean!createdAtISO8601DateTime!defaultServiceServiceidID!importForeignWorklogsBoolean!jiraConnectionJiraSite!jiraProjectIdString!jiraProjectKeyString!lastErrorStringlastSyncedAtISO8601DateTimemirrorConflicts[JiraMirrorConflict!]!mirroredBookedMinutesInt!mirroredTimetrackingCountInt!mirroredWorklogCountInt!projectProject!pushWorklogsBoolean!scopeEpics[JiraEpicRef!]!scopeKindJiraScopeKind!syncStateJiraLinkSyncState!ticketsModeJiraTicketsMode!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"convertWorklogs": true,
"importForeignWorklogs": true,
"jiraProjectId": "text",
"jiraProjectKey": "text"
}
JiraProjectRef
AdminPMBasicTracker
Fields
jiraProjectIdString!keyString!nameString!
Example
{
"name": "Website relaunch",
"jiraProjectId": "text",
"key": "text"
}
JiraSite
AdminPMBasicTracker
Fields
authKindString!cloudIdStringcreatePlaceholderUsersBoolean!createdAtISO8601DateTime!hasTempoTokenBoolean!idID!lastCheckedAtISO8601DateTimelastErrorStringlinkedProjectsCountInt!nameString!placeholderServiceServiceprojectLinks[JiraProjectLink!]siteUrlString!statusJiraConnectionStatus!updatedAtISO8601DateTime!userMappings[JiraUserMapping!]worklogBackendJiraWorklogBackend!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"status": "ACTIVE",
"createdAt": "2026-11-13T09:30:00+01:00",
"authKind": "text",
"cloudId": "text"
}
JiraSiteSummary
AdminPMBasicTracker
Fields
idID!nameString!siteUrlString!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"siteUrl": "text"
}
JiraUserCredential
AdminPMBasicTracker
Fields
authKindString!createdAtISO8601DateTime!displayNameStringemailStringidID!jiraConnectionJiraSiteSummarytokenCheckedAtISO8601DateTimetokenErrorStringtokenStatusJiraTokenStatus!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"authKind": "text",
"displayName": "text",
"tokenCheckedAt": "2026-11-13T09:30:00+01:00"
}
JiraUserMapping
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!displayNameStringidID!jiraAccountIdString!jiraConnectionJiraSite!pendingWorklogCountInt!updatedAtISO8601DateTime!userUser!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"displayName": "text",
"jiraAccountId": "text",
"pendingWorklogCount": 42,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
JiraUserRef
AdminPMBasicTracker
Fields
accountIdString!avatarUrlStringdisplayNameString!emailAddressString
Example
{
"accountId": "text",
"avatarUrl": "text",
"displayName": "text",
"emailAddress": "text"
}
JiraWorklogSummary
AdminPMBasicTracker
Fields
authorDisplayNameString!minutesFloat!revenueFloatuserUser
Example
{
"authorDisplayName": "text",
"minutes": 120.5,
"revenue": 120.5
}
Mention
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!idID!mentionableIdID!mentionableTypeString!updatedAtISO8601DateTime!userUser!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"mentionableId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"mentionableType": "text",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
MonthlyRevenue
AdminPMBasicTracker
Fields
countInt!monthInt!openFloat!- The year's published, unpaid invoices dated in the month
quotedFloat!- Confirmed quotations not invoiced yet, in the month the forecast puts them
totalFloat!
Example
{
"count": 42,
"month": 42,
"open": 120.5,
"quoted": 120.5,
"total": 120.5
}
Notification
AdminPMBasicTracker
Fields
actionNotificationAction!actorCountInt!- How many different people did it
actors[User!]!- Who did it, the latest first, each once; up to three
countInt!countArchivedInt!countIsNewInt!createdAtISO8601DateTime!emojis[String!]!- The reactions, for TICKET_COMMENT_REACTED, the latest first, each once
idString!recordNotificationRecordUnion
Example
{
"id": "text",
"createdAt": "2026-11-13T09:30:00+01:00",
"action": "TICKET_CREATED",
"actorCount": 42,
"count": 42,
"countArchived": 42
}
OrderConfirmation
AdminPMBasicTracker
The order confirmation of a billing cycle. docket creates it with the quotation's content when the quotation is confirmed; delivery notes and invoices are created from it. Only project managers and admins can read it.
Fields
accountingAccounting!- The billing cycle it belongs to
authorUser!- Who created it
commentsOrderConfirmationCommentConnection!contactCustomersContactConnection!- The customer's contacts the document is addressed to
contactInternalsUserConnection!- The agency's contact persons named on the document
createdAtISO8601DateTime!customerCustomer!- The customer of the document's project
customerAddressCustomerAddress- The customer address it is written to; needed before it can go out
dateISO8601DatedeletedBoolean!- Soft-delete flag; deleted documents are not listed
descriptionString- Introductory text (HTML)
filenameString!- File name of its PDF
footerString- Footer text (HTML)
idID!languageString- Language of the document and its PDF: de or en
nameString- Free name beside the number; the project's title unless given
noString!- The number as printed: project number, a dot and the two-digit number
notificationRecipients[User!]!numberInt!- Running number within the project
projectProject!showPositionSubtotalBoolean!- Whether the PDF shows a subtotal under each position
statusOrderConfirmationStatus!streamOrderConfirmationStreamConnection!- Its comments and events (status changes, edits), oldest first
summarySummary!- The document's computed totals: net, discounts and surcharges, VAT, gross
taxNoteString- Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRateFloat!- The VAT rate in percent its lines use unless a line has its own
taxTreatmentTaxTreatment!- How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
titleString!- no followed by the name
updatedAtISO8601DateTime!viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
OrderConfirmationComment
AdminPMBasicTracker
Fields
authorUser!bodyJson!bodyHtmlString!byAiBoolean!- Written by docket when the AI added positions (shown as docket's); the author applied them
createdAtISO8601DateTime!idID!orderConfirmationOrderConfirmation!reactions[Reaction!]!- Its reactions by emoji, in the order they were first given
updatedAtISO8601DateTime!viewerCanEditBoolean!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
Phase
AdminPMBasicTracker
A phase of a project: a stage that groups tickets and gives the roadmap its structure. Lists return the phases of projects the caller can open.
Fields
computedEndDateString- The latest end date of the phase's tickets; null when none has one
computedStartDateString- The earliest start date of the phase's tickets; null when none has one
createdAtISO8601DateTime!descriptionStringendDateString- Planned end (YYYY-MM-DD)
idID!positionInt- Rank among the project's phases, for ordering (not consecutive)
projectProject!slugString!startDateString- Planned start (YYYY-MM-DD)
ticketsTicketConnection!ticketsClosedInt!ticketsOpenInt!titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"computedEndDate": "text",
"computedStartDate": "text",
"description": "text"
}
PinnedPage
AdminPMBasicTracker
Fields
pathString!- The app path it opens, query string included
titleString!
Example
{
"title": "Website relaunch",
"path": "text"
}
Project
AdminPMBasicTracker
A project: the work for one customer, with its tickets, time entries, budget and billing documents. Admins, project managers and basic users read every project; a timetracker only those they are assigned to, directly or through the project's customer.
Fields
accountingCycles[AccountingCycle!]- One entry per billing cycle that has gone out to the customer, oldest first: what is paid, open and overdue.
- Who sees Null unless you may see financial data (project managers and admins).
activity[ProjectActivityItem!]!- What happened in the project lately, newest first: tickets opened, closed and reopened, comments, and status changes of documents for those who may see them. limit is 1 to 50 (default 20).
archivedBoolean!assigneesUserConnection!- Everyone assigned to one of the project's tickets
boardsBoardConnection!budgetExternalCostsFloat- The external costs booked on the project, in the workspace's currency.
- Who sees Null unless you may see the budget (project managers and admins).
budgetOverBoolean!- Whether more than 100 % is used or, for an hour budget, the external costs exceed what the confirmed quotations sold. Always false for a timetracker.
budgetRateFloat- The budget: minutes for MINUTES and MINUTES_PER_MONTH, an amount in the workspace's currency for AMOUNT and AMOUNT_PER_MONTH. Null without a budget.
- Who sees Null unless you may see the budget (project managers and admins).
budgetTimetrackingsTimetrackingConnection!- The time entries the budget counts: for a monthly budget those of the current month unless the filter names dates, otherwise all. Visibility as in timetrackings.
budgetTypeProjectBudget- What the budget counts.
- Who sees Null unless you may see the budget (project managers and admins).
budgetUsedFloat!- How much of the budget is used, in percent (above 100 when over). An amount budget counts the revenue of the booked time and the external costs, an hour budget the booked time; a monthly budget the current month. 0 without a budget and for a timetracker.
createdAtISO8601DateTime!customerCustomer!deadlineISO8601DatedeliveryNotesDeliveryNoteConnection- Who sees Null unless you may see financial data (project managers and admins).
descriptionStringexternalCostsExternalCostConnection- Supplier invoices assigned to the project.
- Who sees Null unless you may see financial data (project managers and admins).
externalCostsCheckExternalCostsCheck- The external costs booked against the external services the project's confirmed quotations sold; null without a confirmed quotation.
- Who sees Null unless you may see financial data (project managers and admins).
externalCostsTotalFloat- The external costs assigned to the project's quotations (drafts left out), with the KSK levy where it applies, in the workspace's currency.
- Who sees Null unless you may see financial data (project managers and admins).
financialsProjectFinancials- What the project's quotations and invoices add up to.
- Who sees Null unless you may see financial data (project managers and admins).
hasBudgetBoolean!- Whether a budget is set. Always false for a timetracker.
idID!invoiceTypesWithoutOrderConfirmation[InvoiceTypeEnum!]!- The types an invoice created without an order confirmation can have
invoicesInvoiceConnection- Who sees Null unless you may see financial data (project managers and admins).
jiraLinkedBoolean!- Whether the project is linked to a Jira project
jiraProjectLinkJiraProjectLink- The link to a Jira project and its settings; null when unlinked
jiraProjectUrlString- Address of the linked project in Jira; null when unlinked
jiraTicketsModeJiraTicketsMode- How the linked Jira project shows up in the tickets area; null when unlinked
jiraWorklogSummary[JiraWorklogSummary!]!- Time logged in Jira and imported read-only, summed per Jira author, most first. A timetracker sees only their own row; revenue is null unless you may see revenue (project managers and admins). Empty when unlinked.
labelsProjectLabelConnection!numberInt!- The project's running number in the workspace (the first is 1001)
orderConfirmationsOrderConfirmationConnection- Who sees Null unless you may see financial data (project managers and admins).
participantsUserConnection!- Supervisors and ticket assignees together
phasesPhaseConnection!pnrString!- The project number as shown everywhere: the customer's initial followed by number, e.g. ACME1001
progressInt!- Share of the project's tickets that are closed, in percent (0 without tickets)
quotationsQuotationConnection- Who sees Null unless you may see financial data (project managers and admins).
retainerRetainer- The project's retainer; null when it isn't one, and unless you may see financial data (project managers and admins).
serviceRates[ServiceRate!]!- Every service with the daily rate that applies to this project (the project's own, else the customer's, else the service's). With customerId: as they would apply under that customer.
sharedReports[SharedProjectReport!]- The project's public report links.
- Who sees Null unless you may see the budget (project managers and admins).
slugString!statusProjectStatus!statusDateISO8601Date- The day the status last changed
stickyTicketsClosedInt!- Closed tickets that are pinned
stickyTicketsOpenInt!- Open tickets that are pinned
supervisorsUserConnection!- The people assigned to the project (project assignments)
ticketsTicketConnection!ticketsClosedInt!ticketsOpenInt!timetrackingsTimetrackingConnection!- Time booked on the project. A timetracker sees only their own entries, everyone else all of them.
titleString!updatedAtISO8601DateTime!viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
workloadWorkloadOverview!- The project's open tickets per assignee by deadline
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"pnr": "ACR1001",
"title": "Website relaunch",
"status": "REQUESTED",
"createdAt": "2026-11-13T09:30:00+01:00"
}
ProjectActivityItem
AdminPMBasicTracker
Fields
actionEventAction- What happened to the document, for DOCUMENT entries
documentProjectDocumentUnion- The document, for DOCUMENT and DOCUMENT_COMMENT_REACTED entries
emojiString- The reaction, for TICKET_COMMENT_REACTED and DOCUMENT_COMMENT_REACTED entries
idID!kindProjectActivityKind!occurredAtISO8601DateTime!ticketTicketuserUser
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"action": "TICKET_REOPENED",
"emoji": "text",
"kind": "TICKET_OPENED",
"occurredAt": "2026-11-13T09:30:00+01:00"
}
ProjectFinancials
AdminPMBasicTracker
Fields
invoicedCountInt!- Issued invoices, paid or not (no cancellations, nothing canceled)
invoicedTotalFloat!- What they ask for: a final invoice counts its debit
openCountInt!- Issued invoices not paid yet
openTotalFloat!overdueCountInt!overdueTotalFloat!paidTotalFloat!quotedCountInt!- Confirmed quotations
quotedTotalFloat!
Example
{
"invoicedCount": 42,
"invoicedTotal": 120.5,
"openCount": 42,
"openTotal": 120.5,
"overdueCount": 42,
"overdueTotal": 120.5
}
ProjectLabel
AdminPMBasicTracker
Fields
colorString!createdAtISO8601DateTime!descriptionStringidID!projectProject!slugString!titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"color": "#ff7a00",
"description": "text",
"slug": "website-relaunch"
}
Quotation
AdminPMBasicTracker
A quotation to a customer. It opens a billing cycle; confirming it creates the cycle's order confirmation. Only project managers and admins can read it.
Fields
accountingAccounting!- The billing cycle it belongs to
authorUser!- Who created it
budgetHandoffQuotationBudgetHandoff- What the quotation sold and what taking it over would make of the project's budget.
- Who sees Null unless it is confirmed, the caller may change the project's budget and there is something to take over.
canceledNoteString- The note given when it was canceled
commentsQuotationCommentConnection!confirmationFileString- Path of the customer's signed confirmation, if one was attached when confirming
confirmationFilenameString- File name of the customer's signed confirmation
confirmedNoteString- The note given when it was confirmed
contactCustomersContactConnection!- The customer's contacts the document is addressed to
contactInternalsUserConnection!- The agency's contact persons named on the document
createdAtISO8601DateTime!customerCustomer!- The customer of the document's project
customerAddressCustomerAddress- The customer address it is written to; needed before it can go out
dateISO8601DatedeletedBoolean!- Soft-delete flag; deleted documents are not listed
descriptionString- Introductory text (HTML)
documentTemplateDocumentTemplate- The template it was started from, if any
externalCosts[ExternalCost!]!- The supplier invoices assigned to this quotation, by invoice date
externalCostsChargeableTotalFloat!- The part of externalCostsTotal that is passed on to the customer
externalCostsCheckExternalCostsCheck- The booked external costs against the external services the quotation sold; null unless it is confirmed
externalCostsFilenameString!- File name of its external-costs PDF
externalCostsNonchargeableTotalFloat!- The part of externalCostsTotal that is not passed on to the customer
externalCostsTotalFloat!- This quotation's share of the external costs assigned to it (drafts left out), with the KSK levy where it applies; net, or with VAT where the workspace could not reclaim it. Workspace currency.
externalServiceTotalFloat- Net total of its external-service lines, in the workspace's currency
filenameString!- File name of its PDF
footerString- Footer text (HTML)
idID!languageString- Language of the document and its PDF: de or en
nameString- Free name beside the number; the project's title unless given
notificationRecipients[User!]!numberInt!- Running number within the project
projectProject!qnrString!- The quotation number as printed: project number, a dot and the two-digit number, e.g. ACME1001.01
qnrWithNameString!- qnr followed by the name
showPositionSubtotalBoolean!- Whether the PDF shows a subtotal under each position
statusQuotationStatus!streamQuotationStreamConnection!- Its comments and events (status changes, edits), oldest first
summarySummary!- The document's computed totals: net, discounts and surcharges, VAT, gross
taxNoteString- Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRateFloat!- The VAT rate in percent its lines use unless a line has its own
taxTreatmentTaxTreatment!- How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
titleString!- The same as qnrWithName
totalNetFloat- Net total in the workspace's currency
updatedAtISO8601DateTime!viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"name": "Website relaunch",
"status": "DRAFT",
"date": "2026-11-13"
}
QuotationBudgetHandoff
AdminPMBasicTracker
Fields
agencyServicesAmountFloat!- The agency's own lines
budgetAfterAddFloatbudgetAfterSetFloat!budgetTypeProjectBudget!- The budget the hand-off writes: the project's, or without one hours when the quote sold any
commissionAmountFloat!- The customer's commission on external services
currentBudgetFloat- The project's budget now (minutes or amount), null without one
discountsAndSurchargesAmountFloat!- Discounts (negative) and surcharges together
externalServicesAmountFloat!- Bought-in work passed on
modes[BudgetHandoffMode!]!- What may be done, the suggestion first: add needs a budget to add to
soldAmountFloat!- The quote's net total, as its PDF prints it
soldMinutesFloat!- Hours sold, in minutes: hour and day lines that reach the total, no external services
suggestedModeBudgetHandoffMode!
Example
{
"agencyServicesAmount": 120.5,
"budgetAfterAdd": 120.5,
"budgetAfterSet": 120.5,
"budgetType": "MINUTES",
"commissionAmount": 120.5,
"currentBudget": 120.5
}
QuotationComment
AdminPMBasicTracker
Fields
authorUser!bodyJson!bodyHtmlString!byAiBoolean!- Written by docket when the AI added positions (shown as docket's); the author applied them
createdAtISO8601DateTime!idID!quotationQuotation!reactions[Reaction!]!- Its reactions by emoji, in the order they were first given
updatedAtISO8601DateTime!viewerCanEditBoolean!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"byAi": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
Example
{
"count": 42,
"emoji": "text",
"viewerReacted": true
}
Retainer
AdminPMBasicTracker
A project billed with a fixed fee per month. With a budget of hours per month the fee covers that contingent, and hours beyond it are billed on top. docket proposes each month's invoice once the month is over.
Fields
billsOverageBoolean!- Whether hours beyond the contingent are billed on top of the fee
contingentMinutesInt- The hours a period's fee covers, in minutes: the retainer's own contingent, else the project's budget when it is hours per month (times three for a quarter); null without either
dueMonths[RetainerMonth!]!- The periods (months or quarters) that are over and have no invoice yet, oldest first
endsOnISO8601Date- Null for an open-ended retainer
feeFloat!- The fee per period (month or quarter), net, in the workspace's currency
intervalMonthsInt!- How many months one fee covers: 1 (billed monthly) or 3 (billed quarterly, from the month it starts in)
months[RetainerMonth!]!- The latest twelve periods of the term up to the current one, newest first
noticeByISO8601Date- The last day to give notice so it ends on its end date; null when open-ended
noticeMonthsInt- The notice period in months
ownContingentMinutesInt- The contingent entered for the retainer itself, in minutes per period; null when the budget stands in
startsOnISO8601Date!
Example
{
"billsOverage": true,
"contingentMinutes": 42,
"endsOn": "2026-11-13",
"fee": 120.5,
"intervalMonths": 42,
"noticeBy": "2026-11-13"
}
RetainerMonth
AdminPMBasicTracker
One billing period of a retainer, a month or a quarter: the time booked against the hours its fee covers, what is over, and whether it has been invoiced.
Fields
billsOverageBoolean!- Whether hours beyond the contingent are billed on top of the fee
bookedMinutesInt!- Billable time booked in the month, in minutes
contingentMinutesInt- The hours the fee covers, in minutes; null without a contingent
dueBoolean!- The month is over and has no invoice yet
feeFloat!- The period's fee, net, in the workspace's currency
fromISO8601Date!- The first day of the period inside the retainer's term
invoiceInvoice- The invoice that bills the month; null while there is none
monthISO8601Date!- The first day of the period's first month
monthsInt!- How many months the period covers: 1 or 3
overageMinutesInt!- Time beyond the contingent, in minutes; 0 without a contingent
projectProject!toISO8601Date!- The last day of the period inside the retainer's term
unusedMinutesInt!- What is left of the contingent and lapses at the end of the month, in minutes
Example
{
"billsOverage": true,
"bookedMinutes": 42,
"contingentMinutes": 42,
"due": true,
"fee": 120.5,
"from": "2026-11-13"
}
Example
{
"title": "Website relaunch"
}
RssItem
AdminPMBasicTracker
Fields
dateISO8601DateTime!excerptStringimageStringlinkString!tags[String!]!titleString!
Example
{
"title": "Website relaunch",
"date": "2026-11-13T09:30:00+01:00",
"excerpt": "text",
"image": "text",
"link": "text",
"tags": [
"text"
]
}
SavedView
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!idID!nameString!queryString!- The list's query string (filters, what it shows; no order)
sharedBoolean!- Shared with everyone in the project or workspace, not someone's own
updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"name": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"query": "text",
"shared": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
SearchResult
AdminPMBasicTracker
Fields
idID!metaStringslugString- A project's or a customer's — to search in it (projectSlug / customerSlug)
titleString!typeSearchResultModel!urlString!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"meta": "text",
"slug": "website-relaunch",
"type": "PROJECT",
"url": "https://example.com"
}
Service
AdminPMBasicTracker
A kind of work the agency sells (design, development, project management …), with a daily rate. Time is booked for a service and document lines are priced by it.
Fields
archivedBoolean!billableBoolean!- false for internal work: it has no rate and its time is never billed
categoryServiceCategory!createdAtISO8601DateTime!dailyRateFloat- The standard rate per day (8 hours), net in the workspace's currency; customers and projects can have their own.
- Who sees Null unless you may see financial data (project managers and admins).
defaultTaxRateFloat- The VAT rate a line of this service starts with; null = the workspace's default
descriptionStringexpertsUserConnection!- The users whose own service this is
idID!slugString!timetrackingsTimetrackingConnection!titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"dailyRate": 120.5
}
ServiceCategory
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!idID!servicesServiceConnection!slugString!ticketsTicketConnection!titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"slug": "website-relaunch",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
ServiceRate
AdminPMBasicTracker
Fields
archivedBoolean!billableBoolean!categoryString!createdAtISO8601DateTime!dailyRateFloatdefaultTaxRateFloat- The VAT rate a line of this service starts with; null = the document's
descriptionStringidID!isCustomRateBoolean!originalRateFloattitleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"billable": true,
"category": "text"
}
StatusBreakdown
AdminPMBasicTracker
Fields
countInt!statusString!totalFloat!
Example
{
"status": "text",
"count": 42,
"total": 120.5
}
Stopwatch
AdminPMBasicTracker
A stopwatch: it collects time until it is booked as a time entry. Several can run at once. Private: only its owner can read it, admins included.
Fields
createdAtISO8601DateTime!idID!roundedMinutesInt!- What booking it suggests: rounded up to the next full 15 minutes
runningBoolean!- false while paused
secondsInt!- Time on the clock right now, in seconds
ticketTicket- Optional — can also be picked when booking
titleString!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"roundedMinutes": 42,
"running": true,
"seconds": 42
}
Summary
AdminPMBasicTracker
Fields
billedBefore[BilledBefore!]!billedTaxBreakdown[TaxGroup!]!blocks[Block!]!commissionPercentFloatcommissionThresholdFloat!commissionTotalFloat!debitTaxBreakdown[TaxGroup!]!deductionTypeStringdeductionValueFloatdiscountSurcharge[DiscountSurcharge!]!exceedsQuotationTotalBoolean!externalServiceTotalFloat!externalServiceTotalBilledFloat!mixedTaxRatesBoolean!- More than one VAT rate on this document
onlyOptionalCostsIncludedBoolean!optionalCostsIncludedBoolean!reachesQuotationTotalBoolean!subtotalFloat!taxBreakdown[TaxGroup!]!taxRateFloat!taxTreatmentTaxTreatment!totalBilledGrossFloat!totalBilledNetFloat!totalBilledSoFarNetFloat!totalBilledTaxFloat!totalDebitGrossFloat!totalDebitNetFloat!totalDebitTaxFloat!totalGrossFloat!totalNetFloat!totalTaxFloat!
Example
{
"totalNet": 120.5,
"commissionPercent": 120.5,
"commissionThreshold": 120.5,
"commissionTotal": 120.5,
"deductionType": "text",
"deductionValue": 120.5
}
Supplier
AdminPMBasicTracker
A supplier whose invoices are recorded as external costs. Basic users, project managers and admins can read it, timetrackers cannot.
Fields
archivedBoolean!createdAtISO8601DateTime!datevAccountString- The supplier's own account (creditor number) in the tax office's DATEV; null = the collective account
externalCostsExternalCostConnection!- The supplier's invoices; only project managers and admins see any
idID!kskBoolean!- Whether the supplier is subject to the KSK levy (German artists' social insurance), which is then added to its invoices' cost
slugString!taxTreatmentSupplierTaxTreatment!- How the supplier's invoices are taxed: domestic, or abroad — then an invoice without VAT is reverse charge (the workspace owes the tax)
titleString!- The supplier's name
updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"title": "Website relaunch",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true,
"datevAccount": "text",
"ksk": true
}
TaxGroup
AdminPMBasicTracker
Fields
grossFloat!netFloat!rateFloat!- The VAT rate in percent (19, 7, 0)
taxFloat!
Example
{
"gross": 120.5,
"net": 120.5,
"rate": 120.5,
"tax": 120.5
}
Ticket
AdminPMBasicTracker
A ticket: a task in a project, and what time is booked on. Lists and lookups return only tickets of projects the caller can open. A ticket mirrored from Jira (isExternal) is read-only here; time is still booked on it.
Fields
assigneesUserConnection!assignmentsTicketAssignmentConnection!- The assignments behind assignees, one per assigned person
attachments[TicketAttachment!]!- The files in the description and the comments, oldest first
authorUser!boardPositionInt!- Rank within its board column, for ordering (not consecutive)
bodyJson!- The description as a rich-text JSON document (type doc with content nodes)
bodyHtmlString!- The description rendered as HTML
bookedMinutesIncludingChildrenInt!- Time booked on this ticket and its sub-tasks — what Jira shows as the aggregate
budgetRateFloat- The ticket's budget: minutes for MINUTES, an amount in the workspace's currency for AMOUNT. Null without a budget.
- Who sees Null unless you may see financial data (project managers and admins).
budgetTypeTicketBudget- What the ticket's budget counts.
- Who sees Null unless you may see financial data (project managers and admins).
budgetUsedFloat!- Share of the ticket's budget used by the time booked on it, in percent (above 100 when over); 0 without a budget or booked time, and for time trackers
childTickets[Ticket!]!- Sub-tasks (and an epic's children) mirrored from Jira, by key
closedAtISO8601Date- The day it was closed; null while open
closedByUser- Who closed it; null while open
commentsTicketCommentConnection!createdAtISO8601DateTime!endDateISO8601Date- Planned end, the ticket's deadline
externalKeyString- The Jira issue key, e.g. ABC-123; null for a native ticket
externalRawAssigneesJson- Jira assignees that have no docket user (accountId, displayName); null for a native ticket
externalSourceString- jira for a ticket mirrored from Jira; null for one created in docket
externalUrlString- Address of the issue in Jira; null for a native ticket
idID!isExternalBoolean!- Whether it is mirrored from Jira and therefore read-only in docket
isStickyBoolean!- Whether the ticket is pinned
jiraIssueTypeString- The Jira issue type (epic, story, sub-task, …); null for a native ticket
jiraSubtaskBoolean!- Whether it mirrors a Jira sub-task
labelsProjectLabelConnection!notificationRecipients[User!]!numberInt!- Running number within the project, starting at 1 (the general ticket every project starts with)
parentTicketTicket- The mirror of its Jira parent issue; null for native tickets and top-level issues
phasePhasephasePositionInt!- Rank within its phase, for ordering (not consecutive)
priorityTicketPriority!projectProject!serviceCategoryServiceCategory- The category of work the ticket belongs to, if one is set
startDateISO8601Date- Planned start
statusTicketStatus!streamTicketStreamConnection!- Its comments and events (status changes, edits), oldest first
timetrackingsTimetrackingConnection!- Time booked on the ticket. A timetracker sees only their own entries, everyone else all of them.
titleString!todosClosedInt!- Checked to-do items in the description
todosOpenInt!- Unchecked to-do items in the description
updatedAtISO8601DateTime!viewerFollowReasonString- Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowingBoolean!- Whether the caller follows it and so gets its notifications
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"number": 1017,
"title": "Website relaunch",
"status": "OPEN",
"createdAt": "2026-11-13T09:30:00+01:00",
"boardPosition": 42
}
TicketAssignment
AdminPMBasicTracker
Fields
assigneeUser!createdAtISO8601DateTime!idID!ticketTicket!updatedAtISO8601DateTime!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"updatedAt": "2026-11-13T09:30:00+01:00"
}
TicketAttachment
AdminPMBasicTracker
Fields
authorUser- Who wrote the comment it is in; null for the description
byteSizeInt!commentIdID- The comment it is in; null for the description
contentTypeStringcreatedAtISO8601DateTime!filenameString!idID!- The file's (blob's) id
imageBoolean!- An image, shown as a thumbnail
thumbnailUrlString- A small square of an image, made on first request
urlString!- Opens the file: an image in the browser, anything else as a download. A path on the workspace; fetch it signed in, or with the API key in the Authorization header
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"byteSize": 42,
"commentId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"contentType": "text",
"filename": "text"
}
TicketComment
AdminPMBasicTracker
Fields
authorUser!bodyJson!bodyHtmlString!createdAtISO8601DateTime!idID!mentions[Mention!]!reactions[Reaction!]!- Its reactions by emoji, in the order they were first given
ticketTicket!todosClosedInt!todosOpenInt!updatedAtISO8601DateTime!viewerCanEditBoolean!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"body": {},
"bodyHtml": "text",
"todosClosed": 42,
"todosOpen": 42
}
TimeEntrySuggestion
AdminPMBasicTracker
Fields
dateISO8601Date!descriptionStringfoundString- What docket saw in the ticket, for an entry found from the person's activity
minutesIntprojectProjectserviceServiceticketTicket
Example
{
"date": "2026-11-13",
"description": "text",
"found": "text",
"minutes": 42
}
Timetracking
AdminPMBasicTracker
A time entry: the time one person booked on a ticket of a project, for a service. Admins see every entry, a timetracker only their own, everyone else their own and those on projects they can open.
Fields
billedBoolean!- Whether an invoice holds this entry as a line. A billed entry can't be changed or deleted until its line or its invoice is gone
createdAtISO8601DateTime!dailyRateFloat- The service's rate per day (8 hours) on this project when the entry was booked, net in the workspace's currency.
- Who sees Null unless you may see revenue (project managers and admins).
dateISO8601Date!- The day the work was done
descriptionStringdurationFloat!- Minutes, in steps of 15
idID!invoiceInvoice- The invoice that bills this entry (billing by effort), drafts included; null while it is not billed, and for those who may not see invoices
jiraMissingForPushJiraPushRequirement- Set while the state is NOT_SYNCABLE: what the person lacks for the push
jiraSyncErrorString- What Jira answered when the push failed
jiraSyncStateTimetrackingJiraSyncState- Where the push of this entry to Jira as a worklog stands; null for entries on tickets not mirrored from Jira
projectProject!revenueFloat- What the entry is worth: daily rate × duration, net in the workspace's currency; 0 for a non-billable service.
- Who sees Null unless you may see revenue (project managers and admins).
serviceService!- The kind of work; it decides the rate
ticketTicket!updatedAtISO8601DateTime!userUser!- Who did the work
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"date": "2026-11-13",
"duration": 120.5,
"createdAt": "2026-11-13T09:30:00+01:00",
"billed": true,
"dailyRate": 120.5
}
User
AdminPMBasicTracker
A person in the workspace. Everyone has exactly one role, which decides what they see and may do.
Fields
archivedBoolean!assignedCustomersCustomerConnection!- Customers the user is assigned to; for a timetracker they open the customers' projects
assignedProjectsProjectConnection!- The same as projects
avatarString- Path of the avatar image, cropped to a square of size pixels (default 256); null without one
birthdayISO8601Date- Null for timetrackers, unless it is their own.
bookedMinutesInt!- All time booked by this user, in minutes. 0 for timetrackers, unless it is their own.
createdAtISO8601DateTime!dashboardRssEnabledBoolean!- Whether the user's dashboard shows an RSS feed
dashboardRssExcerptBoolean!- Whether that feed shows an excerpt of each item
dashboardRssUrlStringemailString!entryDateISO8601Date- The day the person joined the agency. Null for timetrackers, unless it is their own.
expertiseService- The user's own service: what their time is booked for unless another is chosen
firstnameString!highestWorkTimeInMonthFloat- The longest day, in hours, that a working-time profile valid in the month of that date plans; null as for workTimeForMonth
highestWorkTimeInWeekFloat- The longest day, in hours, that a working-time profile valid in the week of that date plans; null as for workTimeForWeek
idID!initialString!- Short code shown where space is tight
jiraPlaceholderBoolean!- A stand-in for a Jira author without a docket account: archived, cannot sign in; its time counts like anyone's
jiraUserMappings[JiraUserMapping!]!- The Jira accounts mapped to this user. Empty unless you are the user or an admin.
lastnameString!localeLocale- The user's own language for emails and sign-in pages; null when it follows the workspace, and unless you are this user or an admin
projectsProjectConnection!- Projects the user is assigned to (project assignments)
roleUserRole!settingsJson- Preferences the app stores for the user (free-form JSON).
- Who sees Null unless you are this user or an admin.
slugString!targetHoursFloat- Target working hours on that day, from the profile valid then (null: none)
ticketsTicketConnection!- Tickets assigned to the user
timetrackingsTimetrackingConnection!twoFactorEnabledBoolean- Whether two-factor sign-in is on; null unless you are this user or an admin
updatedAtISO8601DateTime!usernameString!viewerCanManageAccessBoolean!- Whether the caller may change this user's role and archive them: admins, never for themselves
workTimeForMonthFloat- Target working hours in the month of that date, from the working-time profiles valid then; null when none, and unless you are this user or at least a basic user
workTimeForWeekFloat- Target working hours in the week of that date; null when none, and unless you are this user or at least a basic user
workTimesUserWorkTimeConnection!- The user's working-time profiles: target hours per weekday, each valid from a date
workspaceLocaleLocale- The workspace's language, which locale falls back to; null unless you are this user or an admin
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
UserWorkTime
AdminPMBasicTracker
Fields
activeFromISO8601Date!createdAtISO8601DateTime!friFloat!idID!monFloat!satFloat!sunFloat!thuFloat!tueFloat!updatedAtISO8601DateTime!userUser!wedFloat!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"activeFrom": "2026-11-13",
"fri": 120.5,
"mon": 120.5,
"sat": 120.5
}
VatStatus
AdminPMBasicTracker
Fields
createdAtISO8601DateTime!idID!lockReasonString- Why it can't be deleted, or null when it can
lockedBoolean!- Documents were issued or external costs recorded in its period: it can't be deleted any more
smallBusinessBoolean!updatedAtISO8601DateTime!validFromISO8601Date!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"lockReason": "text",
"locked": true,
"smallBusiness": true,
"updatedAt": "2026-11-13T09:30:00+01:00"
}
Viewer
AdminPMBasicTracker
The signed-in person; with an API key, the key's owner. Everything here is that person's own.
Fields
archivedBoolean!assignedTicketsTicketConnection!- The tickets assigned to the person, open and closed, in projects that are not archived. On a project whose tickets come from Jira only the Jira tickets count.
createdAtISO8601DateTime!emailString!expertiseService- The person's own service: the kind of work their time entries default to
firstnameString!followedTicketsTicketConnection!- The tickets the person follows and may open, in projects that are not archived. On a project whose tickets come from Jira only the Jira tickets count.
idID!initialString!- The person's short sign, e.g. initials, shown on avatars
lastnameString!notificationStreamNotificationConnection!- The person's notification inbox, newest first: one entry per record and event, standing for all notifications of that kind. Only the filters isNew and archived apply here, and orderBy has no effect.
pinnedPages[PinnedPage!]!- Pages pinned to the sidebar
projectsInvolvedProjectConnection!- The projects the person is assigned to or has a ticket assigned in, archived ones included unless filtered.
recentlyTrackedTickets[Ticket!]!- The tickets the person last booked time on, latest first: only tickets of projects that are not archived and that time can still be booked on.
roleUserRole!- The highest role the person holds; it decides what every query returns to them
rssFeedRssFeed- The RSS feed the person put on their dashboard; null when they have none switched on
settingsJson- Interface state the app keeps for the person (e.g. whether the sidebar is open), as free-form JSON
slugString!timetrackingSuggestions[String!]!- The descriptions the person used for earlier time entries on a ticket, latest first, without duplicates.
timetrackingsTimetrackingConnection!- The person's own time entries.
unreadMentionCountInt!- Unread notifications that mention the viewer
unreadNotificationCountInt!- Unread notifications that are not archived, counted once per record and event: three new comments on one ticket count as one
updatedAtISO8601DateTime!usernameString!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"firstname": "Anna",
"lastname": "Becker",
"email": "anna@example.com",
"createdAt": "2026-11-13T09:30:00+01:00",
"archived": true
}
WebhookDelivery
AdminPMBasicTracker
Fields
attemptsInt!createdAtISO8601DateTime!deliveredAtISO8601DateTimeerrorStringeventString!idID!responseCodeIntstatusString!- pending, delivered or failed
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "text",
"createdAt": "2026-11-13T09:30:00+01:00",
"attempts": 42,
"deliveredAt": "2026-11-13T09:30:00+01:00",
"error": "text"
}
WebhookEndpoint
AdminPMBasicTracker
Fields
activeBoolean!createdAtISO8601DateTime!deliveries[WebhookDelivery!]!- The latest twenty deliveries, newest first
disabledAtISO8601DateTime- When docket switched it off after too many failures
events[String!]!failureCountInt!- Deliveries given up on in a row
idID!urlString!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"createdAt": "2026-11-13T09:30:00+01:00",
"active": true,
"disabledAt": "2026-11-13T09:30:00+01:00",
"events": [
"text"
],
"failureCount": 42
}
WorkloadCounts
AdminPMBasicTracker
Fields
dueThisWeekInt!- Of thisWeek: due this week
laterInt!nextMonthInt!overdueInt!thisMonthInt!thisWeekInt!unplannedInt!
Example
{
"dueThisWeek": 42,
"later": 42,
"nextMonth": 42,
"overdue": 42,
"thisMonth": 42,
"thisWeek": 42
}
WorkloadGroup
AdminPMBasicTracker
Fields
categoryServiceCategoryrows[WorkloadRow!]!subtotalsWorkloadCounts!totalInt!
Example
{
"total": 42
}
WorkloadOverview
AdminPMBasicTracker
Fields
groups[WorkloadGroup!]!maxInt!totalInt!totalsWorkloadCounts!unassignedWorkloadRow!
Example
{
"max": 42,
"total": 42
}
Example
{
"total": 42
}
WorkspaceExport
AdminPMBasicTracker
Fields
byteSizeInt- Size of the ZIP in bytes, once it is ready
createdAtISO8601DateTime!downloadUrlString- The app's download link (it checks the session again) — null unless the export is ready and not expired
expiresAtISO8601DateTimeidID!statusWorkspaceExportStatus!
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"status": "PENDING",
"createdAt": "2026-11-13T09:30:00+01:00",
"byteSize": 42,
"downloadUrl": "text",
"expiresAt": "2026-11-13T09:30:00+01:00"
}
Inputs
AccountingCustomFieldInput
Fields
customFieldIdIDcustomFieldValueString
Example
{
"customFieldId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"customFieldValue": "text"
}
AvgTimetrackingPerDayFilter
Fields
dates[String!]userIds[ID!]userIdsNot[ID!]
Example
{
"dates": [
"text"
],
"userIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"userIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
BlockPositionSubpositionInput
Fields
amountFloatdeletedBooleandescriptionStringidIDnameStringoptionalBooleanquantityFloatrateFloatserviceIdStringtaxRateFloat- VAT rate in percent; omit for the document's rate
unitString
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"type": "service",
"service": "agency_service",
"description": "text",
"optional": true,
"serviceId": "text",
"quantity": 120.5,
"unit": "text",
"name": "Website relaunch",
"rate": 120.5,
"amount": 120.5,
"deleted": true,
"taxRate": 120.5
}
BoardFilter
Fields
ids[ID!]
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
ContactFilter
Fields
archivedBooleancustomerIds[ID!]- Contacts of any of these customers
ids[ID!]searchString- Text to find, as the app's search finds it: by the contact's name and details
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"archived": true,
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text"
}
CustomFieldFilter
Fields
archivedBooleancustomerIds[ID!]ids[ID!]
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"archived": true
}
CustomerAddressFilter
Fields
customerIds[ID!]ids[ID!]
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
CustomerFilter
Fields
archivedBooleanids[ID!]projectArchivedBoolean- true = customers with at least one archived project, false = with at least one project that is not archived
projectTitleString- Customers with a project whose title contains this text
searchString- Text to find, as the app's search finds it: by name, customer number or VAT ID
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"archived": true,
"search": "text",
"projectTitle": "text",
"projectArchived": true
}
DeliveryNoteFilter
Fields
ids[ID!]searchString
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text"
}
DocumentAssistantTurnInput
Fields
roleString!- user or assistant
textString!
Example
{
"role": "text",
"text": "2h checkout bug"
}
ExternalCostAssignmentExtendedInput
Fields
boundsHeightFloatboundsLeftFloatboundsTopFloatboundsWidthFloatpageInt
Example
{
"boundsWidth": 120.5,
"boundsHeight": 120.5,
"boundsTop": 120.5,
"boundsLeft": 120.5,
"page": 42
}
ExternalCostAssignmentInput
Fields
amountFloatboundsExtended[ExternalCostAssignmentExtendedInput!]boundsHeightFloatboundsLeftFloatboundsTopFloatboundsWidthFloatchargeableBooleanpageIntprojectIdIDquotationIdID
Example
{
"amount": 120.5,
"projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"quotationId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"page": 42,
"chargeable": true,
"boundsWidth": 120.5,
"boundsHeight": 120.5,
"boundsTop": 120.5,
"boundsLeft": 120.5,
"boundsExtended": [
{
"boundsWidth": 120.5
}
]
}
ExternalCostFilter
Fields
ids[ID!]invoiceDates[String!]- The supplier invoice's date. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
projectIds[ID!]- External costs assigned, in whole or in part, to any of these projects
quotationIds[ID!]- External costs assigned, in whole or in part, to any of these quotations
searchString- Text to find, as the app's search finds it: by the supplier and the supplier's invoice number
status[NegatableExternalCostStatus!]- Any of these statuses. A value with a leading "!" excludes that one, e.g. "!PROCESSED".
statusChangedDates[String!]- The day the status last changed, in the workspace's time zone. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
supplierIds[ID!]userIds[ID!]
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"supplierIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"invoiceDates": [
"text"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"quotationIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"userIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"status": [
"!DRAFT"
],
"search": "text",
"statusChangedDates": [
"text"
]
}
InvoiceFilter
Fields
contactCustomerIds[ID!]- Invoices naming any of these contacts as the customer's contact
contactInternalIds[ID!]- Invoices naming any of these users as internal contact
ids[ID!]isPaidBoolean- true = status paid, false = every other status
paidAt[String!]- The day the invoice was paid, in the workspace's time zone, as "2026-10-20" or with a comparison (">=2026-10-01", "<2026-11-01"); several values must all hold
searchString- Text to find, as the app's search finds it: by number, name, text and customer
statuses[String!]- Any of "draft", "approved", "published", "canceled", "paid"; upper or lower case
yearInt- The year of the invoice date
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text",
"contactInternalIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"contactCustomerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"year": 42,
"statuses": [
"text"
],
"isPaid": true,
"paidAt": [
"text"
]
}
NotificationFilter
Fields
archivedBooleancreatedAt[String!]- The day the notification was created, in the workspace's time zone. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
isNewBoolean- true = unread, false = read
Example
{
"createdAt": [
"text"
],
"isNew": true,
"archived": true
}
Example
{
"type": "TICKET",
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}
OrderConfirmationFilter
Fields
ids[ID!]searchString
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text"
}
PhaseFilter
Fields
ids[ID!]projectIds[ID!]searchString- Phases whose title contains this text
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text"
}
PinnedPageInput
Fields
pathString!titleString!
Example
{
"title": "Website relaunch",
"path": "text"
}
ProjectFilter
Fields
accountingStatus[NegatableAccountingCycleStatus!]- Projects with a billing cycle in any of these states. A value with a leading "!" excludes that one, e.g. "!PAID".
archivedBooleanassigneeIds[ID!]- Projects with a ticket assigned to any of these users
customerIds[ID!]deadlines[String!]- The project's deadline. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
followedByViewerBoolean- true = only projects the current user follows (see Follow)
hasStickyTicketsBoolean- true = projects with at least one sticky ticket, false = with at least one ticket that is not sticky
ids[ID!]participantIds[ID!]- Projects any of these users take part in: assigned to the project or to one of its tickets
searchString- Words to find in the project's number, title or description; any of the words may match, also as the beginning of a word
status[NegatableProjectStatus!]- Any of these statuses. A value with a leading "!" excludes that one, e.g. "!REQUESTED".
supervisorIds[ID!]- Projects any of these users are assigned to
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"participantIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"supervisorIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"assigneeIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"deadlines": [
"text"
],
"status": [
"!ARCHIVED"
],
"accountingStatus": [
"!PAID"
],
"archived": true,
"hasStickyTickets": true,
"followedByViewer": true,
"search": "text"
}
ProjectLabelFilter
Fields
ids[ID!]projectIds[ID!]
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
]
}
QuotationFilter
Fields
customerIds[ID!]cycleStatus[NegatableAccountingCycleStatus!]- Quotations whose billing cycle is in any of these states. A value with a leading "!" excludes that one, e.g. "!PAID".
dates[String!]- The quotation's date. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
forecastYearInt- Quotations dated in this year, or with an invoice that counts for it in the forecast
ids[ID!]invoiceDate[String!]- Quotations with an invoice dated on these days, as "2026-10-20" or with a comparison (">=2026-10-01", "<2026-11-01"); several values must all hold
invoiceDueDate[String!]- Quotations with a sent, unpaid invoice due on these days, as "2026-10-20" or with a comparison (">=2026-10-01", "<2026-11-01"); several values must all hold
invoiceStatuses[String!]- Quotations with an invoice in any of these statuses: "draft", "approved", "published", "canceled", "paid"
isPaidBoolean- true = quotations with at least one paid invoice, false = with none
paidAt[String!]- Quotations with an invoice paid on these days (workspace's time zone), as "2026-10-20" or with a comparison (">=2026-10-01", "<2026-11-01"); several values must all hold
projectIds[ID!]searchString- Text to find, as the app's search finds it: by number, name, text and customer
statuses[String!]- Any of "draft", "approved", "published", "canceled", "confirmed"; upper or lower case
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"statuses": [
"text"
],
"cycleStatus": [
"!PAID"
],
"search": "text",
"forecastYear": 42,
"dates": [
"text"
],
"isPaid": true,
"paidAt": [
"text"
],
"invoiceStatuses": [
"text"
],
"invoiceDate": [
"text"
],
"invoiceDueDate": [
"text"
]
}
ServiceCategoryFilter
Fields
ids[ID!]searchString- Categories whose title contains this text
searchServicesString- Categories with a service whose title contains this text
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"search": "text",
"searchServices": "text"
}
ServiceFilter
Fields
archivedBooleanids[ID!]searchString- Services whose title contains this text
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"archived": true,
"search": "text"
}
ServiceRateInput
Fields
dailyRateFloatidID
Example
{
"id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"dailyRate": 120.5
}
SupplierFilter
Fields
archivedBooleanids[ID!]searchString- Suppliers whose name contains this text
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"archived": true,
"search": "text"
}
TicketFilter
Fields
assignedBoolean- true = has at least one assignee, false = unassigned
assigneeIds[ID!]- Tickets assigned to any of these users
assigneeIdsNot[ID!]- Tickets with an assignee who is none of these users; unassigned tickets do not match
bookableBoolean- true = only what the time-entry form offers (on a Jira-linked project: its Jira tickets)
customerIds[ID!]dueThisWeekBoolean- true = tickets ending between today and Sunday (by end date, else start date), false = all others
endDates[String!]- The ticket's end date. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
externalBoolean- true = only tickets mirrored from Jira, false = only docket's own
followedByViewerBoolean- true = only tickets the current user follows (see Follow)
hasStartOrEndDateBoolean- true = only tickets with a start or an end date; false has no effect
ids[ID!]isStickyBooleanlabelIds[ID!]numberString- The ticket's number within its project
overdueOrCurrentWeekBoolean- Get all tickets scheduled or overdue for this week
phaseIds[ID!]priorities[NegatableTicketPriority!]- Any of these priorities. A value with a leading "!" excludes that one, e.g. "!HIGH".
projectArchivedBooleanprojectIds[ID!]projectSlugs[String!]scheduleBuckets[TicketScheduleBucket!]- When the ticket is planned — the workload buckets
searchString- Words to find in the ticket's title, text, number or comments; any of the words may match, also as the beginning of a word
serviceCategoryIds[ID!]startDates[String!]- The ticket's start date. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
statusTicketStatus
Example
{
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"status": "OPEN",
"number": "text",
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectSlugs": [
"text"
],
"projectArchived": true,
"phaseIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"labelIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"serviceCategoryIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"assigneeIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"assigneeIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"assigned": true,
"followedByViewer": true,
"priorities": [
"!LOW"
],
"startDates": [
"text"
],
"endDates": [
"text"
],
"hasStartOrEndDate": true,
"overdueOrCurrentWeek": true,
"scheduleBuckets": [
"OVERDUE"
],
"dueThisWeek": true,
"isSticky": true,
"external": true,
"bookable": true,
"search": "text"
}
TimetrackingFilter
Fields
billing[TimetrackingBilling!]- Billing by effort: OPEN = billable and on no invoice yet, BILLED = taken into an invoice; both together find either
customerIds[ID!]customerIdsNot[ID!]- Leaves out the entries of these customers' projects
dates[String!]- The day the time was worked. Days as "2026-10-20", with a comparison (">=2026-10-01", "<2026-11-01") or as a range "2026-10-01 > 2026-10-31" (both days included); several values must all hold. "NULL" finds records without this date, "NOT NULL" those with one.
durations[String!]- Minutes, as "60" or with a comparison (">=60", "<120"); several values must all hold
projectIds[ID!]projectIdsNot[ID!]- Leaves out the entries of these projects
revenues[String!]- Whole amounts in the workspace's currency, as "500" or with a comparison (">=500"); several values must all hold. Ignored for callers who may not see financial data
searchString- Entries whose description contains this text
serviceIds[ID!]serviceIdsNot[ID!]- Leaves out the entries booked with these services
ticketIds[ID!]ticketIdsNot[ID!]- Leaves out the entries on these tickets
userIds[ID!]userIdsNot[ID!]- Leaves out the entries of these users
Example
{
"search": "text",
"dates": [
"text"
],
"durations": [
"text"
],
"revenues": [
"text"
],
"customerIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"customerIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"ticketIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"ticketIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"projectIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"serviceIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"serviceIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"userIds": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"userIdsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"billing": [
"OPEN"
]
}
UserFilter
Fields
archivedBooleanbirthdays[String!]- Dates of birth as "1990-05-17" or with a comparison (">=1990-01-01"); several values must all hold. "NULL" finds people without a birthday on file, "NOT NULL" those with one
canAccessDocumentsBoolean- Only users who can open billing documents
canAccessProjectID- Only users who can open this project (ID or slug)
ids[ID!]idsNot[ID!]- Leaves out these users
jiraPlaceholderBoolean- Only (true) or no (false) Jira placeholder users; left out, placeholders are not listed
searchString- People whose first or last name contains this text
usernameString- The exact username
withJiraPlaceholdersBoolean- List the Jira placeholder users too (they're archived, so with archived: false this means active users plus placeholders) — for filters over booked time
Example
{
"archived": true,
"jiraPlaceholder": true,
"withJiraPlaceholders": true,
"search": "text",
"username": "text",
"ids": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"idsNot": [
"8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
],
"birthdays": [
"text"
],
"canAccessProject": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
"canAccessDocuments": true
}
UserWorkTimeFilter
Fields
dateISO8601Date- Only the working hours in force on this day (the latest that started on or before it)
limitCurrentWeekBoolean- true = only the working hours in force today (the latest that started on or before today)
Example
{
"limitCurrentWeek": true,
"date": "2026-11-13"
}
Enums
AiProvider
Values
DOCKET- docket's own Mistral key, under the monthly quota
MISTRAL- The workspace's own Mistral key
OPENAI- The workspace's own OpenAI key
ANTHROPIC- The workspace's own Anthropic key
OPENAI_COMPATIBLE- The workspace's own key with a service that has OpenAI's chat API, at its own address
BlockPositionSubpositionServiceEnum
Values
agency_serviceexternal_service
BlockPositionSubpositionTypeEnum
Values
servicecustomflatrate
BlockTypeEnum
Values
phaseagency_serviceexternal_service
BoardPreset
Values
backlogdonecustom
BudgetHandoffMode
Values
SET- The quote's figure becomes the budget
ADD- The quote's figure is added to the budget (a supplementary quote)
CommentOn
Values
TICKETQUOTATIONORDER_CONFIRMATIONDELIVERY_NOTEINVOICE
Currency
Values
EURUSDGBPCHFAUDBRLCADCNYCZKDKKHKDHUFIDRILSINRISKJPYKRWMXNMYRNOKNZDPHPPLNRONSEKSGDTHBTRYZAR
DeliveryNoteStatus
Values
DRAFT- Not sent yet: its content can be changed.
PUBLISHED- Ready to go to the customer: its content is locked.
DiscountSurchargeTypeEnum
Values
discountsurcharge
DocumentFontStyle
Values
REGULARBOLDITALICBOLD_ITALIC
EventAction
Values
TICKET_REOPENED- Ticket was reopened
TICKET_CLOSED- Ticket was closed
TICKET_CHANGED- Ticket was edited: see ticketChanges
QUOTATION_DRAFT- Quotation was draft
QUOTATION_APPROVED- Quotation was approved
QUOTATION_PUBLISHED- Quotation was published
QUOTATION_CANCELED- Quotation was canceled
QUOTATION_CONFIRMED- Quotation was confirmed
ORDER_CONFIRMATION_DRAFT- Order confirmation was draft
ORDER_CONFIRMATION_PUBLISHED- Order confirmation was published
DELIVERY_NOTE_DRAFT- Delivery note was draft
DELIVERY_NOTE_PUBLISHED- Delivery note was published
INVOICE_DRAFT- Invoice was draft
INVOICE_APPROVED- Invoice was approved
INVOICE_PUBLISHED- Invoice was published
INVOICE_CANCELED- Invoice was canceled
INVOICE_PAID- Invoice was marked as paid
INVOICE_PAYMENT_REVERSED- A payment was taken back: the invoice is unpaid again
ExternalCostStatus
Values
DRAFT- Just captured, not checked yet. The only status in which it may be unassigned; a draft counts in no budget or total.
TO_CLARIFY- Something is off (the amount, the project) and needs a decision. It is assigned and counts.
OK- Checked and correctly assigned.
PROCESSED- Handled downstream, for example paid or passed on to the customer.
InvoiceStatus
Values
DRAFT- Being written: it can be changed and deleted and has no number yet. A published invoice an admin reopened for correction is a draft again, keeps its number and cannot be deleted.
APPROVED- A former internal sign-off that is no longer set. An invoice still in it goes back to draft or is published.
PUBLISHED- Issued: it has its number and due date, its content is frozen and it counts as billed. Only admins publish. From here it is marked as paid, canceled (which creates a cancellation invoice) or corrected.
CANCELED- Reversed by a cancellation invoice. Final: an issued invoice is never deleted.
PAID- The payment has arrived. Final, except that an admin can reverse the payment, which makes it PUBLISHED again.
InvoiceTypeEnum
Values
ADVANCE_PAYMENT- Asks for a percentage or a fixed amount of the job's total before or during the work. Needs an order confirmation; not combined with partial invoices in one billing cycle.
PARTIAL_INVOICE- Bills only the positions selected on it. Needs an order confirmation; as many as needed, not combined with an advance payment in one billing cycle.
FINAL_INVOICE- Bills the job's total minus everything invoiced before in the billing cycle; after it the cycle takes no more invoices. Also the type of an invoice without an order confirmation, which bills all it lists.
CANCELLATION_INVOICE- Reverses a published invoice figure for figure. Created by canceling that invoice; it gets its own number when published.
JiraConnectionStatus
Values
ACTIVE- Connection is healthy
AUTH_FAILED- Service credential was rejected by Jira
DISABLED- Connection manually disabled
JiraLinkSyncState
Values
PENDING- Link created, first sync not started yet
BACKFILLING- Initial full import running
ACTIVE- Incrementally syncing
ERROR- Last sync failed
JiraPushRequirement
Values
OWN_CONNECTION- Their own Jira connection (profile settings) — core Jira posts the worklog as them
ACCOUNT_MAPPING- An admin mapping their Jira account — Tempo posts the worklog for them
JiraScopeKind
Values
PROJECT- Every issue of the Jira project
EPICS- Only the chosen epics, with their children and sub-tasks
JiraTicketsMode
Values
REPLACE- Jira replaces the tickets area: the Tickets tab opens Jira, Boards and Roadmap are hidden
EXTEND- docket's own tickets stay; the Jira tickets are listed below them
JiraTokenStatus
Values
UNCHECKED- Token not verified yet
OK- Token verified against at least one connection
INVALID- Token was rejected by Jira
JiraWorklogBackend
Values
JIRA- Time tracked in Jira core worklogs
TEMPO- Time tracked via Tempo Timesheets
Locale
Values
DE- German
EN- English
NotificationAction
Values
TICKET_CREATED- Ticket was created
TICKET_CLOSED- Ticket was closed
TICKET_REOPENED- Ticket was reopened
TICKET_MENTIONED- A User was mentioned in a ticket
TICKET_ASSIGNED- Ticket was assigned to a user
TICKET_UNASSIGNED- Ticket was unassigned from a user
TICKET_PLANNED- Ticket was planned
TICKET_COMMENT_ADDED- Ticket comment was added
TICKET_COMMENT_MENTIONED- A user was mentioned in a ticket comment
TICKET_COMMENT_REACTED- Someone reacted to the user's ticket comment
QUOTATION_COMMENT_REACTED- Someone reacted to the user's quotation comment
ORDER_CONFIRMATION_COMMENT_REACTED- Someone reacted to the user's order confirmation comment
DELIVERY_NOTE_COMMENT_REACTED- Someone reacted to the user's delivery note comment
INVOICE_COMMENT_REACTED- Someone reacted to the user's invoice comment
QUOTATION_COMMENT_ADDED- Quotation comment was added
QUOTATION_COMMENT_MENTIONED- A user was mentioned in a quotation comment
ORDER_CONFIRMATION_COMMENT_ADDED- Order confirmation comment was added
ORDER_CONFIRMATION_COMMENT_MENTIONED- A user was mentioned in a order confirmation comment
DELIVERY_NOTE_COMMENT_ADDED- Delivery note comment was added
DELIVERY_NOTE_COMMENT_MENTIONED- A user was mentioned in a delivery note comment
INVOICE_COMMENT_ADDED- Invoice comment was added
INVOICE_COMMENT_MENTIONED- A user was mentioned in an invoice comment
QUOTATION_DRAFT- Quotation was set back to draft
QUOTATION_APPROVED- Quotation was approved
QUOTATION_PUBLISHED- Quotation was published
QUOTATION_CANCELED- Quotation was canceled
QUOTATION_CONFIRMED- Quotation was confirmed
ORDER_CONFIRMATION_DRAFT- Order confirmation was set back to draft
ORDER_CONFIRMATION_PUBLISHED- Order confirmation was published
DELIVERY_NOTE_DRAFT- Delivery note was set back to draft
DELIVERY_NOTE_PUBLISHED- Delivery note was published
INVOICE_DRAFT- Invoice was set back to draft
INVOICE_APPROVED- Invoice was approved
INVOICE_PUBLISHED- Invoice was published
INVOICE_CANCELED- Invoice was canceled
INVOICE_PAID- Invoice was paid
NotificationRecordType
Values
TICKETQUOTATIONINVOICEORDER_CONFIRMATIONDELIVERY_NOTE
OrderConfirmationStatus
Values
DRAFT- Not sent yet: its content can be changed, and confirming the quotation again overwrites it.
PUBLISHED- Ready to go to the customer: its content is locked, and the quotation cannot be confirmed again until it is a draft again.
ProjectActivityKind
Values
TICKET_OPENED- A ticket was created
TICKET_CLOSED- A ticket was closed
TICKET_REOPENED- A ticket was reopened
TICKET_COMMENTED- A ticket got a comment
TICKET_COMMENT_REACTED- Someone reacted to a ticket's comment (see emoji)
DOCUMENT_COMMENT_REACTED- Someone reacted to a comment on a quotation, order confirmation, delivery note or invoice (see document and emoji)
DOCUMENT- A quotation, order confirmation, delivery note or invoice changed state (see action)
ProjectBudget
Values
MINUTES- A budget of time for the whole project, in minutes; the booked time counts against it
MINUTES_PER_MONTH- A budget of time per calendar month, in minutes; the time booked in the current month counts against it
AMOUNT- A budget of money for the whole project, in the workspace's currency; the revenue of the booked time and the external costs count against it
AMOUNT_PER_MONTH- A budget of money per calendar month, in the workspace's currency; the current month counts against it
ProjectStatus
Values
REQUESTED- Customer has requested a new project
ON_HOLD- Project is on hold
IN_PROGRESS- Project is in progress
CANCELED- Project was canceled
DONE- Project is done
QuotationStatus
Values
DRAFT- Being written: its content can be changed, and it can be deleted.
APPROVED- A former internal sign-off that is no longer set. A quotation still in it moves on like a draft.
PUBLISHED- Sent to the customer: its content is locked. It is confirmed, canceled, or taken back to draft to change it. Needs a customer address.
CANCELED- Withdrawn or declined. It can be deleted, or reopened as a draft.
CONFIRMED- The customer accepted: the billing cycle's order confirmation is created from it (or updated, unless that is published). It can still be canceled or taken back to draft.
ReceiptSource
Values
E_INVOICE- An e-invoice inside the file, read exactly
AI- Read by the AI (Mistral) — to be checked
NONE- Nothing read
SavedViewList
Values
TICKETSBOARDSCONTROLLING_TIMETRACKINGSCONTROLLING_TICKETSPROJECTSFORECASTEXTERNAL_COSTSWORKLOAD_TICKETSTIMETRACKING_REPORTS
SearchResultModel
Values
PROJECTTICKETUSERQUOTATIONORDER_CONFIRMATIONDELIVERY_NOTEINVOICEEXTERNAL_COSTCUSTOMERCONTACT
SearchScope
Values
PROJECTSTICKETS- Tickets, found by their own text or a comment
DOCUMENTS- Quotations, order confirmations, delivery notes, invoices and external costs
PEOPLE- The team
CUSTOMERS- Customers and their contacts
SupplierTaxTreatment
Values
DOMESTIC- Invoices carry the workspace's country's VAT
REVERSE_CHARGE_EU- In another EU country: without VAT on the invoice the workspace owes the tax
REVERSE_CHARGE_THIRD_COUNTRY- Outside the EU: without VAT on the invoice the workspace owes the tax
TaxTreatment
Values
DOMESTIC- VAT is charged at the lines' rates
EU_REVERSE_CHARGE- Business customer in another EU country: no VAT, reverse-charge note
THIRD_COUNTRY- Customer outside the EU: no VAT, not taxable in Germany
EXEMPT- Tax-exempt supply: no VAT, exemption note
SMALL_BUSINESS- Only on documents: a domestic customer of a workspace under the small business scheme (§ 19 UStG): no VAT, § 19 note. An address can't have it.
NO_VAT- Only on documents issued before the reasons existed: no VAT, no note. An address can't have it.
TicketBudget
Values
MINUTES- A budget of time for the ticket, in minutes; the time booked on it counts against it
AMOUNT- A budget of money for the ticket, in the workspace's currency; the revenue of the time booked on it counts against it
TicketChangeField
What a line of a ticket's change entry is about (Ticket::ChangeLog::FIELDS)
Values
TITLEDESCRIPTIONASSIGNEESLABELSPRIORITYPHASESERVICESTART_DATEEND_DATE
TicketPriority
Values
HIGH- Ticket has high priority
NORMAL- Ticket has normal priority
LOW- Ticket has low priority
TicketScheduleBucket
Values
OVERDUE- Ended before today
THIS_WEEK- Lies in this week
THIS_MONTH- Ends later this month
NEXT_MONTH- Ends next month
LATER- Ends after next month
UNPLANNED- No dates
TicketStatus
Values
OPEN- Work to do
CLOSED- Done: closedAt and closedBy say when and by whom. It can be reopened.
TimetrackingBilling
Values
OPEN- Billable and on no invoice yet
BILLED- A line of an invoice, draft or issued
TimetrackingJiraSyncState
Values
PENDING- Queued to push to Jira
SYNCED- Pushed to the Jira worklog
FAILED- Push failed (see error)
NOT_SYNCABLE- User has no connected Jira token
UserRole
Values
TIMETRACKER- For freelancers and externals: sees only the projects they are assigned to (directly or through the customer) and only their own time. No financial data.
BASIC- The default for team members: sees all projects and tickets and the time booked on them, books time and changes only their own entries. No financial data; of a budget only how much is used.
PM- Project manager: everything BASIC can, plus financial data (rates, revenue, budgets), the billing documents and external costs, and creating projects and changing their settings. Prepares invoices but cannot publish them.
ADMIN- Everything: publishes invoices, corrects anyone's time entries, manages users, customers, services, suppliers, integrations and the workspace's settings.
WorkspaceExportStatus
Values
PENDING- Requested, waiting for the export job
PROCESSING- The ZIP is being built
READY- The ZIP can be downloaded (until expiresAt)
FAILED- Building the ZIP failed; a new export can be requested
Scalars
ISO8601Date
An ISO 8601-encoded date
ISO8601DateTime
An ISO 8601-encoded datetime
JSON
Represents untyped JSON
Json
Any JSON value: an object, a list, a string, a number or a boolean.
NegatableAccountingCycleStatus
An AccountingCycleStatus value; with a leading "!" it excludes that one, e.g. "!PAID".
NegatableExternalCostStatus
An ExternalCostStatus value; with a leading "!" it excludes that one, e.g. "!DRAFT".
NegatableProjectStatus
A ProjectStatus value; with a leading "!" it excludes that one, e.g. "!ARCHIVED".
NegatableTicketPriority
A TicketPriority value; with a leading "!" it excludes that one, e.g. "!LOW".