Owner: Engineering Team | Last Updated: 2026-01-30 | Status: Current
This document describes the primary data flows within the WWAI platform. Each flow details the sequence of operations, data transformations, and service interactions involved in core user journeys: text humanization, AI detection, authentication, and payment processing.
The humanization flow is the core value proposition of WWAI: transforming AI-generated text into human-like prose.
User Web App / Client Django API AI Models Database
---- ---------------- ---------- --------- --------
| | | | |
| Enter text | | | |
| Select options | | | |
|------------------->| | | |
| | | | |
| | POST /api/v1/humanize | |
| | Headers: | | |
| | Authorization: Bearer <jwt> | |
| | X-Fingerprint: <fp> | |
| | Body: | | |
| | { text, mode, | | |
| | readability, | | |
| | purpose } | | |
| |-------------------->| | |
| | | | |
| | | 1. Validate JWT | |
| | | 2. Check credits |---------------->|
| | | & rate limits |<----------------|
| | | | |
| | | 3. Preprocess text | |
| | | (sanitize, | |
| | | chunk if long) | |
| | | | |
| | | 4. Invoke model | |
| | |------------------->| |
| | | | |
| | | Humanized text | |
| | |<-------------------| |
| | | | |
| | | 5. Post-process | |
| | | (quality check, | |
| | | formatting) | |
| | | | |
| | | 6. Deduct credits |---------------->|
| | | 7. Log usage |---------------->|
| | | | |
| | 200 OK | | |
| | { humanized_text, | | |
| | credits_used, | | |
| | credits_remaining } | |
| |<--------------------| | |
| | | | |
| Display result | | | |
|<-------------------| | | |
{
"text": "The AI-generated text to humanize...",
"mode": "standard",
"readability": "high_school",
"purpose": "essay"
}
{
"humanized_text": "The humanized output text...",
"credits_used": 150,
"credits_remaining": 9850,
"word_count": 350,
"processing_time_ms": 2340
}
Credits are consumed based on the word count of the input text:
| Word Count Range | Credits Consumed |
|---|---|
| 1 - 100 words | Base rate (varies by plan) |
| 101 - 500 words | Proportional to word count |
| 500+ words | Text is chunked, each chunk billed separately |
| Error | HTTP Status | Response |
|---|---|---|
| Insufficient credits | 402 | { "error": "insufficient_credits", "credits_needed": 150, "credits_available": 50 } |
| Rate limit exceeded | 429 | { "error": "rate_limit_exceeded", "retry_after": 60 } |
| Text too short | 400 | { "error": "text_too_short", "min_words": 10 } |
| Text too long | 400 | { "error": "text_too_long", "max_words": 10000 } |
| Model unavailable | 503 | { "error": "service_unavailable", "retry_after": 30 } |
The detection flow sends user text to the internal AI detection model and up to 9 external detectors, then aggregates the results.
User Web App Django API Internal External Detectors (x9) DB
---- ------- ---------- Detection ----------------------- --
| | | Model | |
| Submit | | | | |
| text for | | | | |
| detection | | | | |
|------------>| | | | |
| | | | | |
| | POST /api/v1/detect | | |
| | { text, | | | |
| | detectors } | | | |
| |--------------->| | | |
| | | | | |
| | | Validate JWT | | |
| | | Check credits | | |
| | | | | |
| | |--[internal]--->| | |
| | | | | |
| | |--[parallel async fan-out]---------->| |
| | | | GPTzero ------->| score |
| | | | ZeroGPT ------->| score |
| | | | Sapling ------->| score |
| | | | Copyleaks ----->| score |
| | | | Writer -------->| score |
| | | | Turnitin ------>| score |
| | | | Originality --->| score |
| | | | Crossplag ----->| score |
| | | | ContentAtScale->| score |
| | | | | |
| | |<--[internal]---| | |
| | |<--[gather all responses]-----------| |
| | | | | |
| | | Aggregate scores | |
| | | Compute weighted average | |
| | | Deduct credits | | |
| | | Log results | | |
| | |-------------------------------------------------->| |
| | | | | |
| | 200 OK | | | |
| | { scores } | | | |
| |<---------------| | | |
| | | | | |
| Display | | | | |
| results | | | | |
|<------------| | | | |
{
"overall_score": 23.5,
"verdict": "likely_human",
"internal_score": 18.2,
"detectors": {
"gptzero": { "score": 25.0, "status": "success", "latency_ms": 2100 },
"zerogpt": { "score": 30.0, "status": "success", "latency_ms": 1500 },
"sapling": { "score": 15.0, "status": "success", "latency_ms": 1200 },
"copyleaks": { "score": 20.0, "status": "success", "latency_ms": 4500 },
"writer": { "score": 22.0, "status": "success", "latency_ms": 2300 },
"turnitin": { "score": 28.0, "status": "success", "latency_ms": 8500 },
"originality": { "score": 19.0, "status": "success", "latency_ms": 3100 },
"crossplag": { "score": 24.0, "status": "success", "latency_ms": 2800 },
"contentatscale": { "score": 21.0, "status": "success", "latency_ms": 1800 }
},
"credits_used": 50,
"credits_remaining": 9800,
"processing_time_ms": 8700
}
"status": "timeout" or "status": "error" and its score is excluded from the aggregate. User Web App (NextAuth.js) Django API PostgreSQL
---- -------------------- ---------- ----------
| | | |
| Enter email + | | |
| password | | |
| + Turnstile token | | |
|------------------->| | |
| | | |
| | POST /api/v1/auth/login |
| | { email, password, | |
| | turnstile_token, | |
| | fingerprint } | |
| |--------------------->| |
| | | |
| | | Validate Turnstile |
| | | (Cloudflare API) |
| | | |
| | | Verify credentials |
| | |------------------->|
| | |<------------------|
| | | |
| | | Log fingerprint |
| | | + IP address |
| | |------------------->|
| | | |
| | | Generate JWT |
| | | access_token |
| | | (1h expiry) |
| | | refresh_token |
| | | |
| | 200 OK | |
| | { access_token, | |
| | refresh_token, | |
| | user } | |
| |<---------------------| |
| | | |
| | Store tokens in | |
| | NextAuth.js session | |
| | (encrypted cookie) | |
| | | |
| Redirect to | | |
| dashboard | | |
|<-------------------| | |
Web App NextAuth.js (Server) Django API
------- -------------------- ----------
| | |
| (Every 55 minutes OR | |
| on 401 response) | |
| | |
| API request triggers | |
| session check | |
|-------------------------->| |
| | |
| | Check token expiry |
| | (is token >55min old?) |
| | |
| | POST /api/v1/auth/token/refresh
| | { refresh_token } |
| |----------------------->|
| | |
| | | Validate refresh token
| | | Generate new access_token
| | | (new 1h expiry)
| | |
| | { new_access_token, |
| | new_refresh_token } |
| |<-----------------------|
| | |
| | Update session |
| | |
| Continue with new token | |
|<--------------------------| |
User Web App OAuth Provider Django API Database
---- ------- -------------- ---------- --------
| | | | |
| Click | | | |
| "Sign in | | | |
| with Google"| | | |
|------------->| | | |
| | | | |
| | Redirect to | | |
| | Google consent | | |
| |------------------->| | |
| | | | |
| Google | | | |
| consent | | | |
| screen | | | |
|<-------------| | | |
| | | | |
| Approve | | | |
|------------->|------------------->| | |
| | | | |
| | Callback with | | |
| | authorization code | | |
| |<-------------------| | |
| | | | |
| | POST /api/v1/auth/oauth/google | |
| | { code, | | |
| | redirect_uri, | | |
| | fingerprint } | | |
| |----------------------------------->| | |
| | | | | |
| | | | Exchange code |
| | | | for tokens with |
| | |<-------------| Google API |
| | | | |
| | | ID token + | |
| | | profile info | |
| | |------------->| |
| | | | |
| | | | Find or create |
| | | | user account |
| | | |------------------->|
| | | |<------------------|
| | | | |
| | | | Generate JWT |
| | | | |
| | { access_token, | | |
| | refresh_token, | | |
| | user } | | |
| |<----------------------------------| |
| | | | |
| Dashboard | | | |
|<-------------| | | |
User Web App Stripe.js Django API Stripe API Database
---- ------- --------- ---------- ---------- --------
| | | | | |
| Select plan | | | | |
| (e.g. Pro) | | | | |
|-------------->| | | | |
| | | | | |
| | POST /api/v1/billing/checkout | | |
| | { plan_id, | | | |
| | billing_cycle, | | | |
| | currency } | | | |
| |---------------------------------->| | |
| | | | | |
| | | | Create Stripe | |
| | | | Checkout Session| |
| | | |---------------->| |
| | | | | |
| | | | { session_id, | |
| | | | checkout_url } | |
| | | |<----------------| |
| | | | | |
| | { checkout_url } | | | |
| |<---------------------------------| | |
| | | | | |
| | Redirect to | | | |
| | Stripe Checkout | | | |
| |----------------->| | | |
| | | | | |
| Stripe | | | | |
| Checkout | | | | |
| page | | | | |
|<--------------| | | | |
| | | | | |
| Enter payment| | | | |
| details | | | | |
|-------------->|----------------->| | | |
| | | | | |
| | | Process payment | | |
| | |------------------------------------>| |
| | | | | |
| | Redirect to | | | |
| | success URL | | | |
| |<-----------------| | | |
| | | | | |
| Success page | | | | |
|<--------------| | | | |
| | | | | |
| | | [Async Webhook] | |
| | | | | |
| | | | checkout.session| |
| | | | .completed | |
| | | |<----------------| |
| | | | | |
| | | | Update user | |
| | | | subscription | |
| | | | + credits | |
| | | |------------------------------>| |
| | | | | |
Stripe Django API Database
------ ---------- --------
| | |
| POST /api/v1/billing/webhooks/stripe |
| Headers: | |
| Stripe-Signature | |
| Body: event JSON | |
|--------------------->| |
| | |
| | 1. Verify webhook |
| | signature |
| | (stripe.Webhook. |
| | construct_event) |
| | |
| | 2. Parse event type |
| | |
| | Switch on event type: |
| | |
| | checkout.session.completed |
| | -> Create subscription |
| | -> Allocate credits |
| | -> Send welcome email |
| | |
| | invoice.paid |
| | -> Renew credits |
| | -> Update billing date |
| | |
| | invoice.payment_failed |
| | -> Mark payment failed |
| | -> Send retry email |
| | |
| | customer.subscription |
| | .updated |
| | -> Update plan tier |
| | -> Adjust credits |
| | |
| | customer.subscription |
| | .deleted |
| | -> Downgrade to Free |
| | -> Reset credits to 300 |
| | |
| |---------------------------->|
| | |
| 200 OK | |
|<---------------------| |
User Web App Churnkey SDK Django API Stripe
---- ------- ------------ ---------- ------
| | | | |
| Click | | | |
| "Cancel Plan" | | | |
|--------------->| | | |
| | | | |
| | Load Churnkey | | |
| | cancel flow | | |
| |------------------->| | |
| | | | |
| Churnkey | | | |
| retention | | | |
| offers | | | |
| (surveys, | | | |
| discounts) | | | |
|<----------------------------------- | |
| | | | |
| [If user | | | |
| confirms | | | |
| cancel] | | | |
| | | | |
| | | Webhook: | |
| | | cancellation | |
| | | .accepted | |
| | |------------------>| |
| | | | |
| | | | Cancel |
| | | | subscription |
| | | | at period end |
| | | |---------------->|
| | | | |
| | | | Update DB |
| | | | (cancel pending)|
| | | | |
| Confirmation | | | |
|<---------------| | | |
| Flow | Input | Transformation | Output |
|---|---|---|---|
| Humanization | Raw AI text + options | AI model inference + post-processing | Humanized text + credit info |
| Detection | User text | Parallel detector queries + score aggregation | Weighted scores per detector + overall verdict |
| Auth (Login) | Credentials + CAPTCHA | Credential verification + JWT generation | JWT tokens + user profile |
| Auth (OAuth) | OAuth authorization code | Code exchange + account linking + JWT generation | JWT tokens + user profile |
| Auth (Refresh) | Refresh token | Token validation + new token generation | New JWT access + refresh tokens |
| Payment (Checkout) | Plan selection + currency | Stripe session creation | Checkout URL redirect |
| Payment (Webhook) | Stripe event payload | Signature verification + subscription update | Updated user plan + credits |
| Date | Author | Change |
|---|---|---|
| 2026-01-30 | Admin | Initial creation |
Prev: Subscription Model | Next: Internationalization (i18n) | Up: WalterWrites