๐ API Reference & RBAC Architecture
This document provides the canonical API contracts, Role-Based Access Control (RBAC) hierarchy, authentication lifecycle, and idempotency guarantees implemented in apps/api[cite: 3, 5, 7].
๐ Role-Based Access Control (RBAC) Hierarchy
The platform defines a strict 4-tier hierarchical authorization model[cite: 3, 6]:
| Role | Target Identity | Scope & Authority |
|---|---|---|
ROOT_ADMIN[cite: 3, 6] |
Founder / Lead Architect (mert@duespay.local)[cite: 3] |
Unrestricted root platform access[cite: 3, 7]. Can provision system administrators, manage the global chart of accounts (Revenue 600), and oversee cross-tenant PayTR reconciliation[cite: 3]. Bypasses route guards[cite: 7]. |
SUPER_ADMIN[cite: 3, 6] |
Engineering & Operations Team[cite: 3] | Operational management across all complexes[cite: 3]. Oversees DLQ queues, vector telemetry, and audit logs[cite: 3]. Cannot modify ROOT_ADMIN credentials[cite: 3]. |
COMPLEX_ADMIN[cite: 3, 6] |
Complex / Site Manager[cite: 3] | Scoped strictly to assigned complex_id[cite: 3]. Manages units, tariffs, monthly assessments, recurring expenses, and complex announcements[cite: 3, 5, 6]. |
RESIDENT[cite: 3, 6] |
Apartment Tenant / Property Owner[cite: 3] | Scoped to assigned unit_id and complex_id[cite: 3, 6]. Views unpaid dues, executes gateway payments, downloads 5-year digital receipts, and reads announcements[cite: 3]. |
๐ Authentication & Session Model
JWT Token Specifications
- Signature Algorithm: HMAC-SHA256 (
HS256)[cite: 5]. - Session TTL: 24 hours standard; 7 days (168 hours) when
remember_me = true[cite: 5]. - Token Claims Payload:
json { "sub": "e0000000-0000-0000-0000-000000000003", "email": "mert@example.com", "role": "RESIDENT", "complex_id": "a1b2c3d4-0000-0000-0000-000000000001", "unit_id": "b1b2c3d4-0000-0000-0000-000000000002", "iss": "dues-pay-engine-auth", "iat": 1786981111, "exp": 1787067511 }[cite: 3, 5]
Authorization Header Format
Protected endpoints require standard Bearer token transmission[cite: 3, 7]:
http
Authorization: Bearer <JWT_TOKEN>[cite: 3, 7]
๐ก๏ธ Idempotency & Reuse-Intent Standard
To prevent duplicate charges from network retries or multiple button clicks, the engine enforces a 15-minute pending session window[cite: 4]:
- Client Generation: The frontend generates a unique
Idempotency-Key(UUIDv4) upon the first payment click[cite: 4]. - Reuse Window: If an active session with status
CREATEDexists for the givenassessment_idwithin the last 15 minutes, the API returns the existingmerchant_oidand payment token rather than creating a duplicate database record[cite: 4]. - Database Guard: The
merchant_oidandidempotency_keycolumns maintain strict unique constraints on thepayment_intentstable[cite: 3, 4].
๐ก API Endpoint Reference
1. Authentication & Session
Authenticate User
http
POST /api/v1/auth/login
Content-Type: application/json[cite: 3, 5]
* Access Level: Public[cite: 3, 5]
* Request Body:
json
{
"email": "yonetim@flora.example.com",
"password": "manager123",
"remember_me": true
}[cite: 5]
* Response (200 OK):
json
{
"access_token": "eyJhbGciOiJIUzI1...",
"expires_at": "2026-09-07T18:38:31Z",
"user": {
"id": "e0000000-0000-0000-0000-000000000002",
"email": "yonetim@flora.example.com",
"full_name": "Ahmet Yonetici",
"role": "COMPLEX_ADMIN",
"complex_id": "a1b2c3d4-0000-0000-0000-000000000001",
"unit_id": null
}
}[cite: 3, 5, 6]
2. Resident Portal Endpoints
Get Announcements
http
GET /api/v1/portal/announcements
Authorization: Bearer <TOKEN>[cite: 3]
* Allowed Roles: RESIDENT, COMPLEX_ADMIN, ROOT_ADMIN[cite: 3, 7]
* Behavior: Returns announcements scoped to the user's complex_id, sorted with pinned notices first[cite: 3].
Get Outstanding Dues Summary
http
GET /api/v1/portal/dues/summary
Authorization: Bearer <TOKEN>[cite: 3]
* Allowed Roles: RESIDENT, ROOT_ADMIN[cite: 3, 7]
* Response (200 OK):
json
{
"total_outstanding": "1500.00",
"unpaid_count": 1,
"assessments": [
{
"id": "c1b2c3d4-0000-0000-0000-000000000003",
"unit_id": "b1b2c3d4-0000-0000-0000-000000000002",
"period": "2026-08",
"base_amount": "1500.00",
"status": "UNPAID",
"due_date": "2026-08-31"
}
]
}[cite: 3]
Get 5-Year Payment & Document History
http
GET /api/v1/portal/dues/history
Authorization: Bearer <TOKEN>[cite: 3]
* Allowed Roles: RESIDENT, ROOT_ADMIN[cite: 3, 7]
* Behavior: Returns settled payments from the last 5 years along with download URLs for generated PDF receipts and UBL-TR invoices[cite: 3].
3. Manager & Complex Operations
List Complex Units & Balances
http
GET /api/v1/manager/units
Authorization: Bearer <TOKEN>[cite: 3]
* Allowed Roles: COMPLEX_ADMIN, SUPER_ADMIN, ROOT_ADMIN[cite: 3, 7]
* Query Parameters: complex_id (optional for COMPLEX_ADMIN, inferred from JWT)[cite: 5, 7].
Update Resident Contact Assignment (Tenant Transfer)
http
PATCH /api/v1/manager/units/{unit_id}
Authorization: Bearer <TOKEN>
Content-Type: application/json[cite: 3]
* Allowed Roles: COMPLEX_ADMIN, ROOT_ADMIN[cite: 3, 7]
* Request Body:
json
{
"resident_name": "Ayลe Yeni Kiracฤฑ",
"resident_phone": "+905557778899",
"resident_email": "ayse@example.com"
}[cite: 3]
* Behavior: Replaces tenant details while preserving unit billing history and outstanding ledger balance[cite: 3].
Publish Complex Announcement
http
POST /api/v1/manager/announcements
Authorization: Bearer <TOKEN>
Content-Type: application/json[cite: 3]
* Allowed Roles: COMPLEX_ADMIN, ROOT_ADMIN[cite: 3, 7]
* Request Body:
json
{
"title": "2026 Yฤฑlฤฑ Olaฤan Genel Kurul Kararlarฤฑ",
"content": "Aฤustos ayฤฑ genel kurulunda alฤฑnan kararlar gereฤi aidatlar 1.500 TL olarak belirlenmiลtir.",
"type": "DECISION",
"is_pinned": true
}[cite: 3]
4. Webhooks & Gateways
PayTR Settlement Notification Callback
http
POST /api/v1/webhooks/paytr
Content-Type: application/x-www-form-urlencoded[cite: 3]
* Access Level: Gateway IP Whitelist / Public HMAC-SHA256 verification[cite: 3].
* Idempotency Rule: If the associated merchant_oid is already marked SETTLED, the endpoint skips double ledger booking and responds with OK immediately[cite: 3, 4].
* Response: OK (raw text string)[cite: 3, 4].