{"id":20278741,"url":"https://github.com/zrierc/reading-list-api","last_synced_at":"2026-06-01T06:31:48.790Z","repository":{"id":187161661,"uuid":"671418100","full_name":"zrierc/reading-list-api","owner":"zrierc","description":"Mini workshop that build and deploy a Reading List API using AWS Lambda, Amazon API Gateway, Cognito User Pool, and DynamoDB.","archived":false,"fork":false,"pushed_at":"2023-08-09T07:26:52.000Z","size":88,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-04T01:46:17.554Z","etag":null,"topics":["amazon-api-gateway","aws-lambda","cognito","cognito-user-pool","dynamodb","restful-api","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zrierc.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}},"created_at":"2023-07-27T09:15:21.000Z","updated_at":"2023-08-20T14:01:48.000Z","dependencies_parsed_at":"2023-08-09T08:09:56.114Z","dependency_job_id":null,"html_url":"https://github.com/zrierc/reading-list-api","commit_stats":null,"previous_names":["zrierc/reading-list-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zrierc/reading-list-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrierc%2Freading-list-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrierc%2Freading-list-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrierc%2Freading-list-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrierc%2Freading-list-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zrierc","download_url":"https://codeload.github.com/zrierc/reading-list-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrierc%2Freading-list-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33763648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["amazon-api-gateway","aws-lambda","cognito","cognito-user-pool","dynamodb","restful-api","typescript"],"created_at":"2024-11-14T13:26:03.247Z","updated_at":"2026-06-01T06:31:48.765Z","avatar_url":"https://github.com/zrierc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reading List API\n\n#### Tables of Contents:\n\n- [Overview](#overview)\n- [Project Structure](#project-structure)\n- [Requirements](#requirements)\n- [Setup Environment](#setup-environment)\n  - [Lambda](#lambda)\n  - [API Gateway](#api-gateway)\n  - [Cognito](#cognito)\n- [Testing](#-testing)\n- [Clean Up Resources](#clean-up-resources)\n\n---\n\n## Overview\n\nWelcome to this mini workshop! Here you will learn to build and deploy Reading List API using RESTful API, AWS Lambda, Amazon API Gateway, Amazon Cognito, and Amazon DynamoDB. Please take a look the architecture below.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./architecture.png\"\u003e\n\u003c/p\u003e\n\n\u003e The content of this mini workshop may be updated and if you have questions or find issues in this mini workshop, please file them as an Issue.\n\n## Project Structure\n\n```md\nreading-list-api/\n├─ functions/\n├─ .gitignore\n├─ architecture.png\n├─ LICENSE\n├─ README.md\n```\n\n- [`functions/`](/functions/) contains lambda function code for the API.\n- [`architecture.png`](/architecture.png) is an overview of the resources to be deployed.\n- [`README.md`](/README.md) contains guide for this mini workshop.\n\n## Requirements\n\nBefore starting this mini workshop, the following runtime/tools must be met and configured properly.\n\n- Active [AWS Account](https://aws.amazon.com/).\n- [NodeJS](https://nodejs.org/en) `v16` or latest with [npm](https://www.npmjs.com/) or [yarn](https://classic.yarnpkg.com/lang/en/) installed.\n- [AWS CLI version 2](https://aws.amazon.com/cli/).\n- API Testing Tools.\n  \u003e **Note** \u003c/br\u003e\n  \u003e This mini workshop will use [`curl`](https://curl.se/) to test the APIs. However, you can use your favorite API testing tools (e.g. Postman/Insomnia/Thunder Client/etc).\n- (optional) OS based on Linux.\n  \u003e **Note** \u003c/br\u003e\n  \u003e Build script for package lambda function code and it's dependecies require Linux/Unix shell to operate. If you are using an OS other than Linux and/or your device doesn't support Linux shell commands you can customize [this build script](/functions/build.sh) to make sure it runs properly.\n\n### AWS Resources\n\nSome of the services from AWS that are used in this mini workshop are as follows:\n\n- [AWS Lambda](https://aws.amazon.com/lambda/)\n- [Amazon API Gateway](https://aws.amazon.com/api-gateway/)\n- [Amazon Cognito](https://aws.amazon.com/cognito/)\n- [Amazon DynamoDB](https://aws.amazon.com/dynamodb/)\n\n---\n\n## Setup Environment\n\n\u003e **💡 TIP**\n\u003e\n\u003e If the settings/configurations are not specified in this guide, you can leave them as default or you can specify the values with your own.\n\n### DynamoDB\n\n1. Select AWS region.\n\n2. Create dynamoDB tables with following configuration:\n\n   - Table name: `reading-list-db`\n   - Partition key: `readingID` (string)\n   - Sort key: `userID` (string)\n   - Table class: DynamoDB Standard\n   - Capacity mode: On-demand\n\n### Cognito\n\n1. Select AWS region.\n\n2. Create Cognito User pool with following configurations:\n\n   i. Sign-In Experience\n\n   - Provider type: Cognito user pool\n   - Cognito user pool sign-in options: `username`, `email`\n   - Multi-factor authentication: No MFA\n\n   ii. Sign-Up Experience\n\n   - Enable Self-registration: true\n   - Allow Cognito to automatically send messages to verify and confirm: true\n\n   iii. Messaging / Message Delivery\n\n   - Email provider: Send email with Cognito\n\n   iv. App Integration\n\n   - User pool name: `user-auth-reading-list-api`\n   - App type: Public client\n   - App client name: lambda-jwt-auth\n   - Authentication flow: `ALLOW_CUSTOM_AUTH`, `ALLOW_REFRESH_TOKEN_AUTH`, `ALLOW_USER_PASSWORD_AUTH`, `ALLOW_USER_SRP_AUTH`\n   - (optional) Enable Cognito Hosted UI: true\n     \u003e **Note** \u003c/br\u003e\n     \u003e For Domain section, you can use either Cognito domain or custom domain if you have. If you choose Cognito domain, make sure it unique. For example, you can use your name for your cognito domain (e.g `https://shinji-reading-list-api.auth.ap-southeast-1.amazoncognito.com`).\n     - Callback URLs: `http://localhost`\n       \u003e This URL is used for testing purposes only. You can change it to your site or your API endpoint afterwards.\n     - OpenID Connect scopes: Email, OpenID, Phone, Profile\n     - Access token expiration: 1 day(s)\n     - ID token expiration: 1 day(s)\n\n3. Attach Lambda trigger to Cognito user pool.\n\n   \u003e 💡 TIP\n   \u003e\n   \u003e You can setup this after completing [the Lambda section](#lambda).\n\n   - Trigger type: Authentication\n   - Authentication: Pre token generation trigger\n   - Lambda function: use Lambda [Pre-Token Generation](#3-deploy-pre-token-generation-function).\n\n### Lambda\n\n#### 1. Build Code\n\n- Clone [this repository](https://github.com/zrierc/reading-list-api)\n\n  ```bash\n  git clone https://github.com/zrierc/reading-list-api.git\n  ```\n\n- Navigate to [`functions/`](/functions/)\n\n  ```bash\n  cd functions/\n  ```\n\n- Install required dependencies\n\n  ```bash\n  yarn\n  ```\n\n  or\n\n  ```bash\n  npm i\n  ```\n\n- Build your lambda functions code and dependencies to zip\n\n  ```bash\n  yarn build\n  ```\n\n  or\n\n  ```bash\n  npm run build\n  ```\n\n#### 2. Select AWS Region\n\n#### 3. Create IAM Role for Lambda\n\n- Role name: `reading-list-fn-role`\n- Trusted entitiy Type: AWS service\n- Use cases: Lambda\n- Permission policies:\n  - `AWSLambdaBasicExecutionRole` (AWS Managed)\n  - `AmazonDynamoDBFullAccess` (AWS Managed)\n\n#### 4. Deploy Pre-Token Generation Function\n\ni. Create Lambda function with following configurations:\n\n- Function name: `preTokenGenerationFn`\n- Runtime: Node.js 16.x\n- Handler: `cognito-auth/preTokenGeneration.handler`\n- Timeout: 60s\n\nii. Publish [functions code](#1-build-code) that you already build before.\n\n- Navigate to [`functions/`](/functions/) directory\n\n  ```bash\n  cd functions/\n  ```\n\n- Publish code via [AWS CLI](https://aws.amazon.com/cli/)\n\n  ```bash\n  aws lambda update-function-code \\\n    --function-name preTokenGenerationFn \\\n    --zip-file fileb://functions.zip\n  ```\n\n#### 5. Deploy List Book Function\n\ni. Create Lambda function with following configurations:\n\n- Function name: `listBookFn`\n- Runtime: Node.js 16.x\n- Handler: `book/listBook.handler`\n- Execution role: select [`reading-list-fn-role`](#3-create-iam-role-for-lambda) that you already created before.\n- Timeout: 60s\n- Environment variables:\n  - `TABLE_NAME`: dynamoDB table name (`reading-list-db`).\n  - `COGNITO_USER_POOL_ID`: Id of Amazon Cognito user pool that you already created before.\n  - `COGNITO_CLIENT_ID`: Id of user pool app client that you already created before.\n\nii. Publish [functions code](#1-build-code) that you already build before.\n\n- Navigate to [`functions/`](/functions/) directory\n\n  ```bash\n  cd functions/\n  ```\n\n- Publish code via [AWS CLI](https://aws.amazon.com/cli/)\n\n  ```bash\n  aws lambda update-function-code \\\n    --function-name listBookFn \\\n    --zip-file fileb://functions.zip\n  ```\n\n#### 6. Deploy Get Detail Book Function\n\ni. Create Lambda function with following configurations:\n\n- Function name: `getBookFn`\n- Runtime: Node.js 16.x\n- Handler: `book/getBook.handler`\n- Execution role: select [`reading-list-fn-role`](#3-create-iam-role-for-lambda) that you already created before.\n- Timeout: 60s\n- Environment variables:\n  - `TABLE_NAME`: dynamoDB table name (`reading-list-db`).\n  - `COGNITO_USER_POOL_ID`: Id of Amazon Cognito user pool that you already created before.\n  - `COGNITO_CLIENT_ID`: Id of user pool app client that you already created before.\n\nii. Publish [functions code](#1-build-code) that you already build before.\n\n- Navigate to [`functions/`](/functions/) directory\n\n  ```bash\n  cd functions/\n  ```\n\n- Publish code via [AWS CLI](https://aws.amazon.com/cli/)\n\n  ```bash\n  aws lambda update-function-code \\\n    --function-name getBookFn \\\n    --zip-file fileb://functions.zip\n  ```\n\n#### 7. Deploy Add New Book Function\n\ni. Create Lambda function with following configurations:\n\n- Function name: `saveBookFn`\n- Runtime: Node.js 16.x\n- Handler: `book/saveBook.handler`\n- Execution role: select [`reading-list-fn-role`](#3-create-iam-role-for-lambda) that you already created before.\n- Timeout: 60s\n- Environment variables:\n  - `TABLE_NAME`: dynamoDB table name (`reading-list-db`).\n  - `COGNITO_USER_POOL_ID`: Id of Amazon Cognito user pool that you already created before.\n  - `COGNITO_CLIENT_ID`: Id of user pool app client that you already created before.\n\nii. Publish [functions code](#1-build-code) that you already build before.\n\n- Navigate to [`functions/`](/functions/) directory\n\n  ```bash\n  cd functions/\n  ```\n\n- Publish code via [AWS CLI](https://aws.amazon.com/cli/)\n\n  ```bash\n  aws lambda update-function-code \\\n    --function-name saveBookFn \\\n    --zip-file fileb://functions.zip\n  ```\n\n#### 8. Deploy Delete Book Function\n\ni. Create Lambda function with following configurations:\n\n- Function name: `deleteBookFn`\n- Runtime: Node.js 16.x\n- Handler: `book/deleteBook.handler`\n- Execution role: select [`reading-list-fn-role`](#3-create-iam-role-for-lambda) that you already created before.\n- Timeout: 60s\n- Environment variables:\n  - `TABLE_NAME`: dynamoDB table name (`reading-list-db`).\n  - `COGNITO_USER_POOL_ID`: Id of Amazon Cognito user pool that you already created before.\n  - `COGNITO_CLIENT_ID`: Id of user pool app client that you already created before.\n\nii. Publish [functions code](#1-build-code) that you already build before.\n\n- Navigate to [`functions/`](/functions/) directory\n\n  ```bash\n  cd functions/\n  ```\n\n- Publish code via [AWS CLI](https://aws.amazon.com/cli/)\n\n  ```bash\n  aws lambda update-function-code \\\n    --function-name deleteBookFn \\\n    --zip-file fileb://functions.zip\n  ```\n\n#### 😕 Are you stuck?\n\nCheck this common issues:\n\n\u003cdetails\u003e\n  \u003csummary\u003e❌ Failed running build command\u003c/summary\u003e\n\n- Make sure npm or yarn already installed on your machine.\n- Make sure zip and unzip already installed on your machine. Click [here](https://www.tecmint.com/install-zip-and-unzip-in-linux/) to read guide how to install zip and unzip in Linux machine.\n- Make sure your machine support Linux/Unix commands to run build script. For Windows user, you can try to install [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install) to run Linux on your Windows machine OR you can create custom build script using powershell/cmd. Don't forget to change `build` script command inside `package.json`.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e⚠ Error when publish code to Lambda using AWS CLI\u003c/summary\u003e\n\n- Make sure you code already built and `function.zip` in the same directory as `functions/` exists.\n- Make sure you already installed AWS CLI on your machine. Click [here](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions) to read more about how to install the AWS CLI.\n- Setup IAM credentials for authentication AWS CLI. Click [here](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html) to read more about how to setup credentials.\n  \u003e **Note** \u003c/br\u003e\n  \u003e Make sure your IAM credentials for AWS CLI has `AWSLambda_FullAccess` policy.\n\n\u003c/details\u003e\n\n### API Gateway\n\n1. Select AWS region.\n\n2. Create Amazon API Gateway with following configurations:\n\n   - API type: HTTP API\n   - API name: `reading-list-api`\n\n3. Create routes:\n\n   1. Route for list books\n\n      - method: `GET`\n      - path: `/book`\n\n   2. Route for add new books\n\n      - method: `POST`\n      - path: `/book`\n\n   3. Route for get detail book\n\n      - method: `GET`\n      - path: `/book/{id}`\n\n   4. Route for delete book\n\n      - method: `DELETE`\n      - path: `/book/{id}`\n\n4. Attach lambda integrations:\n\n   \u003e **Note** \u003c/br\u003e\n   \u003e Make sure you enable 'Grant API Gateway permission to invoke your Lambda function' option.\n\n   1. Integration for list books API\n\n      - Route: `GET  /book`\n      - Integration type: Lambda function\n      - Target: choose [`listBookFn`](#5-deploy-list-book-function)\n\n   2. Integration for add new books API\n\n      - Route: `POST  /book`\n      - Integration type: Lambda function\n      - Target: choose [`saveBookFn`](#7-deploy-add-new-book-function)\n\n   3. Integration for get detail book API\n\n      - Route: `GET  /book/{id}`\n      - Integration type: Lambda function\n      - Target: choose [`getBookFn`](#6-deploy-get-detail-book-function)\n\n   4. Integration for delete book API\n\n      - Route: `DELETE  /book`\n      - Integration type: Lambda function\n      - Target: choose [`deleteBookFn`](#8-deploy-delete-book-function)\n\n5. Add cognito as API authorization:\n\n   1. Create authorizer with following configurations:\n\n      - Authorizer type: JWT\n      - Name: `JWTCognitoAuth`\n      - Issuer URL: `https://cognito-idp.\u003caws-region\u003e.amazonaws.com/\u003cyour_cognito_userpool_id\u003e`\n      - Audience: `\u003ccognito_app_client_id_of_userpool\u003e`\n\n      \u003e 💡 TIP\n      \u003e\n      \u003e `\u003cyour_cognito_userpool_id\u003e` in Issuer URL **should be same** as `COGNITO_USER_POOL_ID` value on Lambda environment variables. While, Audience value **should be same** as `COGNITO_CLIENT_ID` value on Lambda enviroment variables.\n\n   2. Attach authorizer for all routes.\n\n---\n\n## 🧪 Testing\n\n### Step 1: Create Cognito user.\n\nYou can create via AWS CLI:\n\n- Create user\n\n  ```bash\n  aws cognito-idp sign-up \\\n    --client-id \u003ccognito_app_client_id_of_userpool\u003e \\\n    --username \u003cyour_username\u003e \\\n    --user-attributes Name=email,Value=\u003cyour_mail\u003e \\\n    --password \u003cyour_password\u003e\n  ```\n\n- Verify user\n\n  ```bash\n   aws cognito-idp admin-confirm-sign-up \\\n   --user-pool-id \u003cyour_cognito_userpool_id\u003e \\\n    --username \u003cyour_username\u003e\n  ```\n\nYou can also [create user via Amazon Cognito console](https://docs.aws.amazon.com/cognito/latest/developerguide/how-to-create-user-accounts.html#creating-a-new-user-using-the-users-tab). If you enable hosted UI when setup Cognito, you can [create user via hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-hosted-ui-user-sign-up.html).\n\n### Step 2: Test API\n\n\u003e 🧪⚠ Scenario\n\u003e\n\u003e For testing, you're going to do 3 scenarios:\n\u003e\n\u003e 1. Using random string as authorization token and without using authorization token — which will make the requests failed\n\u003e 2. Using JWT token from Amazon Cognito which will led to successful request\n\u003e 3. Test all API endpoint\n\n1.  First scenario:\n\n    - Open terminal\n\n    - Execute following commands:\n\n      without authorization token\n\n      ```bash\n      curl https://\u003cyour-http-api-gateway-endpoint\u003e/book\n      ```\n\n      with random string as authorization token\n\n      ```bash\n      curl -H \"Authorization: MY-RANDOM-STRING\" https://\u003cyour-http-api-gateway-endpoint\u003e/book\n      ```\n\n    - If you see the following response, then your cognito JWT authorizer works correctly\n\n      ```json\n      { \"message\": \"Unauthorized\" }\n      ```\n\n2.  Second scenario:\n\n    - Open terminal\n\n    - Get JWT token from Cognito using AWS CLI\n\n      ```bash\n      aws cognito-idp initiate-auth \\\n        --auth-flow USER_PASSWORD_AUTH \\\n        --client-id \u003ccognito_app_client_id_of_userpool\u003e \\\n        --auth-parameters USERNAME=\u003cyour-username\u003e,PASSWORD='\u003cyour-password\u003e'\n      ```\n\n      If you see the following response, copy token from `IdToken`\n\n      ```json\n      {\n        \"ChallengeParameters\": {},\n        \"AuthenticationResult\": {\n          \"AccessToken\": \"a1b2c3d4e5c644444555556666Y2X3Z1111\",\n          \"ExpiresIn\": 3600,\n          \"TokenType\": \"Bearer\",\n          \"RefreshToken\": \"xyz654cba321dddccc1111\",\n          \"IdToken\": \"a1b2c3d4e5c6aabbbcccddd\"\n        }\n      }\n      ```\n\n3.  Test `GET /book` endpoint to **list all books**\n\n    Execute the following command:\n\n    ```bash\n    curl -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n    https://\u003cyour-http-api-gateway-endpoint\u003e/book\n    ```\n\n    If you see the following response, then it works correctly\n\n    ```json\n    { \"data\": [] }\n    ```\n\n4.  Test `POST /book` endpoint to **add new books**\n\n    Sample data (single):\n\n    ```json\n    {\n      \"bookTitle\": \"Cosmos\",\n      \"bookAuthor\": \"Carl Sagan\"\n    }\n    ```\n\n    Sample multiple data:\n\n    ```json\n    [\n      {\n        \"bookTitle\": \"Chainsaw Man, Vol. 1\",\n        \"bookAuthor\": \"Tatsuki Fujimoto\"\n      },\n      {\n        \"bookTitle\": \"Chainsaw Man, Vol. 2\",\n        \"bookAuthor\": \"Tatsuki Fujimoto\"\n      },\n      {\n        \"bookTitle\": \"Chainsaw Man, Vol. 3\",\n        \"bookAuthor\": \"Tatsuki Fujimoto\"\n      }\n    ]\n    ```\n\n    Execute the following commands:\n\n    Send data (single)\n\n    ```bash\n    curl -X POST \\\n      https://\u003cyour-http-api-gateway-endpoint\u003e/book \\\n      -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n      -H 'Content-Type: application/json' \\\n      -d '{\"bookTitle\": \"Cosmos\", \"bookAuthor\": \"Carl Sagan\"}'\n    ```\n\n    Send multiple data\n\n    ```bash\n    curl -X POST \\\n      https://\u003cyour-http-api-gateway-endpoint\u003e/book \\\n      -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n      -H 'Content-Type: application/json' \\\n      -d '[{\"bookTitle\":\"Chainsaw Man, Vol. 1\",\"bookAuthor\":\"Tatsuki Fujimoto\"},{\"bookTitle\":\"Chainsaw Man, Vol. 2\",\"bookAuthor\":\"Tatsuki Fujimoto\"},{\"bookTitle\":\"Chainsaw Man, Vol. 3\",\"bookAuthor\":\"Tatsuki Fujimoto\"}]'\n    ```\n\n    If you see the following response, then it works correctly\n\n    ```json\n    { \"message\": \"success\" }\n    ```\n\n    \u003e **💡 TIP**\n    \u003e\n    \u003e To make sure data already stored on database, you can check the data that you sent in DynamoDB Console. [Learn more](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-3.html). \u003c/br\u003e\n    \u003e If successful, the data that you sent before will exist in the DynamoDB table as items.\n\n5.  Test `GET /book/{id}` endpoint to **get detail book**\n\n    Get current book that available\n\n    ```bash\n    curl -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n    https://\u003cyour-http-api-gateway-endpoint\u003e/book\n    ```\n\n    If you see the following response, copy id from `readingID`\n\n    \u003e **Note** \u003c/br\u003e `readingID` may be different value than the example. **Adjust the id with your output**.\n\n    ```json\n    {\n      \"data\": [\n        {\n          \"readingID\": \"abcd1234-ab12-cd23-ef45-abcdef123456\",\n          \"userID\": \"john\",\n          \"bookTitle\": \"Cosmos\",\n          \"bookAuthor\": \"Carl Sagan\",\n          ...\n        },\n        ...\n      ]\n    }\n    ```\n\n    Get detail book:\n\n    ```bash\n    curl -X GET \\\n      https://\u003cyour-http-api-gateway-endpoint\u003e/book/\u003creadingID\u003e \\\n      -H 'Authorization: \u003cpaste-your-IdToken\u003e'\n    ```\n\n    If you see the following response, then it works correctly\n\n    ```json\n    {\n      \"readingID\": \"abcd1234-ab12-cd23-ef45-abcdef123456\",\n      \"userID\": \"john\",\n      \"bookTitle\": \"Cosmos\",\n      \"bookAuthor\": \"Carl Sagan\",\n      \"dateAdded\": 1690370601856,\n      \"readingStatus\": \"added\",\n      \"lastUpdated\": 1690370601856,\n      \"lastPageRead\": null\n      \"dateFinished\": null,\n    }\n    ```\n\n6.  Test `DELETE /book/{id}` endpoint to **delete book**\n\n    Get current book that available\n\n    ```bash\n    curl -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n    https://\u003cyour-http-api-gateway-endpoint\u003e/book\n    ```\n\n    If you see the following response, copy id from `readingID`\n\n    \u003e **Note** \u003c/br\u003e `readingID` may be different value than the example. **Adjust the id with your output**.\n\n    ```json\n    {\n      \"data\": [\n        {\n          \"readingID\": \"abcd1234-ab12-cd23-ef45-abcdef123456\",\n          \"userID\": \"john\",\n          \"bookTitle\": \"Cosmos\",\n          \"bookAuthor\": \"Carl Sagan\",\n          ...\n        },\n        ...\n      ]\n    }\n    ```\n\n    Delete book\n\n    ```bash\n    curl -X DELETE \\\n      https://\u003cyour-http-api-gateway-endpoint\u003e/book/\u003creadingID\u003e \\\n      -H 'Authorization: \u003cpaste-your-IdToken\u003e' \\\n      -H 'Content-Type: application/json'\n    ```\n\n    If you see the following response, then it works correctly\n\n    ```json\n    { \"message\": \"success\" }\n    ```\n\n    \u003e **💡 TIP**\n    \u003e\n    \u003e To make sure data already deleted on database, you can check the data that you sent in DynamoDB Console. [Learn more](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-3.html). \u003c/br\u003e\n    \u003e If successful, the data you deleted before will no longer exist in the DynamoDB table.\n\n---\n\n## Clean Up Resources\n\nThis workshop uses AWS services that are mostly covered by the Free Tier allowance - ONLY if your account is less than 12 months old. For accounts passed the free tier eligibility, it may incur some costs. To minimize the cost, make sure you **delete resources used in this workshop when you are finished**.\n\nFollow the sequence according to the steps to delete the AWS resources:\n\n1. Delete HTTP API Gateway via [Amazon API Gateway console](https://console.aws.amazon.com/apigateway).\n\n2. Delete Cognito User Pool via [Amazon Cognito console](https://console.aws.amazon.com/cognito/home).\n\n   \u003e For detail guide, please follow tutorial from [official docs](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-cleanup-tutorial.html).\n\n3. Delete following Lambda functions via [AWS Lambda Functions console](https://console.aws.amazon.com/lambda/home#/functions):\n\n   - `preTokenGenerationFn`\n   - `listBookFn`\n   - `saveBookFn`\n   - `getBookFn`\n   - `deleteBookFn`\n\n   \u003e **Note** \u003c/br\u003e\n   \u003e You can also delete [custom IAM role for Lambda](#3-create-iam-role-for-lambda) that you've created before via [IAM console](https://console.aws.amazon.com/iamv2/home?#/roles). [Learn more](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage_delete.html#roles-managingrole-deleting-console).\n\n4. Delete DynamoDB table via [DynamoDB console](https://console.aws.amazon.com/dynamodb/).\n\n   \u003e Click [here](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-8.html) to read more how to delete tables in DynamoDB.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrierc%2Freading-list-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzrierc%2Freading-list-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrierc%2Freading-list-api/lists"}