A FastAPI backend for Vedic astrology consultations with Firebase authentication, PostgreSQL, Redis caching, and AI-powered astrology agents. Includes Swiss Ephemeris data for precise calculations and Google Play webhook-based billing for credits/subscriptions.
- FastAPI framework with automatic OpenAPI documentation (when
DEBUG=True) - Firebase Authentication integration
- PostgreSQL with SQLAlchemy ORM and Alembic migrations
- Redis caching for performance
- AI-powered astrology agents (OpenAI)
- Swiss Ephemeris-based calculations (via
jhora) - Real-time chat with Server-Sent Events (SSE)
- Partners & Compatibility (Ashtakoota) with friendship mode
- Google Play Billing (webhook-based) for credits/subscriptions
- Clean architecture (routers, models, schemas, CRUD)
- Python 3.9+
- Docker and Docker Compose (optional, recommended)
- Firebase project with Authentication enabled
- Firebase service account key (server-side Admin SDK)
- OpenAI API key
- Optional: Tavily API key (web search)
git clone <repository-url>
cd <repository-directory>/backend- Create a project in Firebase Console (
https://console.firebase.google.com) - Enable Authentication
- Generate a service account key (Project Settings → Service Accounts → Generate New Private Key)
- Save the JSON as
backend/firebase-service-account.json
Create a .env file (or export in your shell) with at least:
- Firebase:
FIREBASE_PROJECT_IDFIREBASE_SERVICE_ACCOUNT_JSON=./firebase-service-account.json(local) or/app/firebase-service-account.json(in container)- Optionally
GOOGLE_APPLICATION_CREDENTIALSif you prefer ADC
- AI/LLM:
OPENAI_API_KEYTAVILY_API_KEY(optional)
- Database & Cache:
- Either
DATABASE_URLorDB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_NAME REDIS_HOST,REDIS_PORT
- Either
- App:
DEBUG(enable docs whenTrue)CORS_ORIGINS(JSON array, e.g.,["*"]for local dev)SE_EPHE_PATH(e.g.,/app/ephe)
- Email/Support (Mailgun or logging):
EMAIL_PROVIDER=mailgun|logging- If
mailgun:MAILGUN_API_KEY,MAILGUN_DOMAIN,MAILGUN_BASE_URL(optional) - Common:
EMAIL_FROM,EMAIL_FROM_NAME,SUPPORT_TO_EMAIL,SUPPORT_BCC_EMAIL(optional)
- Google Play:
GOOGLE_PLAY_PACKAGE_NAMEGOOGLE_PLAY_SERVICE_ACCOUNT_JSON=./purchase-service-account.json(local) or container path
pip install -r requirements.txtuvicorn app.main:app --reload- API:
http://localhost:8000 - Docs:
http://localhost:8000/docs(whenDEBUG=True)
For a complete setup with PostgreSQL and Redis:
- Ensure
backend/firebase-service-account.jsonexists - Provide required env vars in your shell (or a
.envfile loaded by your shell) - Start services:
docker-compose up -d
- API:
http://localhost:8000 - Logs:
docker-compose logs -f - Stop:
docker-compose down
Alembic migrations are included and applied automatically by the container entrypoint.
- Create new migrations by adding a file under
migrations/versionsnamedv{N}_{description}.py - Run manually if needed:
docker exec -it backend-api alembic upgrade head
Webhook-first integration using Real-time Developer Notifications via Pub/Sub.
- Frontend must set
obfuscatedExternalAccountIdduring purchase via BillingFlowParams - Backend identifies user from notifications and updates credits/subscriptions accordingly
Endpoints:
POST /payments/google-play— Pub/Sub webhook endpoint (returns 200 quickly, processes in background)POST /payments/google-play/verify— Client-side verification after purchase; also processes pending events
Benefits:
- No service account or Console API calls required for core flows
- Real-time, reliable purchase processing and refund handling
Setup:
- Create a Pub/Sub topic and subscription
- Configure Google Play to send RTDN to the Pub/Sub topic
- Point your push subscription/webhook to
/payments/google-play - Frontend must set user ID during purchase (see example below)
Android example:
val billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setObfuscatedAccountId(currentUserId) // Firebase user ID
.build()
billingClient.launchBillingFlow(activity, billingFlowParams)GET /— WelcomeGET /health— Health checkGET /public— Public test routeGET /protected— Protected test route (requires Firebase auth)
Include Firebase ID token:
Authorization: Bearer <firebase-id-token>
GET /users/me— Current user infoPATCH /users/me— Update userGET /users/check-username?username=<name>— Check availabilityGET /users/search-username?username_pattern=<q>&limit=10— Search users
GET /users/me/messages— List my messages (latest first, paginated)GET /users/me/threads/{thread_id}/messages— Messages in a threadGET /users/me/daily-facts?day=yesterday|today|tomorrow|all— Daily facts (cached until next IST day)POST /users/me/charts— Get divisional charts by names (e.g.,["D1","D9"])GET /users/me/life-events— Significant life events (cached 24h)GET /users/me/compatibility/{partner_id}?compatibility_type=love|friendship— User ↔ Partner analysisGET /users/me/compatibility-with-user/{other_user_id}?compatibility_type=love|friendship— User ↔ Another user (friends only)GET /users/me/compatibility-reports— All saved compatibility reports
POST /partners— Create partner (returnsmoon_sign)GET /users/me/partners— My partnersGET /partners/{partner_id}— Partner details (withmoon_sign)DELETE /partners/{partner_id}— Delete partner
GET /users/me/threads— List my threads (paginated)POST /users/me/threads— Create thread (max 1 additional participant; optionalcompatibility_type)GET /users/me/threads/{thread_id}— Get threadPATCH /users/me/threads/{thread_id}— Update title/participants (compatibility_typeallowed only with exactly one participant)DELETE /users/me/threads/{thread_id}— Delete thread
-
GET /chat/stream— Stream responses- Query params:
message, optionalthread_id, optionalparticipant_user_ids(CSV), optionalparticipant_partner_ids(CSV) - Deducts 1 credit per request; validates ownership/friendship/participants
- Query params:
-
GET /chat/suggestions— Follow-up question suggestions based on last assistant answer (requiresthread_id)
GET /credits/balance— Current user credit balance
POST /friends/request— Send request by recipient username (requires you to have a username)POST /friends/request/{request_id}/accept— Accept requestPOST /friends/request/{request_id}/reject— Reject requestDELETE /friends/request/{request_id}— Cancel sent requestGET /friends/requests— Incoming requests (paginated)GET /friends/requests/sent— Sent requests (paginated)GET /friends/list— Friends list with optional username/display_name searchDELETE /friends/{friend_username}— Remove a friend
POST /payments/google-play— Pub/Sub webhookPOST /payments/google-play/verify— Verify purchase and grant entitlements
POST /devices/register— Register or update device token (FCM)DELETE /devices/unregister— Remove device tokenPOST /devices/heartbeat— Update device heartbeatGET /devices— List my device tokens
POST /support/help-email— Send a help email to support (rate limited)
GET /streaks/me— Get my streak info (subscription can protect streak)
POST /rants/— Submit a rant and receive a therapeutic response (updates streak if valid)
- Precise planetary positions
- Divisional charts (Vargas): D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D16, D20, D24, D27, D30, D40, D45, D60
- Panchanga: Tithi, Nakshatra, Yoga, Karana, Vara
- Special Lagnas: Hora, Ghati, Vighati, etc.
- Yogas: Raja, Dhana, and others
- Dashas: Vimsottari and more
- Transit analysis
- Daily facts: cached until next IST day
- Compatibility: cached until data changes
- Chart calculations: cached to reduce computation
- Redis persistence via Docker volume
- User signs in via Firebase (client)
- Client receives Firebase ID token
- Include token in headers:
Authorization: Bearer <firebase-id-token> - Backend validates token and loads user
backend/
├── app/
│ ├── agents/
│ ├── crud/
│ ├── llm/
│ ├── models/
│ ├── routers/
│ │ ├── api.py
│ │ ├── users.py
│ │ ├── partners.py
│ │ ├── chat.py
│ │ ├── payments.py
│ │ ├── friends.py
│ │ ├── credits.py
│ │ ├── streaks.py
│ │ ├── devices.py
│ │ ├── support.py
│ │ └── rants.py
│ ├── schemas/
│ ├── utils/
│ ├── auth.py
│ ├── cache.py
│ ├── config.py
│ ├── database.py
│ └── main.py
├── jhora/
├── ephe/
├── migrations/
├── deployment/
├── docker-compose.yaml
├── Dockerfile
└── requirements.txt
- Extend astrology tools in
app/agents/tools.py - Update agent prompts in
app/agents/prompts.py - Add schemas in
app/llm/schemas.pyas needed - Create API routes under
app/routers - Add models when persistence is required
- Unit tests for calculations (add under
tests/as needed) - Integration tests for API endpoints
- End-to-end checks for chat streaming and payments webhook
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
MIT License - see LICENSE file for details.
- Open issues on GitHub
- Check OpenAPI docs at
/docs(whenDEBUG=True) - See
jhora/README.mdfor astrology calculation details