An API plugin for exposing data to external applications.
Copy the plugin to the folder app/Plugins/APIData, install and enable.
The following tables are created to track deleted entities:
- itk_projects_deleted
- itk_tickets_deleted
- itk_timesheets_deleted
3 triggers populate those tables when entities are deleted.
An itk_data_api_modified column, with an index, is added to zp_projects, zp_tickets,
zp_timesheets and zp_user, and 8 more triggers (insert and update, one pair per table) keep it
current. This column exists because Leantime does not maintain its own modified column on every write
path — time logged from the weekly grid, for instance, leaves it untouched. Since the triggers sit in the
database, no write path can bypass them.
The column is written as UTC, and modifiedAfter filters on it.
The Leantime database user needs ALTER on zp_projects, zp_tickets, zp_timesheets and
zp_user, on top of the CREATE and TRIGGER the plugin already needed. Installation fails, and
says so, if the grant is missing.
NB! Install and update the plugin with the site down. The triggers are absent while the plugin is being replaced, and an edit made in that window is not recoverable — installing only stamps rows that have no timestamp at all, which covers new rows and nothing else.
NB! Installing stamps every existing row with the install time, so the first sync after installing returns everything once.
NB! All 11 triggers are removed on uninstall, but the tables, the column and its data are left alone to avoid data loss through install/uninstalls.
The API consists of the following endpoints:
- Get list of entities
- Get list of deleted entities
GET/POST: https://{{YOUR_DOMAIN}}/apidata/api/{{TYPE}}
TYPE: projects, milestones, tickets, timesheets, users
Attach query/body parameters to the request:
- start: Starting id of the results.
- limit: Maximum number of results to get from start id in ascending order. Must be at least 1,
and is capped at 1000. The limit that was actually applied is echoed in
parameters. - modifiedAfter: Only retrieve entries that have a modified later than modifiedAfter (unix timestamp).
All five types, users included, carry a
modifiedtimestamp in the response. - ids: Array of ids to retrieve. A comma separated string is also accepted, e.g.
?ids=1,2,3. - projectIds: Array of projectIds. Limits the entities to those attached to projects in projectIds. Only applies for types: milestone, tickets, timesheets.
Example request:
curl https://leantime.local.itkdev.dk/apidata/api/tickets
-H "x-api-key: lt_1234567890"
-H "Content-Type: application/json"
-d '{"start":0,"limit":100,"modifiedAfter":1761051213,"ids":[1,2,3],"projectIds":[12,13,14]}'GET/POST: https://{{YOUR_DOMAIN}}/apidata/api/deleted
Attach query/body parameters to the request:
- types: Array of types to get deleted entities for: projects, milestones, tickets, timesheets.
Required, and must name at least one type — each type returns its whole deletion history,
so there is no default. A comma separated string is also accepted, e.g.
?types=tickets,timesheets. - deleted: Unix timestamp. Only retrieve ids of entities deleted after this timestamp.
Example request:
curl https://leantime.local.itkdev.dk/apidata/api/deleted
-H "x-api-key: lt_1234567890"
-H "Content-Type: application/json"
-d '{"deleted":1759906882,"types":["projects","milestones","tickets","timesheets"]}'A parameter that cannot be interpreted answers 400 with the reason, e.g. a non numeric
modifiedAfter, a limit below 1, an id that is not a number, or a missing or unknown type:
{"error": "modifiedAfter must be a whole number."}The plugin has no long-running stack, so everything runs in a one-off
itkdev/php8.3-fpm container. Install Task, then:
task setup
task test
task lintRun task --list-all to see the remaining commands.
The Dockerfile exists only for releases: bin/create-release needs rsync,
which the base image does not carry. It backs the php-release compose service
and is not used for tests or linting.
Leantime core is not a Composer dependency of this plugin, so the development
dependencies stand in for it. illuminate/database and nesbot/carbon are
pinned to the exact versions the targeted Leantime release locks, so the tests
run against the code Leantime itself runs — currently v3.9.7, which runs PHP 8.3
and locks laravel/framework v11.45.1 and nesbot/carbon 3.10.1. Bump those
pins and re-check tests/Stub/ against Leantime's own composer.lock when
upgrading Leantime.
To use the plugin you need an API key for leantime.
See https://docs.leantime.io/api/usage?id=connect.
The API should be set as a header for all requests to the API.
E.g.
curl https://{{YOUR_DOMAIN}}/apidata/api/{{TYPE}}
-H "x-api-key: {{YOUR_APIKEY}}"
-H "Content-Type: application/json"
-d '{"start":0,"limit":100}'