Adding stamp annotations to PDFs programmatically enables teams to automate document status marking, build approval workflow systems, and implement review state tracking. Whether you’re creating automated approval stamps, marking documents as draft or final, implementing confidential document workflows, building review status indicators, or creating custom stamp systems for quality control, stamp annotations provide visual status markers with predefined styles. Stamp annotations display predefined text and icons representing document states, with customizable colors and positioning for integration into automated document processing pipelines.

How Nutrient helps you achieve this

Nutrient Python SDK handles PDF stamp annotation structures and appearance generation. With the SDK, you don’t need to worry about:

  • Parsing stamp annotation dictionaries and rubber stamp icon rendering
  • Managing predefined stamp appearance streams and text positioning
  • Handling stamp style enumeration and icon resource loading
  • Complex annotation appearance states and color transformations

Instead, Nutrient provides an API that handles all the complexity behind the scenes, letting you focus on your business logic.

Complete implementation

Below is a complete working example that demonstrates adding various stamp annotations to a PDF. The following lines set up the Python application. The import statements bring in all necessary classes from the Nutrient SDK:

from nutrient_sdk import Document
from nutrient_sdk import PdfEditor
from nutrient_sdk import Color
from nutrient_sdk import PdfRubberStampIcon
from nutrient_sdk import NutrientException

Working with stamp annotations

The main() function defines the entry point that will contain the stamp annotation creation logic. The Document.open() call opens the PDF document. The context manager(opens in a new tab) syntax ensures the document is automatically closed when you’re done, preventing resource leaks. The following code creates a PDF editor, accesses the page collection, ensures at least one page exists by adding a letter-size page (612×792 points) if the document is empty, and retrieves the annotation collection from the first page:

def main():
try:
with Document.open("input.pdf") as document:
editor = PdfEditor.edit(document)
pages = editor.get_page_collection()
if pages.get_count() == 0:
pages.add(612.0, 792.0)
page = pages.get_first()
annotations = page.get_annotation_collection()

Adding a basic stamp

The following code adds a basic stamp annotation at coordinates (400, 700) with dimensions 150×50 points. The add_stamp() method creates a stamp annotation with position (x, y), size (width, height), author name, and contents text. Stamps are created with a default Draft style (displaying DRAFT text with an icon) and red color (ARGB: 255, 255, 0, 0). The default Draft stamp is commonly used for marking documents that are still in development or awaiting review:

draft_stamp = annotations.add_stamp(
400.0, 700.0, 150.0, 50.0, # x, y, width, height
"Author",
"Work in progress"
)

Adding an approved stamp

The following code adds an approval stamp at coordinates (400, 600) with dimensions 150×50 points, positioned below the draft stamp. After creation, the stamp is customized using property assignments: stamp_style changes the icon to the Approved style (displaying APPROVED text with a checkmark icon), and color applies a green color using ARGB values (255, 0, 128, 0). The Approved stamp style is commonly used in document approval workflows to visually indicate that a document has passed review and is authorized for use:

approved_stamp = annotations.add_stamp(
400.0, 600.0, 150.0, 50.0, # x, y, width, height
"Approver Name",
"Document approved on review"
)
# Customize the stamp appearance
approved_stamp.stamp_style = PdfRubberStampIcon.APPROVED
approved_stamp.color = Color.from_argb(255, 0, 128, 0)

Adding a confidential stamp

The following code adds a confidentiality stamp at coordinates (400, 500) with dimensions 150×50 points. The stamp is configured with the Confidential style using the stamp_style property, which displays CONFIDENTIAL text with an appropriate icon. The Confidential stamp retains the default red color inherited from the base stamp, making it visually prominent. This stamp style is commonly used to mark documents containing sensitive information, proprietary data, or content requiring restricted access:

confidential_stamp = annotations.add_stamp(
400.0, 500.0, 150.0, 50.0, # x, y, width, height
"Security Officer",
"Contains sensitive information"
)
# Customize the stamp appearance
confidential_stamp.stamp_style = PdfRubberStampIcon.CONFIDENTIAL

Other available stamp types

The following code demonstrates additional predefined stamp styles available through the PdfRubberStampIcon enumeration. The first stamp uses the NOT_APPROVED style at coordinates (50, 700), which displays NOT APPROVED text with a rejection indicator, retaining the default red color. The NOT_APPROVED style is used in review workflows to mark documents that failed approval criteria. The second stamp uses the FINAL style at coordinates (50, 600), which displays FINAL text indicating the document has reached its completed state. The FINAL stamp is customized with a blue color using ARGB values (255, 0, 0, 255) to distinguish it from approval/rejection stamps. Additional available stamp styles include DRAFT, APPROVED, CONFIDENTIAL, NOT_APPROVED, FINAL, and others defined in the PdfRubberStampIcon enumeration:

# Not Approved stamp
not_approved_stamp = annotations.add_stamp(
50.0, 700.0, 150.0, 50.0, # x, y, width, height
"Reviewer",
"Rejected"
)
not_approved_stamp.stamp_style = PdfRubberStampIcon.NOT_APPROVED
# Final stamp
final_stamp = annotations.add_stamp(
50.0, 600.0, 150.0, 50.0, # x, y, width, height
"Legal",
"Final version"
)
final_stamp.stamp_style = PdfRubberStampIcon.FINAL
final_stamp.color = Color.from_argb(255, 0, 0, 255)

Saving the document

The final code block saves the document with all stamp annotations and closes the editor. The try-except block handles potential errors using NutrientException:

editor.save_as("output.pdf")
editor.close()
except NutrientException as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()

Conclusion

The stamp annotation workflow consists of several key operations:

  1. Open the document using a context manager(opens in a new tab) for automatic resource cleanup.
  2. Create an editor and access the page collection.
  3. Ensure at least one page exists by adding a letter-size page if needed.
  4. Retrieve the annotation collection for the target page.
  5. Add basic stamp annotations with the default DRAFT style and red color.
  6. Customize stamp styles using the stamp_style property with PdfRubberStampIcon enumeration values.
  7. Customize stamp colors using the color property with ARGB color values.
  8. Add APPROVED stamps with green color for approval workflows.
  9. Add CONFIDENTIAL stamps for marking sensitive documents.
  10. Add NOT_APPROVED stamps for rejection indicators.
  11. Add FINAL stamps to mark completed documents.
  12. Save and close the editor.

Nutrient handles stamp annotation dictionary structures, rubber stamp icon rendering, appearance stream generation, and text positioning so you don’t need to understand PDF stamp annotation specifications or manage icon resource loading manually. The stamp annotation system provides predefined visual status markers for document workflow automation, approval systems, confidentiality marking, and review state tracking.