Skip to content

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=<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_id
  • section_id
  • step_group_id
  • step_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