Every major CRM module exposes a Django REST Framework API alongside the HTMX UI. Routes register through AppLauncher.get_api_paths() — no root URL edits.
This post is Part 9 of 28 in the Horilla CRM Technical Blog series.
What is the Horilla CRM API layer?
The Horilla CRM API layer enables you to:
- ModelViewSet per entity with company filtering
- Serializers with field-level permission awareness
- Router includes under /api/crm/…
- Swagger/OpenAPI documentation
- Bulk operations mixin for integrations
API route registration
AppLauncher.get_api_paths() registers API includes without editing root URLs:
# horilla_crm/leads/apps.py
def get_api_paths(self):
return [{
"pattern": "crm/leads/",
"view_or_include": "horilla_crm.leads.api.urls",
"name": "horilla_crm_leads_api",
"namespace": "horilla_crm_leads",
}]
Each module mirrors this pattern under app/api/.
Router + ViewSet pattern
# horilla_crm/leads/api/urls.py
from rest_framework.routers import DefaultRouter
from horilla.urls import path, include
from horilla_crm.leads.api.views import LeadViewSet, LeadStatusViewSet
router = DefaultRouter()
router.register(r"leads", LeadViewSet, basename="lead")
router.register(r"lead-statuses", LeadStatusViewSet, basename="leadstatus")
urlpatterns = [path("", include(router.urls))]
ViewSet capabilities
LeadViewSet uses Horilla core API mixins:
| Mixin | Provides |
|---|---|
| SearchFilterMixin | ?search= across configured fields |
| BulkOperationsMixin | Bulk update/delete endpoints |
| IsCompanyMember | Tenant-scoped access |
Custom actions (examples from Leads API):
- by_status, by_source, by_owner
- high_score — scoring integration
- convert — lead conversion pipeline
Swagger docs live in api/docs.py with swagger_auto_schema per action.
Serializers
# horilla_crm/leads/api/serializers.py
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = "__all__" # tighten for public APIs
Use read_only_fields for audit columns. Never expose all_objects in queryset — filter via Lead.objects (company manager).
Checklist for a new module API
- api/serializers.py, api/views.py, api/urls.py
- get_api_paths() in apps.py
- IsCompanyMember on ViewSets
- Register model in registration.py (permissions)
- Document endpoints in api/docs.py
Benefits of REST API in Horilla CRM
- Mobile apps and integrations use the same models as the UI
- Tenant isolation enforced at the API layer
- Auto-registered routes per AppLauncher app
- Consistent auth with session and token patterns
The DRF layer makes Horilla CRM integration-ready. Add api/ to your module and return paths from get_api_paths().
Continue the series
- Previous: Part 8 — Build Your First Horilla CRM Module in One Session: A Complete Capstone Tutorial
- Next: Part 10 — How to Implement Real-Time Notifications with Django Channels in Horilla CRM
More posts are at Horilla Blogs; share feedback on GitHub.