How the Drum API works
The Drum API is the same Drum your team uses in the browser, reached by another program. Most of what is surprising about it follows from that one idea.
A request acts as a person
There is no separate “integration” identity in Drum. Every token belongs to a user, and every request runs as that user, in the one account the token was created for. The API does not have its own permission model. It asks the same questions Drum asks when that person opens a page: can they see this project, its budget, this member’s timesheet?
That is why the recommended setup is a dedicated user for each integration. Its role describes exactly what the integration may do, and removing or changing that user changes what the integration can reach, the same way it would for a person. An admin’s token, by contrast, can do anything in the account.
On top of the usual permissions, the API adds one coarse switch for each HTTP method: api_read, api_create, api_update and api_delete. These let a firm allow someone to use Drum in the browser without letting them script it, or allow an integration to read without letting it write.
The data changes shape with permissions
Drum hides money from people who should not see it. In the browser that means a column or a panel is missing. In the API it means fields are missing. The same project can come back with total_budget, work_in_progress and gross profit for one token, and without them for another.
So an integration should never assume a money field is present. A field that is absent means “you may not see this”, not zero.
Hidden records work in a similar way. Where possible, a record the token cannot read is answered as if it did not exist (404), so that the API does not reveal which projects or opportunities exist to someone who cannot see them. Some older endpoints still answer 403. Treat both as “not available to this token”.
Opportunities are projects that have not been won yet
In Drum, an opportunity and a project are the same kind of record at different stages. An opportunity has pipeline dates, a deal value and a lead score. When it is won and converted, Drum creates a new delivery project from it, linked back through opportunity_id. The exception is an opportunity that sells a variation on a project that already exists. Converting it creates no project: it accepts the variation’s proposal, and the variation is added to the existing project.
The API reflects this. Opportunities and projects share one JSON shape, with fields that apply to one stage or the other. The two have separate endpoints, so a list of projects never mixes in pipeline work. Webhooks, on the other hand, use one set of project.* events for both, with project_type to tell them apart.
Money comes in two forms
Drum stores money as whole cents and keeps every figure tax exclusive. Newer endpoints (costs, tracked times, planned invoices, webhooks) send and receive integer cents, in fields ending _cents. Some older endpoints (projects, opportunities, invoices) return decimals in the record’s currency instead, such as 48500.0.
Both describe the same stored values. When you send money to Drum, always send integer cents. Drum refuses decimals on input, so that no rounding happens on the way in.
Writes go through the same rules as the screens
When the API creates a cost or logs time, it runs the same operation as the Drum screen that does the job. The same validation applies, the same approval workflow starts, the same timesheet locks hold, and the same webhook events fire. An integration cannot do something a person in the same role could not do in the browser, and it gets the same result when it does.
This is also why some writes return more than the record. Logging time returns the day and week totals the timesheet would show, because that is what a person would see next.
Safe retries
Networks fail, and a program that retries a create after a timeout could make a duplicate cost or time entry. Creates that are likely to be retried accept an Idempotency-Key. Drum remembers the key for a day and returns the first result to any repeat. Converting an opportunity is safe to repeat without a key, because Drum checks whether the opportunity already has a project, or for a variation opportunity, whether its proposal is already accepted.
Pushing instead of polling
Webhooks let Drum tell your system when something changes, so it does not have to ask over and over. They favour the final state over every step: quick changes to one record are combined, and events may arrive out of order. An integration that keeps the latest version of each record, by updated_at, ends up with the right answer even when individual deliveries are late or combined. How Drum webhooks work explains why.