nestjs shopify
A simple NestJS API integrated with Shopify
Documentation
ποΈ Shopify Orders Webhook Integration (NestJS + Drizzle + Docker)
This project is an API developed using NestJS with Drizzle ORM and PostgreSQL, designed to integrate with the Shopify API. It handles OAuth authentication for Shopify stores and receives order creation webhooks (orders/create).
Table of Contents
- Technologies Used
- Prerequisites
- Setting Up a Public Domain (ngrok or alternative)
- Initial Setup on Shopify
- Project Configuration
- Running the Project
- API Endpoints
- Testing the Integration
- Supported Webhooks
- (Optional) Viewing Saved Data in the Database
- Project Structure
Technologies Used
- NestJS - A progressive Node.js framework for building efficient, reliable, and scalable server-side applications.
- Drizzle ORM - Type-safe operations on the database.
- Shopify API - Shopifyβs REST/GraphQL APIs used for OAuth authentication and order webhooks.
- Ngrok - Tunnel to expose your local API to the internet.
- PostgreSQL - Relational database for data persistence.
- Docker - Containerization for the application and database.
- Zod - TypeScript-first schema and data validation.
Prerequisites
Before getting started, make sure you have:
- Node.js (>= 18.x)
- Docker and Docker Compose
- Ngrok (or an alternative like Cloudflare Tunnel) to expose your local API
- A developer account on Shopify
Setting Up a Public Domain (Ngrok or Alternative)
To receive Shopify webhooks and OAuth callbacks, your local API must be accessible from the internet. Ngrok is recommended for this.
-
Install Ngrok and run:
ngrok http 3000Replace
3000with the port your NestJS app uses if different (e.g.,ngrok http 3333). -
Copy the HTTPS URL generated by ngrok (e.g.,
https://abcd1234.ngrok.io). -
Update your project configuration:
-
In your
.envfile, set:HOST=https://abcd1234.ngrok.io
-
-
You will use this URL in your Shopify app configuration in the next step.
Initial Setup on Shopify
Now that you have a public domain, follow these steps to create and configure your Shopify app:
-
Go to Shopify Partners and log in or create an account.
-
Create a custom app:
- Navigate to Apps β Create app β Custom App.
- Choose a name, for example:
Webhook Orders App.
-
Generate credentials:
- Copy the API Key (Client ID) and API Secret and save them in your
.envfile (see Project Configuration).
- Copy the API Key (Client ID) and API Secret and save them in your
-
Configure your app URLs using the ngrok URL:
-
Set App URL to:
https://abcd1234.ngrok.io/auth/shopify -
Set Redirect URL to:
https://abcd1234.ngrok.io/auth/shopify/redirect
-
-
Create a development store to test your app:
- In the Shopify Partners dashboard, go to Stores β Add store β Create development store.
- Enter a store name and confirm.
-
Install your custom app in the development store:
- In your Shopify Partners dashboard, go to Apps and open your custom app.
- Then go to Distribution and select Custom domain.
- Enter your test store domain (e.g.,
store-name.myshopify.com). - Use the installation link generated by Shopify to install the app into your test store. This link typically looks like:
https://{store-name}.myshopify.com/admin/oauth/authorize?client_id={API_KEY}&scope={SCOPES}&redirect_uri={REDIRECT_URI}- Open this link in your browser and confirm the app installation in your test store.
Tip: You can always update the ngrok URL in Shopify and your
.envfile if you restart ngrok and get a new domain.
Project Configuration
- Create a
.envfile based on.env.example:
# Server Configuration
PORT=3000 # HTTP server port
# Database Connection
DATABASE_HOST=db # e.g., database service name in docker-compose.yml
DATABASE_USER=postgres # your DB username
DATABASE_PASSWORD=postgres # your DB password
DATABASE_PORT=5432 # default PostgreSQL port
DATABASE_NAME=nestshop # your DB name
# Format: postgresql://USER:PASSWORD@DATABASE_HOST:PORT/DATABASE_NAME?schema=public
DATABASE_URL=postgresql://postgres:postgres@db:5432/nestshop?schema=public
# Shopify App Credentials
SHOPIFY_API_KEY=your_api_key_here
SHOPIFY_API_SECRET=your_api_secret_here
SHOPIFY_SCOPES=read_products,write_orders
SHOPIFY_API_VERSION=2025-07 # Shopify API version
# Public App URL (Ngrok or Custom Domain)
HOST=https://your-ngrok-subdomain.ngrok-free.app- (Optional) If you want to view the saved data using Drizzle Studio, create a
.env.studiofile:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/nestshop?schema=publicNote: The URL is similar to the one in
.env, but theDATABASE_HOSTchanges fromdbtolocalhostso Drizzle Studio can connect locally.
Running the Project
You can run the project in two ways: via Docker (recommended for isolated environments) or locally with Node.js and Docker only for the database.
Option 1: Using Docker
Recommended for isolated development environments.
From the project root, run:
docker-compose up --buildThis will build and start both the API and the PostgreSQL database.
To stop containers later:
docker-compose downOption 2: Using Node.js/NPM (Local Development)
- Install dependencies:
npm install- Start the PostgreSQL database container:
docker-compose up -d dbMake sure port 5432 is free on your machine to avoid conflicts. Note:
dbis the service name defined for the database in thedocker-compose.ymlfile. The default port for thedbservice is5432, as it uses PostgreSQL.
- Update your
.envand.env.studioto uselocalhostinDATABASE_URL:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/nestshop?schema=public- Apply database migrations locally:
npm run db:migrate- Run the API server in development mode:
npm run start:devAPI Endpoints
You can explore and test the available API endpoints using the documentation below.
The default base URL is usually one of the following, depending on your setup:
- Local:
http://localhost:3000 - Ngrok:
https://your-ngrok-subdomain.ngrok.io - Custom domain:
https://your-custom-domain.com
Available endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET | /health | Verifies if the API is running properly. |
GET | /auth/shopify | Starts the Shopify OAuth authentication flow. |
GET | /auth/shopify/redirect | Handles the OAuth redirect after authentication. |
POST | /webhooks/orders/create | Receives Shopify order creation webhooks. |
GET | /orders | Retrieves all saved orders with details. |
GET | /orders/:shopDomain | Retrieves all saved orders from a specific Shopify domain. |
Testing the Integration
- Access your test store admin panel:
https://admin.shopify.com/store/your-test-store-name-
Create a product and place an order.
-
Shopify will send order creation webhooks automatically to your public API URL:
POST https://abcd1234.ngrok.io/webhooks/orders/create-
To verify if the webhook was received:
- Check your API logs for webhook request entries.
- Use the
GET /ordersorGET /orders/shopDomainendpoints to confirm the order data is saved.
Supported Webhooks
Currently, this project only listens to:
orders/create: Receives information about new orders placed in the store.
(Optional) Viewing Saved Data in the Database
If you created a .env.studio file and configured the DATABASE_URL for Drizzle Studio, you can view the saved data by running the following command from the project root in a new terminal:
npm run db:studioThen open Drizzle Studio at https://local.drizzle.studio in your browser.
Project Structure
src/
βββ auth/ # OAuth authentication module with Shopify
β βββ dto/ # Data Transfer Objects used by the auth methods
β ...
βββ common/ # Shared code
β βββ dto/ # Reusable DTOs shared across modules (e.g., Shopify Webhooks)
β βββ interceptors/ # Reusable interceptors (e.g., HMAC validation)
β βββ mapper/ # Functions to transform and map external data (e.g., Shopify β DB format)
βββ drizzle/ # Drizzle ORM configuration
β βββ migrations/ # Database migration files
β βββ schema/ # Database table schemas
β βββ types/ # TypeScript types related to the database
β ...
βββ env/ # Environment variable validation using zod
βββ orders/ # View information about orders saved in the system
βββ webhooks/ # Shopify webhooks receiving and handling module
βββ app.module.ts
βββ main.ts
.env
.env.studio
docker-compose.yml
DockerfileNote:
The core flow of the app mainly happens within the auth and webhooks modules, which handle authentication and webhook processing respectively.
Author
Made by Marcos Antonio.
- π» Full Stack developer dedicated to building complete solutions by combining modern, functional user interfaces with robust back-end architectures.
- π Always open to feedback, collaboration, or ideas for improvement!
- π« Feel free to connect with me on LinkedIn or check out more of my projects here on GitHub.