From 7728e015169a71057d61bb3deed29937c5728c56 Mon Sep 17 00:00:00 2001 From: Rachel Jones Date: Thu, 20 Aug 2026 12:09:02 -0700 Subject: [PATCH] Add canonical examples for the marketing SDK pages --- examples/create_etch_existing_cast.py | 123 -------------------------- examples/create_etch_packet.py | 77 ++++++++++++++++ examples/fill.py | 62 +++++++++++++ examples/fill_pdf.py | 87 ------------------ examples/generate_html.py | 56 ++++++++++++ examples/generate_markdown.py | 54 +++++++++++ examples/generate_pdf.py | 74 ---------------- 7 files changed, 249 insertions(+), 284 deletions(-) delete mode 100644 examples/create_etch_existing_cast.py create mode 100644 examples/create_etch_packet.py create mode 100644 examples/fill.py delete mode 100644 examples/fill_pdf.py create mode 100644 examples/generate_html.py create mode 100644 examples/generate_markdown.py delete mode 100644 examples/generate_pdf.py diff --git a/examples/create_etch_existing_cast.py b/examples/create_etch_existing_cast.py deleted file mode 100644 index afe66ac5..00000000 --- a/examples/create_etch_existing_cast.py +++ /dev/null @@ -1,123 +0,0 @@ -# pylint: disable=duplicate-code - -import os - -from python_anvil.api import Anvil -from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket -from python_anvil.api_resources.payload import EtchCastRef, EtchSigner, SignerField - - -API_KEY = os.environ.get("ANVIL_API_KEY") -# or set your own key here -# API_KEY = 'my-api-key' - - -def main(): - anvil = Anvil(api_key=API_KEY) - - # Create an instance of the builder - packet = CreateEtchPacket( - name="Etch packet with existing template", - # - # Optional changes to email subject and body content - signature_email_subject="Please sign these forms", - signature_email_body="This form requires information from your driver's " - "license. Please have that available.", - # - # URL where Anvil will send POST requests when server events happen. - # Take a look at https://www.useanvil.com/docs/api/e-signatures#webhook-notifications - # for other details on how to configure webhooks on your account. - # You can also use sites like webhook.site, requestbin.com or ngrok to - # test webhooks. - # webhook_url="https://my.webhook.example.com/etch-events/", - # - # Email overrides for the "reply-to" email header for signer emails. - # If used, both `reply_to_email` and `reply_to_name` are required. - # By default, this will point to your organization support email. - # reply_to_email="my-org-email@example.com", - # reply_to_name="My Name", - # - # Merge all PDFs into one. Use this if you have many PDF templates - # and/or files, but want the final downloaded package to be only - # 1 PDF file. - # merge_pdfs=True, - ) - - # You can reference an existing PDF Template from your Anvil account - # instead of uploading a new file. - # You can find this information by going to the "PDF Templates" section of - # your Anvil account, choosing a template, and selecting "API Info" at the - # top-right of the page. - # Additionally, you can get this information by using the provided CLI by: - # `anvil cast --list` to list all your available templates, then: - # `anvil cast [THE_EID_OF_THE_CAST]` to get a listing of data in that - # template. - pdf_template = EtchCastRef( - # The `id` here is what should be used by signer objects. - # This can be any string, but should be unique if adding multiple files. - id="introPages", - # The eid of the cast you want to use from "API Info" or through the CLI. - # This is a sample PDF anyone can use - cast_eid="05xXsZko33JIO6aq5Pnr", - ) - - # Gather your signer data - signer1 = EtchSigner( - name="Morgan", - email="morgan@example.com", - # Fields where the signer needs to sign. - # Check your cast fields via the CLI (`anvil cast [cast_eid]`) or the - # PDF Templates section on the Anvil app. - # This basically says: "In the 'introPages' file (defined as - # `pdf_template` above), assign the signature field with cast id of - # 'def456' to this signer." You can add multiple signer fields here. - fields=[ - SignerField( - file_id="introPages", - field_id="def456", - ) - ], - # By default, `signer_type` will be "email" which will automatically - # send emails when this etch packet is created. - # It can also be set to "embedded" which will _not_ send emails, and - # you will need to handle sending the signer URLs manually in some way. - signer_type="email", - # - # You can also change how signatures will be collected. - # "draw" will allow the signer to draw their signature - # "text" will insert a text version of the signer's name into the - # signature field. - # signature_mode="draw", - # - # Whether or not to the signer is required to click each signature - # field manually. If `False`, the PDF will be signed once the signer - # accepts the PDF without making the user go through the PDF. - # accept_each_field=False, - # - # URL of where the signer will be redirected after signing. - # The URL will also have certain URL params added on, so the page - # can be customized based on the signing action. - # redirect_url="https://www.google.com", - ) - - # Add your signer. - packet.add_signer(signer1) - - # Add your file(s) - packet.add_file(pdf_template) - - # If needed, you can also override or add additional payload fields this way. - # This is useful if the Anvil API has new features, but `python-anvil` has not - # yet been updated to support it. - # payload = packet.create_payload() - # payload.aNewFeature = True - - # Create your packet - # If overriding/adding new fields, use the modified payload from - # `packet.create_payload()` - res = anvil.create_etch_packet(payload=packet) - print(res) - - -if __name__ == '__main__': - main() diff --git a/examples/create_etch_packet.py b/examples/create_etch_packet.py new file mode 100644 index 00000000..0b4bfccb --- /dev/null +++ b/examples/create_etch_packet.py @@ -0,0 +1,77 @@ +# Create an Etch e-sign packet via the Anvil API and send it to a signer. +# Docs: https://www.useanvil.com/docs/api/e-signatures +# +# Run this from the project root: +# ANVIL_API_KEY=YOUR_KEY SIGNER_EMAIL=your.real.email@example.com \ +# python examples/create_etch_packet.py +# +# A signature request email is sent to SIGNER_EMAIL, so use your real email +# address. The new packet also appears in your dashboard's e-sign area. + +# pylint: disable=duplicate-code + +import os + +from python_anvil.api import Anvil +from python_anvil.api_resources.mutations.create_etch_packet import CreateEtchPacket +from python_anvil.api_resources.payload import EtchCastRef, EtchSigner, SignerField + + +API_KEY = os.environ.get("ANVIL_API_KEY") +SIGNER_NAME = "Testy Signer" +SIGNER_EMAIL = os.environ.get("SIGNER_EMAIL") or "" + +# The PDF template to sign. This is a sample template available to anyone. +# See https://www.useanvil.com/help/tutorials/set-up-a-pdf-template for details +# on setting up your own template. +PDF_TEMPLATE_EID = "05xXsZko33JIO6aq5Pnr" + + +def main(): + anvil = Anvil(api_key=API_KEY) + + # Test packets use development signatures and do not count toward your + # billed packets (`is_test=True` is the default). Pass `is_draft=True` + # to review the packet in your dashboard before anything is sent. + packet = CreateEtchPacket( + name=f"Test Docs - {SIGNER_NAME}", + signature_email_subject="Custom email subject", + signature_email_body="Custom please sign these documents....", + ) + + # Reference an existing PDF template from your Anvil account. The `id` is + # your own name for this file, used by the signer fields below. + pdf_template = EtchCastRef( + id="sampleTemplate", + cast_eid=PDF_TEMPLATE_EID, + ) + packet.add_file(pdf_template) + + # Fill the PDF with data before it is sent to any signers. Keys here match + # the field IDs configured on the PDF template. + packet.add_file_payloads( + "sampleTemplate", + dict(data={"name": SIGNER_NAME, "email": SIGNER_EMAIL}), + ) + + # Signers sign in the order they are added. `signer_type="email"` sends + # the signature request email automatically. + signer = EtchSigner( + name=SIGNER_NAME, + email=SIGNER_EMAIL, + signer_type="email", + fields=[ + SignerField( + file_id="sampleTemplate", + field_id="signature", + ) + ], + ) + packet.add_signer(signer) + + res = anvil.create_etch_packet(payload=packet) + print(res) + + +if __name__ == "__main__": + main() diff --git a/examples/fill.py b/examples/fill.py new file mode 100644 index 00000000..fd2807df --- /dev/null +++ b/examples/fill.py @@ -0,0 +1,62 @@ +# Fill a PDF template with your data via the Anvil API. +# Docs: https://www.useanvil.com/docs/api/fill-pdf +# +# Run this from the project root: +# ANVIL_API_KEY=YOUR_KEY python examples/fill.py && open ./fill-output.pdf + +import os + +from python_anvil.api import Anvil + + +API_KEY = os.environ.get("ANVIL_API_KEY") + +# The PDF template ID to fill. This is a sample template available to anyone. +# See https://www.useanvil.com/help/tutorials/set-up-a-pdf-template for details +# on setting up your own template. +PDF_TEMPLATE_EID = "05xXsZko33JIO6aq5Pnr" + +# Fill data can be an instance of `FillPDFPayload` or a plain dict. +# The keys in `data` must match the field IDs on the PDF template, +# which are usually camelCase. +FILL_DATA = { + "title": "My PDF Title", + "font_size": 10, + "text_color": "#333333", + "data": { + "shortText": "Hello World!", + "date": "2024-01-15", + "name": {"firstName": "Robin", "mi": "W", "lastName": "Smith"}, + "email": "testy@example.com", + "phone": {"num": "5554443333", "region": "US", "baseRegion": "US"}, + "usAddress": { + "street1": "123 Main St #234", + "city": "San Francisco", + "state": "CA", + "zip": "94106", + "country": "US", + }, + "ssn": "456454567", + "ein": "897654321", + "checkbox": True, + "decimalNumber": 12345.67, + "dollar": 123.45, + "integer": 12345, + "percent": 50.3, + "longText": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + }, +} + + +def main(): + anvil = Anvil(api_key=API_KEY) + + # Returns the PDF binary + res = anvil.fill_pdf(PDF_TEMPLATE_EID, FILL_DATA) + + with open("./fill-output.pdf", "wb") as f: + f.write(res) + + +if __name__ == "__main__": + main() diff --git a/examples/fill_pdf.py b/examples/fill_pdf.py deleted file mode 100644 index a42d2fe6..00000000 --- a/examples/fill_pdf.py +++ /dev/null @@ -1,87 +0,0 @@ -# Run this from the project root -# -# ANVIL_API_KEY=YOUR_KEY python examples/fill_pdf.py && open ./filled.pdf - -import os - -from python_anvil.api import Anvil - - -API_KEY = os.environ.get("ANVIL_API_KEY") -# or set your own key here -# API_KEY = 'my-api-key' - -# The PDF template ID to fill. This PDF template ID is a sample template -# available to anyone. -# -# See https://www.useanvil.com/help/tutorials/set-up-a-pdf-template for details -# on setting up your own template -PDF_TEMPLATE_EID = "05xXsZko33JIO6aq5Pnr" - -# PDF fill data can be an instance of `FillPDFPayload` or a plain dict. -# `FillPDFPayload` is from `python_anvil.api_resources.payload import FillPDFPayload`. -# If using a plain dict, fill data keys can be either Python snake_case with -# underscores, or in camelCase. Note, though, that the keys in `data` must -# match the keys on the form. This is usually in camelCase. -# If you'd like to use camelCase on all data, you can call `Anvil.fill_pdf()` -# with a full JSON payload instead. -FILL_DATA = { - "title": "My PDF Title", - "font_size": 10, - "text_color": "#333333", - "data": { - "shortText": "HELLOO", - "date": "2022-07-08", - "name": {"firstName": "Robin", "mi": "W", "lastName": "Smith"}, - "email": "testy@example.com", - "phone": {"num": "5554443333", "region": "US", "baseRegion": "US"}, - "usAddress": { - "street1": "123 Main St #234", - "city": "San Francisco", - "state": "CA", - "zip": "94106", - "country": "US", - }, - "ssn": "456454567", - "ein": "897654321", - "checkbox": True, - "radioGroup": "cast68d7e540afba11ecaf289fa5a354293a", - "decimalNumber": 12345.67, - "dollar": 123.45, - "integer": 12345, - "percent": 50.3, - "longText": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", - "textPerLine": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", - "textPerLetter": "taH9QGigei6G5BtTUA4", - "image": "https://placehold.co/600x400", - }, -} - - -def main(): - anvil = Anvil(api_key=API_KEY) - - # Fill the provided cast eid (see PDF Templates in your Anvil account) - # with the data above. This will return bytes for use in directly writing - # to a file. - res = anvil.fill_pdf(PDF_TEMPLATE_EID, FILL_DATA) - - # Version number support - # ---------------------- - # A version number can also be passed in. This will retrieve a specific - # version of the PDF to be filled if you don't want the current version - # to be used. - # - # You can also use the constant `Anvil.VERSION_LATEST` to fill a PDF with - # your latest, unpublished changes. Use this if you'd like to fill out a - # draft version of your template/PDF. - # - # res = anvil.fill_pdf('abc123', data, version_number=Anvil.VERSION_LATEST) - - # Write the bytes to disk - with open('./filled.pdf', 'wb') as f: - f.write(res) - - -if __name__ == '__main__': - main() diff --git a/examples/generate_html.py b/examples/generate_html.py new file mode 100644 index 00000000..6f0fcaaa --- /dev/null +++ b/examples/generate_html.py @@ -0,0 +1,56 @@ +# Generate a PDF from HTML and CSS via the Anvil API. +# Docs: https://www.useanvil.com/docs/api/generate-pdf#html--css-to-pdf +# +# Run this from the project root: +# ANVIL_API_KEY=YOUR_KEY python examples/generate_html.py +# Then: open ./generate-html-output.pdf + +import os + +from python_anvil.api import Anvil +from python_anvil.api_resources.payload import GeneratePDFPayload + + +API_KEY = os.environ.get("ANVIL_API_KEY") + +HTML = """ +

What is Lorem Ipsum?

+

+ Lorem Ipsum is simply dummy text of the printing and typesetting + industry. Lorem Ipsum has been the industry's standard dummy text + ever since the 1500s, when an unknown printer took + a galley of type and scrambled it to make a type specimen book. +

+

Where does it come from?

+

+ Contrary to popular belief, Lorem Ipsum is not simply random text. + It has roots in a piece of classical Latin literature from + 45 BC, making it over 2000 years old. +

+""" + +CSS = """ +body { font-size: 14px; color: #171717; } +.header-one { text-decoration: underline; } +.header-two { font-style: italic; } +""" + + +def main(): + anvil = Anvil(api_key=API_KEY) + + payload = GeneratePDFPayload( + type="html", + title="Example HTML to PDF", + data=dict(html=HTML, css=CSS), + ) + + # Returns the PDF binary + response = anvil.generate_pdf(payload) + + with open("./generate-html-output.pdf", "wb") as f: + f.write(response) + + +if __name__ == "__main__": + main() diff --git a/examples/generate_markdown.py b/examples/generate_markdown.py new file mode 100644 index 00000000..8b1ba3ea --- /dev/null +++ b/examples/generate_markdown.py @@ -0,0 +1,54 @@ +# Generate a PDF from Markdown-structured data via the Anvil API. +# Docs: https://www.useanvil.com/docs/api/generate-pdf#markdown-to-pdf +# +# Run this from the project root: +# ANVIL_API_KEY=YOUR_KEY python examples/generate_markdown.py +# Then: open ./generate-markdown-output.pdf + +import os + +from python_anvil.api import Anvil +from python_anvil.api_resources.payload import GeneratePDFPayload + + +API_KEY = os.environ.get("ANVIL_API_KEY") + + +def main(): + anvil = Anvil(api_key=API_KEY) + + payload = GeneratePDFPayload( + type="markdown", + title="Example Invoice", + data=[ + dict(label="Name", content="Sally Jones"), + dict( + content=( + "Lorem **ipsum** dolor sit _amet_, consectetur adipiscing " + "elit, sed [do eiusmod](https://www.useanvil.com/docs) " + "tempor incididunt ut labore et dolore magna aliqua." + ) + ), + dict( + table=dict( + firstRowHeaders=True, + rows=[ + ["Description", "Quantity", "Price"], + ["4x Large Widgets", "4", "$40.00"], + ["10x Medium Sized Widgets in dark blue", "10", "$100.00"], + ["10x Small Widgets in white", "6", "$60.00"], + ], + ) + ), + ], + ) + + # Returns the PDF binary + response = anvil.generate_pdf(payload) + + with open("./generate-markdown-output.pdf", "wb") as f: + f.write(response) + + +if __name__ == "__main__": + main() diff --git a/examples/generate_pdf.py b/examples/generate_pdf.py deleted file mode 100644 index 40a5af54..00000000 --- a/examples/generate_pdf.py +++ /dev/null @@ -1,74 +0,0 @@ -# Run this from the project root -# -# ANVIL_API_KEY=YOUR_KEY python examples/generate_pdf.py && open ./generated.pdf - -import os - -from python_anvil.api import Anvil -from python_anvil.api_resources.payload import GeneratePDFPayload - - -API_KEY = os.environ.get("ANVIL_API_KEY") -# or set your own key here -# API_KEY = 'my-api-key' - - -def main(): - anvil = Anvil(api_key=API_KEY) - - data = html_data() - - # You can specify data in literal dict form - # data = html_data_literal() - - # Or you can generate from markdown - # data = markdown_data() - - response = anvil.generate_pdf(data) - - # Write the bytes to disk - with open('./generated.pdf', 'wb') as f: - f.write(response) - - -def html_data(): - return GeneratePDFPayload( - type="html", - title="Some Title", - data=dict( - html="

HTML Heading

", - css="h2 { color: red }", - ), - # Optional page configuration - # page=dict( - # width="8.5in", - # height="11in", - # ), - ) - - -def html_data_literal(): - return { - "type": "html", - "title": "Some Title", - "data": { - "html": "

HTML Heading

", - "css": "h2 { color: blue }", - }, - } - - -def markdown_data(): - return GeneratePDFPayload( - type="markdown", - title="Some Title", - data=[dict(label="Test", content="Lorem __Ipsum__")], - # Optional args - # font_size=10, - # font_family="Lobster", - # text_color="#cc0000", - ) - - -if __name__ == '__main__': - main()