Tracker Projects API
Create, filter, update, categorize, and remove team-scoped time tracking projects through public API v1.
Summary
Tracker projects group time entries, billing defaults, a customer, and reusable category tags. The response also summarizes users associated with recorded work; creating a project does not assign the caller to it. Eigenn scopes every operation to the authenticated team.
Capabilities
Endpoints
| Method | Endpoint | Scope | Purpose |
|---|---|---|---|
GET | /tracker-projects | tracker-projects.read | List and filter projects |
POST | /tracker-projects | tracker-projects.write | Create a project |
GET | /tracker-projects/{id} | tracker-projects.read | Retrieve one project |
PATCH | /tracker-projects/{id} | tracker-projects.write | Update the fields that you send |
DELETE | /tracker-projects/{id} | tracker-projects.write | Delete a project and its time entries |
Prefix each endpoint with the environment base URL, such as https://api.eigenn.io/v1.
Prerequisites
You need an active Eigenn account with API access and the required tracker-projects scopes. Each request needs a valid bearer token. Write scope does not replace read scope. Use customer and tag IDs from the same team.
Concepts
Project Response
Project responses include:
- identity, name, description, status, and creation timestamp
- billing defaults:
billable,rate, andcurrency estimate,totalDurationin seconds, and calculatedtotalAmountcustomerIdand the linked customer summary- reusable category tags as
{ id, name } - assigned users as
{ id, fullName, avatarUrl }
customer, customerId, billing defaults, estimates, totalDuration, and user avatar URLs can be null. Do not assume a customer or profile image is always present.
Workflow
Create a Project
POST /tracker-projects needs name. All other fields are optional.
| Field | Type | Rules |
|---|---|---|
name | string | 1–255 characters after the whitespace trim |
description | string or null | Up to 2,000 characters |
estimate | integer or null | Non-negative estimated hours |
billable | boolean or null | Defaults to false when omitted |
rate | number or null | Non-negative hourly rate |
currency | string or null | Three uppercase letters, such as USD; the schema checks the format, not membership in a currency registry |
status | enum | in_progress or completed |
customerId | UUID or null | Customer must belong to the authenticated team |
tags | array or null | Up to 50 team tags that already exist, each with id and value |
curl --request POST \
--url https://api.eigenn.io/v1/tracker-projects \
--header "Authorization: Bearer $EIGENN_API_TOKEN" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: project-website-redesign" \
--data '{
"name": "Website redesign",
"description": "Customer portal and billing experience",
"billable": true,
"rate": 175,
"currency": "USD",
"estimate": 120,
"status": "in_progress"
}'Creation returns 201 with a bare project object. Omitted status defaults to in_progress. The tags[].value field is required in each supplied tag object, but it does not rename the tag; names come from the existing tag definition. Use each tag ID only once.
List and Filter Projects
GET /tracker-projects accepts:
| Parameter | Rules |
|---|---|
cursor | Numeric row offset as a string; omit for the first page |
pageSize | Use a whole number from 1 to 100; defaults to 25 |
q | English full-text search over project name and description; not arbitrary substring search |
start, end | YYYY-MM-DD creation-date bounds; supply both, with start on or before end |
status | in_progress or completed |
customers | Up to 100 customer UUIDs |
tags | Up to 100 tag UUIDs. Eigenn returns the projects that match at least one tag |
sort | Two-item tuple: supported field and asc or desc |
Supported sort fields are time, amount, assigned, customer, tags, created_at, and name.
The response has data and meta.hasNextPage / meta.hasPreviousPage. Current limitation: response validation removes the calculated meta.cursor, so there is no next cursor to copy. For this endpoint, advance the numeric offset yourself: with pageSize=25, use cursor=25, then cursor=50. Keep the same filters and sort. Stop on a short page; a full final page can require one additional empty request.
Sorting defaults to newest creation time. assigned sorts by the count of distinct assigned users, and tags by the count of tag assignments. Tied sort values have no additional stable ID order, and concurrent changes can shift offset pages. Deduplicate IDs when collecting a full inventory.
Creation-date bounds compare the stored timestamp directly against the supplied date. The end bound is not expanded to the end of that day. Do not assume records created later on the end date are included.
Update a Project
PATCH /tracker-projects/{id} accepts any non-empty subset of the create fields. Omitted fields keep their current values. Send null only for the fields that permit it in the schema. Send it only when you want to clear the field.
A supplied tags array replaces the project's complete category set. Use tags: [] to remove all assignments. Unlike an empty array, tags: null leaves assignments unchanged. Omission also preserves them. To manage one assignment at a time, use the Tracker Categories API.
Delete a Project
A delete operation removes the project permanently. Tracker entries reference projects with cascade deletion. Thus Eigenn also removes the related time entries. Its tracker-category assignments are also deleted; reusable tag definitions remain. Export or reassign the necessary time records before deletion. Success returns 200 with { "id": "..." }. Missing or foreign-team projects return 404.
Behavior specification
Save and Retry Behavior
Customer and tag ownership are checked before the project write. Project persistence, activity recording, tag insertion/removal, and response loading are separate steps. A later failure does not guarantee that earlier changes were rolled back. For example, duplicate new tag IDs can fail after project fields have saved.
Inspect the project and its assignments after an uncertain response. Reconcile the saved state before retrying a create. Idempotency replays successful responses for the same request key; it does not compare bodies or make failed multi-step writes atomic. See Errors and Safe Retries.
Common Errors
| Status | Cause |
|---|---|
401 | Missing or invalid bearer token |
403 | Missing tracker project scope |
404 | Project, customer, or category is outside the team or no longer exists |
409 | Another request with the same idempotency key is in progress |
400 / 422 | Invalid UUID, date range, currency format, field length, or request shape |
429 | Request-rate limit exceeded |
500 | Unmapped database error, follow-up failure, or response validation failure; writes may already have persisted |
Diagrams
Rendering diagram…
Screenshots
Not applicable: this page describes an API or a non-visual workflow rather than an application screen.
Verification
- Try listing projects using the GET endpoint and confirm the response includes accessible projects for your team.
- Create a new project with a unique name and check for a 201 response and a project object in the output.
- Update an existing project by modifying one field, verify the PATCH request returns the updated data.
- Delete a project and receive a success status, then confirm it no longer appears in project listings and its time entries are removed.
- Submit a request with an invalid or missing token and confirm the API returns a 401 status.
- Check rejected fields and cross-team references, plus
tags: [],tags: null, and omitted tags. - Check numeric-offset pagination, end-date boundaries, duplicate tag failures, and persisted state after an uncertain write.
These are pending runtime acceptance checks. Source review has not advanced the verification metadata.