{"id":21135651,"url":"https://github.com/aalug/job-finder-go","last_synced_at":"2026-04-07T22:31:48.748Z","repository":{"id":191034103,"uuid":"663675480","full_name":"aalug/job-finder-go","owner":"aalug","description":"Job Finder REST API built with Go and Gin.","archived":false,"fork":false,"pushed_at":"2023-10-16T10:06:32.000Z","size":447,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-01T09:07:26.777Z","etag":null,"topics":["api","backend","docker","elasticsearch","gin","go","golang","job-finder","job-finder-app","postgres","postgresql","redis","rest-api","restful-api","swagger"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aalug.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-07-07T21:11:42.000Z","updated_at":"2024-08-24T12:23:40.000Z","dependencies_parsed_at":"2023-08-27T20:10:32.190Z","dependency_job_id":"caa7054a-6e2f-4aa5-8f84-ef75175b4152","html_url":"https://github.com/aalug/job-finder-go","commit_stats":null,"previous_names":["aalug/go-gin-job-search","aalug/job-finder-go"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aalug/job-finder-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalug%2Fjob-finder-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalug%2Fjob-finder-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalug%2Fjob-finder-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalug%2Fjob-finder-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aalug","download_url":"https://codeload.github.com/aalug/job-finder-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalug%2Fjob-finder-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31532216,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","backend","docker","elasticsearch","gin","go","golang","job-finder","job-finder-app","postgres","postgresql","redis","rest-api","restful-api","swagger"],"created_at":"2024-11-20T06:56:57.188Z","updated_at":"2026-04-07T22:31:48.733Z","avatar_url":"https://github.com/aalug.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go job finder\n\u003chr\u003e\n\nA **REST API** that allows registering as users and employers, where both\naccount types have access to different endpoints and are allowed to perform\ndifferent actions (e.g. only employers can create job offers, and only users\ncan create job applications).\nSearch functionality is implemented both with Postgres and Elasticsearch (depending on search complexity).\nRedis is used to perform tasks in the background such as sending verification or confirmation emails.\n\u003chr\u003e\n\n### Built in Go 1.20\n\n### The app uses:\n- Postgres\n- Redis \n- Docker\n- [Elasticsearch](https://github.com/elastic/go-elasticsearch)\n- [Gin](https://github.com/gin-gonic/gin)\n- [golang-migrate](https://github.com/golang-migrate/migrate)\n- [sqlc](https://github.com/kyleconroy/sqlc)\n- [asynq](https://github.com/hibiken/asynq)\n- [testify](https://github.com/stretchr/testify)\n- [PASETO Security Tokens](https://github.com/o1egl/paseto)\n- [Viper](https://github.com/spf13/viper)\n- [gin-swagger](https://github.com/swaggo/gin-swagger)\n\n\u003chr\u003e\n\n## Getting started\n1. Clone the repository\n2. Go to the project's root directory\n3. Rename `app.env.example` to `app.env` and replace the values\n4. Install [golang-migrate](https://github.com/golang-migrate/migrate/tree/master/cmd/migrate)\n5. Run in your terminal:\n     - `docker-compose up` to run the containers\n     - `make migrate_up` to run migrations\n     - `make runserver load_data=true` to run the HTTP server with sample jobs, employers, and companies loaded into both PostgreSQL and Elasticsearch. Set `load_data` to `false` if you do not want test data to be loaded.\n6. Now everything should be ready and server running on `SERVER_ADDRESS` specified in `app.env`\n\u003chr\u003e\n\n## Testing\n1. Run the containers (`docker-compose up`)\n2. Run in your terminal:\n    - `make test` to run all tests\n\n   or\n    - `make test_coverage p={PATH}` - to get the coverage in the HTML format - where `{PATH}` is the path to the target directory for which you want to generate test coverage. The `{PATH}` should be replaced with the actual path you want to use. For example `./internal/api`\n\n   or\n    - use standard `go test` commands (e.g. `go test -v ./internal/api`)\n\u003chr\u003e\n\n## Database\nThe database's schema and intricate details can be found on dedicated webpage, which provides a comprehensive \noverview of the data structure, tables, relationships, and other essential information. To explore the database \nfurther, please visit this [dbdocs.io webpage](https://dbdocs.io/aalug/go_job_search) Password: `jobsearchsecret`\n\n\n\u003chr\u003e\n\n## API endpoints\nThis API provides a set of endpoints for managing:\n- users\n- employers\n- jobs\n- job applications\n\n(and indirectly: user skills, job skills and verify emails tables)\n\n\nAfter running the server, the Swagger documentation is available at http://localhost:8080/swagger/index.html. \nYou can find there detailed information about the API endpoints, including their parameters, \nrequest and response formats, and examples. You can use the Swagger UI to test the API \nendpoints and see their responses in real-time.\n\n### The base path for all endpoints is `/api/v1`\nso for example `/api/v1/users/login`\n\n\nHere is a summary of the available endpoints and their functionality:\n\n\n### Users\n\n+ `POST /users`: This endpoint creates a new user. The request body must contain the user details \nin JSON format. On success, the response has a `201 Created` status code and returns the created \nuser in JSON format. If the request body is invalid, a `400 Bad Request` status code is returned. \nIf a user with the given email already exists, a `403 Forbidden` status code is returned. In case \nof any other error, a `500 Internal Server Error` status code is returned.\nAfter registering, a verification email is sent to the provided email address.\n\n+ `GET /users/send-verification-email`: This endpoint sends an email to the user with a link that should be used \nto verify their email address. The request must contain the user’s email as a query parameter. On success, the response \nhas a `200 OK` status code and returns the result in JSON format. If the email is invalid, a `400 Bad Request` status code \nis returned. If no user is found with the provided email, a `404 Not Found` status code is returned. In case of any \nother error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /users/verify-email`: This endpoint verifies a user’s email by providing a verify email ID and \nsecret code that should be sent to the user in the verification email. The request body must contain the verify \nemail ID and secret code as query parameters. On success, the response has a `200 OK` status code and returns the \nverification result in JSON format. If the request query is invalid, a `400 Bad Request` status code is returned. \nIn case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `POST /users/login`: This endpoint logs in a user. The request body must contain the user credentials\n(email, password) in JSON format. On success, the response has a `200 OK` status code and returns \nan access token and the authenticated user in JSON format. If the request body is invalid, a \n`400 Bad Request` status code is returned. If the password is incorrect, a `401 Unauthorized` \nstatus code is returned. If user has not verified email, `403 Forbidden` is returned. If a user with the given email does not exist, a `404 Not Found` status \ncode is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /users`: This endpoint retrieves the details of the logged-in user. On success, the response \nhas a `200 OK` status code and returns the user details in JSON format. If the user \nis not authorized (does not have an account or is an employer, not user), a \n`401 Unauthorized` status code is returned. In case of any other error, a \n`500 Internal Server Error` status code is returned.\n\n+ `GET /users/employer-company-details/{email}`: This endpoint retrieves the employer \nand company details. It does not require authentication. The response is in JSON format \nand has a `200 OK` status code on success. If the email in the URI is invalid, a \n`400 Bad Request` status code is returned. If the employer with the given email does \nnot exist, a `404 Not Found` status code is returned. In case of any other error, a \n`500 Internal Server Error` status code is returned.\n\n+ `PATCH /users`: This endpoint updates the details of the logged-in user. The request body must \ncontain the updated user details in JSON format. On success, the response has a `200 OK` status code \nand returns the updated user in JSON format. If the request body is invalid, a `400 Bad Request` \nstatus code is returned. If the user is not authorized (does not have an account or is an employer, not user), \na `401 Unauthorized` status code is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `PATCH /users/password`: This endpoint updates the password of the logged-in user. The request body \nmust contain the old and new password in JSON format. On success, the response has a `200 OK` status \ncode and returns a success message. If the request body is invalid, a `400 Bad Request` status code \nis returned. If the old password is incorrect or the user is not authorized (does not have an account or is an employer, not user), \na `401 Unauthorized` status code is returned. In case \nof any other error, a `500 Internal Server Error` status code is returned.\n\n+ `DELETE /users`: This endpoint deletes the logged-in user. On success, the response has a \n`204 No Content` status code. If the user \nis not authorized (does not have an account or is an employer, not user), a \n`401 Unauthorized` status code is returned.In case of any other error, a `500 Internal Server Error` status code is returned.\n\n\n### Employers\n\n+ `POST /employers`: This endpoint creates a new employer. The request body\nmust contain the employer and company details in JSON format. \nOn success, the response has a `201 Created` status code and returns \nthe created employer in JSON format. If the request body is invalid, \na `400` status code is returned. If a company with the given name or an \nemployer with the given email already exists, a `403 Forbidden` status \ncode is returned. In case of any other error, a 500 Internal Error status code is returned.\nAfter registering, a verification email is sent to the provided email address.\n\n+ `GET /employers/send-verification-email`: This endpoint sends an email to the employer with a link that should be used \nto verify their email address. The request must contain the employer’s email as a query parameter. On success, the response \nhas a `200 OK` status code and returns the result in JSON format. If the email is invalid, a `400 Bad Request` status code \nis returned. If no employer is found with the provided email, a `404 Not Found` status code is returned. In case of any \nother error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /employers/verify-email`: This endpoint verifies an employer’s email by providing a verify email ID and \nsecret code that should be sent to the user in the verification email. The request body must contain the verify \nemail ID and secret code as query parameters. On success, the response has a `200 OK` status code and returns the \nverification result in JSON format. If the request query is invalid, a `400 Bad Request` status code is returned. \nIn case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `POST /employers/login`: This endpoint logs in an employer. The request body \nmust contain the employer credentials (email, password) in JSON format. On success, \nthe response has a `200 OK` status code and returns an access token and the authenticated employer \nin JSON format. If the request body is invalid, a `400 Bad Request` status code is returned. \nIf the password is incorrect, a `401 Unauthorized` status code is returned. \nIf the emails is not verified, a `403 Forbidden` is returned.\nIf an employer with the given email or a company with the given id does not \nexist, a `404 Not Found` status code is returned. In case of any other error, \na `500 Internal Server Error` status code is returned.\n\n+ `GET /employers`: This endpoint retrieves the details of the \nauthenticated employer. The response is in JSON format and has a `200 OK` \nstatus code on success. If the employer is not authorized (does not have an account or is a user, not employer), a \n`401 Unauthorized` status code is returned. In case of an any other error, a `500 Internal Server Error` \nstatus code is returned.\n\n+ `GET /employers/user-details/{email}`: This endpoint retrieves the details of a user as an employer. \nThe response is in JSON format and has a `200 OK` status code on success. If the email \nin the URI is invalid, a `400 Bad Request` status code is returned. If the employer is \nnot authorized (does not have an account or is not an employer), a `401 Unauthorized` \nstatus code is returned. If the user with the given email does not exist, a `404 Not Found` \nstatus code is returned. In case of any other error, a `500 Internal Server Error` status code is returned. \n\n+ `PATCH /employers`: This endpoint updates the details of the \nauthenticated employer. The request body must contain the updated \nemployer details in JSON format. On success, the response has a `200 OK` \nstatus code and returns the updated employer in JSON format. If the employer is not \nauthorized (does not have an account or is a user, not employer), a `401 Unauthorized` \nstatus code is returned.In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `PATCH /employers/password`: This endpoint updates the password of the logged-in \nemployer. The request body must contain the old and new password in JSON format.\nOn success, the response has a `200 OK` status code and returns a success message. \nIf the request body is invalid, a `400 Bad Request` status code is returned. \nIf the old password is incorrect or the employer is not authorized (does not have an account or is a user, not employer), a \n, a `401 Unauthorized` status code is returned. \nIn case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `DELETE /employers`: This endpoint deletes the logged-in employer. \nOn success, the response has a `204 No Content` status code. If the employer is not \nauthorized (does not have an account or is a user, not employer), a \n`401 Unauthorized` status code is returned.In case of \nany other error, a `500 Internal Server Error` status code is returned.\n\n\n### Jobs\n\n+ `POST /jobs`: This endpoint creates a new job. The request body must contain \nthe job details in JSON format. On success, the response has a `201 Created` status \ncode and returns the created job in JSON format. If the request body is invalid, \na `400 Bad Request` status code is returned. In case of any other error, a \n`500 Internal Server Error `status code is returned.\n\n+ `GET /jobs/search`: This endpoint searches for jobs with elasticsearch. \nThe request must contain the `page`, `page_size`, and `search` parameters in the \nquery. On success, the response has a `200 OK` status code and returns an array \nof jobs that match the search query in JSON format. If the query is invalid, a \n`400 Bad Request` status code is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /jobs`: This endpoint filters and lists jobs based on the provided query \nparameters. The `page` and `page_size` query parameters are required and specify\nthe page number and page size, respectively. The `title`, `industry`, `job_location`, \n`salary_min`, and `salary_max` query parameters are optional and can be used to \nfilter the jobs by title, industry, location, and salary range, respectively. \nOn success, the response has a `200 OK` status code and returns a list of jobs \nin JSON format. If the query is invalid, a `400` status code is returned. \nIn case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /jobs/company`: This endpoint lists jobs by company name, id, or part \nof the name. The `page` and `page_size` query parameters are required and specify \nthe page number and page size, respectively. The `id`, `name`, and `name_contains` \nquery parameters are optional (one of them has to be provided) and can be used \nto filter the jobs by company id, exact company name, or part of the company name, \nrespectively. Only one of these three parameters is allowed in a single request. \nOn success, the response has a `200 OK` status code and returns a list of jobs \nin JSON format. If the query is invalid, a `400 Bad Request` status code is returned. \nIn case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /jobs/{id}`: This endpoint retrieves the details of the job with the given id. \nThe id path parameter is required and specifies the id of the job to retrieve. On success, \nthe response has a `200 OK` status code and returns the job details in JSON format. If the \nrequest query is invalid, a `400 Bad Request` code is returned. If the job with the given id is \nnot found, a `404 Not Found` status code is returned. In case of any other error, a \n`500 Internal Server Error` status code is returned.\n\n+ `PATCH /jobs/{id}`: This endpoint updates the job with the given id. The id path parameter is required \nand specifies the id of the job to update. The request body must contain the updated job details \nin JSON format. On success, the response has a `200 OK` status code and returns the updated job in \nJSON format. In case of any error, a `500 Internal Server Error` status code is returned.\n\n+ `DELETE /jobs/{id}`: This endpoint deletes the job with the given id. The id path parameter is \nrequired and specifies the id of the job to delete. On success, the response has a `204 No Content` \nstatus code. In case the job is not found, returns `404 Not Found`, in case of any other error, a `500 Internal Server Error` status code is returned.\n\n\n### Job Applications\n\n+ `POST /job-applications`: This endpoint creates a new job application. Only users \ncan access this endpoint. The request must contain the CV file, job ID, and optionally \nmessage for the employer in multipart/form-data format. On success, the response \nhas a `200 OK` status code and returns the created job application details in JSON \nformat. If the request body is invalid, a `400 Bad Request` status code is returned. \nIf the user is not authorized to access this endpoint, a `401 Unauthorized` status \ncode is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /job-applications/employer/{id}`: This endpoint retrieves the details of the job application \nfor an employer with the given id. The id path parameter is required and specifies the id of the job \napplication to retrieve. On success, the response has a `200 OK` status code and returns the job application \ndetails in JSON format. If the request query is invalid, a `400 Bad Request` code is returned. If the employer \nis not authorized (does not have an account or is a user, not employer), a `401 Unauthorized` status code is returned. \nIf the employer is not part of the company that created the job this application is for, a `403 Forbidden` status \ncode is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `PATCH /job-applications/employer/{id}/status`: This endpoint changes the status of the job application with \nthe given id. The id path parameter is required and specifies the id of the job application to update. \nThe `new_status` body parameter is required and specifies the new status of the job application. On success, \nthe response has a `200 OK` status code and returns the updated job application details in JSON format. \nIf the request query is invalid, a `400 Bad Request` code is returned. If the user is not authorized (does not have an account or is a user, not employer), \na `401 Unauthorized` status code is returned. If the employer is not part of the company that created the job this application is for, a `403 Forbidden`\nstatus code is returned. If the job application with the given id is not found, a `404 Not Found` status code \nis returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /job-applications/employer`: This endpoint lists the job applications for a job with \na given ID. Only employers can access this endpoint. The results are paginated based on the \n`page` and `page_size` query parameters, which are both required. The `sort` query parameter is \noptional and can be used to sort the results by date in ascending or descending order. The \n`status` query parameter is also optional and can be used to filter the results by status \n('Applied', 'Seen', 'Interviewing', 'Offered', 'Rejected'). On success, the response has a \n`200 OK` status code and returns a list of job applications in JSON format. If the request \nquery is invalid, a `400 Bad Request` code is returned. If the user is not authorized \n(does not have an account or is not an employer), a `401 Unauthorized` status code is \nreturned. If the job does not exist, a `404 Not Found` status is returned, and if the employer \nis not the owner of the job, `403 Forbidden` is returned. In case of any other error, \na `500 Internal Server Error` status code is returned.\n\n+ `GET /job-applications/user`: This endpoint lists the job applications that the authenticated \nuser created. The results are paginated based on the `page` and `page_size` query parameters, \nwhich are both required. The `sort` query parameter is optional and can be used to sort \nthe results by date in ascending or descending order. The `status` query parameter is also \noptional and can be used to filter the results by status (‘Applied’, ‘Seen’, ‘Interviewing’, ‘Offered’, ‘Rejected’). \nOn success, the response has a `200 OK` status code and returns a list of job applications \nin JSON format. If the request query is invalid, a `400 Bad Request` code is returned. \nIf the user is not authorized (does not have an account or is an employer, not user), a \n`401 Unauthorized` status code is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `GET /job-applications/user/{id}`: This endpoint retrieves the details of the job application for a user. \nThe id path parameter is required and specifies the id of the job application to retrieve. On success, \nthe response has a `200 OK` status code and returns the job application details in JSON format. If the \nrequest query is invalid, a `400 Bad Request` code is returned. If the user is not authorized (does not have an account or is an employer, not user)\n, a `401 Unauthorized` status code is returned. If the user is not the creator of this job application, a `403 Forbidden` status code is \nreturned. In case of any other error, a `500 Internal Server Error` status code is returned. \n\n+ `PATCH /job-applications/user/{id}`: This endpoint updates the details of the job application for a user. \nThe id path parameter is required and specifies the id of the job application to update. The `cv` formData \nparameter is optional and specifies the CV file (.pdf) to update. The `cv_provided` formData parameter is \nrequired and specifies whether a CV file was provided. The `message` formData parameter is optional and \nspecifies the message for the employer to update. On success, the response has a `200 OK` status code and \nreturns the updated job application details in JSON format. If the request query is invalid, a `400 Bad Request` \ncode is returned. If the user is not authorized (does not have an account or is an employer, not user), \na `401 Unauthorized` status code is returned. If the user is not the creator of this job application, \na `403 Forbidden` status code is returned. If the job application with the given id is not found, a \n`404 Not Found` status code is returned. In case of any other error, a `500 Internal Server Error` status code is returned.\n\n+ `DELETE /job-applications/user/{id}`: This endpoint deletes the job application for a user. The id path parameter \nis required and specifies the id of the job application to delete. On success, the response has a `204 No Content` \nstatus code. If the provided id is invalid, a `400 Bad Request` code is returned. If the user is not authorized\n(does not have an account or is an employer, not user), a `401 Unauthorized` status code is returned. \nIf the user is not the creator of this job application, a `403 Forbidden` status code is returned. If the \njob application with the given id is not found, a `404 Not Found` status code is returned. In case of any \nother error, a `500 Internal Server Error` status code is returned.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalug%2Fjob-finder-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faalug%2Fjob-finder-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalug%2Fjob-finder-go/lists"}