Documenting API Endpoints0%

Documenting API Endpoints

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Documenting Request Bodies, Responses, and Query Parameters with @extend_schema

While drf-spectacular inspects serializers automatically, custom actions, query parameters, multipart file uploads, and dynamic responses require explicit annotations. DRF provides the powerful @extend_schema decorator to customize every detail of OpenAPI generation.


1. The @extend_schema Decorator

The @extend_schema decorator can be applied to @api_view functions, APIView methods (get, post), or ViewSet action methods (@action).

Python
from rest_framework import serializers, status
from rest_framework.views import APIView
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiExample
from drf_spectacular.types import OpenApiTypes
 
class CartCheckoutSerializer(serializers.Serializer):
shipping_address = serializers.CharField(max_length=255)
payment_method = serializers.ChoiceField(choices=['stripe', 'paypal', 'apple_pay'])
coupon_code = serializers.CharField(required=False, allow_blank=True)
 
class OrderSuccessSerializer(serializers.Serializer):
order_id = serializers.UUIDField()
status = serializers.CharField()
total_amount = serializers.DecimalField(max_digits=10, decimal_places=2)
created_at = serializers.DateTimeField()

2. Annotating Custom View Logic

Python
class CheckoutAPIView(APIView):
@extend_schema(
summary="Process cart checkout",
description="Creates an order from the active user's cart, verifies inventory, and initiates payment.",
request=CartCheckoutSerializer,
responses={
201: OrderSuccessSerializer,
400: OpenApiTypes.OBJECT,
409: OpenApiTypes.OBJECT,
},
examples=[
OpenApiExample(
'Successful Checkout Request',
value={
'shipping_address': '742 Evergreen Terrace, Springfield, OR',
'payment_method': 'stripe',
'coupon_code': 'SPRING20'
},
request_only=True
),
OpenApiExample(
'Successful Order Response',
value={
'order_id': '3fa85f64-5717-4562-b3fc-2c963f66afa6',
'status': 'PENDING_PAYMENT',
'total_amount': '159.99',
'created_at': '2026-09-15T12:00:00Z'
},
response_only=True
)
],
tags=['Orders & Billing']
)
def post(self, request):
serializer = CartCheckoutSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
# Business logic...
return Response({'status': 'PENDING_PAYMENT'}, status=status.HTTP_201_CREATED)

3. Documenting Query Parameters with OpenApiParameter

When an endpoint filters on parameters not present in the request body (e.g. GET requests), use OpenApiParameter:

Python
from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter
 
@extend_schema_view(
list=extend_schema(
summary="List all courses with filtering",
parameters=[
OpenApiParameter(
name='category',
type=str,
location=OpenApiParameter.QUERY,
description='Filter courses by category slug (e.g., data-analysis, web-dev)',
required=False
),
OpenApiParameter(
name='is_featured',
type=bool,
location=OpenApiParameter.QUERY,
description='Pass true to return only featured showcase courses',
required=False
)
]
)
)
class CourseViewSet(ReadOnlyModelViewSet):
# ViewSet implementation...
pass

Interactive Quiz

Practice Quiz

Question 1
Which decorator from drf_spectacular.utils is used to customize the OpenAPI schema of a view or method?
Question 2
What decorator is used at the class level to override schemas for multiple ViewSet actions (like list, retrieve, create) simultaneously?
Question 3
How do you document a URL query parameter like ?search=term using drf-spectacular?
Question 4
What does the examples argument in @extend_schema accomplish?
Question 5
What is the purpose of the tags argument in @extend_schema?
Next Lesson

Build REST API for E-commerce App

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext