Changelog

API changelog

Changes to the OnRamp API that a client can notice, newest first.

Follow along with the RSS feed.

Added

Upload files to a form's file request

POST /v1/subtasks/{subtask_id}/files saves one or more files as the answer to a form's file request. Send the files as multipart/form-data in the files field. Name the file request in element when the form has more than one.

When the file request asks for a review, each uploaded file comes back with its review findings. The upload does not submit the form.

Changed

A missing or invalid API key answers 401

A request with no Authorization header answered 403, and some endpoints answered an invalid API key with 400. Both now answer 401 Unauthorized, the same status as an unknown or deactivated key.

If your client treats 403 or 400 as an authentication failure, treat 401 that way too.

Added

List the subtasks of several tasks in one call

GET /v1/subtasks?task_ids=… returns the subtasks of up to 200 tasks, in display order within each task. Each subtask carries parent_task_uuid. One call replaces one GET /v1/tasks/{task_id}/subtasks call per task when you export or poll a task list.

Fixed

A permission denial answers 403

When the API key lacked a permission that an endpoint checks, such as the one PUT /v1/tasks/{task_uuid}/time-allotted needs, the API answered 502. It now answers 403 with a message that names the missing permission.

Changed

Responses identify objects by uuid only

An object that has a uuid is identified by it, and responses no longer include its integer or encoded id. Requests still accept integer and encoded identifiers in paths, query filters and bodies.

The response schemas in the OpenAPI document list their fields again. Since 2026-09-11 they had shown data as untyped on project, task, customer, module, user, webhook and note responses.

Added

Read and write time tracking

New endpoints read and write time entries and allotted time:

  • GET, POST /v1/time-entries, and GET, PUT, DELETE /v1/time-entries/{entry_uuid}
  • GET /v1/tasks/{task_uuid}/time and PUT /v1/tasks/{task_uuid}/time-allotted
  • GET /v1/projects/{project_uuid}/time-summary
  • GET /v1/time-tracking/reports/allotted-vs-worked

An identical create sent again with the same API key within 10 minutes returns the existing entry with 200, so a retry never logs time twice. The time tracking guide walks through the rules.

Added

Page the task list by cursor

GET /v1/tasks accepts a cursor parameter. Send back the cursor from pagination.nextPage to fetch the next page. A cursor page costs the same at any depth, so use it to export a large task list. A cursor cannot be combined with page or sort.