{ "openapi": "3.0.1", "info": { "title": "Hourglass API", "description": "This API allows you to do everything you can do in the Redmine Hourglass UI.", "version": "1.6.0-dev", "x-docsVersion": "7e7abfa45af412e9826c43436390a62c" }, "paths": { "/time_bookings.json": { "get": { "summary": "Lists all visible time bookings", "tags": [ "Time bookings" ], "responses": { "200": { "description": "time bookings found", "examples": { "application/json": { "count": 2, "offset": 0, "limit": 25, "records": [ { "id": 4, "start": "2025-03-16T11:54:28.000+03:30", "stop": "2025-03-16T18:52:34.000+03:30", "time_log_id": 4, "time_entry_id": 4, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "time_entry": { "id": 4, "project_id": 24, "author_id": 40, "user_id": 40, "issue_id": null, "hours": "209/30", "comments": null, "activity_id": 13, "spent_on": "2025-03-16", "tyear": 2025, "tmonth": 3, "tweek": 11, "created_on": "2025-03-16T21:36:13.000+03:30", "updated_on": "2025-03-16T21:36:13.000+03:30" } }, { "id": 3, "start": "2025-03-16T11:02:14.000+03:30", "stop": "2025-03-16T18:11:12.000+03:30", "time_log_id": 3, "time_entry_id": 3, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "time_entry": { "id": 3, "project_id": 22, "author_id": 38, "user_id": 38, "issue_id": null, "hours": "143/20", "comments": null, "activity_id": 12, "spent_on": "2025-03-16", "tyear": 2025, "tmonth": 3, "tweek": 11, "created_on": "2025-03-16T21:36:13.000+03:30", "updated_on": "2025-03-16T21:36:13.000+03:30" } } ] } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_booking_index_response" } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_bookings/{id}.json": { "get": { "summary": "Find time booking by ID", "tags": [ "Time bookings" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time booking found", "examples": { "application/json": { "id": 19, "start": "2025-03-16T12:15:49.000+03:30", "stop": "2025-03-16T15:34:16.000+03:30", "time_log_id": 19, "time_entry_id": 19, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "time_entry": { "id": 19, "project_id": 54, "author_id": 72, "user_id": 72, "issue_id": null, "hours": "33/10", "comments": null, "activity_id": 28, "spent_on": "2025-03-16", "tyear": 2025, "tmonth": 3, "tweek": 11, "created_on": "2025-03-16T21:36:13.000+03:30", "updated_on": "2025-03-16T21:36:13.000+03:30" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_booking", "required": [ "id", "start", "stop", "created_at", "updated_at" ] } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "delete": { "summary": "Deletes a time booking", "tags": [ "Time bookings" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "time booking deleted" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "put": { "summary": "Update an existing time booking", "tags": [ "Time bookings" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "time booking found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } }, "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_booking_params" } } } } } }, "/time_bookings/bulk_destroy.json": { "delete": { "summary": "Deletes multiple time bookings at once", "tags": [ "Time bookings" ], "parameters": [ { "name": "time_bookings[]", "in": "query", "items": { "type": "string" }, "collectionFormat": "multi", "schema": { "type": "array" } } ], "responses": { "200": { "description": "time bookings found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_bookings/bulk_update.json": { "post": { "summary": "Updates multiple time bookings at once", "tags": [ "Time bookings" ], "parameters": [], "responses": { "200": { "description": "time bookings found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/time_booking_params" } } } }, "description": "takes an object of time bookings" } } }, "/time_bookings/bulk_create.json": { "post": { "summary": "Create multiple time bookings at once", "tags": [ "Time bookings" ], "parameters": [], "responses": { "200": { "description": "time bookings found" }, "400": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/time_booking_params" } } } }, "description": "takes an array of time bookings" } } }, "/time_logs.json": { "get": { "summary": "Lists all visible time logs", "tags": [ "Time logs" ], "responses": { "200": { "description": "time logs found", "examples": { "application/json": { "count": 2, "offset": 0, "limit": 25, "records": [ { "id": 127, "start": "2025-03-16T15:25:00.000+03:30", "stop": "2025-03-17T01:05:00.000+03:30", "user_id": 288, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 9.666666666666666 }, { "id": 128, "start": "2025-03-16T14:50:00.000+03:30", "stop": "2025-03-16T23:44:00.000+03:30", "comments": "Bypassing the system won't do anything, we need to index the auxiliary smtp array!", "user_id": 290, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 8.9 } ] } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_log_index_response" } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_logs/{id}.json": { "get": { "summary": "Find time log by ID", "tags": [ "Time logs" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time log found", "examples": { "application/json": { "id": 143, "start": "2025-03-16T13:10:00.000+03:30", "stop": "2025-03-16T22:07:00.000+03:30", "user_id": 322, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 8.95 } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_log", "required": [ "id", "start", "stop", "user_id", "created_at", "updated_at" ] } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "delete": { "summary": "Deletes a time log", "tags": [ "Time logs" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "time log deleted" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "put": { "summary": "Update an existing time log", "tags": [ "Time logs" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "time log found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } }, "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_log_update" } } } } } }, "/time_logs/{id}/book.json": { "post": { "summary": "Book a time log", "tags": [ "Time logs" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time log found", "examples": { "application/json": { "id": 138, "start": "2025-03-16T10:15:00.000+03:30", "stop": "2025-03-16T21:12:00.000+03:30", "time_log_id": 187, "time_entry_id": 138, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "time_entry": { "id": 138, "project_id": 296, "author_id": 416, "user_id": 416, "issue_id": null, "hours": "219/20", "comments": null, "activity_id": 146, "spent_on": "2025-03-16", "tyear": 2025, "tmonth": 3, "tweek": 11, "created_on": "2025-03-16T21:36:13.000+03:30", "updated_on": "2025-03-16T21:36:13.000+03:30" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_booking", "required": [ "id", "start", "stop", "created_at", "updated_at" ] } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } }, "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_booking_params" } } } } } }, "/time_logs/{id}/split.json": { "post": { "summary": "Split a time log", "tags": [ "Time logs" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "split_at", "in": "query", "format": "date-time", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time log found", "examples": { "application/json": { "time_log": { "id": 207, "start": "2025-03-16T09:40:00.000+03:30", "stop": "2025-03-16T09:50:00.000+03:30", "user_id": 448, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 0.16666666666666666 }, "new_time_log": { "id": 208, "start": "2025-03-16T09:50:00.000+03:30", "stop": "2025-03-16T21:50:00.000+03:30", "user_id": 448, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 12.0 } } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "time_log": { "$ref": "#/components/schemas/time_log", "required": [ "id", "start", "stop", "user_id", "created_at", "updated_at" ] }, "new_time_log": { "$ref": "#/components/schemas/time_log", "required": [ "id", "start", "stop", "user_id", "created_at", "updated_at" ] } } } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } } }, "/time_logs/join.json": { "post": { "summary": "Joins multiple time logs", "tags": [ "Time logs" ], "parameters": [ { "name": "ids[]", "in": "query", "items": { "type": "integer" }, "collectionFormat": "multi", "schema": { "type": "array" } } ], "responses": { "200": { "description": "time logs found", "examples": { "application/json": { "stop": "2025-03-16T22:39:00.000+03:30", "start": "2025-03-16T13:09:00.000+03:30", "id": 237, "user_id": 480, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 9.5 } }, "content": { "application/json": { "schema": { "type": "object", "properties": { "time_log": { "$ref": "#/components/schemas/time_log", "required": [ "id", "start", "stop", "user_id", "created_at", "updated_at" ] } } } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" }, "400": { "description": "time logs not joined", "examples": { "application/json": { "message": "There are either bookings defined on the submitted time logs or the time logs start and stop doesn't match", "status": 400 } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/error_msg" } } } } } } }, "/time_logs/bulk_destroy.json": { "delete": { "summary": "Deletes multiple time logs at once", "tags": [ "Time logs" ], "parameters": [ { "name": "time_logs[]", "in": "query", "items": { "type": "string" }, "collectionFormat": "multi", "schema": { "type": "array" } } ], "responses": { "200": { "description": "time logs found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_logs/bulk_update.json": { "post": { "summary": "Updates multiple time logs at once", "tags": [ "Time logs" ], "parameters": [], "responses": { "200": { "description": "time logs found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/time_log_update" } } } }, "description": "takes an object of time logs" } } }, "/time_logs/bulk_book.json": { "post": { "summary": "Books multiple time logs at once", "tags": [ "Time logs" ], "parameters": [], "responses": { "200": { "description": "time logs found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/time_booking_update" } } } }, "description": "takes an object of time bookings" } } }, "/time_logs/bulk_create.json": { "post": { "summary": "Create multiple time logs at once", "tags": [ "Time logs" ], "parameters": [], "responses": { "200": { "description": "time logs found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/time_log_update" } } } }, "description": "takes an array of time logs" } } }, "/time_trackers.json": { "get": { "summary": "Lists all visible running time trackers", "tags": [ "Time trackers" ], "responses": { "200": { "description": "time trackers found", "examples": { "application/json": { "count": 2, "offset": 0, "limit": 25, "records": [ { "id": 3, "start": "2025-03-16T21:36:00.000+03:30", "user_id": 680, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30" }, { "id": 4, "start": "2025-03-16T21:36:00.000+03:30", "comments": "test", "user_id": 682, "project_id": 405, "activity_id": 163, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30" } ] } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_tracker_index_response" } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_trackers/start.json": { "post": { "summary": "Starts a new time tracker", "tags": [ "Time trackers" ], "parameters": [], "responses": { "200": { "description": "time tracker created", "examples": { "application/json": { "id": 10, "start": "2025-03-16T21:36:00.000+03:30", "comments": "test", "user_id": 717, "project_id": 422, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "issue_label": null, "activities": [] } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_tracker", "required": [ "id", "start", "user_id", "created_at", "updated_at" ] } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "400": { "description": "time tracker not created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/error_msg" } } } } }, "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_tracker_start" } } } } } }, "/time_trackers/{id}.json": { "get": { "summary": "Find time tracker by ID", "tags": [ "Time trackers" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time tracker found", "examples": { "application/json": { "id": 25, "start": "2025-03-16T21:36:00.000+03:30", "comments": "test", "user_id": 749, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_tracker", "required": [ "id", "start", "user_id", "created_at", "updated_at" ] } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "delete": { "summary": "Deletes a time tracker", "tags": [ "Time trackers" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "time tracker deleted" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" } } }, "put": { "summary": "Update an existing time tracker", "tags": [ "Time trackers" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time tracker updated" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" }, "400": { "description": "time tracker not updated" } }, "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/time_tracker_update" } } } } } }, "/time_trackers/{id}/stop.json": { "delete": { "summary": "Stops a time tracker and create time records from it", "tags": [ "Time trackers" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "time log created", "examples": { "application/json": { "time_log": { "id": 345, "start": "2025-03-16T21:36:00.000+03:30", "stop": "2025-03-16T21:37:00.000+03:30", "comments": "test", "user_id": 847, "created_at": "2025-03-16T21:36:13.000+03:30", "updated_at": "2025-03-16T21:36:13.000+03:30", "hours": 0.016666666666666666 } } } }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" }, "404": { "description": "nothing found" }, "400": { "description": "time tracker not stopped" } } } }, "/time_trackers/bulk_destroy.json": { "delete": { "summary": "Deletes multiple time trackers at once", "tags": [ "Time trackers" ], "parameters": [ { "name": "time_trackers[]", "in": "query", "items": { "type": "string" }, "collectionFormat": "multi", "schema": { "type": "array" } } ], "responses": { "200": { "description": "time trackers found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } } } }, "/time_trackers/bulk_update.json": { "post": { "summary": "Updates multiple time trackers at once", "tags": [ "Time trackers" ], "parameters": [], "responses": { "200": { "description": "time trackers found" }, "403": { "description": "insufficient permissions" }, "401": { "description": "missing or wrong api key" } }, "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/time_tracker_update" } } } }, "description": "takes an object of time trackers" } } } }, "servers": [ { "url": "/hourglass" } ], "components": { "securitySchemes": { "api_key": { "type": "apiKey", "description": "Available on the \"my account\" page in redmine", "name": "key", "in": "query" } }, "schemas": { "time_tracker_start": { "title": "Time Tracker Start", "type": "object", "properties": { "issue_id": { "type": "integer", "minimum": 0 }, "comments": { "type": "string" } } }, "time_tracker": { "title": "Time Tracker", "type": "object", "properties": { "id": { "type": "integer", "minimum": 0 }, "start": { "type": "string", "format": "date-time" }, "user_id": { "type": "integer", "minimum": 0 }, "project_id": { "type": "integer", "minimum": 0, "nullable": true }, "activity_id": { "type": "integer", "minimum": 0, "nullable": true }, "issue_id": { "type": "integer", "minimum": 0, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } } }, "time_tracker_update": { "title": "Time Tracker Update", "type": "object", "properties": { "start": { "type": "string", "format": "date-time" }, "user_id": { "type": "integer", "minimum": 0 }, "project_id": { "type": "integer", "minimum": 0 }, "activity_id": { "type": "integer", "minimum": 0 }, "issue_id": { "type": "integer", "minimum": 0 }, "comments": { "type": "string" } } }, "time_log": { "title": "Time Log", "type": "object", "properties": { "id": { "type": "integer", "minimum": 0 }, "start": { "type": "string", "format": "date-time" }, "stop": { "type": "string", "format": "date-time" }, "hours": { "type": "number", "minimum": 0 }, "comments": { "type": "string" }, "user_id": { "type": "integer", "minimum": 0 }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } } }, "time_log_update": { "title": "Time Log Update", "type": "object", "properties": { "start": { "type": "string", "format": "date-time" }, "stop": { "type": "string", "format": "date-time" }, "comments": { "type": "string" } } }, "time_booking": { "title": "Time Booking", "type": "object", "properties": { "id": { "type": "integer", "minimum": 0 }, "start": { "type": "string", "format": "date-time" }, "stop": { "type": "string", "format": "date-time" }, "time_log_id": { "type": "integer", "minimum": 0 }, "time_entry_id": { "type": "integer", "minimum": 0 }, "time_entry": { "$ref": "#/components/schemas/time_entry" }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } } }, "time_entry": { "title": "Time Entry", "type": "object", "properties": { "id": { "type": "integer", "minimum": 0 }, "author_id": { "type": "integer", "minimum": 0 }, "user_id": { "type": "integer", "minimum": 0 }, "project_id": { "type": "integer", "minimum": 0, "nullable": true }, "issue_id": { "type": "integer", "minimum": 0, "nullable": true }, "hours": { "type": "string" }, "activity_id": { "type": "integer", "minimum": 0 }, "comments": { "type": "string", "nullable": true }, "spent_on": { "type": "string", "format": "date" }, "tyear": { "type": "integer" }, "tmonth": { "type": "integer" }, "tweek": { "type": "integer" }, "created_on": { "type": "string", "format": "date-time" }, "updated_on": { "type": "string", "format": "date-time" } } }, "time_booking_params": { "title": "Time Booking Params", "type": "object", "properties": { "start": { "type": "string", "format": "date-time" }, "stop": { "type": "string", "format": "date-time" }, "user_id": { "type": "integer", "minimum": 0 }, "project_id": { "type": "integer", "minimum": 0 }, "activity_id": { "type": "integer", "minimum": 0 }, "issue_id": { "type": "integer", "minimum": 0 }, "comments": { "type": "string" } } }, "error_msg": { "title": "Error", "type": "object", "properties": { "message": { "type": "string" } } }, "time_tracker_index_response": { "title": "Time Tracker Index", "type": "object", "properties": { "count": { "type": "integer" }, "offset": { "type": "integer" }, "limit": { "type": "integer" }, "records": { "type": "array", "items": { "$ref": "#/components/schemas/time_tracker" } } } }, "time_log_index_response": { "title": "Time Log Index", "type": "object", "properties": { "count": { "type": "integer" }, "offset": { "type": "integer" }, "limit": { "type": "integer" }, "records": { "type": "array", "items": { "$ref": "#/components/schemas/time_log" } } } }, "time_booking_index_response": { "title": "Time Booking Index", "type": "object", "properties": { "count": { "type": "integer" }, "offset": { "type": "integer" }, "limit": { "type": "integer" }, "records": { "type": "array", "items": { "$ref": "#/components/schemas/time_booking" } } } } } }, "security": [ { "api_key": [] } ] }