Skip to main content
Beebole queries are the read operations of the Beebole GraphQL API. They return data from your account — your organisation, people, projects, tasks, tags, time records, and expenses — without modifying anything. Every query is sent as a POST request to https://app.beebole.com/graphql with your API key in the apikey HTTP header.
Queries never change data. To create, update, archive, or delete records, use Mutations instead. For authentication setup, see the API introduction.
Field names follow GraphQL conventions exactly as defined in the schema. Every entity exposes its identifier as id (not _id), and the organisation-level query is spelled currentOrganisation (British spelling, as in the schema). Beebole queries are the read operations of the Beebole GraphQL API. They return data from your account — your organization, people, projects, tasks, tags, time records, and expenses — without modifying anything. Every query is sent as a POST request to https://app.beebole.com/graphql with your API key in the apikey HTTP header.
Queries never change data. To create, update, archive, or delete records, use Mutations instead. For authentication setup, see the API introduction.
Field names follow GraphQL conventions exactly as defined in the schema. Every entity exposes its identifier as id (not _id), and the organization-level query is spelled currentOrganisation (British spelling, as in the schema).

Organisation

Read account-level data with currentOrganisation and getAuditTrails.
QueryArgumentsReturns
currentOrganisationnoneThe organisation linked to the authenticated API key
getAuditTrailsstartTime, fromPersonId, operations, argumentMatch, responseMatchAudit trail entries for the organisation
query {
  currentOrganisation {
    id
    name
    locked
  }
}
getAuditTrails returns mutations performed in the account. With no startTime, it covers the last seven days; startTime selects a different seven-day window.
query {
  getAuditTrails(operations: ["addTimeRecord", "deleteTimeRecords"]) {
    operationName
    timestamp
    person {
      id
      name
    }
    arguments {
      name
      value
    }
  }
}

Organization

Read account-level data with currentOrganisation and getAuditTrails.
QueryArgumentsReturns
currentOrganisationnoneThe organization linked to the authenticated API key
getAuditTrailsstartTime, fromPersonId, operations, argumentMatch, responseMatchAudit trail entries for the organization
query {
  currentOrganisation {
    id
    name
    locked
  }
}
getAuditTrails returns mutations performed in the account. With no startTime, it covers the last seven days; startTime selects a different seven-day window.
query {
  getAuditTrails(operations: ["addTimeRecord", "deleteTimeRecords"]) {
    operationName
    timestamp
    person {
      id
      name
    }
    arguments {
      name
      value
    }
  }
}

People

Read team members with currentPerson, getPerson, getPersons, countPersons, and filterPersonIds. getPotentialProjectOwners lists the people allowed to own a given project. Read team members with currentPerson, getPerson, getPersons, countPersons, and filterPersonIds. getPotentialProjectOwners lists the people allowed to own a given project.
QueryArgumentsReturns
currentPersonnoneThe person linked to the API key
getPersonidA single person
getPersonsfilter, archivedA list of people
countPersonsfilter, archivedThe number of matching people
filterPersonIdsfilter, archivedOnly the IDs of matching people
getPotentialProjectOwnersprojectIdPeople eligible to own the project
query {
  getPersons {
    id
    name
    email
    archived
  }
}
query {
  getPerson(id: "64a1b2c3d4e5f6a7b8c9d0e1") {
    id
    name
    email
    role {
      id
      name
    }
  }
}
By default getPersons returns only active people. Pass archived: true to include archived ones.
query {
  getPersons(archived: true) {
    id
    name
    archived
  }
}
By default getPersons returns only active people. Pass archived: true to include archived ones.
query {
  getPersons(archived: true) {
    id
    name
    archived
  }
}

Projects

Read projects with getProject, getProjects, countProjects, and filterProjectIds. getProjectCategories lists the top-level groupings projects are organised into. Read projects with getProject, getProjects, countProjects, and filterProjectIds. getProjectCategories lists the top-level groupings projects are organised into.
QueryArgumentsReturns
getProjectidA single project
getProjectsfilter, archived, categoryIdA list of projects
countProjectsfilter, archived, categoryIdThe number of matching projects
filterProjectIdsfilter, archived, categoryIdOnly the IDs of matching projects
getProjectCategoriesnoneAll project categories
query {
  getProjects {
    id
    name
    level
    category {
      id
      name
    }
  }
}
The level field is the project’s depth in the hierarchy, where 0 is a top-level project. Restrict results to one category with categoryId:
query {
  getProjects(categoryId: "64a1b2c3d4e5f6a7b8c9d0e1") {
    id
    name
  }
}
query {
  getProjectCategories {
    id
    name
    levelNames
  }
}
The level field is the project’s depth in the hierarchy, where 0 is a top-level project. Restrict results to one category with categoryId:
query {
  getProjects(categoryId: "64a1b2c3d4e5f6a7b8c9d0e1") {
    id
    name
  }
}
query {
  getProjectCategories {
    id
    name
    levelNames
  }
}

Tasks

Read tasks with getTask, getTasks, countTasks, and filterTaskIds. getTaskCategories lists the categories (boards) tasks belong to. Read tasks with getTask, getTasks, countTasks, and filterTaskIds. getTaskCategories lists the categories (boards) tasks belong to.
QueryArgumentsReturns
getTaskidA single task
getTasksfilter, archived, categoryIdA list of tasks
countTasksfilter, archived, categoryIdThe number of matching tasks
filterTaskIdsfilter, archived, categoryIdOnly the IDs of matching tasks
getTaskCategoriesnoneAll task categories
query {
  getTasks {
    id
    name
    startTime
    endTime
    status {
      id
      name
    }
  }
}
query {
  getTasks {
    id
    name
    startTime {
      ts
      iso
    }
    endTime {
      ts
      iso
    }
    status {
      id
      name
    }
  }
}
query {
  getTask(id: "64a1b2c3d4e5f6a7b8c9d0e1") {
    id
    name
    effort
    dependencies {
      id
      name
    }
  }
}
query {
  getTask(id: "64a1b2c3d4e5f6a7b8c9d0e1") {
    id
    name
    effort
    dependencies {
      id
      name
    }
  }
}

Tags

Read tags with getTag, getTags, countTags, and filterTagIds. getTagCategories lists the categories tags are grouped into.
QueryArgumentsReturns
getTagidA single tag
getTagsfilter, archived, categoryIdA list of tags
countTagsfilter, archived, categoryIdThe number of matching tags
filterTagIdsfilter, archived, categoryIdOnly the IDs of matching tags
getTagCategoriesnoneAll tag categories
query {
  getTags {
    id
    name
    level
  }
}

Tags

Read tags with getTag, getTags, countTags, and filterTagIds. getTagCategories lists the categories tags are grouped into.
QueryArgumentsReturns
getTagidA single tag
getTagsfilter, archived, categoryIdA list of tags
countTagsfilter, archived, categoryIdThe number of matching tags
filterTagIdsfilter, archived, categoryIdOnly the IDs of matching tags
getTagCategoriesnoneAll tag categories
query {
  getTags {
    id
    name
    level
  }
}

Time records

A time record is a logged time entry for one person on a specific day, linked to projects, a task, or an absence type. Read them with getTimeRecord, getTimeRecords, and countTimeRecords. getAbsenceConsumed returns how much of an absence type a person has used in a window.
QueryArgumentsReturns
getTimeRecordidA single time record
getTimeRecordsstartTime, endTime, time, absence, wfh, filterA list of time records
countTimeRecordsstartTime, endTime, time, absence, wfh, filterThe number of matching time records
getAbsenceConsumedpersonId, absenceId, startTime, endTimeAbsence consumed in the window, in the type’s unit
getTimeRecords and countTimeRecords accept top-level arguments alongside filter:
  • startTime / endTime — Unix timestamps in milliseconds bounding the period.
  • time — when true, return only worked time (entries without an absence type).
  • absence — when true, return only absence entries (entries with an absence type).
  • wfh — when true, return only entries logged as working from home.
  • filter — a typed filter array (see Filtering results).
query {
  getTimeRecords(startTime: 1704067200000, endTime: 1706745600000, time: true) {
    id
    duration
    startTime
    nonBillable
    person {
      id
      name
    }
    projects {
      id
      name
    }
  }
}
Durations and timestamps are integers in milliseconds. The person, projects, task, and absence fields resolve the related entities inline.
query {
  getAbsenceConsumed(
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
    absenceId: "64a1b2c3d4e5f6a7b8c9d0e2"
    startTime: 1704067200000
    endTime: 1735689600000
  )
}

Expense records

An expense record is an expense logged by a person against a project and an expense type. Read them with getExpenseRecord and getExpenseRecords.
QueryArgumentsReturns
getExpenseRecordidA single expense record
getExpenseRecordsstartTime, endTime, filterA list of expense records
query {
  getExpenseRecords(startTime: 1704067200000, endTime: 1706745600000) {
    id
    date
    amount
    comment
    expenseType {
      id
      name
    }
    project {
      id
      name
    }
  }
}

Absence types

Absence types are the kinds of leave people can log against, such as vacation or sick leave. Read them with getAbsenceType, getAbsenceTypes, and countAbsenceTypes.
QueryArgumentsReturns
getAbsenceTypeidA single absence type
getAbsenceTypesfilter, archivedA list of absence types
countAbsenceTypesfilter, archivedThe number of matching absence types
query {
  getAbsenceTypes {
    id
    name
    unit
    involveCosts
  }
}

Filtering results

The filter argument is a list of typed input objects — not a list of field/value pairs. Each entity has its own filter input type, such as BeeboleTimeRecordFilter, BeebolePersonFilter, or BeeboleProjectFilter. You set the named fields you want to match directly on each object. A time record is a logged time entry for one person on a specific day, linked to projects, a task, or an absence type. Read them with getTimeRecord, getTimeRecords, and countTimeRecords. getAbsenceConsumed returns how much of an absence type a person has used in a window.
QueryArgumentsReturns
getTimeRecordidA single time record
getTimeRecordsstartTime, endTime, time, absence, wfh, filterA list of time records
countTimeRecordsstartTime, endTime, time, absence, wfh, filterThe number of matching time records
getAbsenceConsumedpersonId, absenceId, startTime, endTimeAbsence consumed in the window, in the type’s unit
getTimeRecords and countTimeRecords accept top-level arguments alongside filter:
  • startTime / endTime — Unix timestamps in milliseconds bounding the period.
  • time — when true, return only worked time (entries without an absence type).
  • absence — when true, return only absence entries (entries with an absence type).
  • wfh — when true, return only entries logged as working from home.
  • filter — a typed filter array (see Filtering results).
query {
  getTimeRecords(startTime: 1704067200000, endTime: 1706745600000, time: true) {
    id
    duration
    startTime {
      ts
      iso
    }
    nonBillable
    person {
      id
      name
    }
    projects {
      id
      name
    }
  }
}
duration is an integer in milliseconds. startTime and endTime are BeeboleTime objects — select their subfields ts (a Unix timestamp in milliseconds) and iso (an ISO 8601 string). The person, projects, task, and absence fields resolve the related entities inline.
query {
  getAbsenceConsumed(
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
    absenceId: "64a1b2c3d4e5f6a7b8c9d0e2"
    startTime: 1704067200000
    endTime: 1735689600000
  )
}

Expense records

An expense record is an expense logged by a person against a project and an expense type. Read them with getExpenseRecord and getExpenseRecords.
QueryArgumentsReturns
getExpenseRecordidA single expense record
getExpenseRecordsstartTime, endTime, filterA list of expense records
query {
  getExpenseRecords(startTime: 1704067200000, endTime: 1706745600000) {
    id
    date {
      ts
      iso
    }
    amount {
      value
      currency
    }
    comment
    expenseType {
      id
      name
    }
    project {
      id
      name
    }
  }
}
date is a BeeboleTime object (ts in milliseconds, iso as an ISO 8601 string). amount is an object with value (an integer in the currency’s smallest unit) and currency.

Absence types

Absence types are the kinds of leave people can log against, such as vacation or sick leave. Read them with getAbsenceType, getAbsenceTypes, and countAbsenceTypes.
QueryArgumentsReturns
getAbsenceTypeidA single absence type
getAbsenceTypesfilter, archivedA list of absence types
countAbsenceTypesfilter, archivedThe number of matching absence types
query {
  getAbsenceTypes {
    id
    name
    unit
    involveCosts
  }
}

Filtering results

The filter argument is a list of typed input objects — not a list of field/value pairs. Each entity has its own filter input type, such as BeeboleTimeRecordFilter, BeebolePersonFilter, or BeeboleProjectFilter. You set the named fields you want to match directly on each object.
query {
  getTimeRecords(filter: [{ personId: "64a1b2c3d4e5f6a7b8c9d0e1" }]) {
    id
    duration
    startTime
  }
}
query {
  getTimeRecords(filter: [{ personId: "64a1b2c3d4e5f6a7b8c9d0e1" }]) {
    id
    duration
    startTime {
      ts
      iso
    }
  }
}
Each object in the array should set a single matching field. To combine conditions, add a following value of AND or OR to chain one condition to the next:
query {
  getProjects(
    filter: [
      { categoryId: "64a1b2c3d4e5f6a7b8c9d0e1", following: AND }
      { archived: false }
    ]
  ) {
    id
    name
  }
}

Time record filter fields

BeeboleTimeRecordFilter accepts these fields (each optional):
FieldTypeMatches
id / notIdIDA specific time record, or all but one
personId / notPersonIdIDRecords for (or excluding) one person
personIds[ID]Records for any of several people
startTime / endTimeTimestampRecords starting after / ending before a millisecond timestamp
projectIds / notProjectIds[ID]Records on (or excluding) projects, including their sub-projects
taskIds / notTaskIds[ID]Records on (or excluding) tasks
projectTagIds / projectNotTagIds[ID]Records whose projects carry (or lack) given tags
personTagIds / personNotTagIds[ID]Records whose person carries (or lacks) given tags
projectCategoryIds / notProjectCategoryIds[ID]Records by project category
taskCategoryIds / notTaskCategoryIds[ID]Records by task category
isAbsenceBooleanWhether the record is an absence
followingAND / ORLogical operator chaining this condition to the next
Other entities expose filter types tuned to their own fields — for example BeebolePersonFilter supports roleId, tagIds, and name (a case-insensitive match), while BeeboleProjectFilter supports categoryId, managedById, and subProjectId. Browse every filter type and its fields in the Schema explorer. Each object in the array should set a single matching field. To combine conditions, add a following value of AND or OR to chain one condition to the next:
query {
  getProjects(
    filter: [
      { categoryId: "64a1b2c3d4e5f6a7b8c9d0e1", following: AND }
      { archived: false }
    ]
  ) {
    id
    name
  }
}

Time record filter fields

BeeboleTimeRecordFilter accepts these fields (each optional):
FieldTypeMatches
id / notIdIDA specific time record, or all but one
personId / notPersonIdIDRecords for (or excluding) one person
personIds[ID]Records for any of several people
startTime / endTimeTimestampRecords starting after / ending before a millisecond timestamp
projectIds / notProjectIds[ID]Records on (or excluding) projects, including their subprojects
taskIds / notTaskIds[ID]Records on (or excluding) tasks
projectTagIds / projectNotTagIds[ID]Records whose projects carry (or lack) given tags
personTagIds / personNotTagIds[ID]Records whose person carries (or lacks) given tags
projectCategoryIds / notProjectCategoryIds[ID]Records by project category
taskCategoryIds / notTaskCategoryIds[ID]Records by task category
isAbsenceBooleanWhether the record is an absence
followingAND / ORLogical operator chaining this condition to the next
Other entities expose filter types tuned to their own fields — for example BeebolePersonFilter supports roleId, tagIds, and name (a case-insensitive match), while BeeboleProjectFilter supports categoryId, managedById, and subProjectId. Browse every filter type and its fields in the Schema explorer.

Counting and ID-only queries

For each major entity, alongside the full get… query you also get a counterpart that returns just a count, and (for people, projects, tasks, and tags) one that returns only matching IDs.
  • count… queries (countPersons, countProjects, countTasks, countTags, countTimeRecords, countAbsenceTypes) return an integer. Use them to size a result set before fetching it.
  • filter…Ids queries (filterPersonIds, filterProjectIds, filterTaskIds, filterTagIds) return an array of IDs instead of full objects, which is lighter when you only need identifiers.
query {
  countTimeRecords(startTime: 1704067200000, endTime: 1706745600000)
}
The Beebole query API has no pagination — there are no limit, offset, first, or cursor arguments. A list query returns every record that matches its arguments. Narrow large result sets with filter, the startTime / endTime window, or categoryId, and use a count… query first to gauge the size.

Counting and ID-only queries

For each major entity, alongside the full get… query you also get a counterpart that returns just a count, and (for people, projects, tasks, and tags) one that returns only matching IDs.
  • count… queries (countPersons, countProjects, countTasks, countTags, countTimeRecords, countAbsenceTypes) return an integer. Use them to size a result set before fetching it.
  • filter…Ids queries (filterPersonIds, filterProjectIds, filterTaskIds, filterTagIds) return an array of IDs instead of full objects, which is lighter when you only need identifiers.
query {
  countTimeRecords(startTime: 1704067200000, endTime: 1706745600000)
}
The Beebole query API has no pagination — there are no limit, offset, first, or cursor arguments. A list query returns every record that matches its arguments. Narrow large result sets with filter, the startTime / endTime window, or categoryId, and use a count… query first to gauge the size.

API Introduction

Authenticate with an API key and send your first request.

Mutations

The write operations that create, update, archive, and delete records.

Schema explorer

Browse every query, type, field, and filter input interactively.