Hosted on Heroku: https://buuks-express-api.herokuapp.com
"Buuks" instead of "books"... Another angle 😉 The API allows an (authenticated) user to interact with a database made for storing books. API is built with nodejs, expressjs and mongoDB, and is able to do the following:
- Create Read Update Delete operations for books which are saved in the database
- User signup, authentication and (basic) authorization
- PDF file upload to Cloudinary
- Uses zod for resource validation
Methods & endpoints | Description | Request body | Auth (access token) |
---|---|---|---|
POST /users/signup | Create new user | email, password, passwordConfirmation, name | Not required |
POST /users/login | Sign in as existing user, create access token and refresh token for use in all endpoints that require access token | email, password | Access token is generated at this endpoint |
GET /users/sessions | Gets all users sessions made through the POST /users/login endpoint. Also reissues an access token (if access token is expired and there's refresh token) | No request body | Use access token from the POST /users/login response |
DELETE /users/sessions | Deletes the last recorded session created through the POST /users/login endpoint (Note: this endpoint may need fixing) | No request body | Use access token from the POST /users/login response |
POST /books | Create a new book (authenticated user) | title, description, pdf (file upload) | Use access token from the POST /users/login response |
GET /books/user/:userId | Get/view only books created by a particular user, using the user ID | No request body | Use access token from the POST /users/login response |
GET /books/:bookId | Get/view a book stored in the database, using the book ID | No request body | Not required (for now) |
PUT /books/:bookId | Update already existing book in the database, using the book ID | title, description, pdf (file upload) | Use access token from the POST /users/login response |
DELETE /books/:bookId | Delete a book from the database, using the book ID | No request body | Use access token from the POST /users/login response |
POST /users/signup
Request body
{ "email": "string", "password": "string", "passwordConfirmation": "string", "name": "string" }
Successful response (sample)
{ "user": { "email": "string", "name": "string", "_id": "string", "createdAt": "string", "updatedAt": "string" } }
POST /users/login
Request body
{ "email": "string", "password": "string" }
Successful response (sample)
{ "user": { "name": "string", "email": "string", "_id": "string" }, "accessToken": "string" }
GET /users/sessions
Request body
No response body
Successful response (sample)
{ "count": number, "sessions": [ { "_id": "string", "user": "string", "password": boolean, "userAgent": "string", "createdAt": "string", "updatedAt": "string" }, // etc. ] }
DELETE /users/sessions
Request body
No response body
Successful response (sample)
{ "accessToken": null, "refreshToken": null }
POST /books
Request body
Use form-data (in postman). The title and description keys should have value of type string. The pdf key should have the value of type file.
Successful response (sample)
{ "message": "string" "user": { "name": "string", "_id": "string" }, "book": { "_id": "string", "title": "string", "description": "string", "pdf": "string" "request": { "type": "string", "url": "string", "description": "string" } } }
GET /books/user/:userId
Request body
No response body
Successful response (sample)
{ "count": number, "description": "string", "books": [ { "_id": "string", "title": "string", "description": "string", "pdf": "string", "request": { "type": "string", "url": "string", "description": "string" } }, // etc. ] }
GET /books/:bookId
Request body
No response body
Successful response (sample)
{ "_id": "string", "title": "string", "description": "string", "pdf": "string", "user": { "_id": "string" }, "request": { "type": "string", "url": "string", "description": "string" } }
PUT /books/:bookId
Request body
Use form-data (in postman). The title and description keys should have value of type string. The pdf key should have the value of type file.
Successful response (sample)
{ "message": "string" "user": { "name": "string", "_id": "string" }, "book": { "_id": "string", "title": "string", "description": "string", "pdf": "string" "request": { "type": "string", "url": "string", "description": "string" } } }
DELETE /books/:bookId
Request body
No response body
Successful response (sample)
{ "message": "string" "user": { "name": "string", "_id": "string" }, "request": { "type": "string", "url": "string", "description": "string" } }
Make sure to either have mongoDB installed and running on your computer, or have a monogDB atlas cluster set up in the cloud. Set your API_HOST_URL and other needed environment variables in the .env file you create (see example in .env.example file). Use the commands below to run the API locally on your computer.
Install dependencies:
npm install
Start server for connection to mongoDB (local):
npm run dev
Start server for connection to mongoDB (Atlas):
npm run dev:atlas
- TomDoesTech's youtube video: REST API with Node.js, Express, TypeScript, MongoDB & Zod
- Academind's youtube playlist: Building a RESTful API with Node.js
- Okpukoro Joe's Article: Uploading Images to Cloudinary Using Multer and ExpressJS
- Yilmaz's stackoverflow answer to multer/clouudinary issue: Converting image to base64 with data-uri with typescript
- JWT doc: Introduction to JSON Web Tokens