Inbify Backend
AI-powered email management platform with multi-provider support, smart classification, and subscription-based feature gating.
System Architecture
Multi-layered architecture with provider-agnostic email handling and background processing.
Tech Stack
Core dependencies and frameworks powering the backend.
Core framework with custom user model, UUID primary keys, and modular app structure.
JWT access + refresh tokens with blacklisting, 60-min access / 7-day refresh lifetime.
Anthropic's Claude Haiku 4.5 for email classification, summaries, and smart reply generation.
Full Gmail integration via google-api-python-client with OAuth2, sync, send, and status management.
Outlook integration via Graph API v1.0 with direct HTTP requests and auto token refresh.
Primary datastore with indexed queries on account + received_at, category, read status, and starred.
Authentication Flow
JWT-based authentication with token refresh and blacklisting.
State parameter carries the JWT token so the callback can identify the user without a session.
Email Sync Flow
Non-blocking background sync with automatic AI classification.
Fetches ALL emails from inbox (metadata only, body lazy-loaded). Paginates through all available messages using nextPageToken.
Fetches recent emails and stops when it hits 10 already-known emails in a row. Only new/unread emails get AI classified.
AI Classification Flow
Smart classification that only processes what matters — saving tokens and cost.
Only unread emails are classified automatically. Old read emails stay as "other" to save AI tokens.
When a user opens an old unclassified email, it gets classified on-demand (counts toward monthly limit).
Users can POST /reclassify/ to batch-classify older emails on demand.
10 Email Categories
Data Model
Entity-relationship diagram showing all models and their connections.
Authentication Endpoints
User registration, login, and profile management with JWT tokens.
Register a new user. Returns user data with JWT access + refresh tokens.
{
"email": "user@example.com",
"full_name": "John Doe",
"password": "securePass123",
"password_confirm": "securePass123"
}
Returns JWT tokens and full user data including subscription info.
// Request
{ "email": "user@example.com", "password": "securePass123" }
// Response
{
"access": "eyJ...",
"refresh": "eyJ...",
"user": { "id": "uuid", "email": "...", "full_name": "..." }
}
{ "refresh": "eyJ..." }
// Request: { "refresh": "eyJ..." }
// Response: { "access": "eyJ...", "refresh": "eyJ..." }
Returns user profile: id, email, full_name, avatar, onboarding_completed.
{ "full_name": "New Name" }{ "old_password": "...", "new_password": "..." }Returns user + subscription + all email accounts + 20 recent emails. Also triggers background sync for stale accounts (>5 min old).
Email Endpoints
Core email operations: list, detail, update, bulk actions, sync, and classification.
Paginated email list with cached counts and classification status. Supports filtering by category, priority, is_read, is_starred, and full-text search.
Query params: ?category=work &is_read=false &search=invoice &ordering=-received_at &page=1
{
"count": 500,
"next": "...?page=2",
"results": [ { "id": "uuid", "subject": "...", "category": "work", ... } ],
"total_emails": 500,
"unread_count": 45,
"needs_reply_count": 12,
"starred_count": 8,
"category_counts": { "work": 30, "personal": 20, "newsletters": 15 },
"classification": {
"total_classified": 450,
"remaining_unclassified": 50,
"is_classifying": false,
"classify_limit": 500,
"ai_classifications_remaining": 3994,
"hit_limit": false,
"plan": "pro"
}
}
Returns full email detail. On first access: lazy-loads body from provider, auto-marks as read, and classifies old unclassified emails on-demand via AI.
Update read/starred/archived/deleted status. Changes are synced to the email provider (Gmail/Outlook).
{ "is_read": true, "is_starred": false }
Apply actions to multiple emails at once. All changes sync to provider.
// Actions: read, unread, star, unstar, archive, delete
{ "ids": ["uuid1", "uuid2"], "action": "read" }
Returns sync/classification status for all connected accounts. Frontend can poll this.
[{
"account_id": "uuid",
"email": "user@gmail.com",
"is_syncing": false,
"is_classifying": true,
"last_synced_at": "2026-04-14T10:30:00Z",
"total_emails": 500,
"unread_count": 45,
"unclassified_count": 12
}]
Re-run AI classification on unclassified emails. Respects the subscription's monthly AI limit.
// Optional body
{ "account_id": "uuid", "limit": 100 }
Returns 3 AI-generated reply suggestions (short, detailed, action). Available on all plans.
// GET /emails/{id}/smart-reply/?tone=professional
{
"email_id": "uuid",
"subject": "Project Update",
"sender": "boss@company.com",
"suggestions": [
{ "type": "short", "text": "Thanks for the update..." },
{ "type": "detailed", "text": "Thank you for sharing..." },
{ "type": "action", "text": "I'll review the report..." }
]
}
Compose & Reply
Send new emails and manage conversations through connected providers.
{
"account_id": "uuid",
"to": ["recipient@example.com"],
"cc": ["cc@example.com"],
"subject": "Hello",
"body_html": "<p>Hello world</p>",
"body_text": "Hello world"
}
{ "body_html": "<p>Thanks!</p>" }{ "body_html": "<p>Noted, thanks all!</p>" }{ "to": ["forward@example.com"], "body_html": "FYI..." }Provider OAuth & Sync
Connect Gmail and Outlook accounts via OAuth, then trigger background syncs.
Scopes: gmail.readonly, gmail.modify, gmail.send, userinfo.email, userinfo.profile
Scopes: openid, profile, email, offline_access, Mail.Read, Mail.ReadWrite, Mail.Send
Pass ?state=JWT_TOKEN so the callback identifies the user.
Google redirects here. Exchanges code for tokens, creates EmailAccount, returns a styled HTML page with success/error state and auto-close countdown.
Same pattern as Gmail connect.
Microsoft redirects here. Same flow as Gmail callback.
Starts a background thread that syncs emails then triggers AI classification on new unread emails.
Same as Gmail sync, routes through provider_service dispatch layer.
Returns all active EmailAccount objects with cached counts and sync status.
Hard-deletes the account and all its emails.
Subscription Endpoints
Manage plans and view usage. Payment integration ready for Stripe.
Returns all 4 plans with features, limits, and pricing. No auth required.
Returns the user's current subscription with usage tracking. Auto-creates Free if none exists.
{
"id": "uuid",
"plan": { "name": "pro", "max_ai_classifications_per_month": 5000, ... },
"status": "active",
"billing_cycle": "monthly",
"ai_classifications_used": 1006,
"ai_classifications_limit": 5000,
"ai_classifications_remaining": 3994,
"can_connect_account": true
}
{ "plan": "pro", "billing_cycle": "yearly" }
Resets AI usage on upgrade. Checks lifetime plan cap (1000 slots).
Cancels current subscription and downgrades to Free plan.
Analytics Endpoints
Email insights and productivity metrics. Full analysis is Pro/Lifetime only.
{ "total_emails": 500, "unread": 45, "ai_sorted": 450,
"action_required": 12, "by_category": {...}, "recent_unread_7d": 30 }
Deep analysis including: category breakdown, priority distribution, productivity metrics, time-saved estimates, weekly trends, top senders, daily activity heatmap, and peak hours.
Query param: ?days=30 (default 30)
Returns non-dismissed AI insights (tips, alerts, summaries).
Marks the insight as dismissed so it no longer appears.
Subscription Plans
4-tier model with monthly AI classification limits and feature gating.
- ✓ 1 email account
- ✓ 100 AI classifications/mo
- ✓ Smart reply
- ✓ Urgent reminders
- ✕ AI summaries
- ✕ Advanced analytics
- ✕ Priority support
- ✓ 3 email accounts
- ✓ 1,000 AI classifications/mo
- ✓ Smart reply
- ✓ AI summaries
- ✓ Urgent reminders
- ✓ Advanced analytics
- ✕ Priority support
- ✓ 10 email accounts
- ✓ 5,000 AI classifications/mo
- ✓ Smart reply
- ✓ AI summaries
- ✓ Advanced analytics
- ✓ Priority support
- ✓ Future features
- ✓ 5 email accounts
- ✓ 2,000 AI classifications/mo
- ✓ Smart reply
- ✓ AI summaries
- ✓ Advanced analytics
- ✓ Limited to 1,000 slots
- ✓ One-time payment
Feature Gating Matrix
| Feature | Free | Basic | Pro | Lifetime |
|---|---|---|---|---|
| AI Classification | 100/mo | 1,000/mo | 5,000/mo | 2,000/mo |
| Email Accounts | 1 | 3 | 10 | 5 |
| AI Sorting | ✓ | ✓ | ✓ | ✓ |
| Smart Reply | ✓ | ✓ | ✓ | ✓ |
| AI Summaries | ✕ | ✓ | ✓ | ✓ |
| Advanced Analytics | ✕ | ✓ | ✓ | ✓ |
| Priority Support | ✕ | ✕ | ✓ | ✓ |
| Future Features | ✕ | ✕ | ✓ | ✓ |
| Urgent Reminders | ✓ | ✓ | ✓ | ✓ |
| Monthly Price | $0 | $4.99 | $12.99 | $179.99 once |
| Yearly Price | $0 | $49.99 | $129.99 | — |
AI Classification Engine
Dual-mode classification with AI-first approach and rule-based fallback.
Processes emails in batches of 10. Returns category, priority, action_required, and a 20-word summary for each email. Costs ~1 AI credit per email.
Uses domain keywords, subject regex patterns, and sender analysis. Activates automatically when AI is unavailable or returns "other".
Classification Output
{
"category": "work", // 1 of 10 categories
"action_required": true, // Does sender expect a reply?
"priority": "high", // low | medium | high
"summary": "Manager requesting project status update by Friday"
}
Smart Reply
AI-generated reply suggestions with customizable tone. Available on all plans.
Generates 3 reply suggestions per email using Claude Haiku, considering thread context (up to 5 emails). Supports tones: professional, casual, friendly, formal.
// Suggestion types returned: 1. "short" — Brief 1-2 sentence reply 2. "detailed" — Thorough 3-4 sentence reply 3. "action" — Reply confirming action or next steps
Performance: Lazy Loading
Email bodies are fetched on-demand to dramatically reduce sync time and bandwidth.
EmailAccount stores pre-computed counts (total, unread, starred, needs_reply, category_counts) that refresh after sync and state changes. No expensive COUNT queries on every list request.
Sync and classification run as daemon threads. API responds immediately with cached data while heavy work happens in the background.
Environment Configuration
Required environment variables in .env file.
| Variable | Description | Example |
|---|---|---|
| SECRET_KEY | Django secret key | your-secret-key |
| DEBUG | Debug mode | True |
| DATABASE_URL | PostgreSQL connection | postgres://user:pass@postgres_db/inbify |
| GOOGLE_CLIENT_ID | Google OAuth client ID | xxx.apps.googleusercontent.com |
| GOOGLE_CLIENT_SECRET | Google OAuth secret | GOCSPX-xxx |
| GOOGLE_REDIRECT_URI | Gmail callback URL | https://inbifymail.com/api/v1/emails/callback/gmail/ |
| MICROSOFT_CLIENT_ID | Azure app client ID | a701abb6-xxx |
| MICROSOFT_CLIENT_SECRET | Azure app secret value | V6N8Q~xxx |
| MICROSOFT_REDIRECT_URI | Outlook callback URL | https://inbifymail.com/api/v1/emails/callback/outlook/ |
| ANTHROPIC_API_KEY | Anthropic API key | sk-ant-xxx |
| AI_CLASSIFY_LIMIT | Max emails per classification batch | 500 |
| ACCESS_TOKEN_LIFETIME | JWT access token lifetime (minutes) | 60 |
| REFRESH_TOKEN_LIFETIME | JWT refresh token lifetime (days) | 7 |
| CORS_ALLOWED_ORIGINS | Allowed CORS origins | https://inbifymail.com |
Inbify Backend Documentation — Built with Django REST Framework
Base URL: https://inbifymail.com/api/v1/ ·
Swagger: swagger.yaml