Overview
Credits
Text Analysis
Text Summarisation
Summarise creates an async background job. You receive a job ID instantly — switch to the Jobs tab to poll for the result.
A fully-featured backend API platform with Google OAuth, JWT auth, organisation-level credit system, async job processing, and idempotency — all in one.
Built with FastAPI · PostgreSQL · Redis · SQLAlchemy 2.0 · ARQ
One-click login with Google. Auto-creates organisations from email domains. First user per domain becomes admin, all others are members.
Signed, stateless tokens with configurable expiry. Role-based access control with admin and member roles. Bearer token standard.
Double-entry accounting with atomic deductions using SELECT FOR UPDATE row locking. Credits granted, deducted, and refunded with full audit trail.
Complete organisational data isolation. Each tenant owns their credit pool, job history, and user roster. No cross-tenant data leakage.
Background processing with ARQ and Redis. Submit jobs, get an ID immediately, poll for results. Credits deducted upfront, automatically refunded on failure.
Safe retries on all product endpoints. Unique constraint enforced at the DB level — submit the same key twice, pay only once, every time.
Base URL: http://localhost:8000
· All responses are JSON
· Open Swagger UI →
Redirects the browser to Google's OAuth consent screen. On approval, Google sends the browser back to /auth/callback with an authorization code.
302 Redirect → accounts.google.com/o/oauth2/auth?...
Exchanges the Google authorization code for user info. Auto-creates an Organisation (from email domain) and User if this is a new login. First user per domain becomes admin; subsequent users are members. Returns a signed JWT.
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
{"detail": {"error": "google_auth_failed", "message": "..."}}
Returns the authenticated user's full profile and their organisation details. Use this to verify your token and retrieve user metadata.
{
"user": {
"id": "da9706bf-b44e-460e-a8c7-f4d6bf1025b1",
"email": "user@company.com",
"name": "Jane Doe",
"role": "admin",
"organisation_id": "7f751a8a-c2d9-4a7c-a508-a96c1eef89af",
"created_at": "2026-01-01T00:00:00Z"
},
"organisation": {
"id": "7f751a8a-c2d9-4a7c-a508-a96c1eef89af",
"name": "Company",
"slug": "company-com",
"created_at": "2026-01-01T00:00:00Z"
}
}
Adds credits to the organisation's ledger balance. Restricted to admin users. Creates a transaction record with the provided reason for full audit trail.
{
"amount": 100, // positive integer, required
"reason": "string" // 1–500 chars, required
}
{
"message": "Granted 100 credits",
"balance": 100,
"transaction_id": "fe4a9ba0-531a-4e12-a9ad-11d5ae5780cf"
}
{"detail": {"error": "forbidden", "message": "This action requires admin privileges."}}
Returns the current credit balance (computed from the full ledger) and the 10 most recent transactions, ordered newest first.
{
"organisation_id": "7f751a8a-c2d9-4a7c-a508-a96c1eef89af",
"balance": 275,
"recent_transactions": [
{
"id": "d02b2ca6-2e14-4f76-afb6-0bfe819a23cd",
"amount": -25,
"reason": "API call: /api/analyse",
"created_at": "2026-03-02T10:38:42Z",
"user_id": "da9706bf-b44e-460e-a8c7-f4d6bf1025b1"
}
]
}
Performs synchronous text analysis. Deducts 25 credits atomically using SELECT FOR UPDATE. Accepts an optional Idempotency-Key header — same key returns the cached result without additional charges.
Authorization: Bearer <token>
Idempotency-Key: <unique-key> // optional
{
"text": "string" // 10–2000 characters, required
}
{
"result": "Analysis complete. Word count: 9. Unique words: 8.",
"credits_remaining": 275
}
402 {"error": "insufficient_credits", "balance": 0, "required": 25}
401 {"error": "authentication_required", "message": "..."}
422 {"error": "validation_error", "message": "body → text: ..."}
Submits a background summarisation job via ARQ/Redis. Deducts 10 credits immediately. Returns a job_id — poll /api/jobs/{job_id} for results. Credits are automatically refunded if job fails to enqueue.
{
"text": "string" // 10–2000 characters, required
}
{
"job_id": "9d767976-470b-40f0-855e-0f72efded6a2",
"credits_remaining": 240
}
Returns the current status of a job. Tenant-isolated — only the organisation that created the job can retrieve it. Returns 404 for unknown or cross-tenant job IDs.
{
"job_id": "9d767976-470b-40f0-855e-0f72efded6a2",
"status": "pending", // pending | running | completed | failed
"result": null, // string when completed
"error": null, // string when failed
"created_at": "2026-03-02T10:38:42Z"
}
{"detail": {"error": "job_not_found", "message": "No job found with ID ..."}}
Returns 200 if the API is running and the database is reachable. Returns 503 if the database connection fails. Suitable for load balancer health checks.
{
"status": "healthy",
"database": "reachable",
"timestamp": "2026-03-02T10:38:42.079590+00:00"
}
{"status": "unhealthy", "database": "unreachable", "timestamp": "..."}
Only organisation admins can grant credits. Ask your admin to grant credits to your organisation.
Summarise creates an async background job. You receive a job ID instantly — switch to the Jobs tab to poll for the result.