""" upload_docusign_template.py --------------------------- Uploads a DocuSign template JSON file to DocuSign via the REST API. Authenticates using JWT grant (no Node.js dependency required). Usage: python3 src/upload_docusign_template.py --file migration-output//docusign-template.json First-time setup: python3 src/docusign_auth.py --consent # grant consent once python3 src/upload_docusign_template.py --file Required .env keys (see docusign_auth.py for full list): DOCUSIGN_CLIENT_ID, DOCUSIGN_USER_ID, DOCUSIGN_ACCOUNT_ID, DOCUSIGN_PRIVATE_KEY_PATH, DOCUSIGN_AUTH_SERVER, DOCUSIGN_BASE_URL """ import argparse import json import os import sys import requests from dotenv import load_dotenv load_dotenv() sys.path.insert(0, os.path.dirname(__file__)) from docusign_auth import get_access_token def upload_template(file_path: str) -> str: """ POST a template JSON file to the DocuSign Templates API. Returns the created templateId. """ if not os.path.exists(file_path): print(f"ERROR: File not found: {file_path}") sys.exit(1) with open(file_path) as f: template = json.load(f) account_id = os.getenv("DOCUSIGN_ACCOUNT_ID") base_url = os.getenv("DOCUSIGN_BASE_URL", "https://demo.docusign.net/restapi") if not account_id: print("ERROR: DOCUSIGN_ACCOUNT_ID must be set in .env") sys.exit(1) token = get_access_token() headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept": "application/json", } url = f"{base_url}/v2.1/accounts/{account_id}/templates" print(f"Uploading '{template.get('name', file_path)}' to DocuSign...") resp = requests.post(url, headers=headers, json=template) if resp.status_code == 401: # Token may have just expired — clear cache and retry once os.environ.pop("DOCUSIGN_ACCESS_TOKEN", None) os.environ.pop("DOCUSIGN_TOKEN_EXPIRY", None) token = get_access_token() headers["Authorization"] = f"Bearer {token}" resp = requests.post(url, headers=headers, json=template) if not resp.ok: print(f"ERROR: Upload failed ({resp.status_code})") print(resp.text) sys.exit(1) result = resp.json() template_id = result.get("templateId") print(f"Template created: {template_id}") return template_id def main(): parser = argparse.ArgumentParser( description="Upload a DocuSign template JSON to your DocuSign account" ) parser.add_argument( "--file", required=True, help="Path to the docusign-template.json file to upload" ) args = parser.parse_args() upload_template(args.file) if __name__ == "__main__": main()