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, billing and cost rates, 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. 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:

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.

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.
At least one of personId or projectId is required on addExpenseRecord — both are otherwise optional.

Log an expense


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. 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

Approve or reject


People

deletePerson accepts check: true to validate references without deleting.

Create a person


Projects

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


Tasks

Tasks are independent planning entities you create, schedule, and track time against. Task categories, the plannings of the Beebole app, organize tasks into workflow statuses. Task categories and their workflow statuses are managed with the category mutations: To move a task to another status, use editTaskStatus (single task) or moveTasksToStatus (one or more tasks). Both only move tasks between statuses of the same category: a status from another category is refused with CantAssignStatusFromOtherCategory, and no mutation moves a task to another category. editCategoryTaskMove sets the Dependent tasks option of the Gantt and Staffing views, which decides how dependent tasks follow when a task they depend on moves: 0 for Free, 1 for Pushing, 2 for Together. archiveTask and unarchiveTask (and their plural forms) are what the Beebole app shows as Done and Reopen on a task: a done task is an archived task. Archiving does not change the task’s status. addTask without a name creates a nameless task, whose displayed name comes from its owner or project. In a planning set to Bookings, a name is refused with CantNameTaskInBookingsPlanning, since a booking is always named after its project and person.

Create a task


Billing and cost rates

A billing or cost rate is a dated amount set on the organization, a tag, a person, or a project. It takes effect on its startTime, the From date in Beebole, and applies until a rate with a later date takes over. Rates cascade from the organization, tags, and parent projects to the people and projects that have none of their own. How Beebole picks the rate of each time entry is described in Billing and Costs. A time record carries no amount, only its nonBillable flag. Beebole computes billing and cost in reports from the rates, so to value time entries, including entries you import, set rates whose dates cover them. The arguments of the add mutations:
  • startTime is a BeeboleTimestamp in milliseconds. Pass midnight UTC of the From date (1735689600000 for January 1, 2025): a rate applies to the entries that start at or after it. A record can’t hold two billing rates, or two cost rates, with the same startTime: the second is refused with RateWithSameDateAlreadyExists.
  • amount is a BeeboleInputAmount { value, currency }. value is an integer in the currency’s smallest unit (15000 with "USD" is $150.00), and currency is an ISO 4217 code.
  • method is hourly, daily, fixed, or nonBillable: the Hourly rate, Daily rate, Fixed fee, and Non-billable methods (No cost on a cost rate).
  • splitType is persons, projects, or tags, to give each person, project, or tag its own amount. Fill the split with addBillingSplit (rateId, entityId, amount, nonBillable), and adjust it with editBillingSplitAmount, editBillingSplitNonBillable, and removeBillingSplit, or their Cost twins.
  • repeatEnabled makes a fixed fee recur. The editBillingRepeat… and editCostRepeat… mutations set the recurrence.
The delete, duplicate, and localize mutations exist for each kind of record (deleteOrganisationBilling, deleteTagBilling, deletePersonBilling, and so on), with the record’s ID argument except on the organization. A duplicate is dated one day after the record’s latest rate. A localize mutation copies the inherited rates you list in rateIds onto a record that has no rates of its own, so you can then change them for that record only. Every rate mutation returns a BeeboleBilling or a BeeboleCost. Read rates and their id through the billings and costs fields, as shown under Billing and cost rates on the Queries page. An inherited rate’s id belongs to the record it is set on, so editing it changes the rate for everything that inherits it. Use the Billing mutations on billing rates and the Cost mutations on cost rates: a cost rate passed to editBillingAmount fails with InvalidRateType. Adding a billing rate needs a plan that includes billing rates, and adding a cost rate one that includes costs; otherwise the call fails with SubscriptionFeatureRequired:billing or SubscriptionFeatureRequired:costs.

Add a rate and change its amount

This sets an hourly billing rate of $150.00 on a project, from January 1, 2025:
To change the amount to $165.00, pass the returned id to editBillingAmount:
editBillingAmount changes the rate for every entry it covers, past ones included. To raise a rate from a given date only, add a new rate with that startTime instead: entries before it keep the previous rate.

Custom fields

Custom field definitions and the values stored on records have separate mutations. Definitions are managed with addCustomField, duplicateCustomField, archiveCustomField / unarchiveCustomField (and their plural forms), deleteCustomField, editCustomFieldName, editCustomFieldType, a family of editCustomField…Option… mutations for each type’s options, and the editCustomFieldVisibility… mutations that decide where a field appears. Values are written with: entityType is one of Person, Project, Task, Tag, TimeRecord, or AbsenceType; dateValue and dateTimeValue are UTC timestamps. As in Beebole, deleteCustomField is refused while any value is stored on the field — delete or clear the values first, or archive the field.

Store an external identifier on a person

To find the record that carries a given identifier, read the field’s values with getCustomFieldValues — see Custom fields on the Queries page.

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.

Rename the organization


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.