{"id":13686616,"url":"https://github.com/BryanMorgan/time-tracking-api","last_synced_at":"2025-05-01T09:32:18.391Z","repository":{"id":65298799,"uuid":"236583716","full_name":"BryanMorgan/time-tracking-api","owner":"BryanMorgan","description":"Go API for tracking time in tasks across multiple projects. See https://github.com/BryanMorgan/time-tracking-app for reference React app.","archived":false,"fork":false,"pushed_at":"2025-04-15T16:41:06.000Z","size":273,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T17:43:02.674Z","etag":null,"topics":["api","database","go","golang","postgresql","time","time-tracking","tracking"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BryanMorgan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-27T20:10:18.000Z","updated_at":"2025-04-15T16:41:03.000Z","dependencies_parsed_at":"2024-01-02T18:48:07.830Z","dependency_job_id":"4a6a3e77-403d-46c2-aa4d-0034afd00bdd","html_url":"https://github.com/BryanMorgan/time-tracking-api","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BryanMorgan%2Ftime-tracking-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BryanMorgan%2Ftime-tracking-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BryanMorgan%2Ftime-tracking-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BryanMorgan%2Ftime-tracking-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BryanMorgan","download_url":"https://codeload.github.com/BryanMorgan/time-tracking-api/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251852847,"owners_count":21654475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","database","go","golang","postgresql","time","time-tracking","tracking"],"created_at":"2024-08-02T15:00:36.136Z","updated_at":"2025-05-01T09:32:18.022Z","avatar_url":"https://github.com/BryanMorgan.png","language":"Go","funding_links":[],"categories":["golang"],"sub_categories":[],"readme":"# Time Tracking API\n\n\u003cimg align=\"right\" width=\"128\" src=\"https://user-images.githubusercontent.com/479339/74610686-49244e80-50aa-11ea-8a3d-dd4a11856d6c.png\"\u003e\n\n![build](https://github.com/BryanMorgan/time-tracking-api/workflows/build/badge.svg?branch=main\u0026event=push)\n[![Go Report Card](https://goreportcard.com/badge/github.com/BryanMorgan/time-tracking-api)](https://goreportcard.com/report/github.com/BryanMorgan/time-tracking-api)\n\nGo API for tracking time.\n\nManage time entries for tasks that are associated with projects. Built with Golang and PostgreSQL.\n\nSee the React [Time Tracking App](https://github.com/BryanMorgan/time-tracking-app) for a reference UI.\n\n# Setup\nYou can use Docker to get started quickly or run the Go server locally using a PostgreSQL instance.\n\n## Option #1: Docker\nTo run the Go server and PostgreSQL database in a container you can start both using Docker Compose:\n\n```docker-compose up```\n\nThe API will be available at [http://localhost:8000](http://localhost:8000) and the PostgreSQL instance will be exposed on port 5432.\n\n## Option #2: Local\n\n### Database\nEnsure you have PostgreSQL 12 or higher installed and running.\n\nCreate a `timetracker` database and role using the bootstrap SQL in:\n\n```./database/bootstrap.sql```\n\nThen create the schema in the `timetracker` database using:\n\n```./database/schema-1.sql```\n\n# Run Server\nTo run the Go API server use the `run` Makefile target:\n\n```make run```\n\nwhich will start the server on the port configured in `config/dev.yml`. By default the API will be available at [http://localhost:8000](http://localhost:8000)\n\n# Testing\n\n## Unit Tests\nUnit tests can be run using:\n\n```make unit_test```\n\n## Integration Tests\nIntegration tests are managed under the `integration_test` root folder and can be run using:\n\n```make int_test```\n\n## Postman Tests\nAdditional functional tests are available using the [Postman](https://www.postman.com/) tool.\nThese tests require the [newman](https://github.com/postmanlabs/newman) Postman command-line runner. Install using:\n\n```npm install -g newman```\n\nThe test rely on the `database/bootstrap.sql` data to be present. To run the Postman tests locally, first start the web server:\n\n```make run```\n\nthen run the Postman tests:\n\n```make postman```\n\n# API\n\n### Authentication Token\nMost of the REST endpoints require an authentication token which can be supplied as a custom header:\n\n```Authorization: Bearer {token}```\n\nEndpoints that do not require a token are noted below.\n\nTo validate the local or Docker instance is working you can hit the `/_ping` endpoint and you should get back an `OK` response:\n\n```curl http://localhost:8000/_ping```\n\n### Authentication\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| POST | /api/auth/login | [LoginRequest](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L65) | [AuthResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L79) | Does not require an authentication token |\n| POST | /api/auth/token |  |  [AuthResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L79) |  |\n| POST | /api/auth/logout |  | `{}` | |\n| POST | /api/auth/forgot | [EmailRequest](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L61) | `{}` | Does not require an authentication token. Sends a forgot password validation email. |\n\n### Profile\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/profile/ |  | [ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L39) | |\n| PUT | /api/profile/ | [ProfileRequest](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L25) | [ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L39) | |\n| PUT | /api/profile/password | [PasswordChangeRequest](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L33) | `{}` | |\n\n### Account\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| POST | /api/account |  [AccountRequest](https://github.com/BryanMorgan/time-tracking-api/blob/9b6d78799f7738a41bf955004fa6a0b8e5311da5/profile/handler.go#L53) | [ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L39) | Does not require an authentication token |\n| PUT | /api/account |  [AccountUpdateRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/profile/handler.go#L71) | [ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L39) | |\n| GET | /api/account |   | [AccountResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/profile/handler.go#L63) | |\n| GET | /api/account/users |   | [][ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/profile/handler.go#L39) | |\n| POST | /api/account/user |  [AddUserRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/profile/handler.go#L78) | [ProfileResponse](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/profile/handler.go#L39) | |\n\n### Client\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/client/{client_id} | string | [ClientResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L25) | |\n| GET | /api/client/all |   | [][ClientResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L25) | |\n| GET | /api/client/archived|  |  [][ClientResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L25) | |\n| POST | /api/client/ |  [ClientRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L19) | [ClientResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L25) | |\n| PUT | /api/client/ |  [ClientRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L19) | `{}` | |\n| DELETE | /api/client/ | [ClientRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L19) | `{}` | |\n| PUT | /api/client/archive |  [ClientRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L19) | `{}` | |\n| PUT | /api/client/restore |  [ClientRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L19) | `{}` | |\n\n### Project\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/project/{project_id} |  string  | [ProjectResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L62) | |\n| GET | /api/project/all |   | [][ProjectResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L62) | |\n| GET | /api/project/archived |   | [][ProjectResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L62) | |\n| POST | /api/project/ |  [ProjectContainerRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L41) | [ProjectResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L62) | |\n| PUT | /api/project/ |  [ProjectContainerRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L41) | `{}` | |\n| DELETE | /api/project/ | [ProjectIdRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L31) | `{}` | |\n| PUT | /api/project/archive | [ProjectIdRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L31) | `{}` | |\n| PUT | /api/project/restore | [ProjectIdRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L31) | `{}` | |\n| POST | /api/project/copy/last/week | [StartAndEndDateRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/client/handler.go#L72) | `{}` or [TimeRangeResponse](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L51) | Empty if no records the prior week|\n\n### Time\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/time/week |   | [TimeRangeResponse](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L51) | |\n| GET | /api/time/week/{startDate} | string | [TimeRangeResponse](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L51) | Date must be in the `ISOShortDateFormat` (e.g. \"2006-01-02\") |\n| PUT | /api/time/ | [TimeEntryRangeRequest](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L23) | `{}` | |\n| POST | /api/time/project/week |  [ProjectWeekRequest](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L27) | `{}` | |\n| DELETE | /api/time/project/week |  [ProjectDeleteRequest](https://github.com/BryanMorgan/time-tracking-api/blob/main/timesheet/handler.go#L34) | `{}` | |\n\n### Task\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/task/{taskId} | string | [TaskResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | |\n| GET | /api/task/all |  | [][TaskResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | |]\n| GET | /api/task/archived |  | [][TaskResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | |]\n| POST | /api/task/ | [TaskRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | [TaskResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | |\n| PUT | /api/task/ |  [TaskRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | `{}` | |\n| PUT | /api/task/archive | [TaskRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | `{}` | |\n| PUT | /api/task/restore | [TaskRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | `{}` | |\n| DELETE | /api/task/ | [TaskRequest](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/task/handler.go#L23) | `{}` | |\n\n### Report\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /api/report/time/client | query parameters: `from`, `to`, `page` | [][ClientReportResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/reporting/handler.go#L18) | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/project | query parameters: `from`, `to`, `page` | [][ProjectReportResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/reporting/handler.go#L26) | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/task | query parameters: `from`, `to`, `page` | [][TaskReportResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/reporting/handler.go#L35) | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/person | query parameters: `from`, `to`, `page`| [][PersonReportResponse](https://github.com/BryanMorgan/time-tracking-api/blob/c9d110f52882ede1544121abf9762bcc6451492c/reporting/handler.go#L45) | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/export/client | query parameters: `from`, `to` | CSV file with content type `text/csv` | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/export/project | query parameters: `from`, `to` | CSV file with content type `text/csv` | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/export/task | query parameters: `from`, `to` | CSV file with content type `text/csv` | `from` and `to` are date strings in the `ISOShortDateFormat` format |\n| GET | /api/report/time/export/person | query parameters: `from`, `to` | CSV file with content type `text/csv` | `from` and `to` are date strings in the `ISOShortDateFormat` format|\n\n### Ping\n\n| Method | Path | Request | Response | Notes |\n|--------|------|---------|----------|-------|\n| GET | /_ping |   | Text `ok` with content type `text/plain` | |\n\n\n## Errors\nIf an API fails, the HTTP status code will reflect the type of error response. Common error status codes are:\n\n| Status Code | Error |\n|-------------|-------|\n| 400 | `http.StatusBadRequest` |\n| 401 | `http.StatusUnauthorized` |\n| 404 | `http.StatusNotFound` |\n| 405 | `http.StatusMethodNotAllowed` |\n| 500 | `http.StatusInternalServerError` |\n\nErrors will produce a JSON response that contains a `status` field set to `error`.\nError details will be included as part of the serialized [Error](https://github.com/BryanMorgan/time-tracking-api/blob/34d9b71d7ce096280cb15f1e3be25c616e5044ad/api/error.go#L62) struct.\n\nFor example the error response below shows the JSON response for a 400 error when an `email` value is invalid:\n```json\n{\n  \"status\": \"error\",\n  \"error\": \"invalid input\",\n  \"message\": \"Invalid email\",\n  \"code\": \"InvalidEmail\",\n  \"detail\": {\"field\": \"email\" }\n}\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBryanMorgan%2Ftime-tracking-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FBryanMorgan%2Ftime-tracking-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FBryanMorgan%2Ftime-tracking-api/lists"}