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

AdminPMBasicTracker

The workspace itself: its settings and company data.

Who may Only the caller's own workspace is returned; any other id gives null.

Arguments

id ID! 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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

Whether the workspace allows connecting AI apps over MCP.

Returns: Boolean!

Example

query {
  aiConnectionsEnabled
}

Response

{
  "data": {
    "aiConnectionsEnabled": true
  }
}

Query

apiTokens

AdminPMBasicTracker

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

AdminPMBasicTracker

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

from ISO8601Date! required
First day of the period
to ISO8601Date! 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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ContactFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ContactEdge!]!
A list of edges.
max Float
min Float
nodes [Contact!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

AdminPMBasicTracker

A custom field defined for a customer by id.

Who may Basic users, project managers and admins; null for timetrackers.

Arguments

id ID! 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

AdminPMBasicTracker

The custom fields defined for customers.

Who may Basic users, project managers and admins; an empty list for timetrackers.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter CustomFieldFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [CustomFieldEdge!]!
A list of edges.
max Float
min Float
nodes [CustomField!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

A customer's address by id.

Who may Null when the caller cannot see the customer (see customer).

Arguments

id ID! 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

AdminPMBasicTracker

Addresses of customers, limited to the customers the caller can see (see customers).

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter CustomerAddressFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [CustomerAddressEdge!]!
A list of edges.
max Float
min Float
nodes [CustomerAddress!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A customer by its slug, the name in its URL.

Who may Visibility as for customer.

Arguments

slug String! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter CustomerFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [CustomerEdge!]!
A list of edges.
max Float
min Float
nodes [Customer!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A delivery note by id.

Who may Project managers and admins only; null for everyone else.

Arguments

id ID! 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

AdminPMBasicTracker

A delivery note by its number and the project it belongs to.

Who may Visibility as for deliveryNote.

Arguments

number Int! required
projectId ID! 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

AdminPMBasicTracker

Delivery notes.

Who may Project managers and admins only; an empty list for everyone else.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter DeliveryNoteFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [DeliveryNoteEdge!]!
A list of edges.
max Float
min Float
nodes [DeliveryNote!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

Templates for quotations and invoices, sorted by name.

Who may Project managers and admins only; an empty list for everyone else.

Arguments

customerId ID
Only the templates offered for this customer's documents: its own and those for every customer
kind String
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

AdminPMBasicTracker

An external cost (a supplier's invoice) by id.

Who may Project managers and admins only; null for everyone else.

Arguments

id ID! 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

AdminPMBasicTracker

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

currency Currency! required
The currency of the supplier's invoice
amount Float
Net amount in the workspace's currency; leave out to have it converted from originalAmount
invoiceDate ISO8601Date
Decides which day's ECB rate applies
originalAmount Float
Net amount in the invoice's currency, when that is not the workspace's currency
taxRate Float
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

AdminPMBasicTracker

External costs (suppliers' invoices).

Who may Project managers and admins only; an empty list for everyone else.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ExternalCostFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ExternalCostEdge!]!
A list of edges.
max Float
min Float
nodes [ExternalCost!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

year Int
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

AdminPMBasicTracker

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

year Int! required
filter QuotationFilter
Narrows the quotations
invoiceFilter InvoiceFilter
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

AdminPMBasicTracker

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

AdminPMBasicTracker

An invoice by id.

Who may Project managers and admins only; null for everyone else.

Arguments

id ID! 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

AdminPMBasicTracker

An invoice by its invoice number.

Who may Visibility as for invoice.

Arguments

number Int! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter InvoiceFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [InvoiceEdge!]!
A list of edges.
max Float
min Float
nodes [Invoice!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A connected Jira site by id.

Who may Admins only.

Arguments

id ID! 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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

jiraConnectionId ID! required
jiraProjectKey String! required
The Jira project's key, e.g. "WEB"
query String
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

AdminPMBasicTracker

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

jiraConnectionId ID! required
jiraProjectKey String! required
The Jira project's key, e.g. "WEB"
excludeProjectId ID
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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

jiraConnectionId ID! required
query String
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

AdminPMBasicTracker

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

jiraConnectionId ID! required
query String! 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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

AdminPMBasicTracker

An order confirmation by id.

Who may Project managers and admins only; null for everyone else.

Arguments

id ID! 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

AdminPMBasicTracker

An order confirmation by its number and the project it belongs to.

Who may Visibility as for orderConfirmation.

Arguments

number Int! required
projectId ID! 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

AdminPMBasicTracker

Order confirmations.

Who may Project managers and admins only; an empty list for everyone else.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter OrderConfirmationFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [OrderConfirmationEdge!]!
A list of edges.
max Float
min Float
nodes [OrderConfirmation!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A project phase by id.

Who may Null when the caller cannot open its project.

Arguments

id ID! 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

AdminPMBasicTracker

Project phases, limited to projects the caller can open (see projects).

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter PhaseFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [PhaseEdge!]!
A list of edges.
max Float
min Float
nodes [Phase!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

A project by its slug, the name in its URL.

Who may Visibility as for project.

Arguments

slug String! 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

AdminPMBasicTracker

A ticket label of a project by id.

Who may Null when the caller cannot open its project.

Arguments

id ID! 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

AdminPMBasicTracker

The ticket labels of projects, limited to projects the caller can open (see projects).

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ProjectLabelFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ProjectLabelEdge!]!
A list of edges.
max Float
min Float
nodes [ProjectLabel!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ProjectFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ProjectEdge!]!
A list of edges.
groupBy ProjectGroup!
max Float
min Float
nodes [Project!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A quotation by id.

Who may Project managers and admins only; null for everyone else.

Arguments

id ID! 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

AdminPMBasicTracker

A quotation by its number and the project it belongs to.

Who may Visibility as for quotation.

Arguments

number Int! required
projectId ID! 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

AdminPMBasicTracker

Quotations of all projects that are not archived.

Who may Project managers and admins only; an empty list for everyone else.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter QuotationFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [QuotationEdge!]!
A list of edges.
max Float
min Float
nodes [Quotation!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

list SavedViewList! required
projectId ID
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

AdminPMBasicTracker

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

query String! required
The text to look for
customerSlug String
Only this customer's projects, what's in them, and its contacts
projectSlug String
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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

A service by its slug, the name in its URL.

Who may Visibility as for service.

Arguments

slug String! 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

AdminPMBasicTracker

The workspace's service categories (groups of services).

Who may Visible to everyone in the workspace.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ServiceCategoryFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ServiceCategoryEdge!]!
A list of edges.
max Float
min Float
nodes [ServiceCategory!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

A service category (a group of services) by id.

Who may Visible to everyone in the workspace.

Arguments

id ID! 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

AdminPMBasicTracker

A service category by its slug, the name in its URL.

Arguments

slug String! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter ServiceFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [ServiceEdge!]!
A list of edges.
max Float
min Float
nodes [Service!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

sharedProjectReport

AdminPMBasicTracker

A public report link of a project by id.

Who may Project managers and admins only, and only for projects they can open; null otherwise.

Arguments

id ID! required

Returns: SharedProjectReport

Example

query SharedProjectReport($id: ID!) {
  sharedProjectReport(id: $id) {
    id
    createdAt
    budgetRate
    budgetType
    budgetUsed
    crypt
  }
}

Variables

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}

Response

{
  "data": {
    "sharedProjectReport": {
      "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
      "createdAt": "2026-11-13T09:30:00+01:00",
      "budgetRate": 120.5,
      "budgetType": "MINUTES",
      "budgetUsed": 120.5,
      "crypt": "text"
    }
  }
}

Query

stopwatches

AdminPMBasicTracker

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

AdminPMBasicTracker

A supplier by id.

Who may Basic users, project managers and admins; null for timetrackers.

Arguments

id ID! 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

AdminPMBasicTracker

A supplier by its slug, the name in its URL.

Who may Visibility as for supplier.

Arguments

slug String! 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

AdminPMBasicTracker

The workspace's suppliers, archived ones included unless filtered.

Who may Basic users, project managers and admins; an empty list for timetrackers.

Arguments

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter SupplierFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [SupplierEdge!]!
A list of edges.
max Float
min Float
nodes [Supplier!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

A ticket by its number within a project.

Who may Visibility as for ticket.

Arguments

number Int! required
The ticket's number within its project
projectId ID! 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

AdminPMBasicTracker

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

number Int! required
The ticket's number within its project
projectSlug String! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter TicketFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [TicketEdge!]!
A list of edges.
groupBy TicketGroup!
max Float
min Float
nodes [Ticket!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

date ISO8601Date! required
The day of the time entry
ticketId ID! 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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter TimetrackingFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [TimetrackingEdge!]!
A list of edges.
groupBy TimetrackingGroup!
max Float
min Float
nodes [Timetracking!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

A person of the workspace by their slug, the name in their profile's URL.

Arguments

slug String! 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

AdminPMBasicTracker

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

id ID! 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

AdminPMBasicTracker

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

after String
Returns the elements in the list that come after the specified cursor.
before String
Returns the elements in the list that come before the specified cursor.
filter UserFilter
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>"].
first Int
Returns the first _n_ elements from the list.
last Int
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.
page Int
Page number, starting at 1. Only takes effect together with perPage. The cursor arguments (first/after) page through the same list instead.
perPage Int
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

count Int!
edges [UserEdge!]!
A list of edges.
max Float
min Float
nodes [User!]!
A list of nodes.
pageInfo PageInfo!
Information to aid in pagination.
sum Float
totalCount Int!

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

AdminPMBasicTracker

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

AdminPMBasicTracker

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

AdminPMBasicTracker

The events a webhook can ask for

Returns: [String!]!

Example

query {
  webhookEvents
}

Response

{
  "data": {
    "webhookEvents": [
      "text"
    ]
  }
}

Query

workloadOverview

AdminPMBasicTracker

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

excludeGeneral Boolean
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

AdminPMBasicTracker

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

id ID! required
The billing cycle (accounting) of a project

Answer

accounting Accounting
errors Json

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newIndex Int
Where the block goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newIndex Int
Where the block goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
newIndex Int! required
Where the block goes, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
newIndex Int! required
Where the block goes, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newIndex Int
Where the block goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
The block's place in the document, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newIndex Int
Where the block goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
optional Boolean! required
Offered as an option: printed, but not counted into the total
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! 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
title String! required
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
newPositionIndex Int
Where in that block the position goes, counted from 0
selected Boolean
Ticked: a partial or final invoice bills the position

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
newPositionIndex Int
Where in that block the position goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
selected Boolean
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
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
newPositionIndex Int! required
Where in that block the position goes, counted from 0
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
selected Boolean
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
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
newBlockIndex Int! required
The block the position goes into, counted from 0
newPositionIndex Int! required
Where in that block the position goes, counted from 0
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
optional Boolean
Offered as an option: printed, but not counted into the total
selected Boolean
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
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! required
The draft quotation or invoice to change
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
newPositionIndex Int
Where in that block the position goes, counted from 0
optional Boolean
Offered as an option: printed, but not counted into the total
selected Boolean
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
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! required
The draft quotation or invoice to change
selected Boolean! required
Ticked: a partial or final invoice bills the position
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
newPositionIndex Int
Where in that block the position goes, counted from 0
optional Boolean
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
title String

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

blockIndex Int! required
The place of the position's block in the document, counted from 0
optional Boolean! required
Offered as an option: printed, but not counted into the total
positionIndex Int! required
The position's place in its block, counted from 0
recordId ID! 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
title String! required
description String
footer String
id ID
newBlockIndex Int
The block the position goes into, counted from 0
newPositionIndex Int
Where in that block the position goes, counted from 0
selected Boolean
Ticked: a partial or final invoice bills the position

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

recordId ID! required
The quotation or invoice the line is meant for; its project's rates price the line
amount Float
For a flatrate line: the net price
description String
id String
name String
The label of a custom or flatrate line
optional Boolean
Offered as an option: printed, but not counted into the total
quantity Float
How many units; for a service line, hours or days
rate Float
For a custom line: the net price per unit
service BlockPositionSubpositionServiceEnum
Whether the line is the agency's own work or an external service
serviceId String
For a service line: the service's id as the document's billing cycle lists its rates (a_<accounting id>_<service id>)
taxRate Float
VAT rate in percent; omit for the document's rate
type BlockPositionSubpositionTypeEnum
service: time of a service at the project's rate; custom: a free line with rate and quantity; flatrate: a fixed amount
unit String
For a service line hours or days (a day is 8 hours); for a custom line any unit to print

Answer

errors Json

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

AdminPMBasicTracker

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

projectId ID
ticketStatus TicketStatus
The status a ticket takes when it is put into this column
title String

Answer

board Board
errors Json

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

AdminPMBasicTracker

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

id ID! required

Answer

board Board
errors Json

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

AdminPMBasicTracker

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

id ID! required
toPosition Int! required
The new position, counted from 1

Answer

board Board
errors Json
project Project

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

AdminPMBasicTracker

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

id ID! required
projectId ID
ticketStatus TicketStatus
The status a ticket takes when it is put into this column
title String

Answer

board Board
errors Json

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

AdminPMBasicTracker

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

commentId ID! required
emoji String! required
A single emoji. A comment takes at most 20 different ones
kind CommentOn! required
What the comment is on

Answer

comment CommentUnion
errors Json

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

AdminPMBasicTracker

Adds a contact person and links them to customers.

Who may Admins only.

Arguments

archived Boolean
customerIds [ID!]
The customers this person is a contact of; replaces the whole list
department String
email String
firstname String
lastname String
phone String
salutation String
title String

Answer

contact Contact
errors Json

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

AdminPMBasicTracker

Deletes a contact person; quotations and invoices that named them keep existing without a contact.

Who may Admins only.

Arguments

id ID! required

Answer

contact Contact
errors Json

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

AdminPMBasicTracker

Changes a contact person. Only the arguments sent are changed.

Who may Admins only.

Arguments

id ID! required
archived Boolean
customerIds [ID!]
The customers this person is a contact of; replaces the whole list
department String
email String
firstname String
lastname String
phone String
salutation String
title String

Answer

contact Contact
errors Json

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

AdminPMBasicTracker

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

archived Boolean
customerId ID
The customer whose documents carry the field
defaultValue String
fieldType String
text or contact
label String
name String

Answer

customField CustomField
errors Json

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

AdminPMBasicTracker

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

id ID! required

Answer

customField CustomField
errors Json

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

AdminPMBasicTracker

Changes a customer's custom field. Only the arguments sent are changed.

Who may Admins only.

Arguments

id ID! required
archived Boolean
customerId ID
The customer whose documents carry the field
defaultValue String
fieldType String
text or contact
label String
name String

Answer

customField CustomField
errors Json

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

AdminPMBasicTracker

Adds a customer. Its addresses (which carry the customer number) are added with createCustomerAddress.

Who may Admins only.

Arguments

accountingCommissionPercent Float
Commission in percent on the external costs billed in a document
accountingCommissionThreshold Float
Net total of external costs in a document from which the commission applies
archived Boolean
company String
datevAccount String
The customer's own account (debtor number) in DATEV; empty = the collective account
description String
email String
initial String
invoiceFooterDe String
invoiceFooterEn String
masterAgreement Boolean
The customer has a master agreement; advance-payment invoices then name it
paymentTermDays Int
This customer's payment term in days, 0 to 365; null = the workspace's
phone String
quotationFooterDe String
quotationFooterEn String
serviceRates [ServiceRateInput!]
The customer's own daily rates; id is a ServiceRate id as Customer.serviceRates returns it
web String

Answer

customer Customer
errors Json

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

AdminPMBasicTracker

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

id ID! required

Answer

customer Customer
errors Json

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

AdminPMBasicTracker

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

id ID! required
accountingCommissionPercent Float
Commission in percent on the external costs billed in a document
accountingCommissionThreshold Float
Net total of external costs in a document from which the commission applies
archived Boolean
company String
datevAccount String
The customer's own account (debtor number) in DATEV; empty = the collective account
description String
email String
initial String
invoiceFooterDe String
invoiceFooterEn String
masterAgreement Boolean
The customer has a master agreement; advance-payment invoices then name it
paymentTermDays Int
This customer's payment term in days, 0 to 365; null = the workspace's
phone String
quotationFooterDe String
quotationFooterEn String
serviceRates [ServiceRateInput!]
The customer's own daily rates; id is a ServiceRate id as Customer.serviceRates returns it
updateTimetrackings Boolean
true: time already booked for this customer is repriced where a service's rate changed, in the background
web String

Answer

customer Customer
errors Json

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

AdminPMBasicTracker

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

customerId ID! required
address1 String
address2 String
buyerReference String
The e-invoice's buyer reference (BT-10), e.g. a Leitweg-ID
city String
country String
Free text, from before the list; prefer countryCode
countryCode String
ISO 3166-1 alpha-2
department String
invoiceEmail String
Where this customer receives e-invoices (BT-49)
number Int
The customer number; typed where the workspace numbers its customers itself, else docket's
recipient String
taxTreatment TaxTreatment
vatNo String
zip String

Answer

customerAddress CustomerAddress
errors Json

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

AdminPMBasicTracker

Removes an address of a customer. Refused for an address that documents were written to.

Who may Admins only.

Arguments

id ID! required

Answer

customerAddress CustomerAddress
errors Json

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

AdminPMBasicTracker

Changes an address of a customer. Only the arguments sent are changed.

Who may Admins only.

Arguments

id ID! required
address1 String
address2 String
buyerReference String
The e-invoice's buyer reference (BT-10), e.g. a Leitweg-ID
city String
country String
Free text, from before the list; prefer countryCode
countryCode String
ISO 3166-1 alpha-2
department String
invoiceEmail String
Where this customer receives e-invoices (BT-49)
number Int
The customer number; typed where the workspace numbers its customers itself, else docket's
recipient String
taxTreatment TaxTreatment
vatNo String
zip String

Answer

customerAddress CustomerAddress
errors Json

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

AdminPMBasicTracker

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

authorId ID
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
footer String
invoiceId ID
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The delivery note's running number within its project; the next free one when omitted
orderConfirmationId ID
showPositionSubtotal Boolean

Answer

deliveryNote DeliveryNote
errors Json

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

AdminPMBasicTracker

Deletes a delivery note.

Who may Admins only.

Arguments

id ID! required

Answer

deliveryNote DeliveryNote
errors Json

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

AdminPMBasicTracker

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

id ID! required

Answer

deliveryNote DeliveryNote
errors Json

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

AdminPMBasicTracker

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

id ID! required

Answer

deliveryNote DeliveryNote
errors Json

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

AdminPMBasicTracker

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

id ID! required
authorId ID
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The delivery note's running number within its project; the next free one when omitted
showPositionSubtotal Boolean

Answer

deliveryNote DeliveryNote
errors Json

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

AdminPMBasicTracker

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

authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
deliveryNoteId ID
The delivery note to comment on; needed when creating, ignored when updating

Answer

deliveryNoteComment DeliveryNoteComment
errors Json

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

AdminPMBasicTracker

Deletes a comment on a delivery note.

Who may Only its author, as long as they are a project manager or admin.

Arguments

id ID! required

Answer

deliveryNoteComment DeliveryNoteComment
errors Json

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

AdminPMBasicTracker

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

id ID! required
authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
deliveryNoteId ID
The delivery note to comment on; needed when creating, ignored when updating

Answer

deliveryNoteComment DeliveryNoteComment
errors Json

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

AdminPMBasicTracker

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

index Int! required
Its place in the document's list of discounts and surcharges, counted from 0
recordId ID! required
The draft quotation or invoice to change
type DiscountSurchargeTypeEnum! required
amount Float
The net amount as a positive number; a discount is subtracted, a surcharge added
title String

Answer

discountSurcharge JSON
errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
Its place in the document's list of discounts and surcharges, counted from 0
recordId ID! required
The draft quotation or invoice to change
amount Float
The net amount as a positive number; a discount is subtracted, a surcharge added
title String

Answer

discountSurcharge JSON
errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

index Int! required
Its place in the document's list of discounts and surcharges, counted from 0
recordId ID! required
The draft quotation or invoice to change
amount Float
The net amount as a positive number; a discount is subtracted, a surcharge added
title String

Answer

discountSurcharge JSON
errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

plan Json! required
As askDocumentAssistant answered it
recordId ID! required
The draft quotation or invoice
uploadKey String
The file it came from, attached to the comment

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

message String! required
What the document should get, in plain words; at most 4,000 characters
recordId ID! required
The quotation's or invoice's id
history [DocumentAssistantTurnInput!]
The conversation so far, oldest first
uploadKey String
An XLSX or CSV from /api/upload

Answer

errors Json
notice String
Why nothing came of it
plan Json
To hand to applyDocumentPlan as it is
summary String

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

AdminPMBasicTracker

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

documentId ID! required
The empty quotation or invoice to fill
id ID! required

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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

documentId ID! required
The quotation or invoice to save
name String! required
customerId ID
Offer it only for this customer; omit for every customer
note String
An internal note on what the template is for

Answer

documentTemplate DocumentTemplate
errors Json

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

AdminPMBasicTracker

Deletes a template. Documents started from it keep their content.

Who may Project managers and admins.

Arguments

id ID! required

Answer

documentTemplate DocumentTemplate
errors Json

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

AdminPMBasicTracker

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

id ID! required
customerId ID
null: offer it for every customer
documentId ID
Replace the template's content with this quotation's or invoice's
name String
note String
An internal note on what the template is for

Answer

documentTemplate DocumentTemplate
errors Json

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

AdminPMBasicTracker

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

id ID! required
projectId ID! required

Answer

errors Json
invoice Invoice
quotation Quotation

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

AdminPMBasicTracker

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
amount Float
Net, in the workspace's currency
assignmentsAttributes [ExternalCostAssignmentInput!]
Always send all positions, since using this argument will replace the whole collection
blobId ID
The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currency Currency
The invoice's currency, where it is not the workspace's
inputTaxDeductible Boolean
Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDate ISO8601Date
invoiceNumber String
originalAmount Float
Net in the invoice's currency; amount is then the net in the workspace's (omitted: at the ECB rate of the invoice date)
partialAmount Boolean
true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBill Boolean
One of several invoices from the supplier for the same job
relatedCostId String
Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
supplierId ID
tax Float
The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRate Float
In percent
userId ID
The responsible person; they get an email when it is set or changed

Answer

errors Json
externalCosts ExternalCostConnection

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

AdminPMBasicTracker

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

amount Float
Net, in the workspace's currency
assignmentsAttributes [ExternalCostAssignmentInput!]
Always send all positions, since using this argument will replace the whole collection
blobId ID
The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currency Currency
The invoice's currency, where it is not the workspace's
inputTaxDeductible Boolean
Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDate ISO8601Date
invoiceNumber String
originalAmount Float
Net in the invoice's currency; amount is then the net in the workspace's (omitted: at the ECB rate of the invoice date)
partialAmount Boolean
true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBill Boolean
One of several invoices from the supplier for the same job
relatedCostId String
Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
supplierId ID
tax Float
The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRate Float
In percent
userId ID
The responsible person; they get an email when it is set or changed

Answer

errors Json
externalCost ExternalCost

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

AdminPMBasicTracker

Deletes an external cost together with its assignments to projects and quotations.

Who may Project managers and admins.

Arguments

id ID! required

Answer

errors Json
externalCost ExternalCost

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

AdminPMBasicTracker

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

blobId ID! required
A file uploaded through /api/upload, or the invoice file of an existing external cost
withAi Boolean
Read with AI if there's no e-invoice (the wand); else only when the workspace reads every upload

Answer

amount Float
Net
currency String
As the invoice says; amount and tax are in it
errors Json
exchangeRate ExchangeRate
The ECB rate of the invoice date, for an invoice in another currency docket can convert
invoiceDate ISO8601Date
invoiceNumber String
mixedTaxRates Boolean
notice String
Why nothing was read, when it says
source ReceiptSource
supplier Supplier
The workspace's supplier of that name
supplierName String
tax Float
The VAT amount the invoice states
taxRate Float

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

AdminPMBasicTracker

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

id ID! required
amount Float
Net, in the workspace's currency
assignmentsAttributes [ExternalCostAssignmentInput!]
Always send all positions, since using this argument will replace the whole collection
blobId ID
The supplier's invoice file: the id of a file uploaded through /api/upload. Required on create; on update it replaces the file.
currency Currency
The invoice's currency, where it is not the workspace's
inputTaxDeductible Boolean
Omitted on a new cost: taken from the workspace's VAT status on the invoice date
invoiceDate ISO8601Date
invoiceNumber String
originalAmount Float
Net in the invoice's currency; amount is then the net in the workspace's (omitted: at the ECB rate of the invoice date)
partialAmount Boolean
true: the cost is split over several assignments; false: it goes to one quotation as a whole
partialBill Boolean
One of several invoices from the supplier for the same job
relatedCostId String
Another cost of the same supplier this one belongs with: both join one group (see relatedCosts). An empty string takes it out
supplierId ID
tax Float
The VAT amount as the invoice states it; omitted, it is worked out from amount and rate
taxRate Float
In percent
userId ID
The responsible person; they get an email when it is set or changed

Answer

errors Json
externalCost ExternalCost

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

AdminPMBasicTracker

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

following Boolean! required
true follows, false unfollows
id ID! required
ID of a ticket, a project, a quotation, an order confirmation, a delivery note or an invoice

Answer

errors Json
followableId ID
viewerIsFollowing Boolean

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

AdminPMBasicTracker

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

id ID! required
canceledNote String
Why it was canceled; kept with the canceled invoice

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required
note String
Why it is corrected — kept as the canceled invoice's note

Answer

errors Json
invoice Invoice
The new draft

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

AdminPMBasicTracker

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

invoiceType InvoiceTypeEnum! required
authorId ID
blocks Json
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
deductionType String
How to read deductionValue: percentage_amount or fixed_amount. Advance payments only
deductionValue Float
An advance payment's share of the job: a percentage (above 0, up to 100) or a net amount, as deductionType says
deliveryDate ISO8601Date
The date of delivery or service printed on the invoice; today when omitted on creation
description String
discountSurcharge Json
The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The invoice number. Leave it out: publishing assigns the next one in the workspace's sequence
orderConfirmationId ID
The order confirmation whose billing cycle the invoice joins
projectId ID
The project to bill, for an invoice without a quotation or order confirmation
quotationId ID
The quotation whose billing cycle the invoice joins
showPositionSubtotal Boolean
status InvoiceStatus
Only PUBLISHED can be set, in updateInvoice and by admins; every other status change has its own mutation
taxRate Float
The VAT rate lines use unless they set their own; fixed once the document leaves draft
timetrackingsAsPosition Boolean
Take the project's time entries that are still open (billable, on no other invoice) as lines
timetrackingsFrom ISO8601Date
Only entries from this day on
timetrackingsUntil ISO8601Date
Only entries up to this day

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

month ISO8601Date! required
Any day of the month to invoice
projectId ID! required

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required
projectId ID! required
The project the copy goes into

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required
paidAt ISO8601DateTime
When the payment arrived; now when omitted

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required
notSentToCustomer Boolean! required
The customer hasn't received this invoice
reason String! required
What is wrong — kept with the correction

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

id ID! required
authorId ID
blocks Json
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
deductionType String
How to read deductionValue: percentage_amount or fixed_amount. Advance payments only
deductionValue Float
An advance payment's share of the job: a percentage (above 0, up to 100) or a net amount, as deductionType says
deliveryDate ISO8601Date
The date of delivery or service printed on the invoice; today when omitted on creation
description String
discountSurcharge Json
The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footer String
invoiceType InvoiceTypeEnum
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The invoice number. Leave it out: publishing assigns the next one in the workspace's sequence
showPositionSubtotal Boolean
status InvoiceStatus
Only PUBLISHED can be set, in updateInvoice and by admins; every other status change has its own mutation
taxRate Float
The VAT rate lines use unless they set their own; fixed once the document leaves draft

Answer

errors Json
invoice Invoice

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

AdminPMBasicTracker

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

authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
invoiceId ID
The invoice to comment on; needed when creating, ignored when updating

Answer

errors Json
invoiceComment InvoiceComment

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

AdminPMBasicTracker

Deletes a comment on an invoice.

Who may Only its author, as long as they are a project manager or admin.

Arguments

id ID! required

Answer

errors Json
invoiceComment InvoiceComment

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

AdminPMBasicTracker

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

id ID! required
authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
invoiceId ID
The invoice to comment on; needed when creating, ignored when updating

Answer

errors Json
invoiceComment InvoiceComment

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

AdminPMBasicTracker

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

userId ID! required
The caller's own user id

Answer

errors Json
notifications [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

AdminPMBasicTracker

Marks one notification as read.

Who may Only the person it was sent to.

Arguments

id ID! required

Answer

errors Json
notification Notification

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

AdminPMBasicTracker

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

archived Boolean! required
isNew Boolean! required
false marks them as read, true as unread
records [NotificationRecordInput!]! required

Answer

errors Json
notifications [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

AdminPMBasicTracker

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

quotationId ID! required
The quotation it confirms
authorId ID
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The order confirmation's running number within its project; the next free one when omitted
showPositionSubtotal Boolean

Answer

errors Json
orderConfirmation OrderConfirmation

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

AdminPMBasicTracker

Deletes an order confirmation.

Who may Admins only.

Arguments

id ID! required

Answer

errors Json
orderConfirmation OrderConfirmation

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
orderConfirmation OrderConfirmation

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
orderConfirmation OrderConfirmation

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

AdminPMBasicTracker

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

id ID! required
authorId ID
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The order confirmation's running number within its project; the next free one when omitted
showPositionSubtotal Boolean

Answer

errors Json
orderConfirmation OrderConfirmation

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

AdminPMBasicTracker

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

authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
orderConfirmationId ID
The order confirmation to comment on; needed when creating, ignored when updating

Answer

errors Json
orderConfirmationComment OrderConfirmationComment

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

AdminPMBasicTracker

Deletes a comment on an order confirmation.

Who may Only its author, as long as they are a project manager or admin.

Arguments

id ID! required

Answer

errors Json
orderConfirmationComment OrderConfirmationComment

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

AdminPMBasicTracker

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

id ID! required
authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
orderConfirmationId ID
The order confirmation to comment on; needed when creating, ignored when updating

Answer

errors Json
orderConfirmationComment OrderConfirmationComment

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

AdminPMBasicTracker

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

description String
endDate String
ISO 8601 date (YYYY-MM-DD)
projectId ID
startDate String
ISO 8601 date (YYYY-MM-DD)
title String

Answer

errors Json
phase Phase

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

AdminPMBasicTracker

Deletes a phase. Its tickets stay in the project, without a phase.

Who may Project managers and admins.

Arguments

id ID! required

Answer

errors Json
phase Phase

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

AdminPMBasicTracker

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

id ID! required
toPosition Int! required
The new position, counted from 1

Answer

errors Json
phase Phase
project Project

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

AdminPMBasicTracker

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

id ID! required
description String
endDate String
ISO 8601 date (YYYY-MM-DD)
projectId ID
startDate String
ISO 8601 date (YYYY-MM-DD)
title String

Answer

errors Json
phase Phase

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

AdminPMBasicTracker

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

archived Boolean
budgetRate Float
The budget in the unit of budgetType: minutes, or an amount in the workspace's currency
budgetType ProjectBudget
customerId ID
deadline ISO8601Date
description String
number Int
Project number, unique in the workspace. Default: the next free number
retainerBillsOverage Boolean
Whether hours beyond the contingent (a budget of hours per month) are billed on top of the fee. Default: true
retainerContingentMinutes Int
The hours one fee covers, in minutes per period (month or quarter). Null: the budget stands in when it is hours per month
retainerEndsOn ISO8601Date
The last day of the retainer; null for an open-ended one
retainerFee Float
The retainer's fee per period (month or quarter), net, in the workspace's currency
retainerIntervalMonths Int
1: billed monthly (default); 3: billed quarterly, counted from the month it starts in
retainerNoticeMonths Int
The notice period in months
retainerStartsOn ISO8601Date
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. id is a rate's id as serviceRates returns it (it ends in the service's id)
status ProjectStatus
statusDate ISO8601Date
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
title String

Answer

errors Json
project Project

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
project Project

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

AdminPMBasicTracker

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

id ID! required
archived Boolean
budgetRate Float
The budget in the unit of budgetType: minutes, or an amount in the workspace's currency
budgetType ProjectBudget
customerId ID
deadline ISO8601Date
description String
number Int
Project number, unique in the workspace. Default: the next free number
retainerBillsOverage Boolean
Whether hours beyond the contingent (a budget of hours per month) are billed on top of the fee. Default: true
retainerContingentMinutes Int
The hours one fee covers, in minutes per period (month or quarter). Null: the budget stands in when it is hours per month
retainerEndsOn ISO8601Date
The last day of the retainer; null for an open-ended one
retainerFee Float
The retainer's fee per period (month or quarter), net, in the workspace's currency
retainerIntervalMonths Int
1: billed monthly (default); 3: billed quarterly, counted from the month it starts in
retainerNoticeMonths Int
The notice period in months
retainerStartsOn ISO8601Date
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. id is a rate's id as serviceRates returns it (it ends in the service's id)
status ProjectStatus
statusDate ISO8601Date
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
title String
updateTimetrackings Boolean
true: time already booked on services whose rate changed is repriced at the new rate

Answer

errors Json
project Project

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

AdminPMBasicTracker

Adds a label to a project, to tag its tickets with. projectId, title and color are required.

Who may Project managers and admins.

Arguments

color String
Hex colour code: #rgb or #rrggbb
description String
projectId ID
title String

Answer

errors Json
projectLabel ProjectLabel

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

AdminPMBasicTracker

Deletes a label and takes it off every ticket that carries it.

Who may Project managers and admins.

Arguments

id ID! required

Answer

errors Json
projectLabel ProjectLabel

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

AdminPMBasicTracker

Changes a label's title, description or colour. The label stays in its project: projectId is ignored.

Who may Project managers and admins.

Arguments

id ID! required
color String
Hex colour code: #rgb or #rrggbb
description String
projectId ID
title String

Answer

errors Json
projectLabel ProjectLabel

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

AdminPMBasicTracker

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

id ID! required
mode BudgetHandoffMode! required

Answer

errors Json
project Project

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

AdminPMBasicTracker

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

id ID! required
canceledNote String
Why it was canceled; shown with the quotation

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required
confirmationFile String
The customer's signed confirmation as a data URL (data:application/pdf;base64,...): a PDF of at most 2 MB
confirmationFilename String
The file name to store the confirmation under
confirmedNote String
A note on the confirmation, e.g. how the customer accepted

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

projectId ID! required
authorId ID
blocks Json
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
discountSurcharge Json
The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The quotation's running number within its project; the next free one when omitted
showPositionSubtotal Boolean
taxRate Float
The VAT rate lines use unless they set their own; fixed once the document leaves draft

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required
moveExternalCostsToId ID
Another quotation of the same project that takes over this one's external costs
unassignExternalCosts Boolean
Take the external costs off the quotation and set them back to draft

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required
projectId ID! required
The project the copy goes into

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required
authorId ID
blocks Json
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
customerAddressId ID
One of the customer's addresses; the document is made out to it
description String
discountSurcharge Json
The whole list of discounts and surcharges, each with type (discount or surcharge), title and amount (net). Only in a draft
footer String
language String
The language the document is printed in, as a locale code: de (the default) or en
name String
number Int
The quotation's running number within its project; the next free one when omitted
showPositionSubtotal Boolean
taxRate Float
The VAT rate lines use unless they set their own; fixed once the document leaves draft

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

id ID! required
confirmationFile String
The customer's signed confirmation as a data URL (data:application/pdf;base64,...): a PDF of at most 2 MB
confirmationFilename String
The file name to store the confirmation under

Answer

errors Json
quotation Quotation

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

AdminPMBasicTracker

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

authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
quotationId ID
The quotation to comment on; needed when creating, ignored when updating

Answer

errors Json
quotationComment QuotationComment

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

AdminPMBasicTracker

Deletes a comment on a quotation.

Who may Only its author, as long as they are a project manager or admin.

Arguments

id ID! required

Answer

errors Json
quotationComment QuotationComment

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

AdminPMBasicTracker

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

id ID! required
authorId ID
body Json
The comment as a rich-text document in the editor's JSON format (Tiptap/ProseMirror)
quotationId ID
The quotation to comment on; needed when creating, ignored when updating

Answer

errors Json
quotationComment QuotationComment

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

AdminPMBasicTracker

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

list SavedViewList! required
name String! required
query String! required
The list's URL query string (its filters), at most 2000 characters
projectId ID
For a project's lists (its tickets, its controlling)
shared Boolean
For everyone in the project or workspace (PMs and admins)

Answer

errors Json
savedView SavedView

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

AdminPMBasicTracker

Deletes a saved view.

Who may Own views: their owner. Shared views: project managers and admins.

Arguments

id ID! required

Answer

errors Json
savedView SavedView

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

AdminPMBasicTracker

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

archived Boolean
billable Boolean
Whether time booked on this service is billed to the customer
dailyRate Float
Net, in the workspace's currency
defaultTaxRate Float
The VAT rate in percent a document line of this service starts with; null = the document's
description String
serviceCategoryId ID
title String

Answer

errors Json
service Service

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

AdminPMBasicTracker

Deletes a service. Fails for a service that time was booked on; set archived with updateService instead.

Who may Admins only.

Arguments

id ID! required

Answer

errors Json
service Service

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

AdminPMBasicTracker

Changes a service. Send updateTimetrackings: true to reprice the time already booked on it with the new rate.

Who may Admins only.

Arguments

id ID! required
archived Boolean
billable Boolean
Whether time booked on this service is billed to the customer
dailyRate Float
Net, in the workspace's currency
defaultTaxRate Float
The VAT rate in percent a document line of this service starts with; null = the document's
description String
serviceCategoryId ID
title String
updateTimetrackings Boolean
true: time already booked on this service is repriced with the new rate, in the background

Answer

errors Json
service Service

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

AdminPMBasicTracker

Adds a category that groups services.

Who may Admins only.

Arguments

title String

Answer

errors Json
serviceCategory ServiceCategory

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

AdminPMBasicTracker

Deletes a service category. Fails while services or tickets still use it.

Who may Admins only.

Arguments

id ID! required

Answer

errors Json
serviceCategory ServiceCategory

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

AdminPMBasicTracker

Renames a service category.

Who may Admins only.

Arguments

id ID! required
title String

Answer

errors Json
serviceCategory ServiceCategory

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

Mutation

createSharedProjectReport

AdminPMBasicTracker

Creates a public link to a project's report, meant for the customer: whoever has the link opens the report without signing in. projectId is required.

Who may Project managers and admins.

Arguments

expiresOn ISO8601Date
Last day the link works; null: no end
projectId ID
showBudget Boolean
Shows the budget and the revenue of the time entries
showExecutive Boolean
Shows who booked the time
showTickets Boolean
Adds the list of the project's tickets. Default: false

Answer

errors Json
project Project
sharedProjectReport SharedProjectReport

Example

mutation CreateSharedProjectReport($input: CreateSharedProjectReportInput!) {
  createSharedProjectReport(input: $input) {
    errors
    project {
      id
      number
      pnr
      title
      status
      createdAt
    }
    sharedProjectReport {
      id
      createdAt
      budgetRate
      budgetType
      budgetUsed
      crypt
    }
  }
}

Variables

{
  "input": {
    "projectId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  }
}

Response

{
  "data": {
    "createSharedProjectReport": {
      "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"
      },
      "sharedProjectReport": {
        "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
        "createdAt": "2026-11-13T09:30:00+01:00",
        "budgetRate": 120.5,
        "budgetType": "MINUTES",
        "budgetUsed": 120.5,
        "crypt": "text"
      }
    }
  }
}

Mutation

deleteSharedProjectReport

AdminPMBasicTracker

Deletes a public report link: it stops working at once.

Who may Project managers and admins.

Arguments

id ID! required

Answer

errors Json
project Project
sharedProjectReport SharedProjectReport

Example

mutation DeleteSharedProjectReport($input: DeleteSharedProjectReportInput!) {
  deleteSharedProjectReport(input: $input) {
    errors
    project {
      id
      number
      pnr
      title
      status
      createdAt
    }
    sharedProjectReport {
      id
      createdAt
      budgetRate
      budgetType
      budgetUsed
      crypt
    }
  }
}

Variables

{
  "input": {
    "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  }
}

Response

{
  "data": {
    "deleteSharedProjectReport": {
      "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"
      },
      "sharedProjectReport": {
        "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
        "createdAt": "2026-11-13T09:30:00+01:00",
        "budgetRate": 120.5,
        "budgetType": "MINUTES",
        "budgetUsed": 120.5,
        "crypt": "text"
      }
    }
  }
}

Mutation

updateSharedProjectReport

AdminPMBasicTracker

Changes what a public report link shows or when it ends; the link itself stays the same.

Who may Project managers and admins.

Arguments

id ID! required
expiresOn ISO8601Date
Last day the link works; null: no end
projectId ID
showBudget Boolean
Shows the budget and the revenue of the time entries
showExecutive Boolean
Shows who booked the time
showTickets Boolean
Adds the list of the project's tickets. Default: false

Answer

errors Json
project Project
sharedProjectReport SharedProjectReport

Example

mutation UpdateSharedProjectReport($input: UpdateSharedProjectReportInput!) {
  updateSharedProjectReport(input: $input) {
    errors
    project {
      id
      number
      pnr
      title
      status
      createdAt
    }
    sharedProjectReport {
      id
      createdAt
      budgetRate
      budgetType
      budgetUsed
      crypt
    }
  }
}

Variables

{
  "input": {
    "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  }
}

Response

{
  "data": {
    "updateSharedProjectReport": {
      "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"
      },
      "sharedProjectReport": {
        "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
        "createdAt": "2026-11-13T09:30:00+01:00",
        "budgetRate": 120.5,
        "budgetType": "MINUTES",
        "budgetUsed": 120.5,
        "crypt": "text"
      }
    }
  }
}

Stopwatch

Mutation

createStopwatch

AdminPMBasicTracker

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

start Boolean
Start it right away
ticketId ID
A ticket the caller can open; it can be set later
title String
Default: Stopwatch 1, 2, …

Answer

errors Json
stopwatch Stopwatch
stopwatches [Stopwatch!]!

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

AdminPMBasicTracker

Discards a stopwatch without booking its time.

Who may Only the stopwatch's owner.

Arguments

id ID! required

Answer

errors Json
stopwatch Stopwatch
stopwatches [Stopwatch!]!

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

AdminPMBasicTracker

Pauses a running stopwatch; the time counted so far stays.

Who may Only the stopwatch's owner.

Arguments

id ID! required

Answer

errors Json
stopwatch Stopwatch
stopwatches [Stopwatch!]!

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

AdminPMBasicTracker

Starts a stopwatch or resumes a paused one; does nothing to one that is running.

Who may Only the stopwatch's owner.

Arguments

id ID! required

Answer

errors Json
stopwatch Stopwatch
stopwatches [Stopwatch!]!

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

AdminPMBasicTracker

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

id ID! required
seconds Int
Sets the clock, in seconds (at most 7 days). A running stopwatch keeps running from there
ticketId ID
null detaches the ticket
title String

Answer

errors Json
stopwatch Stopwatch
stopwatches [Stopwatch!]!

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

AdminPMBasicTracker

Adds a supplier, whose invoices are entered as external costs.

Who may Project managers and admins.

Arguments

archived Boolean
datevAccount String
The supplier's own account (creditor number) in DATEV; empty = the collective account
ksk Boolean
Subject to the German artists' social insurance levy (KSK), which is then shown on each of their invoices
taxTreatment SupplierTaxTreatment
title String

Answer

errors Json
supplier Supplier

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

AdminPMBasicTracker

Deletes a supplier. Fails while external costs of this supplier exist; set archived with updateSupplier instead.

Who may Admins only.

Arguments

id ID! required

Answer

errors Json
supplier Supplier

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

AdminPMBasicTracker

Changes a supplier. Only the arguments sent are changed.

Who may Admins only.

Arguments

id ID! required
archived Boolean
datevAccount String
The supplier's own account (creditor number) in DATEV; empty = the collective account
ksk Boolean
Subject to the German artists' social insurance levy (KSK), which is then shown on each of their invoices
taxTreatment SupplierTaxTreatment
title String

Answer

errors Json
supplier Supplier

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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
authorId ID
boardId ID
The column of the project's kanban board. Default: Backlog for an open ticket, Done for a closed one
body Json
The ticket's description. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
budgetRate Float
The budget in the unit of budgetType: minutes, or an amount in the workspace's currency
budgetType TicketBudget
Ignored, like budgetRate, unless the caller sees financial data (project managers and admins)
endDate ISO8601Date
labelIds [ID!]
Labels of the ticket's project. On update: the whole list, labels left out are removed
number Int
Ignored on create: a new ticket gets the next number in its project
phaseId ID
priority TicketPriority
projectId ID
serviceCategoryId ID
startDate ISO8601Date
status TicketStatus
Default: OPEN. A ticket created with boardId takes that column's status instead
text String
Plain text instead of body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored when body is sent
title String

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required
toBoard ID! required
ID of the column (board) of the same project to put the ticket into
toPosition Int! required
The position in that column, counted from 1

Answer

board Board
errors Json
project Project
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required
toPhase ID! required
ID of a phase of the same project, or __NO__PHASE__ for no phase
toPosition Int! required
The position in that phase, counted from 1

Answer

errors Json
phase Phase
project Project
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required
todoId String! required
The id attribute of the checklist item in the body's JSON

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

id ID! required
assigneeIds [ID!]
Users who can open the project. On update: the whole list, users left out are unassigned
authorId ID
boardId ID
The column of the project's kanban board. Default: Backlog for an open ticket, Done for a closed one
body Json
The ticket's description. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
budgetRate Float
The budget in the unit of budgetType: minutes, or an amount in the workspace's currency
budgetType TicketBudget
Ignored, like budgetRate, unless the caller sees financial data (project managers and admins)
endDate ISO8601Date
labelIds [ID!]
Labels of the ticket's project. On update: the whole list, labels left out are removed
number Int
Ignored on create: a new ticket gets the next number in its project
phaseId ID
priority TicketPriority
projectId ID
serviceCategoryId ID
startDate ISO8601Date
status TicketStatus
Default: OPEN. A ticket created with boardId takes that column's status instead
text String
Plain text instead of body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored when body is sent
title String

Answer

errors Json
ticket Ticket

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

AdminPMBasicTracker

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

projectId ID
Ignored: the project is the ticket's
ticketId ID
userId ID

Answer

errors Json
ticketAssignment TicketAssignment

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

AdminPMBasicTracker

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

authorId ID
body Json
The comment's text. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
text String
Plain text instead of body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored when body is sent
ticketId ID

Answer

errors Json
ticketComment TicketComment

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

AdminPMBasicTracker

Deletes a ticket comment.

Who may Only its author, while they can still open the ticket's project.

Arguments

id ID! required

Answer

errors Json
ticketComment TicketComment

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

AdminPMBasicTracker

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

id ID! required
todoId String! required
The id attribute of the checklist item in the body's JSON

Answer

errors Json
ticketComment TicketComment

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

AdminPMBasicTracker

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

id ID! required
authorId ID
body Json
The comment's text. As a Tiptap (ProseMirror) document in JSON: { type: 'doc', content: […] }
text String
Plain text instead of body: blank lines separate paragraphs, single line breaks stay line breaks. Ignored when body is sent
ticketId ID

Answer

errors Json
ticketComment TicketComment

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

AdminPMBasicTracker

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!]! required
description String
duration Float
In minutes, in steps of 15
projectId ID
serviceId ID
The kind of work; the entry is priced at the project's rate for it
ticketId ID
A ticket of the project in projectId
userId ID
Whose time it is. Default on create: the caller. Only admins may name someone else

Answer

errors Json
timetrackings TimetrackingConnection

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

AdminPMBasicTracker

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

id ID! required
date ISO8601Date
The day of the copy. Default: the day of the original

Answer

errors Json
timetracking Timetracking

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

AdminPMBasicTracker

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

description String
duration Float
In minutes, in steps of 15
projectId ID
serviceId ID
The kind of work; the entry is priced at the project's rate for it
stopwatchId ID
Books this stopwatch of yours: it is removed together with creating the entry
ticketId ID
A ticket of the project in projectId
userId ID
Whose time it is. Default on create: the caller. Only admins may name someone else

Answer

errors Json
timetracking Timetracking

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

AdminPMBasicTracker

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

id ID! required

Answer

errors Json
timetracking Timetracking

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

AdminPMBasicTracker

Moves a time entry to another day.

Who may Everyone their own entries, on projects they can open; admins any entry.

Arguments

id ID! required
date ISO8601Date
The day to move the entry to

Answer

errors Json
timetracking Timetracking

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

AdminPMBasicTracker

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

date ISO8601Date! required
The day the note is about, unless it names another
note String! required

Answer

entries [TimeEntrySuggestion!]!
errors Json
heading String
What the suggestions are, when it isn't obvious: the period of work found without booked time
notice String
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

AdminPMBasicTracker

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

date ISO8601Date! required
ticketId ID! required

Answer

description String
errors Json
notice String
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

AdminPMBasicTracker

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

id ID! required
description String
duration Float
In minutes, in steps of 15
projectId ID
serviceId ID
The kind of work; the entry is priced at the project's rate for it
ticketId ID
A ticket of the project in projectId
userId ID
Whose time it is. Default on create: the caller. Only admins may name someone else

Answer

errors Json
timetracking Timetracking

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

AdminPMBasicTracker

Marks the product tour as seen for the caller, so it is not shown again.

Who may Anyone, for themselves.

Answer

errors Json
onboarded Boolean!

Example

mutation CompleteUserOnboarding($input: CompleteUserOnboardingInput!) {
  completeUserOnboarding(input: $input) {
    errors
    onboarded
  }
}

Variables

{
  "input": {}
}

Response

{
  "data": {
    "completeUserOnboarding": {
      "errors": null,
      "onboarded": true
    }
  }
}

Mutation

updatePinnedPages

AdminPMBasicTracker

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

errors Json
pinnedPages [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

AdminPMBasicTracker

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

activeFrom ISO8601Date
The first day the profile applies; required, one profile per user and day
fri Float
Target working hours on Fridays
mon Float
Target working hours on Mondays
sat Float
Target working hours on Saturdays
sun Float
Target working hours on Sundays
thu Float
Target working hours on Thursdays
tue Float
Target working hours on Tuesdays
userId ID
wed Float
Target working hours on Wednesdays

Answer

errors Json
userWorkTime UserWorkTime

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

AdminPMBasicTracker

Removes a working-hours profile of a user.

Who may Admins only.

Arguments

id ID! required

Answer

errors Json
userWorkTime UserWorkTime

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

AdminPMBasicTracker

Changes a working-hours profile of a user.

Who may Admins only.

Arguments

id ID! required
activeFrom ISO8601Date
The first day the profile applies; required, one profile per user and day
fri Float
Target working hours on Fridays
mon Float
Target working hours on Mondays
sat Float
Target working hours on Saturdays
sun Float
Target working hours on Sundays
thu Float
Target working hours on Thursdays
tue Float
Target working hours on Tuesdays
userId ID
wed Float
Target working hours on Wednesdays

Answer

errors Json
userWorkTime UserWorkTime

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

accountingFont String
accountingFooterManagingDirector String
accountingFooterOffice String
accountingHeader String
accountingTaxNumber String
accountingVatId String
advancePaymentTitleDe String
advancePaymentTitleEn String
aiApiKeyHint String
aiBaseUrl String
aiConnectionsEnabled Boolean!
aiDocumentRules String
aiDocuments Boolean!
aiModel String
aiProvider AiProvider!
aiQuotaShare Float
aiReceiptReading Boolean!
aiReceiptReadingAutomatic Boolean!
aiTimeEntry Boolean!
apiAccessEnabled Boolean!
Whether members may make personal API keys for the GraphQL API
bic String
cancellationInvoiceTitleDe String
cancellationInvoiceTitleEn String
companyCity String
companyName String
companyPostalCode String
companyStreet String
country String!
countryAndCurrencyLocked Boolean!
createdAt ISO8601DateTime!
currency String!
customCustomerNumber Boolean!
Whether customer numbers are typed on the address instead of given by docket
customInvoiceNumber Boolean!
customerNumberStart Int!
Where docket's customer numbers start
customerNumberStep Int!
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
datevAccounts JSON
The account per case, by the keys of datevAccountKeys
datevAvailable Boolean!
Whether the workspace can have the DATEV booking batch (a German one)
datevBookings Boolean
datevClientNumber Int
datevConsultantNumber Int
datevFiscalYearStart Int
The month the fiscal year starts in
datevStandardAccounts JSON!
What the form starts with, per chart (skr03, skr04)
defaultTaxRate Float!
documentFontConfirmedAt ISO8601DateTime
documentFontFiles [DocumentFontFile!]!
domain String!
finalInvoiceTitleDe String
finalInvoiceTitleEn String
iban String
id ID!
invoiceContactEmail String
invoiceContactName String
invoiceContactPhone String
invoiceFooterDe String
invoiceFooterEn String
invoiceNumberPrefix String
invoiceTitleDe String
invoiceTitleEn String
latestExport WorkspaceExport
The most recent full workspace export (admins only)
letterheadLines String
locale Locale
logo String
logoSize Int
name String!
nextCustomerNumber Int!
The number docket gives the next customer address (Account#next_customer_number)
onboardingCompleted Boolean!
partialInvoiceTitleDe String
partialInvoiceTitleEn String
paymentTermDays Int!
Days from the invoice date to the due date, unless the customer has its own term
quotationFooterDe String
quotationFooterEn String
requireTwoFactor Boolean!
smallBusiness Boolean!
Whether the workspace is a small business today
taxRates [Float!]!
updatedAt ISO8601DateTime!
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

createdAt ISO8601DateTime!
email String!
The address the sign-in links go to
id ID!
invitedBy User
The member who gave the access; null once they are gone
lastSignedInAt ISO8601DateTime
Null until the tax office first signs in
name String
The tax office's name, if one was given
revokedAt ISO8601DateTime
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

accountId ID!
accountingCustomFields AccountingCustomFieldConnection!
createdAt ISO8601DateTime!
customFields [AccountingCustomFieldValue!]!
The values of the workspace's custom fields for this cycle
id ID!
invoices InvoiceConnection!
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.
quotation Quotation
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
serviceRatesUpdatable Boolean!
Whether a rate of a service, the customer or the project changed since, so the cycle could take over the new rates
updatedAt ISO8601DateTime!

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

accounting Accounting!
createdAt ISO8601DateTime!
customField CustomField!
customFieldValue String
id ID!
updatedAt ISO8601DateTime!

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

createdAt ISO8601DateTime!
id ID!
name String!
type String!
updatedAt ISO8601DateTime!
value String

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

invoiceCount Int!
Issued invoices (published or paid); cancellation invoices are not counted
open Float!
What published invoices that are not overdue ask for
overdue Float!
What published invoices past their due date ask for
overdueDays Int
How many days the longest-overdue invoice is past its due date; null when none is overdue
paid Float!
What the paid invoices asked for
quotationNumber String
The quotation's number as printed (Quotation.qnr); null for a cycle without a quotation
quotationStatus QuotationStatus
PUBLISHED (sent, not confirmed yet), CONFIRMED, or CANCELED while invoices still stand; null for a cycle without a quotation
total Float!
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

createdAt ISO8601DateTime!
expiresAt ISO8601DateTime
From when the key is refused; null: it never expires
id ID!
lastFour String!
The key's last four characters, to tell keys apart
lastUsedAt ISO8601DateTime
name String!

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

blobId ID!
byteSize Int!
contentType String!
createdAt ISO8601DateTime!
downloadUrl String!
The file's path on the workspace. Fetch it signed in, or with the API key in the Authorization header
filename String!
id ID!
previewImage String
updatedAt ISO8601DateTime!

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

from ISO8601Date!

Example

{
  "from": "2026-11-13",
  "to": "2026-11-13"
}

AvgTimetrackingPerDayNode

AdminPMBasicTracker

Fields

date ISO8601Date!
duration Float!

Example

{
  "date": "2026-11-13",
  "duration": 120.5
}

BilledBefore

AdminPMBasicTracker

Fields

invoiceId ID!
net Float!

Example

{
  "invoiceId": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "net": 120.5
}

Block

AdminPMBasicTracker

Fields

deleted Boolean
description String
footer String
id ID!
modified Boolean
new Boolean
optional Boolean!
positions [BlockPosition!]!
title String
total Float!

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "title": "Website relaunch",
  "deleted": true,
  "description": "text",
  "footer": "text",
  "modified": true
}

BlockPosition

AdminPMBasicTracker

Fields

alreadySelected Boolean
deleted Boolean
description String
footer String
id ID!
modified Boolean
new Boolean
optional Boolean!
selected Boolean
subpositions [BlockPositionSubposition!]!
title String!
total Float!

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "title": "Website relaunch",
  "alreadySelected": true,
  "deleted": true,
  "description": "text",
  "footer": "text"
}

BlockPositionSubposition

AdminPMBasicTracker

Fields

amount Float
billedQuantity Float
dailyRate Float
deleted Boolean
description String
exists Boolean
id ID!
modified Boolean
name String
new Boolean
optional Boolean!
quantity Float
rate Float
serviceId String
taxRate Float
This line's VAT rate in percent (the document's unless set on the line)
title String
total Float!
unit String
unitLabel String

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

createdAt ISO8601DateTime!
id ID!
position Int!
Rank among the project's columns, for ordering (not consecutive)
preset BoardPreset!
BACKLOG and DONE are the two columns every project has, where tickets land by their status; they cannot be deleted. CUSTOM is any other.
project Project!
ticketStatus TicketStatus!
The ticket status this column stands for
tickets TicketConnection!
title String!
updatedAt ISO8601DateTime!

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

createdAt ISO8601DateTime!
exportedBy String
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
externalCostsCount Int!
id ID!
invoicesCount Int!
periodFrom ISO8601Date!
periodTo ISO8601Date!
userName String
The member who made it in the app; null for the tax office's own exports
withBookings Boolean!
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

exportedBeforeCount Int!
How many of these documents an earlier export already held
exports [BookkeepingExport!]!
The latest exports, newest first
externalCostsCount Int!
External costs of the period that are ok or processed
invoicesCount Int!
Invoices issued in the period, cancellations included
withBookings Boolean!
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

connectedAt ISO8601DateTime!
id ID!
lastUsedAt ISO8601DateTime
name String!
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

archived Boolean!
createdAt ISO8601DateTime!
customers CustomerConnection!
The customers this person is a contact of
department String
email String!
firstname String!
id ID!
lastname String!
phone String
salutation String!
title String
Academic or professional title, e.g. Dr.
updatedAt ISO8601DateTime!

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

code String!
name String!

Example

{
  "name": "Website relaunch",
  "code": "text"
}

CustomField

AdminPMBasicTracker

Fields

archived Boolean!
createdAt ISO8601DateTime!
customer Customer!
defaultValue String
fieldType String!
id ID!
name String!
updatedAt ISO8601DateTime!

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

accountingCommissionPercent Float
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).
accountingCommissionThreshold Float
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).
archived Boolean!
company String!
The customer's name
contacts ContactConnection!
createdAt ISO8601DateTime!
customFields CustomFieldConnection!
datevAccount String
The customer's own account (debtor number) in the tax office's DATEV; null = the collective account
description String
email String
id ID!
initial String!
Short code, unique in the workspace; it starts the numbers of the customer's projects (Project.pnr)
invoiceFooterDe String
Footer text for this customer's invoices in German
invoiceFooterEn String
Footer text for this customer's invoices in English
masterAgreement Boolean
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).
paymentTermDays Int
This customer's payment term in days; null = the workspace's
phone String
projects ProjectConnection!
quotationFooterDe String
Footer text for this customer's quotations in German
quotationFooterEn String
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).
slug String!
updatedAt ISO8601DateTime!
web String

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

address1 String
address2 String
buyerReference String
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
city String
country String
What was typed as the country before the list, where it names none docket knows
countryCode String
ISO 3166-1 alpha-2; none for a customer in the workspace's own country
countryName String
The country as the app shows it (English)
createdAt ISO8601DateTime!
deletionRefusal String
Why this address can't be deleted, or null when it can
department String
documentsCount Int!
Quotations, order confirmations, delivery notes and invoices written to this address
id ID!
invoiceEmail String
Where this customer receives e-invoices (BT-49); none: the customer's e-mail
number Int!
The customer number, unique in the workspace
recipient String
taxTreatment TaxTreatment!
How documents to this address are taxed
updatedAt ISO8601DateTime!
vatEnabled Boolean!
Whether VAT is charged (tax treatment is domestic)
vatNo String
The customer's VAT identification number; needed for reverse charge
zip String

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

accounting Accounting!
The billing cycle it belongs to
author User!
Who created it
contactCustomers ContactConnection!
The customer's contacts the document is addressed to
contactInternals UserConnection!
The agency's contact persons named on the document
createdAt ISO8601DateTime!
customer Customer!
The customer of the document's project
customerAddress CustomerAddress
The customer address it is written to; needed before it can go out
deleted Boolean!
Soft-delete flag; deleted documents are not listed
description String
Introductory text (HTML)
filename String!
File name of its PDF
footer String
Footer text (HTML)
id ID!
language String
Language of the document and its PDF: de or en
name String
Free name beside the number; the project's title unless given
no String!
The number as printed: project number, a dot and the two-digit number
notificationRecipients [User!]!
number Int!
Running number within the project
project Project!
showPositionSubtotal Boolean!
Whether the PDF shows a subtotal under each position
stream DeliveryNoteStreamConnection!
Its comments and events (status changes, edits), oldest first
summary Summary!
The document's computed totals: net, discounts and surcharges, VAT, gross
taxNote String
Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRate Float!
The VAT rate in percent its lines use unless a line has its own
taxTreatment TaxTreatment!
How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
title String!
no followed by the name
updatedAt ISO8601DateTime!
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
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

author User!
body Json!
bodyHtml String!
byAi Boolean!
Written by docket when the AI added positions (shown as docket's); the author applied them
createdAt ISO8601DateTime!
deliveryNote DeliveryNote!
id ID!
reactions [Reaction!]!
Its reactions by emoji, in the order they were first given
updatedAt ISO8601DateTime!
viewerCanEdit Boolean!

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

amount Float!
title String!

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

service String
The service's title; null when none fits
value String!

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
multiple Boolean!
Several answers may be picked
options [String!]!
question String!

Example

{
  "multiple": true,
  "options": [
    "text"
  ],
  "question": "text"
}

DocumentAssistantSkipped

AdminPMBasicTracker

Rows of the file that didn't count

Fields

noQuantity Int!
Without hours or days to read
noService Int!
Without a service to bill

Example

{
  "noQuantity": 42,
  "noService": 42
}

DocumentFontFile

AdminPMBasicTracker

Fields

filename String!

Example

{
  "filename": "text",
  "style": "REGULAR"
}

DocumentPlanLine

AdminPMBasicTracker

A service line of the plan, priced from the project's rates

Fields

description String!
quantity Float!
service String!
The service's title
total Float
What the line comes to; null for a service the document's rates lack
unit String!
hours or days

Example

{
  "description": "text",
  "quantity": 120.5,
  "service": "text",
  "total": 120.5,
  "unit": "text"
}

DocumentPlanPhase

AdminPMBasicTracker

Fields

positions [DocumentPlanPosition!]!
title String!

Example

{
  "title": "Website relaunch"
}

DocumentPlanPosition

AdminPMBasicTracker

Fields

lines [DocumentPlanLine!]!
title String!

Example

{
  "title": "Website relaunch"
}

DocumentPlanPreview

AdminPMBasicTracker

What a plan adds to a document and what it comes to, net

Fields

net Float!
phases [DocumentPlanPhase!]!
positions [DocumentPlanPosition!]!

Example

{
  "net": 120.5
}

DocumentTemplate

AdminPMBasicTracker

Fields

author User
blockTitles [String!]!
Its phase or block titles, for a preview
createdAt ISO8601DateTime!
customer Customer
The one customer it's offered for; null: every customer
id ID!
kind String!
quotation or invoice: the documents it's for
missingServiceCount Int!
Services in it the workspace no longer has: their lines would be priced at nothing
name String!
note String
What the template is for
structure String!
phases or agency (agency and external services)
updatedAt ISO8601DateTime!

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

on ISO8601Date!
The day the rate is from: the date asked for, or the last working day before it
rate Float!

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

amount Float!
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
assignmentsDifference Float!
With partial amounts: the net amount not assigned yet; otherwise 0
createdAt ISO8601DateTime!
currency Currency!
The currency of the supplier's invoice
exchangeRate Float
Units of the currency per euro (ECB)
exchangeRateOn ISO8601Date
The day the exchange rate is from
id ID!
inputTaxDeductible Boolean!
false when the workspace could not reclaim the VAT (a small business): the cost then counts with its VAT
invoice Attachment!
The invoice file (PDF)
invoiceDate ISO8601Date!
invoiceNumber String!
The supplier's invoice number; unique per supplier and VAT rate
ksk Float!
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
originalAmount Float
Net amount in the invoice's currency, for an invoice in another currency than the workspace's
partialAmount Boolean!
Whether the invoice is split: each assignment takes a part of the amount. Otherwise it has one assignment for all of it.
partialBill Boolean!
Marks an invoice that is one of several from the supplier for the same job
projects ProjectConnection!
The projects it is assigned to
quotations QuotationConnection!
The quotations it is assigned to
relatedCosts [ExternalCost!]!
The supplier's other invoices for the same job, linked to this one; oldest first
relatedTotal Float!
What the linked invoices come to, this one included (net, in the workspace's currency)
statusChangedAt ISO8601DateTime!
When the status last changed
supplier Supplier!
tax Float!
The VAT amount, as the supplier's invoice states it
taxRate Float!
The VAT rate in percent, e.g. 19.0
updatedAt ISO8601DateTime!
user User
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

amount Float
boundsExtended [ExternalCostAssignmentExtended!]
boundsHeight Float
boundsLeft Float
boundsTop Float
boundsWidth Float
chargeable Boolean!
createdAt ISO8601DateTime!
id ID!
page Int
project Project!
quotation Quotation!
updatedAt ISO8601DateTime!

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

boundsHeight Float!
boundsLeft Float!
boundsTop Float!
boundsWidth Float!
page Int!

Example

{
  "boundsHeight": 120.5,
  "boundsLeft": 120.5,
  "boundsTop": 120.5,
  "boundsWidth": 120.5,
  "page": 42
}

ExternalCostFigures

AdminPMBasicTracker

Fields

convertedAmount Float
The net amount at that rate, in the workspace's currency
exchangeRate ExchangeRate
The ECB rate of the invoice date, for an invoice in another currency
inputTaxDeductible Boolean!
Whether the VAT comes back as input tax: not while the workspace was a small business
taxAtRate Float
The net amount given (or the converted one) at the VAT rate

Example

{
  "convertedAmount": 120.5,
  "inputTaxDeductible": true,
  "taxAtRate": 120.5
}

ExternalCostsCheck

AdminPMBasicTracker

Fields

booked Float!
Supplier invoices assigned to the quote, passed on or not, net, drafts left out
notCharged Float!
The part of booked that isn't passed on to the customer
over Boolean!
Booked above quoted
percent Float
Booked as a percentage of quoted; null when nothing was quoted
quoted Float!
The external services the confirmed quote sold

Example

{
  "booked": 120.5,
  "notCharged": 120.5,
  "over": true,
  "percent": 120.5,
  "quoted": 120.5
}

ExternalCostsOverrun

AdminPMBasicTracker

Fields

quotation Quotation!

FinancialSummary

AdminPMBasicTracker

Fields

awaitingOrderConfirmation [Quotation!]!
awaitingOrderConfirmationCount Int!
The year's confirmed quotations whose order confirmation isn't published yet
awaitingOrderConfirmationTotal Float!
carriedOverCount Int!
Unpaid invoices from earlier years
carriedOverInvoices [Invoice!]!
carriedOverTotal Float!
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!]!
openInvoicesCount Int!
openInvoicesTotal Float!
orderConfirmationsCount Int!
orderConfirmationsTotal Float!
overdueCount Int!
overdueInvoices [Invoice!]!
overdueTotal Float!
paidCount Int!
paidTotal Float!
pipelineCount Int!
pipelineTotal Float!
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

expected Float!
month Int!
paid Float!

Example

{
  "expected": 120.5,
  "month": 42,
  "paid": 120.5
}

ForecastReport

AdminPMBasicTracker

Fields

invoiceCount Int!
months [ForecastMonth!]!
quotationCount Int!
rows [ForecastRow!]!
totals ForecastTotals!
year Int!
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

allocationMonth Int
bookedExternalCosts Float
deltaToQuotation Float!
externalCosts Float!
externalCostsOver Boolean
id ID!
invoiceDate ISO8601Date
invoiceNumber String
invoicePaidDate ISO8601DateTime
invoiceStatus String
invoiceTotal Float!
isPaid Boolean!
kvNumber String
monthlyAmount Float!
poNumber String
projectManager String
projectSlug String!
projectTitle String
quotationBudget Float!
quotationDate ISO8601Date
quotationNumber Int
quotationStatus String

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "allocationMonth": 42,
  "bookedExternalCosts": 120.5,
  "deltaToQuotation": 120.5,
  "externalCosts": 120.5,
  "externalCostsOver": true
}

ForecastTotals

AdminPMBasicTracker

Fields

bookedExternalCosts Float!
The confirmed quotations' booked external costs
deltaToQuotation Float!
externalCosts Float!
invoiceTotal Float!
quotationBudget Float!
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

accounting Accounting!
The billing cycle it belongs to
author User!
Who created it
canceledNote String
The note given when it was canceled
contactCustomers ContactConnection!
The customer's contacts the document is addressed to
contactInternals UserConnection!
The agency's contact persons named on the document
corrections [InvoiceCorrection!]!
Each time it was reopened for correction before it went out, oldest first
createdAt ISO8601DateTime!
customer Customer!
The customer of the document's project
customerAddress CustomerAddress
The customer address it is written to; needed before it can go out
date ISO8601Date
The invoice date
daysOverdue Int
Days past the due date of a published, unpaid invoice; null otherwise
deleted Boolean!
Soft-delete flag; deleted documents are not listed
deliveryDate ISO8601Date
The date of delivery or performance printed on the invoice
description String
Introductory text (HTML)
documentTemplate DocumentTemplate
The template it was started from, if any
dueDate ISO8601Date
The invoice date plus the payment term (the customer's, else the workspace's), fixed when it is published; null for a cancellation invoice
dueNet Float!
What the invoice asks the customer for, net: a final invoice's total minus what was invoiced before, any other invoice's total
eInvoiceAvailable Boolean!
Whether the e-invoice (XRechnung XML) archived at publish can be downloaded, at /api/invoices/xml/:id
externalServiceTotal Float
Net total of its external-service lines, in the workspace's currency
filename String!
File name of its PDF
footer String
Footer text (HTML)
id ID!
inCorrection Boolean!
Reopened for correction and not published again yet — a draft that keeps its number
inr String!
The invoice number as printed: project number, a dot, the workspace's number prefix if any, and the number (a placeholder while a draft)
inrWithName String!
inr followed by the name
invoiceType InvoiceTypeEnum
Advance payment, partial, final or cancellation invoice
language String
Language of the document and its PDF: de or en
name String
Free name beside the number; the project's title unless given
notificationRecipients [User!]!
number Int
Assigned when it is published; null for a draft
orderConfirmation OrderConfirmation
The cycle's order confirmation, if its quotation was confirmed
originalInvoice Invoice
For a cancellation invoice: the invoice it reverses
paid Boolean!
Whether its status is PAID
paidAt ISO8601DateTime
When it was marked as paid
paidBy User
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.
project Project!
quotation Quotation
The quotation of its billing cycle; null for an invoice without one
retainerMonth ISO8601Date
The month of a retainer this invoice bills (its first day); null for any other invoice
selectsPositions Boolean!
Whether someone picks the positions it bills: a partial invoice, and a job's final invoice; one on its own bills all
showPositionSubtotal Boolean!
Whether the PDF shows a subtotal under each position
status InvoiceStatus!
stream InvoiceStreamConnection!
Its comments and events (status changes, edits), oldest first
summary Summary!
The document's computed totals: net, discounts and surcharges, VAT, gross
taxNote String
Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRate Float!
The VAT rate in percent its lines use unless a line has its own
taxTreatment TaxTreatment!
How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
templateCanFill Boolean!
Whether a document template can still fill it, which needs an empty draft
title String!
What the app calls it, in the caller's language: its kind, its number and the quotation or invoice it refers to
totalNet Float
Net total in the workspace's currency; for a final invoice the whole job, before what was invoiced earlier is deducted
updatedAt ISO8601DateTime!
viewerCanCorrect Boolean!
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
viewerCanReopenForCorrection Boolean!
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
viewerCanReturnToDraft Boolean!
Whether the caller may take it back to draft: an invoice without a number that is not a draft
viewerCanReversePayment Boolean!
Whether the caller may make a paid invoice unpaid again: admins
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
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

author User!
body Json!
bodyHtml String!
byAi Boolean!
Written by docket when the AI added positions (shown as docket's); the author applied them
createdAt ISO8601DateTime!
id ID!
invoice Invoice!
reactions [Reaction!]!
Its reactions by emoji, in the order they were first given
updatedAt ISO8601DateTime!
viewerCanEdit Boolean!

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

createdAt ISO8601DateTime!
When it was reopened
id ID!
previousDate ISO8601Date
The invoice date before the correction
reason String!
republishedAt ISO8601DateTime
When it was published again; null while it is being corrected
supersededPdfUrl String
The PDF as it was archived before the correction
user User!
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

id String!
key String!
status String
summary String

Example

{
  "id": "text",
  "status": "text",
  "key": "text",
  "summary": "text"
}

JiraMirrorConflict

AdminPMBasicTracker

Fields

bookedMinutes Float!
project Project!
ticketCount Int!

Example

{
  "bookedMinutes": 120.5,
  "ticketCount": 42
}

JiraProjectLink

AdminPMBasicTracker

Fields

convertWorklogs Boolean!
createdAt ISO8601DateTime!
defaultService Service
id ID!
importForeignWorklogs Boolean!
jiraConnection JiraSite!
jiraProjectId String!
jiraProjectKey String!
lastError String
lastSyncedAt ISO8601DateTime
mirrorConflicts [JiraMirrorConflict!]!
mirroredBookedMinutes Int!
mirroredTimetrackingCount Int!
mirroredWorklogCount Int!
project Project!
pushWorklogs Boolean!
scopeEpics [JiraEpicRef!]!
scopeKind JiraScopeKind!
syncState JiraLinkSyncState!
ticketsMode JiraTicketsMode!
updatedAt ISO8601DateTime!

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

jiraProjectId String!
key String!
name String!

Example

{
  "name": "Website relaunch",
  "jiraProjectId": "text",
  "key": "text"
}

JiraSite

AdminPMBasicTracker

Fields

authKind String!
cloudId String
createPlaceholderUsers Boolean!
createdAt ISO8601DateTime!
hasTempoToken Boolean!
id ID!
lastCheckedAt ISO8601DateTime
lastError String
linkedProjectsCount Int!
name String!
placeholderService Service
projectLinks [JiraProjectLink!]
siteUrl String!
updatedAt ISO8601DateTime!
userMappings [JiraUserMapping!]
worklogBackend JiraWorklogBackend!

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

id ID!
name String!
siteUrl String!

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "name": "Website relaunch",
  "siteUrl": "text"
}

JiraUserCredential

AdminPMBasicTracker

Fields

authKind String!
createdAt ISO8601DateTime!
displayName String
email String
id ID!
jiraConnection JiraSiteSummary
tokenCheckedAt ISO8601DateTime
tokenError String
tokenStatus JiraTokenStatus!
updatedAt ISO8601DateTime!

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

createdAt ISO8601DateTime!
displayName String
id ID!
jiraAccountId String!
jiraConnection JiraSite!
pendingWorklogCount Int!
updatedAt ISO8601DateTime!
user User!

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

accountId String!
avatarUrl String
displayName String!
emailAddress String

Example

{
  "accountId": "text",
  "avatarUrl": "text",
  "displayName": "text",
  "emailAddress": "text"
}

JiraWorklogSummary

AdminPMBasicTracker

Fields

authorDisplayName String!
minutes Float!
revenue Float
user User

Example

{
  "authorDisplayName": "text",
  "minutes": 120.5,
  "revenue": 120.5
}

Mention

AdminPMBasicTracker

Fields

createdAt ISO8601DateTime!
id ID!
mentionableId ID!
mentionableType String!
updatedAt ISO8601DateTime!
user User!

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

count Int!
month Int!
open Float!
The year's published, unpaid invoices dated in the month
quoted Float!
Confirmed quotations not invoiced yet, in the month the forecast puts them
total Float!

Example

{
  "count": 42,
  "month": 42,
  "open": 120.5,
  "quoted": 120.5,
  "total": 120.5
}

Notification

AdminPMBasicTracker

Fields

actorCount Int!
How many different people did it
actors [User!]!
Who did it, the latest first, each once; up to three
count Int!
countArchived Int!
countIsNew Int!
createdAt ISO8601DateTime!
emojis [String!]!
The reactions, for TICKET_COMMENT_REACTED, the latest first, each once
id String!
record NotificationRecordUnion

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

accounting Accounting!
The billing cycle it belongs to
author User!
Who created it
contactCustomers ContactConnection!
The customer's contacts the document is addressed to
contactInternals UserConnection!
The agency's contact persons named on the document
createdAt ISO8601DateTime!
customer Customer!
The customer of the document's project
customerAddress CustomerAddress
The customer address it is written to; needed before it can go out
deleted Boolean!
Soft-delete flag; deleted documents are not listed
description String
Introductory text (HTML)
filename String!
File name of its PDF
footer String
Footer text (HTML)
id ID!
language String
Language of the document and its PDF: de or en
name String
Free name beside the number; the project's title unless given
no String!
The number as printed: project number, a dot and the two-digit number
notificationRecipients [User!]!
number Int!
Running number within the project
project Project!
showPositionSubtotal Boolean!
Whether the PDF shows a subtotal under each position
stream OrderConfirmationStreamConnection!
Its comments and events (status changes, edits), oldest first
summary Summary!
The document's computed totals: net, discounts and surcharges, VAT, gross
taxNote String
Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRate Float!
The VAT rate in percent its lines use unless a line has its own
taxTreatment TaxTreatment!
How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
title String!
no followed by the name
updatedAt ISO8601DateTime!
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
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

author User!
body Json!
bodyHtml String!
byAi Boolean!
Written by docket when the AI added positions (shown as docket's); the author applied them
createdAt ISO8601DateTime!
id ID!
orderConfirmation OrderConfirmation!
reactions [Reaction!]!
Its reactions by emoji, in the order they were first given
updatedAt ISO8601DateTime!
viewerCanEdit Boolean!

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

computedEndDate String
The latest end date of the phase's tickets; null when none has one
computedStartDate String
The earliest start date of the phase's tickets; null when none has one
createdAt ISO8601DateTime!
description String
endDate String
Planned end (YYYY-MM-DD)
id ID!
position Int
Rank among the project's phases, for ordering (not consecutive)
project Project!
slug String!
startDate String
Planned start (YYYY-MM-DD)
tickets TicketConnection!
ticketsClosed Int!
ticketsOpen Int!
title String!
updatedAt ISO8601DateTime!

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

path String!
The app path it opens, query string included
title String!

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).
archived Boolean!
assignees UserConnection!
Everyone assigned to one of the project's tickets
boards BoardConnection!
budgetExternalCosts Float
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).
budgetOver Boolean!
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.
budgetRate Float
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).
budgetTimetrackings TimetrackingConnection!
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.
budgetType ProjectBudget
What the budget counts.
Who sees Null unless you may see the budget (project managers and admins).
budgetUsed Float!
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.
createdAt ISO8601DateTime!
customer Customer!
deadline ISO8601Date
deliveryNotes DeliveryNoteConnection
Who sees Null unless you may see financial data (project managers and admins).
description String
externalCosts ExternalCostConnection
Supplier invoices assigned to the project.
Who sees Null unless you may see financial data (project managers and admins).
externalCostsCheck ExternalCostsCheck
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).
externalCostsTotal Float
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).
financials ProjectFinancials
What the project's quotations and invoices add up to.
Who sees Null unless you may see financial data (project managers and admins).
hasBudget Boolean!
Whether a budget is set. Always false for a timetracker.
id ID!
invoiceTypesWithoutOrderConfirmation [InvoiceTypeEnum!]!
The types an invoice created without an order confirmation can have
invoices InvoiceConnection
Who sees Null unless you may see financial data (project managers and admins).
jiraLinked Boolean!
Whether the project is linked to a Jira project
jiraProjectLink JiraProjectLink
The link to a Jira project and its settings; null when unlinked
jiraProjectUrl String
Address of the linked project in Jira; null when unlinked
jiraTicketsMode JiraTicketsMode
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.
number Int!
The project's running number in the workspace (the first is 1001)
orderConfirmations OrderConfirmationConnection
Who sees Null unless you may see financial data (project managers and admins).
participants UserConnection!
Supervisors and ticket assignees together
phases PhaseConnection!
pnr String!
The project number as shown everywhere: the customer's initial followed by number, e.g. ACME1001
progress Int!
Share of the project's tickets that are closed, in percent (0 without tickets)
quotations QuotationConnection
Who sees Null unless you may see financial data (project managers and admins).
retainer Retainer
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).
slug String!
status ProjectStatus!
statusDate ISO8601Date
The day the status last changed
stickyTicketsClosed Int!
Closed tickets that are pinned
stickyTicketsOpen Int!
Open tickets that are pinned
supervisors UserConnection!
The people assigned to the project (project assignments)
tickets TicketConnection!
ticketsClosed Int!
ticketsOpen Int!
timetrackings TimetrackingConnection!
Time booked on the project. A timetracker sees only their own entries, everyone else all of them.
title String!
updatedAt ISO8601DateTime!
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
Whether the caller follows it and so gets its notifications
workload WorkloadOverview!
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

action EventAction
What happened to the document, for DOCUMENT entries
document ProjectDocumentUnion
The document, for DOCUMENT and DOCUMENT_COMMENT_REACTED entries
emoji String
The reaction, for TICKET_COMMENT_REACTED and DOCUMENT_COMMENT_REACTED entries
id ID!
occurredAt ISO8601DateTime!
ticket Ticket
user User

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

invoicedCount Int!
Issued invoices, paid or not (no cancellations, nothing canceled)
invoicedTotal Float!
What they ask for: a final invoice counts its debit
openCount Int!
Issued invoices not paid yet
openTotal Float!
overdueCount Int!
overdueTotal Float!
paidTotal Float!
quotedCount Int!
Confirmed quotations
quotedTotal Float!

Example

{
  "invoicedCount": 42,
  "invoicedTotal": 120.5,
  "openCount": 42,
  "openTotal": 120.5,
  "overdueCount": 42,
  "overdueTotal": 120.5
}

ProjectLabel

AdminPMBasicTracker

Fields

color String!
createdAt ISO8601DateTime!
description String
id ID!
project Project!
slug String!
title String!
updatedAt ISO8601DateTime!

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

accounting Accounting!
The billing cycle it belongs to
author User!
Who created it
budgetHandoff QuotationBudgetHandoff
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.
canceledNote String
The note given when it was canceled
confirmationFile String
Path of the customer's signed confirmation, if one was attached when confirming
confirmationFilename String
File name of the customer's signed confirmation
confirmedNote String
The note given when it was confirmed
contactCustomers ContactConnection!
The customer's contacts the document is addressed to
contactInternals UserConnection!
The agency's contact persons named on the document
createdAt ISO8601DateTime!
customer Customer!
The customer of the document's project
customerAddress CustomerAddress
The customer address it is written to; needed before it can go out
deleted Boolean!
Soft-delete flag; deleted documents are not listed
description String
Introductory text (HTML)
documentTemplate DocumentTemplate
The template it was started from, if any
externalCosts [ExternalCost!]!
The supplier invoices assigned to this quotation, by invoice date
externalCostsChargeableTotal Float!
The part of externalCostsTotal that is passed on to the customer
externalCostsCheck ExternalCostsCheck
The booked external costs against the external services the quotation sold; null unless it is confirmed
externalCostsFilename String!
File name of its external-costs PDF
externalCostsNonchargeableTotal Float!
The part of externalCostsTotal that is not passed on to the customer
externalCostsTotal Float!
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.
externalServiceTotal Float
Net total of its external-service lines, in the workspace's currency
filename String!
File name of its PDF
footer String
Footer text (HTML)
id ID!
language String
Language of the document and its PDF: de or en
name String
Free name beside the number; the project's title unless given
notificationRecipients [User!]!
number Int!
Running number within the project
project Project!
qnr String!
The quotation number as printed: project number, a dot and the two-digit number, e.g. ACME1001.01
qnrWithName String!
qnr followed by the name
showPositionSubtotal Boolean!
Whether the PDF shows a subtotal under each position
status QuotationStatus!
stream QuotationStreamConnection!
Its comments and events (status changes, edits), oldest first
summary Summary!
The document's computed totals: net, discounts and surcharges, VAT, gross
taxNote String
Why it charges no VAT, as its PDF says it; null when VAT is charged
taxRate Float!
The VAT rate in percent its lines use unless a line has its own
taxTreatment TaxTreatment!
How the customer is taxed; anything but DOMESTIC means no VAT on any line. Frozen once the document is issued.
title String!
The same as qnrWithName
totalNet Float
Net total in the workspace's currency
updatedAt ISO8601DateTime!
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
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

agencyServicesAmount Float!
The agency's own lines
budgetAfterAdd Float
budgetAfterSet Float!
budgetType ProjectBudget!
The budget the hand-off writes: the project's, or without one hours when the quote sold any
commissionAmount Float!
The customer's commission on external services
currentBudget Float
The project's budget now (minutes or amount), null without one
discountsAndSurchargesAmount Float!
Discounts (negative) and surcharges together
externalServicesAmount Float!
Bought-in work passed on
modes [BudgetHandoffMode!]!
What may be done, the suggestion first: add needs a budget to add to
soldAmount Float!
The quote's net total, as its PDF prints it
soldMinutes Float!
Hours sold, in minutes: hour and day lines that reach the total, no external services
suggestedMode BudgetHandoffMode!

Example

{
  "agencyServicesAmount": 120.5,
  "budgetAfterAdd": 120.5,
  "budgetAfterSet": 120.5,
  "budgetType": "MINUTES",
  "commissionAmount": 120.5,
  "currentBudget": 120.5
}

QuotationComment

AdminPMBasicTracker

Fields

author User!
body Json!
bodyHtml String!
byAi Boolean!
Written by docket when the AI added positions (shown as docket's); the author applied them
createdAt ISO8601DateTime!
id ID!
quotation Quotation!
reactions [Reaction!]!
Its reactions by emoji, in the order they were first given
updatedAt ISO8601DateTime!
viewerCanEdit Boolean!

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"
}

Reaction

AdminPMBasicTracker

Fields

count Int!
emoji String!
users [User!]!
viewerReacted Boolean!

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

billsOverage Boolean!
Whether hours beyond the contingent are billed on top of the fee
contingentMinutes Int
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
endsOn ISO8601Date
Null for an open-ended retainer
fee Float!
The fee per period (month or quarter), net, in the workspace's currency
intervalMonths Int!
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
noticeBy ISO8601Date
The last day to give notice so it ends on its end date; null when open-ended
noticeMonths Int
The notice period in months
ownContingentMinutes Int
The contingent entered for the retainer itself, in minutes per period; null when the budget stands in
startsOn ISO8601Date!

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

billsOverage Boolean!
Whether hours beyond the contingent are billed on top of the fee
bookedMinutes Int!
Billable time booked in the month, in minutes
contingentMinutes Int
The hours the fee covers, in minutes; null without a contingent
due Boolean!
The month is over and has no invoice yet
fee Float!
The period's fee, net, in the workspace's currency
from ISO8601Date!
The first day of the period inside the retainer's term
invoice Invoice
The invoice that bills the month; null while there is none
month ISO8601Date!
The first day of the period's first month
months Int!
How many months the period covers: 1 or 3
overageMinutes Int!
Time beyond the contingent, in minutes; 0 without a contingent
project Project!
to ISO8601Date!
The last day of the period inside the retainer's term
unusedMinutes Int!
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"
}

RssFeed

AdminPMBasicTracker

Fields

feed [RssItem!]!
title String!

Example

{
  "title": "Website relaunch"
}

RssItem

AdminPMBasicTracker

Fields

excerpt String
image String
link String!
tags [String!]!
title String!

Example

{
  "title": "Website relaunch",
  "date": "2026-11-13T09:30:00+01:00",
  "excerpt": "text",
  "image": "text",
  "link": "text",
  "tags": [
    "text"
  ]
}

SavedView

AdminPMBasicTracker

Fields

createdAt ISO8601DateTime!
id ID!
name String!
query String!
The list's query string (filters, what it shows; no order)
shared Boolean!
Shared with everyone in the project or workspace, not someone's own
updatedAt ISO8601DateTime!

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

id ID!
meta String
slug String
A project's or a customer's — to search in it (projectSlug / customerSlug)
title String!
url String!

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

archived Boolean!
billable Boolean!
false for internal work: it has no rate and its time is never billed
category ServiceCategory!
createdAt ISO8601DateTime!
dailyRate Float
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).
defaultTaxRate Float
The VAT rate a line of this service starts with; null = the workspace's default
description String
experts UserConnection!
The users whose own service this is
id ID!
slug String!
timetrackings TimetrackingConnection!
title String!
updatedAt ISO8601DateTime!

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

createdAt ISO8601DateTime!
id ID!
services ServiceConnection!
slug String!
tickets TicketConnection!
title String!
updatedAt ISO8601DateTime!

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

archived Boolean!
billable Boolean!
category String!
createdAt ISO8601DateTime!
dailyRate Float
defaultTaxRate Float
The VAT rate a line of this service starts with; null = the document's
description String
id ID!
isCustomRate Boolean!
originalRate Float
title String!
updatedAt ISO8601DateTime!

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "title": "Website relaunch",
  "createdAt": "2026-11-13T09:30:00+01:00",
  "archived": true,
  "billable": true,
  "category": "text"
}

SharedProjectReport

AdminPMBasicTracker

Fields

budgetRate Float
budgetType ProjectBudget!
budgetUsed Float!
createdAt ISO8601DateTime!
crypt String!
earliestTimetracking ISO8601Date
expired Boolean!
expiresOn ISO8601Date
id ID!
latestTimetracking ISO8601Date
project Project!
showBudget Boolean!
showExecutive Boolean!
showTickets Boolean!
tickets [SharedReportTicket!]!
The project's tickets (number, title, status) — empty unless the link shows them; open ones first
updatedAt ISO8601DateTime!

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "createdAt": "2026-11-13T09:30:00+01:00",
  "budgetRate": 120.5,
  "budgetType": "MINUTES",
  "budgetUsed": 120.5,
  "crypt": "text"
}

SharedReportTicket

AdminPMBasicTracker

Fields

number Int!
status TicketStatus!
title String!

Example

{
  "number": 1017,
  "title": "Website relaunch",
  "status": "OPEN"
}

StatusBreakdown

AdminPMBasicTracker

Fields

count Int!
status String!
total Float!

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

createdAt ISO8601DateTime!
id ID!
roundedMinutes Int!
What booking it suggests: rounded up to the next full 15 minutes
running Boolean!
false while paused
seconds Int!
Time on the clock right now, in seconds
ticket Ticket
Optional — can also be picked when booking
title String!
updatedAt ISO8601DateTime!

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!]!
commissionPercent Float
commissionThreshold Float!
commissionTotal Float!
debitTaxBreakdown [TaxGroup!]!
deductionType String
deductionValue Float
discountSurcharge [DiscountSurcharge!]!
exceedsQuotationTotal Boolean!
externalServiceTotal Float!
externalServiceTotalBilled Float!
mixedTaxRates Boolean!
More than one VAT rate on this document
onlyOptionalCostsIncluded Boolean!
optionalCostsIncluded Boolean!
reachesQuotationTotal Boolean!
subtotal Float!
taxBreakdown [TaxGroup!]!
taxRate Float!
taxTreatment TaxTreatment!
totalBilledGross Float!
totalBilledNet Float!
totalBilledSoFarNet Float!
totalBilledTax Float!
totalDebitGross Float!
totalDebitNet Float!
totalDebitTax Float!
totalGross Float!
totalNet Float!
totalTax Float!

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

archived Boolean!
createdAt ISO8601DateTime!
datevAccount String
The supplier's own account (creditor number) in the tax office's DATEV; null = the collective account
externalCosts ExternalCostConnection!
The supplier's invoices; only project managers and admins see any
id ID!
ksk Boolean!
Whether the supplier is subject to the KSK levy (German artists' social insurance), which is then added to its invoices' cost
slug String!
taxTreatment SupplierTaxTreatment!
How the supplier's invoices are taxed: domestic, or abroad — then an invoice without VAT is reverse charge (the workspace owes the tax)
title String!
The supplier's name
updatedAt ISO8601DateTime!

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

gross Float!
net Float!
rate Float!
The VAT rate in percent (19, 7, 0)
tax Float!

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

assignees UserConnection!
assignments TicketAssignmentConnection!
The assignments behind assignees, one per assigned person
attachments [TicketAttachment!]!
The files in the description and the comments, oldest first
author User!
boardPosition Int!
Rank within its board column, for ordering (not consecutive)
body Json!
The description as a rich-text JSON document (type doc with content nodes)
bodyHtml String!
The description rendered as HTML
bookedMinutesIncludingChildren Int!
Time booked on this ticket and its sub-tasks — what Jira shows as the aggregate
budgetRate Float
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).
budgetType TicketBudget
What the ticket's budget counts.
Who sees Null unless you may see financial data (project managers and admins).
budgetUsed Float!
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
closedAt ISO8601Date
The day it was closed; null while open
closedBy User
Who closed it; null while open
createdAt ISO8601DateTime!
endDate ISO8601Date
Planned end, the ticket's deadline
externalKey String
The Jira issue key, e.g. ABC-123; null for a native ticket
externalRawAssignees Json
Jira assignees that have no docket user (accountId, displayName); null for a native ticket
externalSource String
jira for a ticket mirrored from Jira; null for one created in docket
externalUrl String
Address of the issue in Jira; null for a native ticket
id ID!
isExternal Boolean!
Whether it is mirrored from Jira and therefore read-only in docket
isSticky Boolean!
Whether the ticket is pinned
jiraIssueType String
The Jira issue type (epic, story, sub-task, …); null for a native ticket
jiraSubtask Boolean!
Whether it mirrors a Jira sub-task
notificationRecipients [User!]!
number Int!
Running number within the project, starting at 1 (the general ticket every project starts with)
parentTicket Ticket
The mirror of its Jira parent issue; null for native tickets and top-level issues
phase Phase
phasePosition Int!
Rank within its phase, for ordering (not consecutive)
priority TicketPriority!
project Project!
serviceCategory ServiceCategory
The category of work the ticket belongs to, if one is set
startDate ISO8601Date
Planned start
status TicketStatus!
stream TicketStreamConnection!
Its comments and events (status changes, edits), oldest first
timetrackings TimetrackingConnection!
Time booked on the ticket. A timetracker sees only their own entries, everyone else all of them.
title String!
todosClosed Int!
Checked to-do items in the description
todosOpen Int!
Unchecked to-do items in the description
updatedAt ISO8601DateTime!
viewerFollowReason String
Why the caller follows it (for example because they wrote it or were assigned); null when they don't
viewerIsFollowing Boolean!
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

assignee User!
createdAt ISO8601DateTime!
id ID!
ticket Ticket!
updatedAt ISO8601DateTime!

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

author User
Who wrote the comment it is in; null for the description
byteSize Int!
commentId ID
The comment it is in; null for the description
contentType String
createdAt ISO8601DateTime!
filename String!
id ID!
The file's (blob's) id
image Boolean!
An image, shown as a thumbnail
thumbnailUrl String
A small square of an image, made on first request
url String!
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

author User!
body Json!
bodyHtml String!
createdAt ISO8601DateTime!
id ID!
mentions [Mention!]!
reactions [Reaction!]!
Its reactions by emoji, in the order they were first given
ticket Ticket!
todosClosed Int!
todosOpen Int!
updatedAt ISO8601DateTime!
viewerCanEdit Boolean!

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

date ISO8601Date!
description String
found String
What docket saw in the ticket, for an entry found from the person's activity
minutes Int
project Project
service Service
ticket Ticket

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

billed Boolean!
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
createdAt ISO8601DateTime!
dailyRate Float
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).
date ISO8601Date!
The day the work was done
description String
duration Float!
Minutes, in steps of 15
id ID!
invoice Invoice
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
jiraMissingForPush JiraPushRequirement
Set while the state is NOT_SYNCABLE: what the person lacks for the push
jiraSyncError String
What Jira answered when the push failed
jiraSyncState TimetrackingJiraSyncState
Where the push of this entry to Jira as a worklog stands; null for entries on tickets not mirrored from Jira
project Project!
revenue Float
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).
service Service!
The kind of work; it decides the rate
ticket Ticket!
updatedAt ISO8601DateTime!
user User!
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
}

TimetrackingAggregation

AdminPMBasicTracker

Fields

avgTimetrackingsPerDay AvgTimetrackingPerDay!

User

AdminPMBasicTracker

A person in the workspace. Everyone has exactly one role, which decides what they see and may do.

Fields

archived Boolean!
assignedCustomers CustomerConnection!
Customers the user is assigned to; for a timetracker they open the customers' projects
assignedProjects ProjectConnection!
The same as projects
avatar String
Path of the avatar image, cropped to a square of size pixels (default 256); null without one
birthday ISO8601Date
Null for timetrackers, unless it is their own.
bookedMinutes Int!
All time booked by this user, in minutes. 0 for timetrackers, unless it is their own.
createdAt ISO8601DateTime!
dashboardRssEnabled Boolean!
Whether the user's dashboard shows an RSS feed
dashboardRssExcerpt Boolean!
Whether that feed shows an excerpt of each item
dashboardRssUrl String
email String!
entryDate ISO8601Date
The day the person joined the agency. Null for timetrackers, unless it is their own.
expertise Service
The user's own service: what their time is booked for unless another is chosen
firstname String!
highestWorkTimeInMonth Float
The longest day, in hours, that a working-time profile valid in the month of that date plans; null as for workTimeForMonth
highestWorkTimeInWeek Float
The longest day, in hours, that a working-time profile valid in the week of that date plans; null as for workTimeForWeek
id ID!
initial String!
Short code shown where space is tight
jiraPlaceholder Boolean!
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.
lastname String!
locale Locale
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
projects ProjectConnection!
Projects the user is assigned to (project assignments)
role UserRole!
settings Json
Preferences the app stores for the user (free-form JSON).
Who sees Null unless you are this user or an admin.
slug String!
targetHours Float
Target working hours on that day, from the profile valid then (null: none)
tickets TicketConnection!
Tickets assigned to the user
timetrackings TimetrackingConnection!
twoFactorEnabled Boolean
Whether two-factor sign-in is on; null unless you are this user or an admin
updatedAt ISO8601DateTime!
username String!
viewerCanManageAccess Boolean!
Whether the caller may change this user's role and archive them: admins, never for themselves
workTimeForMonth Float
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
workTimeForWeek Float
Target working hours in the week of that date; null when none, and unless you are this user or at least a basic user
workTimes UserWorkTimeConnection!
The user's working-time profiles: target hours per weekday, each valid from a date
workspaceLocale Locale
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

activeFrom ISO8601Date!
createdAt ISO8601DateTime!
fri Float!
id ID!
mon Float!
sat Float!
sun Float!
thu Float!
tue Float!
updatedAt ISO8601DateTime!
user User!
wed Float!

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

createdAt ISO8601DateTime!
id ID!
lockReason String
Why it can't be deleted, or null when it can
locked Boolean!
Documents were issued or external costs recorded in its period: it can't be deleted any more
smallBusiness Boolean!
updatedAt ISO8601DateTime!
validFrom ISO8601Date!

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

archived Boolean!
assignedTickets TicketConnection!
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.
createdAt ISO8601DateTime!
email String!
expertise Service
The person's own service: the kind of work their time entries default to
firstname String!
followedTickets TicketConnection!
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.
id ID!
initial String!
The person's short sign, e.g. initials, shown on avatars
lastname String!
notificationStream NotificationConnection!
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
projectsInvolved ProjectConnection!
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.
role UserRole!
The highest role the person holds; it decides what every query returns to them
rssFeed RssFeed
The RSS feed the person put on their dashboard; null when they have none switched on
settings Json
Interface state the app keeps for the person (e.g. whether the sidebar is open), as free-form JSON
slug String!
timetrackingSuggestions [String!]!
The descriptions the person used for earlier time entries on a ticket, latest first, without duplicates.
timetrackings TimetrackingConnection!
The person's own time entries.
unreadMentionCount Int!
Unread notifications that mention the viewer
unreadNotificationCount Int!
Unread notifications that are not archived, counted once per record and event: three new comments on one ticket count as one
updatedAt ISO8601DateTime!
username String!

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

attempts Int!
createdAt ISO8601DateTime!
deliveredAt ISO8601DateTime
error String
event String!
id ID!
responseCode Int
status String!
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

active Boolean!
createdAt ISO8601DateTime!
deliveries [WebhookDelivery!]!
The latest twenty deliveries, newest first
disabledAt ISO8601DateTime
When docket switched it off after too many failures
events [String!]!
failureCount Int!
Deliveries given up on in a row
id ID!
url String!

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

dueThisWeek Int!
Of thisWeek: due this week
later Int!
nextMonth Int!
overdue Int!
thisMonth Int!
thisWeek Int!
unplanned Int!

Example

{
  "dueThisWeek": 42,
  "later": 42,
  "nextMonth": 42,
  "overdue": 42,
  "thisMonth": 42,
  "thisWeek": 42
}

WorkloadGroup

AdminPMBasicTracker

Fields

category ServiceCategory
rows [WorkloadRow!]!
subtotals WorkloadCounts!
total Int!

Example

{
  "total": 42
}

WorkloadOverview

AdminPMBasicTracker

Fields

groups [WorkloadGroup!]!
max Int!
total Int!
totals WorkloadCounts!
unassigned WorkloadRow!

Example

{
  "max": 42,
  "total": 42
}

WorkloadRow

AdminPMBasicTracker

Fields

assignee User
counts WorkloadCounts!
total Int!

Example

{
  "total": 42
}

WorkspaceExport

AdminPMBasicTracker

Fields

byteSize Int
Size of the ZIP in bytes, once it is ready
createdAt ISO8601DateTime!
downloadUrl String
The app's download link (it checks the session again) — null unless the export is ready and not expired
expiresAt ISO8601DateTime
id ID!

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

customFieldId ID
customFieldValue String

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

amount Float
deleted Boolean
description String
id ID
name String
optional Boolean
quantity Float
rate Float
serviceId String
taxRate Float
VAT rate in percent; omit for the document's rate
unit String

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

archived Boolean
customerIds [ID!]
Contacts of any of these customers
ids [ID!]
search String
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

archived Boolean
customerIds [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

archived Boolean
ids [ID!]
projectArchived Boolean
true = customers with at least one archived project, false = with at least one project that is not archived
projectTitle String
Customers with a project whose title contains this text
search String
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!]
search String

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "search": "text"
}

DocumentAssistantTurnInput

Fields

role String!
user or assistant
text String!

Example

{
  "role": "text",
  "text": "2h checkout bug"
}

ExternalCostAssignmentExtendedInput

Fields

boundsHeight Float
boundsLeft Float
boundsTop Float
boundsWidth Float
page Int

Example

{
  "boundsWidth": 120.5,
  "boundsHeight": 120.5,
  "boundsTop": 120.5,
  "boundsLeft": 120.5,
  "page": 42
}

ExternalCostAssignmentInput

Fields

amount Float
boundsHeight Float
boundsLeft Float
boundsTop Float
boundsWidth Float
chargeable Boolean
page Int
projectId ID
quotationId ID

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
search String
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!]
isPaid Boolean
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
search String
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
year Int
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

archived Boolean
createdAt [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.
isNew Boolean
true = unread, false = read

Example

{
  "createdAt": [
    "text"
  ],
  "isNew": true,
  "archived": true
}

NotificationRecordInput

Fields

id ID!

Example

{
  "type": "TICKET",
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
}

OrderConfirmationFilter

Fields

ids [ID!]
search String

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "search": "text"
}

PhaseFilter

Fields

ids [ID!]
projectIds [ID!]
search String
Phases whose title contains this text

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "projectIds": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "search": "text"
}

PinnedPageInput

Fields

path String!
title String!

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".
archived Boolean
assigneeIds [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.
followedByViewer Boolean
true = only projects the current user follows (see Follow)
hasStickyTickets Boolean
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
search String
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.
forecastYear Int
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"
isPaid Boolean
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!]
search String
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!]
search String
Categories whose title contains this text
searchServices String
Categories with a service whose title contains this text

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "search": "text",
  "searchServices": "text"
}

ServiceFilter

Fields

archived Boolean
ids [ID!]
search String
Services whose title contains this text

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "archived": true,
  "search": "text"
}

ServiceRateInput

Fields

dailyRate Float
id ID

Example

{
  "id": "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90",
  "dailyRate": 120.5
}

SupplierFilter

Fields

archived Boolean
ids [ID!]
search String
Suppliers whose name contains this text

Example

{
  "ids": [
    "8c3d2f4e-6b1a-4e7d-9a52-0f6e3b1c7d90"
  ],
  "archived": true,
  "search": "text"
}

TicketFilter

Fields

assigned Boolean
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
bookable Boolean
true = only what the time-entry form offers (on a Jira-linked project: its Jira tickets)
customerIds [ID!]
dueThisWeek Boolean
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.
external Boolean
true = only tickets mirrored from Jira, false = only docket's own
followedByViewer Boolean
true = only tickets the current user follows (see Follow)
hasStartOrEndDate Boolean
true = only tickets with a start or an end date; false has no effect
ids [ID!]
isSticky Boolean
labelIds [ID!]
number String
The ticket's number within its project
overdueOrCurrentWeek Boolean
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".
projectArchived Boolean
projectIds [ID!]
projectSlugs [String!]
scheduleBuckets [TicketScheduleBucket!]
When the ticket is planned — the workload buckets
search String
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.
status TicketStatus

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
search String
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

archived Boolean
birthdays [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
canAccessDocuments Boolean
Only users who can open billing documents
canAccessProject ID
Only users who can open this project (ID or slug)
ids [ID!]
idsNot [ID!]
Leaves out these users
jiraPlaceholder Boolean
Only (true) or no (false) Jira placeholder users; left out, placeholders are not listed
search String
People whose first or last name contains this text
username String
The exact username
withJiraPlaceholders Boolean
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

date ISO8601Date
Only the working hours in force on this day (the latest that started on or before it)
limitCurrentWeek Boolean
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_service
external_service

BlockPositionSubpositionTypeEnum

Values

service
custom
flatrate

BlockTypeEnum

Values

phase
agency_service
external_service

BoardPreset

Values

backlog
done
custom

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

TICKET
QUOTATION
ORDER_CONFIRMATION
DELIVERY_NOTE
INVOICE

Currency

Values

EUR
USD
GBP
CHF
AUD
BRL
CAD
CNY
CZK
DKK
HKD
HUF
IDR
ILS
INR
ISK
JPY
KRW
MXN
MYR
NOK
NZD
PHP
PLN
RON
SEK
SGD
THB
TRY
ZAR

DeliveryNoteStatus

Values

DRAFT
Not sent yet: its content can be changed.
PUBLISHED
Ready to go to the customer: its content is locked.

DiscountSurchargeTypeEnum

Values

discount
surcharge

DocumentFontStyle

Values

REGULAR
BOLD
ITALIC
BOLD_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

TICKET
QUOTATION
INVOICE
ORDER_CONFIRMATION
DELIVERY_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

TICKETS
BOARDS
CONTROLLING_TIMETRACKINGS
CONTROLLING_TICKETS
PROJECTS
FORECAST
EXTERNAL_COSTS
WORKLOAD_TICKETS
TIMETRACKING_REPORTS

SearchResultModel

Values

PROJECT
TICKET
USER
QUOTATION
ORDER_CONFIRMATION
DELIVERY_NOTE
INVOICE
EXTERNAL_COST
CUSTOMER
CONTACT

SearchScope

Values

PROJECTS
TICKETS
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

TITLE
DESCRIPTION
ASSIGNEES
LABELS
PRIORITY
PHASE
SERVICE
START_DATE
END_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".