Hey there, fellow developer! Ready to supercharge your document workflows? Let's dive into building a PandaDoc API integration in Python. PandaDoc's API is a powerhouse for automating document creation, sending, and tracking. By the end of this guide, you'll be wielding this tool like a pro.
Before we jump in, make sure you've got:
Got all that? Great! Let's roll.
First things first, let's get our project structure in order:
mkdir pandadoc_integration cd pandadoc_integration python -m venv venv source venv/bin/activate # On Windows, use `venv\Scripts\activate` pip install requests
Alright, time to get that API key. Head over to your PandaDoc account, navigate to the API section, and grab your key. We'll use it to authenticate our requests:
import requests API_KEY = 'your_api_key_here' BASE_URL = 'https://api.pandadoc.com/public/v1' headers = { 'Authorization': f'API-Key {API_KEY}', 'Content-Type': 'application/json' }
Let's start with the bread and butter of document operations:
def create_document(name, content): url = f'{BASE_URL}/documents' payload = { 'name': name, 'document_template_uuid': 'your_template_id', 'recipients': [{'email': '[email protected]', 'first_name': 'John', 'last_name': 'Doe'}], 'fields': content } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage doc = create_document('My Awesome Document', {'field1': 'value1', 'field2': 'value2'}) print(f"Document created with ID: {doc['id']}")
def get_document(doc_id): url = f'{BASE_URL}/documents/{doc_id}' response = requests.get(url, headers=headers) return response.json() # Usage doc_details = get_document('abc123') print(f"Document status: {doc_details['status']}")
def send_document(doc_id): url = f'{BASE_URL}/documents/{doc_id}/send' payload = {'message': 'Please sign this document'} response = requests.post(url, headers=headers, json=payload) return response.json() # Usage send_result = send_document('abc123') print(f"Document sent: {send_result['id']}")
Now that we've got the basics down, let's spice things up:
def create_from_template(template_id, data): url = f'{BASE_URL}/documents' payload = { 'template_uuid': template_id, 'recipients': [{'email': '[email protected]', 'first_name': 'John', 'last_name': 'Doe'}], 'tokens': data } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage doc = create_from_template('template123', {'customer_name': 'Acme Inc', 'order_number': '12345'})
from flask import Flask, request app = Flask(__name__) @app.route('/webhook', methods=['POST']) def handle_webhook(): data = request.json if data['event'] == 'document_state_changed': print(f"Document {data['document']['id']} changed to status: {data['document']['status']}") return '', 200 if __name__ == '__main__': app.run(port=5000)
Always expect the unexpected:
import time def api_call_with_retry(func, *args, max_retries=3, **kwargs): for attempt in range(max_retries): try: return func(*args, **kwargs) except requests.exceptions.RequestException as e: if attempt == max_retries - 1: raise time.sleep(2 ** attempt) # Exponential backoff # Usage try: doc = api_call_with_retry(create_document, 'Retry Test', {'field': 'value'}) except requests.exceptions.RequestException as e: print(f"Failed to create document after multiple attempts: {e}")
Don't forget to test! Here's a quick unit test example:
import unittest from unittest.mock import patch from your_module import create_document class TestPandaDocIntegration(unittest.TestCase): @patch('requests.post') def test_create_document(self, mock_post): mock_post.return_value.json.return_value = {'id': 'test123'} result = create_document('Test Doc', {'field': 'value'}) self.assertEqual(result['id'], 'test123') if __name__ == '__main__': unittest.main()
As you scale up, keep these in mind:
And there you have it! You're now equipped to build a robust PandaDoc integration in Python. Remember, the API has a ton more features to explore, so don't be afraid to dive deeper into the official documentation.
Happy coding, and may your documents always be perfectly formatted and promptly signed!