Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AndrewwCO/Panahashi-Backend/llms.txt

Use this file to discover all available pages before exploring further.

This guide takes you from a fresh clone to a running Panahashi Backend server with a verified API call. You will configure Firebase, start the Ktor server on port 8080, and authenticate your first request using a real Firebase ID token.

Prerequisites

Before you begin, make sure you have the following installed and ready:
  • JDK 17 or later — the server targets JVM 17. Run java -version to check.
  • Gradle 8 or later — the project ships with the Gradle wrapper, so a global install is optional.
  • A Firebase project — you need owner or editor access to create a service account and enable services.
  • Git — to clone the repository.

Setup steps

1

Clone the repository

Clone the Panahashi Backend source to your machine:
git clone https://github.com/AndrewwCO/Panahashi-Backend.git
cd Panahashi-Backend
The project root contains build.gradle.kts, gradlew, and the src/ directory with the Ktor application.
2

Create and configure your Firebase project

Panahashi Backend relies on four Firebase services. Enable all of them before running the server.
  1. Open the Firebase Console and create a new project (or use an existing one).
  2. Firestore — go to Build → Firestore Database and create a database in production mode. Choose the region closest to your users.
  3. Authentication — go to Build → Authentication → Sign-in method and enable at least one provider. Email/Password and Google are recommended for testing.
  4. Storage — go to Build → Storage and set up the default bucket. The backend defaults to the bucket name panahashi.appspot.com; set FIREBASE_STORAGE_BUCKET if your bucket name differs.
  5. Cloud Messaging (FCM) — FCM is enabled automatically for every Firebase project. No extra steps are needed.
The Firestore security rules you configure for client SDKs do not affect server-side Admin SDK calls. The Firebase Admin SDK bypasses client-facing rules and uses your service account’s IAM permissions instead.
3

Download and place your service account key

The server authenticates to Firebase using a service account JSON key.
  1. In the Firebase Console, go to Project Settings → Service accounts.
  2. Click Generate new private key and confirm. A JSON file downloads to your machine.
  3. Rename the file to serviceAccountKey.json and place it in the project root (the same directory as build.gradle.kts):
Panahashi-Backend/
├── build.gradle.kts
├── serviceAccountKey.json   ← place it here
├── gradlew
└── src/
Never commit serviceAccountKey.json to version control. It grants admin access to your entire Firebase project. Add it to .gitignore immediately:
echo "serviceAccountKey.json" >> .gitignore
Alternatively, point the GOOGLE_APPLICATION_CREDENTIALS environment variable at the file path, or set FIREBASE_SERVICE_ACCOUNT_PATH to override the config default. The server falls back to Application Default Credentials when no file is found.
4

Set up Firestore collections

The backend reads and writes to these Firestore collections. You can let the server create them on first write, or initialize them manually in the Firebase Console by adding a placeholder document to each.
CollectionPurpose
usersUser profiles with roles and FCM tokens
bakeriesBakery storefronts and metadata
productsProducts belonging to bakeries
ordersCustomer orders and their lifecycle status
reviewsCustomer reviews scoped to bakeries
favoritesPer-user favorited bakeries
cartsActive shopping carts
promotionsDiscount promotions scoped to bakeries
loyaltyStamp card records per user per bakery
paymentsPayment records linked to orders
Create collections in the Firebase Console by adding a document with a placeholder field, then deleting the placeholder. This is useful if you want to configure indexes or composite query rules before the first server write.
5

Run the server

Start the Ktor server using the Gradle wrapper. No configuration files need editing if you placed serviceAccountKey.json in the project root:
./gradlew run
On the first run, Gradle downloads all dependencies — Ktor 3.1.3, Firebase Admin SDK 9.4.2, and others. Subsequent runs are faster.When the server is ready, you will see output similar to:
2026-05-19 10:00:00.000 [main] INFO  Application - Responding at http://0.0.0.0:8080
The server binds to 0.0.0.0:8080 by default. Override the port with the PORT environment variable:
PORT=9000 ./gradlew run
6

Check the health endpoint

Verify the server is running by calling the public health endpoint — no authentication required:
curl http://localhost:8080/health
Expected response:
{
  "status": "ok",
  "service": "panahashi-backend",
  "version": "1.0.0"
}
If you get a connection error, check that the Gradle build finished without errors and that no other process is using port 8080.
7

Get a Firebase ID token

Protected API endpoints require a Firebase ID token in the Authorization header. Obtain one from a Firebase-connected client application.The examples below show two approaches — the Firebase JavaScript SDK for web apps, and the Firebase Admin SDK for server-to-server testing:
import { initializeApp } from "firebase/app";
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";

const app = initializeApp({
  apiKey: "YOUR_WEB_API_KEY",
  authDomain: "YOUR_PROJECT.firebaseapp.com",
  projectId: "YOUR_PROJECT_ID",
});

const auth = getAuth(app);

// Sign in an existing user
const { user } = await signInWithEmailAndPassword(
  auth,
  "user@example.com",
  "password123"
);

// Retrieve the ID token — expires after 1 hour
const idToken = await user.getIdToken();
console.log("ID token:", idToken);
Firebase ID tokens expire after 1 hour. See the Authentication guide for details on refreshing tokens automatically.
8

Make your first authenticated API call

With your ID token, call a protected endpoint. GET /api/v1/users/me returns the profile for the authenticated user:
curl -X GET http://localhost:8080/api/v1/users/me \
  -H "Authorization: Bearer YOUR_FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json"
A successful 200 response returns the user’s profile:
{
  "uid": "abc123xyz",
  "displayName": "Jane Baker",
  "email": "jane@example.com",
  "phone": "+1234567890",
  "role": "CUSTOMER",
  "bakeryId": null,
  "fcmToken": null,
  "createdAt": "2026-05-19T10:00:00Z"
}
If you receive a 401 Unauthorized response, your token has likely expired or was formatted incorrectly. Confirm the Authorization header starts with Bearer (including the trailing space) followed by the raw token string.

What’s next

Now that your server is running and you have made your first authenticated call, explore the rest of the documentation.

Authentication

Understand token lifecycle, refresh strategies, and which endpoints require authentication.

API reference

Browse every endpoint grouped by resource — bakeries, orders, users, and more.

Roles & permissions

Learn how the CUSTOMER, BAKER, and ADMIN roles control access across the API.

Build docs developers (and LLMs) love