URLs¶
The manuals app exposes a REST API built on Django REST Framework viewsets and custom endpoints.
Overview¶
The API is structured around:
- ViewSets (CRUD endpoints via routers)
- Custom actions (e.g. cover upload, PDF export)
- Download endpoints (file access)
Base path¶
All endpoints are typically mounted under:
/api/v1/manuals/
Registered routes¶
Taxonomy¶
Categories¶
GET /categories/POST /categories/GET /categories/{id}/PUT /categories/{id}/PATCH /categories/{id}/DELETE /categories/{id}/
Topics¶
GET /topics/POST /topics/GET /topics/{id}/PUT /topics/{id}/PATCH /topics/{id}/DELETE /topics/{id}/
Manuals¶
ManualViewSet¶
Standard endpoints¶
GET /manuals/POST /manuals/GET /manuals/{id}/PUT /manuals/{id}/PATCH /manuals/{id}/DELETE /manuals/{id}/
Query parameters¶
Filtering¶
?category=<id>?topic=<id>?is_public_external=true|false
Search¶
?search=<text>
Searches:
- title
- description
Ordering¶
?ordering=published_at?ordering=-published_at?ordering=title?ordering=order
Embed¶
Controls depth of response:
?embed=chapters?embed=items?embed=media?embed=callouts
Example:
?embed=chapters,items
Manual custom actions¶
Cover management¶
Upload cover¶
POST /manuals/{id}/cover/
Body:
- multipart/form-data with
cover_image
Remove cover¶
DELETE /manuals/{id}/cover/
Cover download¶
GET /manuals/{id}/cover/download/
Behavior:
- S3 → redirect to signed URL
- local storage → streamed response
PDF export¶
GET /manuals/{id}/export/pdf/
Query params:
mode=inline(default)mode=download
Response:
- generated PDF using WeasyPrint
Chapters¶
ChapterViewSet¶
Standard endpoints¶
GET /chapters/POST /chapters/GET /chapters/{id}/PUT /chapters/{id}/PATCH /chapters/{id}/DELETE /chapters/{id}/
Chapter custom actions¶
Cover upload¶
POST /chapters/{id}/cover/
Cover remove¶
DELETE /chapters/{id}/cover/
Callouts¶
CalloutPresetViewSet¶
GET /callout-presets/POST /callout-presets/GET /callout-presets/{id}/PUT /callout-presets/{id}/PATCH /callout-presets/{id}/DELETE /callout-presets/{id}/
CalloutViewSet¶
GET /callouts/POST /callouts/GET /callouts/{id}/PUT /callouts/{id}/PATCH /callouts/{id}/DELETE /callouts/{id}/
Media¶
ManualMediaViewSet¶
List / retrieve¶
GET /media/GET /media/{id}/
Upload¶
POST /media/
Requirements:
- file must be provided
-
exactly one parent must be specified:
-
manual_id chapter_idsection_idstep_group_idstep_id
Delete¶
DELETE /media/{id}/
Behavior:
- removes file
- cleans inline references in content
Media download¶
GET /media/{id}/download/
Behavior:
- S3 → redirect
- local → streamed file
Routing structure¶
Typical router setup:
router.register("categories", CategoryViewSet)
router.register("topics", TopicViewSet)
router.register("manuals", ManualViewSet)
router.register("chapters", ChapterViewSet)
router.register("callout-presets", CalloutPresetViewSet)
router.register("callouts", CalloutViewSet)
router.register("media", ManualMediaViewSet)
Additional endpoints¶
path("manuals/<int:manual_id>/cover/download/", ManualCoverDownloadView.as_view()),
path("media/<int:media_id>/download/", ManualMediaDownloadView.as_view()),
Design principles¶
- RESTful structure via viewsets
- consistent org scoping across endpoints
- separation of file upload vs metadata endpoints
- explicit custom actions for non-CRUD behavior
- scalable via query params (filter, search, embed)
Summary¶
The manuals API provides:
- full CRUD for manuals and related content
- nested content support via serializers
- file upload and download capabilities
- PDF export
- flexible querying and embedding
All endpoints are:
- org-scoped
- authenticated
- optimized for both list and detail use cases