Django REST Framework

Inbify Backend

AI-powered email management platform with multi-provider support, smart classification, and subscription-based feature gating.

40+
API Endpoints
4
Subscription Tiers
2
Email Providers
10
AI Categories

System Architecture

Multi-layered architecture with provider-agnostic email handling and background processing.

Client Layer
Flutter Mobile App
Web Dashboard
Admin Panel
API Layer — Django REST Framework
JWT Auth
Email Views
Subscription Views
Analytics Views
User Views
Service Layer
Provider Dispatch
Gmail Service
Outlook Service
AI Classifier
Background Threads
External Services
Gmail API
Microsoft Graph API
Anthropic Claude API
PostgreSQL

Tech Stack

Core dependencies and frameworks powering the backend.

Django 4.2
Web Framework

Core framework with custom user model, UUID primary keys, and modular app structure.

🔒
SimpleJWT
Authentication

JWT access + refresh tokens with blacklisting, 60-min access / 7-day refresh lifetime.

🤖
Claude Haiku
AI Classification

Anthropic's Claude Haiku 4.5 for email classification, summaries, and smart reply generation.

📧
Gmail API
Email Provider

Full Gmail integration via google-api-python-client with OAuth2, sync, send, and status management.

📩
Microsoft Graph
Email Provider

Outlook integration via Graph API v1.0 with direct HTTP requests and auto token refresh.

🗃
PostgreSQL
Database

Primary datastore with indexed queries on account + received_at, category, read status, and starred.

Authentication Flow

JWT-based authentication with token refresh and blacklisting.

User Authentication Lifecycle
Register / Login
JWT Access + Refresh
API Requests (Bearer)
Token Expires (60m)
Refresh Token
OAuth Provider Connection
Frontend
GET /connect/gmail/
Google Consent
GET /callback/gmail/
Account Created

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.

Sync → Classify Pipeline
POST /sync/gmail/
Background Thread
Fetch Metadata
Save Emails
Classify Unread
Refresh Counts
First Sync

Fetches ALL emails from inbox (metadata only, body lazy-loaded). Paginates through all available messages using nextPageToken.

🔄
Subsequent Syncs

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.

Classification Strategy
① After Sync

Only unread emails are classified automatically. Old read emails stay as "other" to save AI tokens.

② On Detail View

When a user opens an old unclassified email, it gets classified on-demand (counts toward monthly limit).

③ Manual Trigger

Users can POST /reclassify/ to batch-classify older emails on demand.

AI Pipeline (per batch of 10 emails)
Email Batch
Claude Haiku
Parse JSON
Save Results
Email Batch
AI Fails
Rule-Based Fallback
Save Results

10 Email Categories

work personal newsletters bills ads receipts updates social spam other

Data Model

Entity-relationship diagram showing all models and their connections.

Relationships
User1:NEmailAccount
EmailAccount1:NEmail
EmailN:NLabel
Email1:NAttachment
User1:1Subscription
SubscriptionN:1Plan
User1:NDailyEmailStat
User1:NAIInsight
User
idUUID PK
emailEmailField
full_nameCharField
avatarImageField
is_activeBoolean
onboarding_completedBoolean
EmailAccount
idUUID PK
userFK → User
providergmail|outlook
email_addressEmailField
is_syncingBoolean
is_classifyingBoolean
cached_*_countInteger
access_tokenTextField
refresh_tokenTextField
Email
idUUID PK
accountFK → EmailAccount
message_idCharField
subjectCharField
sender_emailEmailField
category10 choices
prioritylow|med|high
ai_summaryTextField
body_fetchedBoolean
Plan
idUUID PK
namefree|basic|pro|lifetime
max_accountsInteger
max_ai_per_monthInteger
ai_summariesBoolean
smart_replyBoolean
advanced_analyticsBoolean
featuresJSONField
Subscription
idUUID PK
user1:1 → User
planFK → Plan
statusactive|cancelled|...
billing_cyclemonthly|yearly|lifetime
ai_classifications_usedInteger
ai_usage_reset_atDateTime
Label & Attachment
Label.idUUID PK
Label.nameCharField
Label.color#hex
Attachment.idUUID PK
Attachment.filenameCharField
Attachment.size_bytesInteger

Authentication Endpoints

User registration, login, and profile management with JWT tokens.

POST /api/v1/auth/register/ Create a new user account Public

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"
}
POST /api/v1/auth/login/ Login with email & password Public

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": "..." }
}
POST /api/v1/auth/logout/ Blacklist refresh token Auth
{ "refresh": "eyJ..." }
POST /api/v1/auth/token/refresh/ Refresh access token Public
// Request:  { "refresh": "eyJ..." }
// Response: { "access": "eyJ...", "refresh": "eyJ..." }
GET /api/v1/auth/me/ Get current user profile Auth

Returns user profile: id, email, full_name, avatar, onboarding_completed.

PATCH /api/v1/auth/me/ Update user profile Auth
{ "full_name": "New Name" }
POST /api/v1/auth/me/change-password/ Change password Auth
{ "old_password": "...", "new_password": "..." }
GET /api/v1/auth/me/dashboard/ Full dashboard data Auth

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.

GET /api/v1/emails/ List emails (paginated, filterable) Auth

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"
  }
}
GET /api/v1/emails/{id}/ Email detail (lazy-load, classify, mark read) Auth

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.

PATCH /api/v1/emails/{id}/ Update email state Auth

Update read/starred/archived/deleted status. Changes are synced to the email provider (Gmail/Outlook).

{ "is_read": true, "is_starred": false }
POST /api/v1/emails/bulk/ Bulk email actions Auth

Apply actions to multiple emails at once. All changes sync to provider.

// Actions: read, unread, star, unstar, archive, delete
{ "ids": ["uuid1", "uuid2"], "action": "read" }
GET /api/v1/emails/sync-status/ Sync & classification status Auth

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
}]
POST /api/v1/emails/reclassify/ Manual AI reclassification Auth

Re-run AI classification on unclassified emails. Respects the subscription's monthly AI limit.

// Optional body
{ "account_id": "uuid", "limit": 100 }
GET /api/v1/emails/{id}/smart-reply/ AI-generated reply suggestions Auth

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.

POST /api/v1/emails/compose/ Send a new email Auth
{
  "account_id": "uuid",
  "to": ["recipient@example.com"],
  "cc": ["cc@example.com"],
  "subject": "Hello",
  "body_html": "<p>Hello world</p>",
  "body_text": "Hello world"
}
POST /api/v1/emails/{id}/reply/ Reply to sender Auth
{ "body_html": "<p>Thanks!</p>" }
POST /api/v1/emails/{id}/reply-all/ Reply to all recipients Auth
{ "body_html": "<p>Noted, thanks all!</p>" }
POST /api/v1/emails/{id}/forward/ Forward email Auth
{ "to": ["forward@example.com"], "body_html": "FYI..." }

Provider OAuth & Sync

Connect Gmail and Outlook accounts via OAuth, then trigger background syncs.

G
Gmail
Google OAuth 2.0

Scopes: gmail.readonly, gmail.modify, gmail.send, userinfo.email, userinfo.profile

O
Outlook
Microsoft Graph

Scopes: openid, profile, email, offline_access, Mail.Read, Mail.ReadWrite, Mail.Send

GET /api/v1/emails/connect/gmail/ Get Gmail OAuth URL Auth

Pass ?state=JWT_TOKEN so the callback identifies the user.

GET /api/v1/emails/callback/gmail/ Gmail OAuth callback (HTML page) Public

Google redirects here. Exchanges code for tokens, creates EmailAccount, returns a styled HTML page with success/error state and auto-close countdown.

GET /api/v1/emails/connect/outlook/ Get Outlook OAuth URL Auth

Same pattern as Gmail connect.

GET /api/v1/emails/callback/outlook/ Outlook OAuth callback (HTML page) Public

Microsoft redirects here. Same flow as Gmail callback.

POST /api/v1/emails/sync/gmail/{id}/ Trigger Gmail sync Auth

Starts a background thread that syncs emails then triggers AI classification on new unread emails.

POST /api/v1/emails/sync/outlook/{id}/ Trigger Outlook sync Auth

Same as Gmail sync, routes through provider_service dispatch layer.

GET /api/v1/emails/accounts/ List connected accounts Auth

Returns all active EmailAccount objects with cached counts and sync status.

DELETE /api/v1/emails/accounts/{id}/ Disconnect account Auth

Hard-deletes the account and all its emails.

Subscription Endpoints

Manage plans and view usage. Payment integration ready for Stripe.

GET /api/v1/subscriptions/plans/ List all plans Public

Returns all 4 plans with features, limits, and pricing. No auth required.

GET /api/v1/subscriptions/my/ Get my subscription Auth

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
}
POST /api/v1/subscriptions/change/ Change plan Auth
{ "plan": "pro", "billing_cycle": "yearly" }

Resets AI usage on upgrade. Checks lifetime plan cap (1000 slots).

POST /api/v1/subscriptions/cancel/ Cancel subscription Auth

Cancels current subscription and downgrades to Free plan.

Analytics Endpoints

Email insights and productivity metrics. Full analysis is Pro/Lifetime only.

GET /api/v1/analytics/summary/ Quick stats overview Auth
{ "total_emails": 500, "unread": 45, "ai_sorted": 450,
  "action_required": 12, "by_category": {...}, "recent_unread_7d": 30 }
GET /api/v1/analytics/full-analysis/ Comprehensive analytics Pro+

Deep analysis including: category breakdown, priority distribution, productivity metrics, time-saved estimates, weekly trends, top senders, daily activity heatmap, and peak hours.

GET /api/v1/analytics/daily/ Daily statistics Auth

Query param: ?days=30 (default 30)

GET /api/v1/analytics/insights/ AI-generated insights Auth

Returns non-dismissed AI insights (tips, alerts, summaries).

POST /api/v1/analytics/insights/{id}/dismiss/ Dismiss an insight Auth

Marks the insight as dismissed so it no longer appears.

Subscription Plans

4-tier model with monthly AI classification limits and feature gating.

Free
$0/forever
  • 1 email account
  • 100 AI classifications/mo
  • Smart reply
  • Urgent reminders
  • AI summaries
  • Advanced analytics
  • Priority support
Basic
$4.99/mo
  • 3 email accounts
  • 1,000 AI classifications/mo
  • Smart reply
  • AI summaries
  • Urgent reminders
  • Advanced analytics
  • Priority support
Lifetime
$179.99/once
  • 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 Classification100/mo1,000/mo5,000/mo2,000/mo
Email Accounts13105
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.

AI
Claude Haiku 4.5
Primary Classifier

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.

Rule-Based Fallback
Zero-Cost Backup

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.

Lazy Body Loading Flow
Sync (metadata only)
body_fetched = false
User opens email
Fetch full body
body_fetched = true
Cached Counts

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.

📌
Background Threads

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_KEYDjango secret keyyour-secret-key
DEBUGDebug modeTrue
DATABASE_URLPostgreSQL connectionpostgres://user:pass@postgres_db/inbify
GOOGLE_CLIENT_IDGoogle OAuth client IDxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRETGoogle OAuth secretGOCSPX-xxx
GOOGLE_REDIRECT_URIGmail callback URLhttps://inbifymail.com/api/v1/emails/callback/gmail/
MICROSOFT_CLIENT_IDAzure app client IDa701abb6-xxx
MICROSOFT_CLIENT_SECRETAzure app secret valueV6N8Q~xxx
MICROSOFT_REDIRECT_URIOutlook callback URLhttps://inbifymail.com/api/v1/emails/callback/outlook/
ANTHROPIC_API_KEYAnthropic API keysk-ant-xxx
AI_CLASSIFY_LIMITMax emails per classification batch500
ACCESS_TOKEN_LIFETIMEJWT access token lifetime (minutes)60
REFRESH_TOKEN_LIFETIMEJWT refresh token lifetime (days)7
CORS_ALLOWED_ORIGINSAllowed CORS originshttps://inbifymail.com

Inbify Backend Documentation — Built with Django REST Framework

Base URL: https://inbifymail.com/api/v1/  ·  Swagger: swagger.yaml