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 asvalue 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 aBeeboleApprovalEvent.
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 itsstartTime, 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:
startTimeis aBeeboleTimestampin milliseconds. Pass midnight UTC of the From date (1735689600000for 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 samestartTime: the second is refused withRateWithSameDateAlreadyExists.amountis aBeeboleInputAmount{ value, currency }.valueis an integer in the currency’s smallest unit (15000with"USD"is $150.00), andcurrencyis an ISO 4217 code.methodishourly,daily,fixed, ornonBillable: the Hourly rate, Daily rate, Fixed fee, and Non-billable methods (No cost on a cost rate).splitTypeispersons,projects, ortags, to give each person, project, or tag its own amount. Fill the split withaddBillingSplit(rateId,entityId,amount,nonBillable), and adjust it witheditBillingSplitAmount,editBillingSplitNonBillable, andremoveBillingSplit, or theirCosttwins.repeatEnabledmakes a fixed fee recur. TheeditBillingRepeat…andeditCostRepeat…mutations set the recurrence.
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: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 withaddCustomField, 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
getCustomFieldValues — see Custom fields on the Queries page.
Organization
Organization settings are edited on the single current organization, so these mutations take noid. The GraphQL field names keep the British spelling Organisation.
Rename the organization
Related content
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.