Skip to main content
Mutations are the GraphQL write operations of the Beebole API. They create, update, archive, or delete data in your Beebole account — logging time and expenses, running the timesheet approval workflow, and managing people, projects, tasks, and organization settings. Send every mutation as a POST request to https://app.beebole.com/graphql with your key in the apikey HTTP header (see Introduction). Each mutation returns the affected object so you can read back fields in the same request. Object IDs are exposed as id (not _id). For read-only operations, see Queries.
Time durations in Beebole are expressed in milliseconds. To log 2 hours, pass 7200000 (2 × 60 × 60 × 1000), not 120.

Time records

A time record is one logged entry for a person on a given day, linked to projects, a task, or an absence type. Durations are in milliseconds.
MutationKey arguments
addTimeRecordstartTime, duration, personId, optional endTime, taskId, absenceId, projectIds
editTimeRecordStartTimeid, startTime
editTimeRecordEndTimeid, endTime
editTimeRecordDurationid, duration (milliseconds)
editTimeRecordProjectsid, projectIds
editTimeRecordTaskid, taskId
editTimeRecordAbsenceid, absenceId
editTimeRecordCommentid, comment
editTimeRecordNonBillableid, nonBillable
editTimeRecordWfhid, wfh
deleteTimeRecordsids (array)
cloneTimeRecordspersonId, sourceStartTime, sourceEndTime, targetStartTime, targetEndTime, optional replaceExisting
startTime and endTime are Unix timestamps in milliseconds. duration is an integer count of milliseconds.

Log a time entry

This logs 2 hours (7200000 milliseconds) for a person against a task:
mutation {
  addTimeRecord(
    startTime: 1717200000000
    duration: 7200000
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
    taskId: "64a1b2c3d4e5f6a7b8c9d0e3"
  ) {
    id
    duration
    startTime {
      ts
      iso
    }
  }
}

Clone a week of time records

cloneTimeRecords copies a person’s entries from a source period to a target period. Set replaceExisting: true to clear the target period first.
mutation {
  cloneTimeRecords(
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
    sourceStartTime: 1717200000000
    sourceEndTime: 1717718400000
    targetStartTime: 1717804800000
    targetEndTime: 1718323200000
    replaceExisting: true
  ) {
    id
    startTime {
      ts
      iso
    }
    duration
  }
}

Expense records

An expense record is an actual expense logged against a person and/or a project. The amount is sent as value with an optional currency; if you omit the currency, Beebole uses the person’s or organization’s default.
MutationKey arguments
addExpenseRecorddate, expenseTypeId, value, optional currency, personId, projectId, comment
deleteExpenseRecordid
editExpenseRecordDateid, date
editExpenseRecordExpenseid, expenseTypeId
editExpenseRecordPersonid, personId (null to remove)
editExpenseRecordProjectid, projectId (null to remove)
editExpenseRecordAmountValueid, value
editExpenseRecordAmountCurrencyid, currency
editExpenseRecordCommentid, comment
At least one of personId or projectId is required on addExpenseRecord — both are otherwise optional.

Log an expense

mutation {
  addExpenseRecord(
    date: 1717200000000
    expenseTypeId: "64a1b2c3d4e5f6a7b8c9d0e4"
    value: 4250
    currency: "EUR"
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
  ) {
    id
    amount {
      value
      currency
    }
    date {
      ts
      iso
    }
  }
}

Timesheets and approvals

The approval workflow runs through three mutations. There is no single “add approval event” call — submitting, approving, and rejecting are distinct operations that return a BeeboleApprovalEvent.
MutationKey arguments
submitTimesheetpersonId, startTime, endTime
approveTimesheetid (the submit event ID)
rejectTimesheetid (the submit event ID), stage, comment
sendTimesheetReminderpersonIds (array), startTime, endTime
Beebole determines the current approval stage automatically. submitTimesheet returns the submit event whose id you pass to approveTimesheet or rejectTimesheet.

Submit a timesheet for a period

mutation {
  submitTimesheet(
    personId: "64a1b2c3d4e5f6a7b8c9d0e1"
    startTime: 1717200000000
    endTime: 1719792000000
  ) {
    id
    status
    stage
  }
}

Approve or reject

mutation {
  approveTimesheet(id: "64a1b2c3d4e5f6a7b8c9d0e5") {
    id
    status
  }
}
mutation {
  rejectTimesheet(
    id: "64a1b2c3d4e5f6a7b8c9d0e5"
    stage: 0
    comment: "Please add the client meeting on Tuesday."
  ) {
    id
    status
    comment
  }
}

People

MutationKey arguments
addPersonname, email, roleId, optional color
deletePersonid, optional check (dry-run)
duplicatePersonid, name, optional email, roleId
archivePerson / unarchivePersonid
archivePersons / unarchivePersonsids (array)
editPersonNameid, name
editPersonEmailid, email
editPersonRoleid, roleId
editPersonStartDateid, startDate
editPersonColorid, color
editPersonLangid, lang
deletePerson accepts check: true to validate references without deleting.

Create a person

mutation {
  addPerson(
    name: "Alice Martin"
    email: "alice@example.com"
    roleId: "64a1b2c3d4e5f6a7b8c9d0e1"
  ) {
    id
    name
  }
}

Projects

MutationKey arguments
addProjectname, optional categoryId, parentId, color
deleteProjectid, optional check (dry-run)
deleteProjectsids (array)
duplicateProjectid, name, optional parentId
archiveProject / unarchiveProjectid
archiveProjects / unarchiveProjectsids (array)
editProjectNameid, name
editProjectParentid, parentId
editProjectColorid, color
editProjectAvailabilityid, availability
addProjectCategoryname
deleteProjectCategoryid
editProjectCategoryNameid, name
editProjectCategoryLevelNamesid, levelNames
To create a subproject, pass the parent project’s parentId. The subproject inherits the parent’s category unless you set a different categoryId.

Create a project

mutation {
  addProject(
    name: "Website Redesign"
    categoryId: "64a1b2c3d4e5f6a7b8c9d0e2"
  ) {
    id
    name
  }
}

Tasks

Tasks are independent planning entities you create, schedule, and track time against. Categories organize tasks into workflow statuses.
MutationKey arguments
addTaskname, optional categoryId, parentId, color, statusId
deleteTaskid, optional check (dry-run)
archiveTask / unarchiveTaskid
archiveTasks / unarchiveTasksids (array)
editTaskNameid, name
editTaskParentid, parentId
editTaskColorid, color
editTaskStatusid, statusId
editTaskPeriodid, optional startTime, endTime, effort
editTaskDurationid, effort (minutes)
moveTasksToStatustaskIds, targetStatusId, orderedTaskIds
Task categories and their workflow statuses are managed with the category mutations:
MutationKey arguments
addTaskCategoryStatuscategoryId, name
deleteTaskCategoryStatuscategoryId, statusId
editTaskCategoryStatusNamestatusId, name
editTaskCategoryStatusColorstatusId, color
editTaskCategoryStatusMaxConcurrentTasksstatusId, maxConcurrentTasks
editCategoryTaskMovecategoryId, taskMove
To move a task between categories or statuses, use editTaskStatus (single task) or moveTasksToStatus (one or more tasks). editCategoryTaskMove sets a category’s task-move behavior.

Create a task

mutation {
  addTask(
    name: "Write copy"
    categoryId: "64a1b2c3d4e5f6a7b8c9d0e3"
  ) {
    id
    name
  }
}

Organization

Organization settings are edited on the single current organization, so these mutations take no id. The GraphQL field names keep the British spelling Organisation.
MutationKey arguments
editOrganisationNamename
editOrganisationColorcolor
editGoogleSSOgoogle (input)
editMicrosoftSSOmicrosoft (input)
editCustomSSOcustomSSO (input, null to clear)

Rename the organization

mutation {
  editOrganisationName(name: "Acme Corp") {
    id
    name
  }
}

Mutations that delete data cannot be undone through the API. Where a check argument is available (deletePerson, deleteProject, deleteTask), pass check: true first to validate references without deleting anything.
When creating records, store the returned id values so you can reference or update them in follow-up mutations. Batch mutations such as archivePersons, deleteProjects, and deleteTimeRecords accept arrays — prefer them over looping single-item calls.

API Introduction

Authenticate with your API key and send your first request.

Queries

Read time records, people, projects, and tasks over GraphQL.

Schema explorer

Browse the full GraphQL schema interactively.