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:

MixinProvides
SearchFilterMixin?search= across configured fields
BulkOperationsMixinBulk update/delete endpoints
IsCompanyMemberTenant-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

More posts are at Horilla Blogs; share feedback on GitHub.

Share this article