| Method | Route | Purpose |
|---|
| POST | /api/auth/otp/send | Send 6-digit OTP to buyer email/WhatsApp |
| POST | /api/auth/otp/verify | Verify OTP code, create session |
| POST | /api/auth/logout | Invalidate buyer session |
| POST | /api/auth/otp/reset | Reset OTP for re-verification |
| Method | Route | Purpose |
|---|
| GET | /api/favorites | List buyer’s favorite units |
| POST | /api/favorites | Toggle unit favorite status |
| Method | Route | Purpose |
|---|
| GET | /api/profile | Get buyer profile |
| PATCH | /api/profile | Update buyer profile |
Browser URLs use clean paths (e.g. /units, /leads) — the /admin/ prefix is a legacy internal detail; the middleware redirects /admin/* to clean paths.
| Method | Route | Purpose |
|---|
| POST | /api/auth/admin/otp/send | Send 6-digit OTP to CRM email |
| POST | /api/auth/admin/otp/verify | Verify CRM OTP code, create Lucia session |
| POST | /api/auth/admin/logout | Invalidate CRM session |
Deprecated (to be removed):
| Method | Route | Purpose |
|---|
| GET | /accept?token=... | Former magic-link token handler |
| Method | Route | Purpose |
|---|
| GET | /api/admin/session/me | Current admin user + accessible projects |
| POST | /api/admin/session/active-project | Set active project for session |
| Method | Route | Purpose |
|---|
| GET | /api/admin/leads | List leads with search and date filtering |
| GET | /api/admin/leads/stats | Lead statistics (counts by project) |
| Method | Route | Purpose |
|---|
| GET | /api/admin/units | List units with status/category filters + pagination |
| POST | /api/admin/units | Create new unit |
| GET | /api/admin/units/[id] | Get unit details |
| PATCH | /api/admin/units/[id] | Update unit |
| DELETE | /api/admin/units/[id] | Delete unit |
| GET | /api/admin/units/[id]/images | List unit images |
| POST | /api/admin/units/[id]/images | Upload/reorder unit images |
| Method | Route | Purpose |
|---|
| GET | /api/admin/agents | List agents for current project |
| POST | /api/admin/agents | Create Makler profile + CRM user (crmRole, active project) |
| GET | /api/admin/agents/[id] | Get agent details + units |
| PATCH | /api/admin/agents/[id] | Update agent |
| DELETE | /api/admin/agents/[id] | Delete agent |
| Method | Route | Purpose |
|---|
| GET | /api/admin/documents | List documents with category filter |
| POST | /api/admin/documents/presign | Generate presigned upload URL for R2 |
| Method | Route | Purpose |
|---|
| GET | /api/admin/portal-settings | Get portal branding configuration |
| PATCH | /api/admin/portal-settings | Update portal branding/features |
| GET | /api/admin/portal-settings/logo | Get logo upload URL |
| Method | Route | Purpose |
|---|
| GET | /api/admin/domains | List domains for current project (also used by portal-settings UI) |
| POST | /api/admin/domains | Add new custom domain |
| DELETE | /api/admin/domains | Remove domain (?hostname=) |
CRM UI: domains card on Portal-Einstellungen; browser path /domains redirects to ?section=domains (internally rewrites to /admin/domains and /admin/portal-settings).
| Method | Route | Purpose |
|---|
| POST | /api/admin/invite | Invite CRM user — body: email, name, role, projectIds |
| POST | /api/admin/invite-developer | Legacy — email, name, projectIds (role forced to developer) |
| Method | Route | Purpose |
|---|
| GET | /api/admin/makler | List organization members |
| POST | /api/admin/makler | Invite developer member |
| PATCH | /api/admin/makler/[id] | Update member role |
| DELETE | /api/admin/makler/[id] | Remove member |
| Method | Route | Purpose |
|---|
| GET | /api/proxy-public/config | Public portal config (no auth) |
| GET | /api/proxy-public/units | Public unit listing with filters |
| GET | /api/proxy-public/units/[id] | Public unit detail (with agent info) |
| GET | /api/proxy-public/contact | Get contact info (phone, email) |
| POST | /api/contact | Contact form submission |