
Implementation Guide: Auto-populate transaction management platforms when a contract is executed
Step-by-step implementation guide for deploying AI to auto-populate transaction management platforms when a contract is executed for Real Estate clients.
Hardware Procurement
Ricoh ScanSnap iX1600 Wireless Document Scanner
$380 MSP cost / $495–$550 suggested resale (bundled with setup and ScanSnap Home configuration)
Digitizes paper contracts that arrive via fax, courier, or in-person signing so they can be processed by the OCR/document parsing pipeline. 40 ppm duplex scanning with automatic document feeder. Required only if the brokerage still handles any paper contracts; skip if 100% of contracts are executed electronically via DocuSign or equivalent.
Ricoh ScanSnap iX2500 Wireless Document Scanner
$400 MSP cost / $530–$600 suggested resale (bundled with setup)
Premium alternative to the iX1600 for high-volume offices. 45 ppm with 100-sheet ADF. Recommended for brokerages processing 50+ paper documents per week. Choose either the iX1600 OR iX2500, not both, based on client volume.
Software Procurement
Zapier Professional Plan
$19.99/month (750 tasks) billed annually; Team plan at $69/month (2,000 tasks) if multi-user access is needed
Primary automation middleware that connects the eSignature webhook trigger to the TM platform API. Handles the orchestration logic: receive webhook, parse payload, map fields, create transaction record, notify team. Professional plan required for multi-step Zaps and webhooks.
Make (formerly Integromat) Core Plan
$9/month (Core); $16/month (Pro with priority execution)
Alternative to Zapier with more granular control over data transformation, better error handling, and lower per-operation cost at scale. Recommended for brokerages processing 50+ transactions/month where Zapier task limits become costly.
DocuSign Real Estate Starter or REALTORS® Plan
$10/month (Starter, 5 envelopes/month) to $20/month (Enhanced, unlimited envelopes) billed annually; NAR member pricing available
eSignature platform that serves as the trigger event source. When an envelope status changes to 'completed,' DocuSign fires a webhook (Connect) or Zapier trigger that initiates the entire automation workflow. Most brokerages already have this.
Dotloop Business+ or Premium
$31.99/month (single agent); custom brokerage pricing starting at $149/month for teams, $199/month for enterprise
Target transaction management platform that receives auto-populated deal data. Dotloop's Facade API enables creating a loop and populating all data (property info, contacts, loop template) in a single API call, making it the most automation-friendly TM platform on the market.
SkySlope Essentials or Professional
$25/user/month (Essentials, 10 transactions/month) to $40/user/month (Professional, unlimited transactions)
Alternative target TM platform. SkySlope's Transaction Management API and Forms API allow programmatic creation and population of transaction files. Recommended for compliance-focused brokerages that value SkySlope's built-in Smart Audit capability.
Azure AI Document Intelligence (Form Recognizer)
$10 per 1,000 pages (prebuilt contract model); $30 per 1,000 pages (custom extraction model). Typical brokerage: $5–$30/month
Optional but recommended OCR/document parsing service that extracts structured data from PDF contracts. The prebuilt Contract model extracts parties, jurisdictions, contract ID, title, dates, and amounts. A custom model can be trained on the brokerage's specific contract templates (state-specific purchase agreements, listing agreements, amendments) for higher accuracy.
Follow Up Boss CRM
$69/user/month (Grow); $499/month for 10 users (Pro); $1,000/month for 30 users (Platform)
Optional downstream integration target. When a transaction record is created in the TM platform, the automation can also update the corresponding contact record in Follow Up Boss to reflect the deal stage, ensuring CRM and TM platforms stay in sync. Most brokerages already subscribe.
QuickBooks Online
$30–$200/month depending on plan; most brokerages already have this
Optional downstream integration target. Automation can create a preliminary deal record or invoice entry in QuickBooks when a transaction is opened, pre-populating commission split data for the accounting team.
Prerequisites
- Active subscription to an eSignature platform (DocuSign, SkySlope DigiSign, or Authentisign) with API/webhook access enabled. DocuSign Connect or Zapier integration must be available on the client's plan.
- Active subscription to a transaction management platform (Dotloop, SkySlope, Docusign Rooms, or Lone Wolf Transactions) with API access enabled. Confirm with the vendor that API access is included in the client's current plan tier.
- Business internet connection with minimum 25 Mbps download speed and reliable uptime. All platforms are cloud-hosted SaaS, so no special network configuration is required beyond standard HTTPS (port 443) outbound access.
- Client must designate a Transaction Coordinator or Office Manager as the primary point of contact for workflow mapping, field definitions, and user acceptance testing.
- Complete inventory of all contract types the brokerage uses: purchase agreements, listing agreements, buyer agency agreements, amendments, addenda, counter-offers, lease agreements. Obtain blank templates and 5–10 completed examples (with PII redacted) of each type for field mapping.
- Microsoft 365 or Google Workspace account for the brokerage (for email notifications, document storage, and optional Power Automate integration).
- Azure subscription (free tier is sufficient to start) if using Azure AI Document Intelligence for document parsing. The MSP can provision this under their own Azure tenant and bill the client with markup.
- Admin access to the client's eSignature platform to configure webhooks/API credentials.
- Admin access to the client's TM platform to configure API keys, create custom fields if needed, and set up integration users.
- List of all agents and their roles (listing agent, buyer's agent, team lead, TC, broker) for role-based access configuration in the automation workflows.
- Confirmation of state-specific compliance requirements: document retention period, required disclosures, electronic signature validity rules for the client's operating state(s).
Installation Steps
...
Step 1: Discovery & Workflow Audit
Conduct a 2–3 hour on-site or virtual discovery session with the brokerage's Transaction Coordinator, Office Manager, and Broker of Record. Map the current manual workflow from contract execution to transaction file creation. Document every field that is currently entered manually, the source of that data (which page/section of the contract), and the target field in the TM platform. Identify all contract types (purchase agreement, listing agreement, amendment, addendum, lease) and their frequency. Document the brokerage's compliance requirements, state-specific forms, and any custom fields in their TM platform.
Use a shared spreadsheet or Miro board for collaborative field mapping. Template available: create a Google Sheet with columns for Source Field Name, Source Location (document/page/section), Target Platform, Target Field Name, Data Type, Required/Optional, and Transformation Rules. This mapping document becomes the blueprint for all automation configuration.
Step 2: Provision Automation Platform Account
Create and configure the automation middleware account. For Zapier: sign up for the Professional plan ($19.99/month) under the MSP's billing. For Make: sign up for the Core plan ($9/month). The MSP should own the account and grant the client view-only or editor access as appropriate. This ensures the MSP retains control for ongoing management and the client cannot accidentally break workflows.
- For Zapier: Sign up at https://zapier.com/sign-up
- Create a dedicated workspace named: [ClientName]-RealEstate-Automation
- For Make: Sign up at https://www.make.com/en/register
- Create an organization named: [ClientName]-RealEstate-Automation
Use a dedicated service account email (e.g., automation@mspdomain.com or clientname-automation@mspdomain.com) rather than a personal email. Enable 2FA on the account. Store credentials in the MSP's password manager (e.g., IT Glue, Hudu, or 1Password Business).
Step 3: Configure eSignature Platform Webhook/API Credentials
Log into the client's DocuSign admin console and configure the webhook trigger. For DocuSign Connect: navigate to Settings > Connect > Add Configuration. Set the webhook URL to your automation platform's webhook endpoint. For Zapier: use the built-in DocuSign trigger 'Envelope Sent or Completed.' For Make: use the DocuSign Watch Envelope module. Configure the trigger to fire only on the 'Completed' status to avoid processing partial signatures. Generate API credentials (Integration Key, Secret Key, RSA Key) if using direct API access.
DocuSign Connect requires a paid plan (not the free developer account). Confirm the client's DocuSign plan supports Connect or API access. For SkySlope DigiSign, the trigger mechanism differs—use SkySlope's API endpoint or Zapier integration instead. Always test the webhook with a non-production envelope first.
Step 4: Configure Transaction Management Platform API Access
Generate API credentials for the target TM platform. For Dotloop: register as a developer at developer.dotloop.com, create an application, and obtain OAuth2 client credentials. For SkySlope: contact SkySlope support or your SkySlope partner manager to request API access keys. For Docusign Rooms: use the same DocuSign developer account but enable the Rooms API scope. Create a dedicated 'integration user' in the TM platform with appropriate permissions—typically admin-level access to create transactions and populate all fields, but restricted from deleting records.
- Dotloop API Setup: Navigate to https://developer.dotloop.com
- Register as developer with MSP service account
- Create new application: '[ClientName] Auto-Population'
- Note Client ID and Client Secret
- Configure redirect URI: https://zapier.com/dashboard/auth/oauth/return/App[XXXXX]CLIAPI/
- Request OAuth2 scopes: loop:read, loop:write, contact:write, profile:read
- SkySlope API Setup: Contact SkySlope support: support@skyslope.com
- Request API access for brokerage account [Account ID]
- Specify endpoints needed: Transactions (POST/PUT), Files (POST)
- Receive API key and documentation
# Single-call loop creation example. See custom_ai_components for full body
# payload specification.
POST https://api-gateway.dotloop.com/public/v2/profile/{profile_id}/loop
Authorization: Bearer {access_token}Dotloop API rate limits: 2,000 requests per hour. SkySlope API access may require a brokerage-level subscription. Store all API keys in the MSP's secrets management system—never hard-code them in automation workflows. OAuth2 tokens expire; configure automatic token refresh in your middleware.
Step 5: Build Core Automation Workflow - Zapier Implementation
Build the primary Zap that fires when a contract is completed and creates a transaction record in the TM platform. This is the central workflow. Structure: Trigger (DocuSign Envelope Completed) → Filter (only purchase agreements) → Formatter (parse and transform fields) → Action (create Dotloop loop or SkySlope transaction). For each contract type, you will create a separate Zap or use Zapier Paths to branch logic based on the contract type detected in the envelope name or custom fields.
# Zapier Workflow Structure:
#
# TRIGGER: DocuSign - Envelope Completed
# → Returns: envelope_id, subject, sender, recipients[], tabs/fields[], documents[]
#
# STEP 2: Filter - Only Continue If
# → Condition: Envelope Subject contains 'Purchase Agreement' OR
# Custom Field 'contract_type' = 'purchase'
#
# STEP 3: Formatter - Text Utilities
# → Extract buyer name from recipients[0].name
# → Extract seller name from recipients[1].name
# → Parse property address from tabs['property_address'].value
# → Parse purchase price from tabs['purchase_price'].value
# → Parse closing date from tabs['closing_date'].value
# → Parse earnest money from tabs['earnest_money'].value
#
# STEP 4: Dotloop - Create Loop (via Facade API)
# → Profile: [Client's Dotloop Profile ID]
# → Loop Name: '{property_address} - {buyer_name}'
# → Transaction Type: 'PURCHASE_OFFER'
# → Status: 'UNDER_CONTRACT'
# → Property Address: {parsed_address}
# → Purchase Price: {parsed_price}
# → Closing Date: {parsed_closing_date}
# → Buyer Contact: {buyer_name, buyer_email}
# → Seller Contact: {seller_name, seller_email}
# → Listing Agent: {listing_agent_name, listing_agent_email}
# → Buyer Agent: {buyer_agent_name, buyer_agent_email}
#
# STEP 5: Dotloop - Upload Document
# → Loop ID: {loop_id from Step 4}
# → Document: {PDF from DocuSign envelope}
# → Folder: 'Executed Contracts'
#
# STEP 6: Email/Slack Notification
# → To: Transaction Coordinator
# → Message: 'New transaction auto-created: {property_address}'
# → Include: Link to Dotloop loopDocuSign tabs/fields must be properly named in the contract templates for extraction to work. Work with the client to standardize their DocuSign template field names (e.g., 'property_address', 'purchase_price', 'closing_date'). If field names are inconsistent across templates, you'll need separate parsing logic per template. Zapier's built-in DocuSign integration can pull tab values directly without OCR if the contracts use fillable DocuSign fields.
Step 6: Configure DocuSign Template Field Standardization
This is a critical step that ensures reliable data extraction. Review all of the client's DocuSign contract templates and standardize the field (tab) names. Each fillable field in a DocuSign template has a tab label—this label is what the API returns in the webhook payload. Map every field the automation needs to a consistent naming convention. Update all templates to use these standardized names. This eliminates the need for OCR on electronically-signed contracts and ensures 100% extraction accuracy.
# DocuSign Template Field Naming Convention:
#
# Property Information:
# property_street_address → '123 Main St'
# property_city → 'Austin'
# property_state → 'TX'
# property_zip → '78701'
# property_county → 'Travis'
# mls_number → 'MLS12345678'
#
# Financial Terms:
# purchase_price → '450000'
# earnest_money → '10000'
# option_fee → '500'
# financing_type → 'Conventional'
# loan_amount → '360000'
#
# Dates:
# effective_date → '2025-01-15'
# closing_date → '2025-02-28'
# option_period_end → '2025-01-25'
# financing_deadline → '2025-02-15'
# inspection_deadline → '2025-01-22'
#
# Parties:
# buyer_name → 'John and Jane Smith'
# buyer_email → 'jsmith@email.com'
# buyer_phone → '512-555-1234'
# seller_name → 'Robert Johnson'
# seller_email → 'rjohnson@email.com'
# seller_phone → '512-555-5678'
# listing_agent_name → 'Sarah Williams'
# listing_agent_email → 'sarah@realty.com'
# buying_agent_name → 'Mike Davis'
# buying_agent_email → 'mike@realty.com'
# listing_brokerage → 'ABC Realty'
# buying_brokerage → 'XYZ Realty'
# title_company → 'First American Title'
#
# Contract Metadata:
# contract_type → 'purchase_agreement'
# amendment_number → ''
#
# In DocuSign Template Editor:
# 1. Open template
# 2. Click on each field/tab
# 3. In Properties panel, set 'Data Label' to the standardized name
# 4. Save template
# 5. Repeat for all templatesThis step requires coordination with the brokerage's designated admin or TC who manages DocuSign templates. If the brokerage uses state association forms (e.g., TAR forms in Texas, CAR forms in California), the field standardization must be done on their specific copies/overlays of these forms. Some form providers (zipForms, SkySlope Forms) may have their own field naming—document the mapping. This is the single most impactful step for automation reliability.
Step 7: Build Document Parsing Pipeline (Optional - for Scanned/Non-Standard Contracts)
If the brokerage receives contracts that are not digitally signed via DocuSign (e.g., scanned paper contracts, contracts from counterparties using different eSignature platforms, or legacy PDF forms), configure Azure AI Document Intelligence to extract structured data from these documents. This is an optional but recommended capability that handles edge cases and provides a fallback for non-standard documents.
# 1. Create Azure AI Document Intelligence resource:
az login
az group create --name rg-realestate-docai --location eastus2
az cognitiveservices account create \
--name docai-[clientname] \
--resource-group rg-realestate-docai \
--kind FormRecognizer \
--sku S0 \
--location eastus2
# 2. Get API endpoint and key:
az cognitiveservices account keys list \
--name docai-[clientname] \
--resource-group rg-realestate-docai
az cognitiveservices account show \
--name docai-[clientname] \
--resource-group rg-realestate-docai \
--query properties.endpoint
# 3. Test with prebuilt Contract model:
curl -X POST "{endpoint}/formrecognizer/documentModels/prebuilt-contract:analyze?api-version=2023-07-31" \
-H "Content-Type: application/pdf" \
-H "Ocp-Apim-Subscription-Key: {api_key}" \
--data-binary @sample_contract.pdf
# 4. Train custom model (for state-specific forms):
# Upload 5-10 labeled examples to Azure Blob Storage
# Use Document Intelligence Studio (https://formrecognizer.appliedai.azure.com/)
# Create a custom extraction model with fields matching Step 6 naming convention
# Training typically completes in 5-15 minutes
# 5. In Zapier/Make, add an HTTP action step:
# POST to Azure Document Intelligence analyze endpoint
# Wait for result (polling or async callback)
# Parse JSON response to extract field values
# Feed extracted values into TM platform creation stepThe prebuilt Contract model works well for standard purchase agreements but may miss state-specific fields. Training a custom model on the client's actual forms (5-10 labeled examples) significantly improves accuracy. Cost is minimal: $10/1,000 pages for prebuilt, $30/1,000 pages for custom. A typical brokerage processing 100 transactions/month with 20% requiring OCR would cost approximately $2-6/month. Always validate OCR-extracted data by flagging low-confidence fields for human review.
Step 8: Build Error Handling and Notification Logic
Configure comprehensive error handling to ensure no transaction is lost due to automation failures. Every step in the workflow should have a fallback. If the TM platform API returns an error, the automation should: (1) log the error with full context, (2) store the transaction data for retry, (3) notify the MSP and TC via email/Slack. Implement a dead-letter queue pattern where failed transactions are saved to a Google Sheet or Airtable for manual processing.
- In Zapier: Use built-in error handling — on each action step, enable 'Error Handler' (available on Professional plan)
- If Dotloop/SkySlope API step fails → Path A (on error): Log to Google Sheets 'Failed Transactions' spreadsheet; send email to tc@brokerage.com AND alerts@msp.com; include: envelope_id, property_address, error_message, timestamp
- If Dotloop/SkySlope API step succeeds → Path B: continue normal flow
- In Make: Add 'Error Handler' route to each API module; route errors to Google Sheets 'Failed Transactions' module, Email notification module, and Slack webhook module (if client uses Slack)
- Google Sheets 'Failed Transactions' structure — Column A: Timestamp, Column B: Envelope ID, Column C: Property Address, Column D: Error Message, Column E: Full Payload (JSON), Column F: Retry Status (Pending/Retried/Resolved), Column G: Resolution Notes
- Set up a daily digest Zap — Trigger: Schedule every day at 8:00 AM; Action: Google Sheets - get rows where Retry Status = 'Pending'; Action: Email digest to TC and MSP with pending failures
Error handling is what separates a professional automation from a fragile script. Common failure modes include: expired OAuth tokens (configure auto-refresh), API rate limits (add delays between calls), network timeouts (configure retries with exponential backoff), and data validation errors (field too long, wrong format). Test each failure mode deliberately during QA.
Step 9: Build CRM Sync Workflow (Optional Downstream Integration)
If the client uses Follow Up Boss or another CRM, build a secondary workflow that updates the CRM contact record when a new transaction is created. This ensures the CRM reflects the deal stage without manual updates. The trigger is the successful completion of the primary workflow (TM platform record created).
# Follow Up Boss integration steps and API reference
# Zapier CRM Sync Workflow:
#
# TRIGGER: Zapier - Catch Hook (internal webhook from primary Zap)
# OR: Dotloop - Loop Status Changed
#
# STEP 2: Follow Up Boss - Update Person
# → Search by email: {buyer_email}
# → Update stage to: 'Under Contract'
# → Add note: 'Transaction created in Dotloop: {loop_link}'
# → Add tag: 'Active Transaction'
#
# STEP 3: Follow Up Boss - Update Person
# → Search by email: {seller_email}
# → Update stage to: 'Under Contract (Seller)'
# → Add note: 'Transaction created in Dotloop: {loop_link}'
#
# Follow Up Boss API direct call (alternative):
# PUT https://api.followupboss.com/v1/people/{person_id}
# Headers: Authorization: Basic {base64(api_key:)}
# Body: {
# "stage": "Under Contract",
# "tags": ["Active Transaction"],
# "customFields": {
# "transaction_link": "{loop_link}",
# "closing_date": "{closing_date}",
# "property_address": "{property_address}"
# }
# }Follow Up Boss API uses Basic authentication with the API key as username and empty password. Rate limit is 200 requests per minute. If the contact doesn't exist in the CRM (common for seller-side when the listing was from another brokerage), the automation should create a new contact rather than failing silently. Coordinate with the client on whether they want auto-created contacts or just updates to existing ones.
Step 10: Configure Accounting System Pre-Population (Optional)
If the client uses QuickBooks Online, build a workflow that creates a preliminary sales receipt or journal entry when a transaction is created, pre-populating commission data for the accounting team. This is typically a Phase 2 enhancement after the core workflow is stable.
- TRIGGER: Completion of primary Zap (via Zapier webhook or schedule)
- STEP 2: QuickBooks Online - Create Sales Receipt or Invoice → Customer: {buyer_name} or {seller_name} → Line Items: → Listing Side Commission: {purchase_price} × {listing_commission_%} → Buyer Side Commission: {purchase_price} × {buyer_commission_%} → Memo: 'Transaction: {property_address}, Closing: {closing_date}' → Status: Draft (requires manual review before finalization)
- Note: Commission splits are typically NOT in the purchase agreement. The automation may need to pull commission data from: 1. The listing agreement (already in TM platform) 2. A custom field added to the DocuSign template 3. A lookup table maintained by the brokerage — Coordinate with the client's bookkeeper on the desired workflow.
QuickBooks integration is the most customization-heavy part of this project because commission structures vary widely: flat fees, percentage splits, tiered commissions, team splits, franchise fees, E&O deductions, etc. Recommend implementing this as a Phase 2 enhancement after the core TM auto-population is proven stable. The initial automation can simply create a placeholder entry with gross commission amounts, leaving the detailed split calculation to the bookkeeper.
Step 11: Scanner Configuration and Cloud Upload Pipeline (If Applicable)
If the client purchased a document scanner for paper contracts, configure the scanner to automatically upload scanned documents to a cloud folder that triggers the OCR parsing workflow. The ScanSnap iX1600/iX2500 supports direct cloud upload to Google Drive, OneDrive, SharePoint, or Dropbox via ScanSnap Home software.
Set scanner resolution to 300 DPI—this is the optimal balance between OCR accuracy and file size. Lower resolution reduces accuracy; higher resolution increases processing time without significant accuracy gains. Enable 'searchable PDF' in ScanSnap Home settings so that simple text extraction can be attempted before falling back to the full Document Intelligence API call.
Step 12: Security Hardening and Compliance Configuration
Implement security controls to protect PII flowing through the automation pipeline. Real estate contracts contain highly sensitive data: SSNs (on some state forms), financial account numbers, property details, and personal contact information. Configure encryption, access controls, and audit logging to meet GLBA, RESPA, and state privacy requirements.
Wire fraud is a critical concern in real estate. The automation must NEVER transmit or display wire instructions, bank account numbers, or routing numbers. If OCR accidentally extracts these fields, the automation should flag the transaction for manual review and suppress the sensitive data. Include a wire fraud warning in every automated notification email sent to parties.
Step 13: User Acceptance Testing (UAT)
Conduct structured testing with the client's Transaction Coordinator and a volunteer agent. Create test scenarios for each contract type and edge case. Use actual contract templates with synthetic (fake) data. Verify that every field populates correctly in the TM platform, notifications are delivered, and error handling works as expected.
- Test Case 1: Standard Purchase Agreement (Happy Path) — Create a DocuSign envelope using the standard purchase agreement template. Fill all fields with test data (use 'TEST' in property address). Complete signing ceremony with test signers. Verify: Dotloop loop created with correct property address. Verify: All mapped fields populated correctly. Verify: PDF document uploaded to loop. Verify: TC received notification email/Slack message. Verify: CRM contact updated (if configured).
- Test Case 2: Listing Agreement — Same flow but with listing-specific fields (commission %, listing period).
- Test Case 3: Amendment to Existing Contract — Verify automation updates existing loop rather than creating duplicate.
- Test Case 4: Missing Required Fields — Send envelope with blank purchase_price field. Verify: error logged, TC notified, transaction added to Failed sheet.
- Test Case 5: Scanned Paper Contract (if OCR configured) — Scan a sample contract through the scanner. Verify: OCR extracts fields with >90% accuracy. Verify: Transaction created in TM platform.
- Test Case 6: Duplicate Prevention — Trigger the same envelope twice. Verify: automation detects duplicate and skips or updates (not creates new).
- Test Case 7: API Failure Simulation — Temporarily invalidate TM platform API key. Trigger automation. Verify: error logged, TC notified, data preserved for retry.
UAT should involve at least 10 test transactions across all contract types before go-live. The TC should validate every field in the TM platform against the source contract. Document any field mapping corrections needed and update the automation accordingly. Sign-off from the TC and Broker on UAT results before proceeding to production.
Step 14: Agent Training and Go-Live
Conduct a 30-60 minute training session with all agents and the TC team. Cover: what the automation does, what agents need to do differently (nothing for DocuSign contracts, scan-and-upload for paper contracts), how to report issues, and what to expect in terms of timing (transactions appear in TM platform within 1-3 minutes of contract completion). Provide a one-page quick reference guide. Go live with monitoring enabled and a 30-day hypercare period.
The most common cause of automation failure post-go-live is agents modifying DocuSign templates and breaking field names. Emphasize in training that template changes must go through the TC or MSP to ensure field names remain standardized. Consider locking templates at the DocuSign admin level so only designated users can edit them. Schedule a 2-week check-in and 30-day review meeting during the hypercare period.
Custom AI Components
DocuSign-to-Dotloop Transaction Populator
Type: workflow Primary automation workflow that triggers when a DocuSign envelope reaches 'Completed' status and creates a fully populated Dotloop loop with property information, contacts, financial terms, and key dates. This is the core deterministic automation that replaces manual data entry by the Transaction Coordinator. Implementation:
Zapier Workflow Specification
Trigger
- App: DocuSign
- Event: Envelope Sent or Completed
- Account: Client's DocuSign account (OAuth2 connection)
- Filter: Status equals 'completed'
Step 2: Filter
- Type: Filter by Zapier
- Condition: Envelope Subject does not contain 'TEST' AND Envelope Subject does not contain 'VOID'
- Purpose: Exclude test envelopes and voided envelopes
Step 3: Paths (Contract Type Router)
- Type: Paths by Zapier
Path A: Purchase Agreement
- Condition: Tab 'contract_type' equals 'purchase_agreement' OR Envelope Subject contains 'Purchase Agreement' OR Envelope Subject contains 'Contract of Sale'
Path A - Step 1: Formatter - Utilities
- Transform: Parse property_street_address + property_city + property_state + property_zip into single formatted address
- Output:
{property_street_address}, {property_city}, {property_state} {property_zip}
Path A - Step 2: Formatter - Number
- Transform: Convert purchase_price from string to number (remove $ and commas)
- Input:
$450,000.00 - Output:
450000
Path A - Step 3: Formatter - Date/Time
- Transform: Convert closing_date to ISO 8601 format
- Input: Various formats (01/15/2025, January 15, 2025, etc.)
- Output:
2025-01-15
Path A - Step 4: Dotloop - Create Loop
- App: Dotloop
- Event: Create Loop
- Profile: {client_profile_id}
- Loop Name:
{formatted_address} - {buyer_name} - Loop Status: Under Contract
- Transaction Type: PURCHASE_OFFER
Loop Detail Mapping (via Dotloop API):
{
"name": "{formatted_address} - {buyer_name}",
"status": "UNDER_CONTRACT",
"transactionType": "PURCHASE_OFFER",
"loopDetails": {
"propertyAddress": {
"streetNumber": "{parsed_street_number}",
"streetName": "{parsed_street_name}",
"unit": "{property_unit}",
"city": "{property_city}",
"state": "{property_state}",
"zipCode": "{property_zip}",
"county": "{property_county}",
"mlsNumber": "{mls_number}"
},
"financials": {
"purchasePrice": {purchase_price_number},
"earnestMoney": {earnest_money_number},
"optionFee": {option_fee_number}
},
"dates": {
"contractDate": "{effective_date}",
"closingDate": "{closing_date}",
"optionPeriodExpiration": "{option_period_end}",
"financingDeadline": "{financing_deadline}",
"inspectionDeadline": "{inspection_deadline}"
},
"contacts": [
{
"role": "BUYER",
"name": "{buyer_name}",
"email": "{buyer_email}",
"phone": "{buyer_phone}"
},
{
"role": "SELLER",
"name": "{seller_name}",
"email": "{seller_email}",
"phone": "{seller_phone}"
},
{
"role": "LISTING_AGENT",
"name": "{listing_agent_name}",
"email": "{listing_agent_email}"
},
{
"role": "BUYERS_AGENT",
"name": "{buying_agent_name}",
"email": "{buying_agent_email}"
},
{
"role": "TITLE_CLOSER",
"name": "{title_company}"
}
]
}
}Path A - Step 5: Dotloop - Upload Document
- Loop ID:
{loop_id from Step 4} - Folder Name: Executed Contracts
- File: DocuSign envelope PDF (from trigger step)
- File Name:
Purchase_Agreement_{effective_date}_{buyer_name}.pdf
Path A - Step 6: Gmail/Outlook - Send Email
- To: {tc_email}
- Subject: ✅ New Transaction Auto-Created: {formatted_address}
Body: A new purchase transaction has been automatically created in Dotloop. Property: {formatted_address} Buyer: {buyer_name} Seller: {seller_name} Price: ${purchase_price} Closing Date: {closing_date} Dotloop Link: {loop_url} Please review the auto-populated fields within 24 hours and add any missing information.
WIRE FRAUD WARNING: Never send wire transfer instructions via email.
Path B: Listing Agreement
- Condition: Tab 'contract_type' equals 'listing_agreement' OR Envelope Subject contains 'Listing Agreement'
- Steps: Similar to Path A but with listing-specific fields (list price, listing period start/end, commission percentage, MLS status)
- Dotloop Transaction Type: LISTING
- Dotloop Status: ACTIVE_LISTING
Path C: Amendment/Addendum
- Condition: Tab 'contract_type' equals 'amendment' OR Envelope Subject contains 'Amendment' OR Envelope Subject contains 'Addendum'
- Search Dotloop for existing loop by property address
- If found: Upload document to existing loop, update modified fields
- If not found: Log to error sheet, notify TC
Default Path: Unknown Contract Type
- Log envelope details to Google Sheet for manual processing
- Notify TC
Error Handling (Applied to all paths)
- On API error (4xx/5xx): Log to Google Sheets 'Failed Transactions', send error email to MSP and TC
- On timeout: Retry once after 60 seconds, then fail to error handler
- On duplicate detection (Dotloop returns 409 Conflict): Log as duplicate, do not create new loop
Scanned Contract OCR Extraction Pipeline
Type: workflow Secondary automation workflow that processes scanned paper contracts uploaded to a cloud folder. Uses Azure AI Document Intelligence to extract structured data from the PDF, then feeds the extracted data into the same TM platform population logic as the primary workflow. Acts as a fallback for contracts not signed through DocuSign.
Implementation:
Make (Integromat) Scenario Specification
Module 1: Google Drive / OneDrive - Watch Files
- Folder: /Real Estate/Scanned Contracts/Inbox
- File Types: PDF, JPEG, PNG, TIFF
- Polling Interval: Every 5 minutes
Module 2: HTTP - Make a Request (Azure Document Intelligence - Analyze)
- Method: POST
- URL:
{azure_endpoint}/formrecognizer/documentModels/{model_id}:analyze?api-version=2023-07-31 - Headers:
Content-Type: application/pdf(or image type),Ocp-Apim-Subscription-Key: {azure_api_key} - Body: Binary file content from Module 1
- Model ID Options:
prebuilt-contractfor general contracts,custom-{clientname}-purchase-agreementfor trained custom model - Response: Operation-Location header with result URL
Module 3: HTTP - Make a Request (Poll for Result)
- Method: GET
- URL:
{operation_location_from_module_2} - Headers:
Ocp-Apim-Subscription-Key: {azure_api_key} - Retry: Poll every 5 seconds until status = 'succeeded' (max 60 seconds)
Module 4: JSON - Parse JSON
Input: Response body from Module 3
{
"property_address": "$.analyzeResult.documents[0].fields.PropertyAddress.content",
"buyer_name": "$.analyzeResult.documents[0].fields.Parties[?(@.role=='Buyer')].name",
"seller_name": "$.analyzeResult.documents[0].fields.Parties[?(@.role=='Seller')].name",
"purchase_price": "$.analyzeResult.documents[0].fields.PurchasePrice.content",
"closing_date": "$.analyzeResult.documents[0].fields.ClosingDate.content",
"effective_date": "$.analyzeResult.documents[0].fields.ContractDate.content",
"confidence_scores": {
"address_confidence": "$.analyzeResult.documents[0].fields.PropertyAddress.confidence",
"price_confidence": "$.analyzeResult.documents[0].fields.PurchasePrice.confidence"
}
}Module 5: Router (Confidence Check)
- Route A (High Confidence): All field confidence scores >= 0.85 → Continue to Module 6 (auto-populate TM platform)
- Route B (Low Confidence): Any field confidence score < 0.85 → Log to 'Manual Review Required' Google Sheet with extracted values and confidence scores → Send email to TC: 'Scanned contract requires manual review - OCR confidence low' → Move file to /NeedsReview folder
Module 6: Dotloop - Create Loop
- Uses extracted fields from Module 4 (same field mapping as primary workflow)
- Adds tag: 'OCR-Processed' to loop for TC awareness
- Adds note: 'This transaction was auto-populated from a scanned document via OCR. Please verify all fields.'
Module 7: Google Drive / OneDrive - Move File
- Move processed file from /Inbox to /Processed/{YYYY-MM} subfolder
Module 8: Gmail - Send Notification
- To: TC email
- Subject: 📄 Scanned Contract Processed: {property_address}
- Body: Includes all extracted fields, confidence scores, and Dotloop link
Error Handler (attached to all modules)
- On any error: Move file to /Failed folder, log error to Google Sheet, notify MSP
Custom Model Training Instructions
training-data-{clientname}Duplicate Transaction Detector
Type: integration Utility component that checks whether a transaction already exists in the TM platform before creating a new one. Prevents duplicate loops/files when contracts are re-signed, amendments trigger the workflow, or webhooks fire multiple times for the same envelope. Searches by property address and buyer name combination.
Implementation
// Runs before the Dotloop Create Loop action to check for existing
// transactions.
// Zapier Code Step: Duplicate Detection
// Input Data: property_address, buyer_name, dotloop_profile_id, dotloop_access_token
const propertyAddress = inputData.property_address.trim().toLowerCase();
const buyerName = inputData.buyer_name.trim().toLowerCase();
const profileId = inputData.dotloop_profile_id;
const accessToken = inputData.dotloop_access_token;
// Search existing loops in Dotloop
const response = await fetch(
`https://api-gateway.dotloop.com/public/v2/profile/${profileId}/loop?filter=*${encodeURIComponent(propertyAddress.substring(0, 30))}*&batchSize=50`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
if (!response.ok) {
// If search fails, allow creation (fail open) but flag for review
output = [{
duplicate_found: false,
existing_loop_id: null,
action: 'create_new',
warning: 'Duplicate check failed - API error. Proceeding with creation.'
}];
} else {
const data = await response.json();
const loops = data.data || [];
// Fuzzy match on property address
const matchingLoop = loops.find(loop => {
const loopName = (loop.name || '').toLowerCase();
const loopAddress = loopName.split(' - ')[0].trim();
// Check if addresses match (allowing for minor formatting differences)
const addressWords = propertyAddress.split(/[\s,]+/).filter(w => w.length > 2);
const matchCount = addressWords.filter(word => loopAddress.includes(word)).length;
const matchRatio = matchCount / addressWords.length;
return matchRatio >= 0.7; // 70% word overlap = likely same property
});
if (matchingLoop) {
output = [{
duplicate_found: true,
existing_loop_id: matchingLoop.id,
existing_loop_name: matchingLoop.name,
existing_loop_status: matchingLoop.status,
action: 'update_existing',
message: `Existing loop found: ${matchingLoop.name} (ID: ${matchingLoop.id}). Will update instead of creating new.`
}];
} else {
output = [{
duplicate_found: false,
existing_loop_id: null,
action: 'create_new',
message: 'No duplicate found. Safe to create new loop.'
}];
}
}Integration into Main Workflow
duplicate_found is false → Create new loop (existing Step 4)
- Path B (Duplicate Found): duplicate_found is true → Update existing loop with new data, upload new document to existing loop, notify TC that an existing transaction was updatedPUT https://api-gateway.dotloop.com/public/v2/profile/{profile_id}/loop/{existing_loop_id}/detailTransaction Data Field Mapper Configuration
Type: skill A reusable configuration map that defines the field-level translation between DocuSign tab names, Azure Document Intelligence output fields, and Dotloop/SkySlope API input fields. This acts as the single source of truth for all field mappings and can be updated without modifying the automation workflows themselves.
Implementation:
Store this configuration in a Google Sheet named 'Field Mapping Config' or as a JSON file in the automation platform's data store. The automation workflows reference this mapping to translate fields between systems.
{
"version": "1.0",
"last_updated": "2025-01-01",
"contract_types": {
"purchase_agreement": {
"dotloop_transaction_type": "PURCHASE_OFFER",
"dotloop_status": "UNDER_CONTRACT",
"skyslope_transaction_type": "Sale",
"fields": [
{
"canonical_name": "property_street_address",
"docusign_tab_label": "property_street_address",
"azure_docai_field": "PropertyAddress.streetAddress",
"dotloop_api_field": "loopDetails.propertyAddress.streetName",
"skyslope_api_field": "transaction.propertyAddress.street",
"data_type": "string",
"required": true,
"max_length": 200,
"transformation": "trim"
},
{
"canonical_name": "property_city",
"docusign_tab_label": "property_city",
"azure_docai_field": "PropertyAddress.city",
"dotloop_api_field": "loopDetails.propertyAddress.city",
"skyslope_api_field": "transaction.propertyAddress.city",
"data_type": "string",
"required": true,
"max_length": 100,
"transformation": "trim|title_case"
},
{
"canonical_name": "property_state",
"docusign_tab_label": "property_state",
"azure_docai_field": "PropertyAddress.state",
"dotloop_api_field": "loopDetails.propertyAddress.state",
"skyslope_api_field": "transaction.propertyAddress.state",
"data_type": "string",
"required": true,
"max_length": 2,
"transformation": "trim|uppercase",
"validation": "us_state_abbreviation"
},
{
"canonical_name": "property_zip",
"docusign_tab_label": "property_zip",
"azure_docai_field": "PropertyAddress.postalCode",
"dotloop_api_field": "loopDetails.propertyAddress.zipCode",
"skyslope_api_field": "transaction.propertyAddress.zip",
"data_type": "string",
"required": true,
"max_length": 10,
"transformation": "trim",
"validation": "regex:^[0-9]{5}(-[0-9]{4})?$"
},
{
"canonical_name": "purchase_price",
"docusign_tab_label": "purchase_price",
"azure_docai_field": "PurchasePrice.content",
"dotloop_api_field": "loopDetails.financials.purchasePrice",
"skyslope_api_field": "transaction.salePrice",
"data_type": "currency",
"required": true,
"transformation": "strip_currency_symbols|to_number",
"validation": "positive_number|max:999999999"
},
{
"canonical_name": "earnest_money",
"docusign_tab_label": "earnest_money",
"azure_docai_field": "EarnestMoney.content",
"dotloop_api_field": "loopDetails.financials.earnestMoney",
"skyslope_api_field": "transaction.earnestMoney",
"data_type": "currency",
"required": false,
"transformation": "strip_currency_symbols|to_number"
},
{
"canonical_name": "closing_date",
"docusign_tab_label": "closing_date",
"azure_docai_field": "ClosingDate.content",
"dotloop_api_field": "loopDetails.dates.closingDate",
"skyslope_api_field": "transaction.closingDate",
"data_type": "date",
"required": true,
"transformation": "parse_date|to_iso8601",
"validation": "future_date"
},
{
"canonical_name": "effective_date",
"docusign_tab_label": "effective_date",
"azure_docai_field": "ContractDate.content",
"dotloop_api_field": "loopDetails.dates.contractDate",
"skyslope_api_field": "transaction.contractDate",
"data_type": "date",
"required": true,
"transformation": "parse_date|to_iso8601"
},
{
"canonical_name": "buyer_name",
"docusign_tab_label": "buyer_name",
"azure_docai_field": "Parties[role=Buyer].name",
"dotloop_api_field": "contacts[role=BUYER].name",
"skyslope_api_field": "transaction.buyers[0].name",
"data_type": "string",
"required": true,
"transformation": "trim|title_case"
},
{
"canonical_name": "buyer_email",
"docusign_tab_label": "buyer_email",
"azure_docai_field": null,
"dotloop_api_field": "contacts[role=BUYER].email",
"skyslope_api_field": "transaction.buyers[0].email",
"data_type": "email",
"required": false,
"transformation": "trim|lowercase",
"validation": "email_format",
"notes": "Rarely present in scanned contracts; DocuSign source preferred"
},
{
"canonical_name": "seller_name",
"docusign_tab_label": "seller_name",
"azure_docai_field": "Parties[role=Seller].name",
"dotloop_api_field": "contacts[role=SELLER].name",
"skyslope_api_field": "transaction.sellers[0].name",
"data_type": "string",
"required": true,
"transformation": "trim|title_case"
},
{
"canonical_name": "seller_email",
"docusign_tab_label": "seller_email",
"azure_docai_field": null,
"dotloop_api_field": "contacts[role=SELLER].email",
"skyslope_api_field": "transaction.sellers[0].email",
"data_type": "email",
"required": false,
"transformation": "trim|lowercase"
},
{
"canonical_name": "listing_agent_name",
"docusign_tab_label": "listing_agent_name",
"azure_docai_field": null,
"dotloop_api_field": "contacts[role=LISTING_AGENT].name",
"skyslope_api_field": "transaction.listingAgent.name",
"data_type": "string",
"required": false,
"transformation": "trim|title_case"
},
{
"canonical_name": "buying_agent_name",
"docusign_tab_label": "buying_agent_name",
"azure_docai_field": null,
"dotloop_api_field": "contacts[role=BUYERS_AGENT].name",
"skyslope_api_field": "transaction.buyingAgent.name",
"data_type": "string",
"required": false,
"transformation": "trim|title_case"
},
{
"canonical_name": "mls_number",
"docusign_tab_label": "mls_number",
"azure_docai_field": "MLSNumber.content",
"dotloop_api_field": "loopDetails.propertyAddress.mlsNumber",
"skyslope_api_field": "transaction.mlsNumber",
"data_type": "string",
"required": false,
"transformation": "trim|uppercase"
},
{
"canonical_name": "title_company",
"docusign_tab_label": "title_company",
"azure_docai_field": "TitleCompany.content",
"dotloop_api_field": "contacts[role=TITLE_CLOSER].name",
"skyslope_api_field": "transaction.titleCompany",
"data_type": "string",
"required": false,
"transformation": "trim|title_case"
}
]
},
"listing_agreement": {
"dotloop_transaction_type": "LISTING",
"dotloop_status": "ACTIVE_LISTING",
"skyslope_transaction_type": "Listing",
"fields": [
{
"canonical_name": "list_price",
"docusign_tab_label": "list_price",
"dotloop_api_field": "loopDetails.financials.listingPrice",
"data_type": "currency",
"required": true,
"transformation": "strip_currency_symbols|to_number"
},
{
"canonical_name": "listing_start_date",
"docusign_tab_label": "listing_start_date",
"dotloop_api_field": "loopDetails.dates.listingStartDate",
"data_type": "date",
"required": true,
"transformation": "parse_date|to_iso8601"
},
{
"canonical_name": "listing_expiration_date",
"docusign_tab_label": "listing_expiration_date",
"dotloop_api_field": "loopDetails.dates.listingExpirationDate",
"data_type": "date",
"required": true,
"transformation": "parse_date|to_iso8601"
},
{
"canonical_name": "commission_percentage",
"docusign_tab_label": "commission_percentage",
"dotloop_api_field": "loopDetails.financials.commissionRate",
"data_type": "percentage",
"required": false,
"transformation": "strip_percent_sign|to_decimal"
}
]
}
},
"transformation_functions": {
"trim": "Remove leading and trailing whitespace",
"title_case": "Capitalize first letter of each word",
"uppercase": "Convert to all uppercase",
"lowercase": "Convert to all lowercase",
"strip_currency_symbols": "Remove $, commas, and spaces from currency values",
"to_number": "Convert string to numeric value",
"parse_date": "Parse date from various formats (MM/DD/YYYY, Month DD YYYY, etc.)",
"to_iso8601": "Convert date to YYYY-MM-DD format",
"strip_percent_sign": "Remove % symbol",
"to_decimal": "Convert percentage to decimal (e.g., 6% → 0.06)"
}
}Usage
- When adding a new contract type, add a new entry to
contract_typeswith its field mappings - When the client adds a new field to their DocuSign templates, add a new field entry
- When switching TM platforms (e.g., Dotloop to SkySlope), only the target API field paths need updating
- Reference this config in all automation workflows to ensure consistent field handling
Automation Health Monitor Dashboard
Type: integration A monitoring component that tracks automation success rates, processing times, error counts, and data quality metrics. Provides the MSP and client TC with visibility into automation performance. Implemented as a Google Sheet dashboard updated by the automation workflows themselves.
Implementation:
# Execution Log, KPI formulas, and Failed Transactions schema
## Google Sheets Dashboard Specification
### Sheet 1: 'Execution Log' (auto-populated by workflows)
| Column | Field | Source |
|--------|-------|--------|
| A | Timestamp | Auto-generated |
| B | Workflow Name | 'DocuSign-to-Dotloop' or 'OCR-Pipeline' |
| C | Trigger Type | 'webhook' or 'file_upload' |
| D | Envelope/File ID | DocuSign envelope ID or filename |
| E | Property Address | Extracted field |
| F | Contract Type | purchase_agreement, listing_agreement, etc. |
| G | Status | success, error, duplicate, manual_review |
| H | TM Record ID | Dotloop loop ID or SkySlope file ID |
| I | Processing Time (sec) | End time - start time |
| J | Fields Populated | Count of fields successfully mapped |
| K | Fields Missing | Count of expected fields that were empty |
| L | OCR Confidence (avg) | Average confidence score (OCR only) |
| M | Error Message | Error details if Status = error |
| N | Retry Count | Number of retry attempts |
### Sheet 2: 'Dashboard' (formulas for KPI display)
Cell B2 (Total Processed This Month):
=COUNTIFS('Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!G:G,"success")
Cell B3 (Success Rate This Month):
=COUNTIFS('Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!G:G,"success")/COUNTIFS('Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!G:G,"<>")
Cell B4 (Average Processing Time):
=AVERAGEIFS('Execution Log'!I:I,'Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!G:G,"success")
Cell B5 (Errors This Month):
=COUNTIFS('Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!G:G,"error")
Cell B6 (Pending Manual Review):
=COUNTIFS('Execution Log'!G:G,"manual_review",'Execution Log'!N:N,"")
Cell B7 (Average Fields Populated):
=AVERAGEIFS('Execution Log'!J:J,'Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1))
Cell B8 (Average OCR Confidence):
=AVERAGEIFS('Execution Log'!L:L,'Execution Log'!A:A,">="&DATE(YEAR(TODAY()),MONTH(TODAY()),1),'Execution Log'!L:L,">0")
### Sheet 3: 'Failed Transactions' (error queue)
| Column | Field |
|--------|-------|
| A | Timestamp |
| B | Envelope/File ID |
| C | Property Address |
| D | Error Message |
| E | Full Payload (JSON) |
| F | Retry Status (Pending/Retried/Resolved/Abandoned) |
| G | Resolution Notes |
| H | Resolved By |
| I | Resolved Date |# schedule trigger, Dashboard sheet lookup, and Gmail send configuration
### Weekly Report Automation (separate Zap):
Trigger: Schedule - Every Monday at 8:00 AM
Step 1: Google Sheets - Lookup Rows (Dashboard sheet)
Step 2: Gmail - Send Email
To: tc@brokerage.com, broker@brokerage.com, account-manager@msp.com
Subject: Weekly Transaction Automation Report - {date_range}
Body:
Transactions Processed: {total}
Success Rate: {rate}%
Average Processing Time: {time} seconds
Errors: {error_count}
Pending Manual Review: {pending_count}
[Link to full dashboard]Testing & Validation
- Test Case 1 - Happy Path Purchase Agreement: Execute a complete DocuSign signing ceremony using the client's standard purchase agreement template with all fields filled. Verify that within 3 minutes, a new Dotloop loop appears with the correct property address as the loop name, transaction type set to PURCHASE_OFFER, status set to UNDER_CONTRACT, purchase price matching the contract, closing date matching the contract, and buyer/seller contact records created with correct names and emails.
- Test Case 2 - Happy Path Listing Agreement: Execute a listing agreement through DocuSign with list price, listing dates, and commission percentage. Verify a Dotloop loop is created with transaction type LISTING, status ACTIVE_LISTING, and all listing-specific fields populated correctly.
- Test Case 3 - Amendment to Existing Transaction: With an existing Dotloop loop for a property, execute an amendment/addendum through DocuSign referencing the same property address. Verify the automation updates the existing loop (uploads the amendment document, updates any modified fields like price or closing date) rather than creating a duplicate loop.
- Test Case 4 - Duplicate Envelope Prevention: Trigger the same completed DocuSign envelope webhook twice within 60 seconds (simulating a webhook retry). Verify that only one Dotloop loop is created and the second trigger is detected as a duplicate and logged accordingly.
- Test Case 5 - Missing Required Field Handling: Create a DocuSign envelope with the purchase_price field left blank. Complete signing and verify that the automation: (a) logs an error to the Failed Transactions sheet, (b) sends a notification email to the TC with the specific missing field identified, and (c) does NOT create a malformed Dotloop loop.
- Test Case 6 - OCR Pipeline (Scanned Contract): Scan a paper purchase agreement using the configured ScanSnap scanner and upload to the Inbox folder. Verify the file is detected within 5 minutes, processed by Azure Document Intelligence, and a Dotloop loop is created with at least 80% of fields correctly populated. Verify the loop is tagged with 'OCR-Processed' and the TC receives a notification with confidence scores.
- Test Case 7 - OCR Low Confidence Handling: Scan a low-quality or partially illegible contract. Verify that when OCR confidence falls below the 0.85 threshold, the automation routes the document to the Manual Review queue, sends a notification to the TC, and does NOT auto-create a Dotloop loop.
- Test Case 8 - API Failure Recovery: Temporarily revoke the Dotloop API token (or change the API key to an invalid value). Trigger a contract completion. Verify the automation: (a) catches the 401/403 error, (b) logs the full transaction payload to the Failed Transactions sheet for later retry, (c) sends an alert email to both the TC and the MSP helpdesk. Then restore the API key and verify the transaction can be manually re-triggered.
- Test Case 9 - CRM Sync Verification: After a successful transaction creation, verify that the buyer contact in Follow Up Boss has been updated with stage 'Under Contract', the transaction link is added as a custom field, and the closing date is populated. Verify the seller contact is similarly updated.
- Test Case 10 - End-to-End Timing: Process 5 test transactions in sequence and measure the time from DocuSign completion to Dotloop loop visibility. All 5 should complete within 3 minutes each. Document the average processing time for the baseline SLA.
- Test Case 11 - Notification Delivery: Verify that all notification channels are working: (a) TC receives email notification for successful transactions, (b) TC receives email notification for failed transactions, (c) MSP receives alert email for API errors, (d) Weekly report email is delivered on Monday at 8 AM with accurate metrics.
- Test Case 12 - Data Accuracy Audit: Process 10 test transactions with known data values. Export the Dotloop loop details for all 10 and compare every field against the source DocuSign envelope data. Calculate field-level accuracy rate. Target: 100% accuracy for DocuSign-sourced fields, 90%+ for OCR-sourced fields. Document any discrepancies and adjust field mapping accordingly.
- Test Case 13 - Security Validation: Verify that (a) no PII (SSN, bank account numbers) is stored in Zapier/Make execution logs, (b) all API calls use HTTPS, (c) DocuSign webhook signature validation is active and rejects unsigned requests, (d) automation platform account has 2FA enabled, (e) integration user in Dotloop has create/update but not delete permissions.
- Test Case 14 - Wire Fraud Safeguard: Send a test contract that contains wire instructions or bank account numbers in a text field. Verify the automation does NOT propagate this sensitive financial data to any notification emails or downstream systems. If OCR extracts bank details, verify they are suppressed/redacted.
Client Handoff
Client Handoff Checklist
Training Session (60 minutes with TC, Office Manager, and Broker)
Documentation Package to Leave Behind
Success Criteria Review (jointly confirm with client)
30-Day Hypercare Period
- MSP checks automation dashboard daily for the first 2 weeks, then weekly
- Scheduled check-in call at Day 7 and Day 14
- Full review meeting at Day 30 to confirm success criteria, adjust field mappings, and transition to standard managed service cadence
- Any new contract types or workflow changes requested during hypercare are included at no additional charge
Maintenance
Ongoing Maintenance Plan
Weekly Tasks (15-30 minutes)
- Review the Automation Health Monitor Dashboard for error trends, processing time increases, or declining success rates
- Check the Failed Transactions queue and resolve or escalate any pending items
- Verify weekly report email was delivered and metrics are within SLA targets
Monthly Tasks (1-2 hours)
- Review Zapier/Make execution logs for any warnings or deprecated actions
- Check API rate limit usage against quotas (Dotloop: 2,000 req/hour)
- Verify OAuth2 tokens are refreshing properly (DocuSign tokens expire every 8 hours; refresh tokens expire after 30 days of inactivity)
- Review Azure Document Intelligence usage and costs if OCR is enabled
- Export and archive execution logs for compliance (append to long-term storage)
- Update field mapping configuration if client has added new contract types or DocuSign template fields
Quarterly Tasks (2-4 hours)
- Full automation health review with the client (TC and Broker): review metrics, discuss pain points, propose enhancements
- Test all automation pathways end-to-end with synthetic data to verify nothing has broken due to platform updates
- Review and update API credentials if any are approaching expiration
- Check for platform updates (Dotloop API version changes, Zapier/Make feature updates, DocuSign API deprecations)
- Review compliance posture: confirm document retention periods are being met, PII handling is still appropriate, audit logs are intact
- Assess whether transaction volume has changed significantly; adjust Zapier/Make plan tier if task/operation counts have grown
Annual Tasks
- Full security review: rotate all API keys and service account passwords
- Re-evaluate the automation stack for cost optimization (e.g., should Zapier be replaced with Make or n8n for cost savings at current volume?)
- Review state compliance requirements for any regulatory changes affecting document handling or electronic signatures
- Renew software subscriptions and negotiate pricing based on actual usage
- Conduct a client satisfaction review and propose a roadmap for Phase 2 enhancements (e.g., accounting sync, MLS integration, commission calculation)
SLA Targets
- Automation uptime: 99.5% (measured as successful webhook processing rate)
- Transaction processing time: < 3 minutes from contract completion to TM record creation
- Error notification delivery: < 5 minutes from error occurrence
- Error resolution: 4-hour response during business hours (M-F 8AM-6PM), next business day for non-critical errors
- Monthly success rate: > 98% for electronically-signed contracts, > 92% for OCR-processed contracts
Escalation Path
Triggers for Workflow Updates
- Client adds a new contract type (e.g., lease agreements, commercial purchase agreements)
- Client changes TM platform (e.g., migrates from Dotloop to SkySlope)
- State association releases updated contract forms with new or renamed fields
- eSignature platform releases a new API version or deprecates the current one
- Transaction volume exceeds current automation platform plan limits
- Client opens offices in new states with different compliance requirements
Alternatives
...
Microsoft Power Automate with Dataverse
n8n Self-Hosted Automation Engine
Replace Zapier/Make with n8n, an open-source workflow automation platform, self-hosted on a Linux VPS (AWS EC2, Azure VM, or DigitalOcean droplet) or a small on-premises server. n8n provides full white-label capability, unlimited workflows and executions, and no per-task pricing. The MSP hosts n8n on their infrastructure and manages it as a service.
RealSynch or API Nation Managed Integration Hub
Instead of building the automation in-house using Zapier/Make/n8n, outsource the integration to a real estate-specific integration platform like RealSynch or API Nation. These vendors specialize in connecting real estate software stacks and have pre-built connectors for DocuSign, Dotloop, SkySlope, Follow Up Boss, and other real estate platforms. The MSP acts as the reseller and project manager rather than the automation builder.
SkySlope Native AI Transaction Creation
If the client uses SkySlope, leverage SkySlope's built-in AI capabilities (Smart Audit, automated transaction creation) rather than building a custom middleware automation. SkySlope is investing heavily in AI-driven transaction management and may offer native auto-population features that eliminate the need for external automation entirely.
Direct API Integration (Custom Code)
Skip the iPaaS middleware entirely and build a lightweight microservice (Node.js or Python) that directly receives DocuSign webhooks, parses the envelope data, and calls the Dotloop/SkySlope API. Deploy as an Azure Function, AWS Lambda, or Google Cloud Function. This provides maximum control and lowest per-execution cost at scale.
Want early access to the full toolkit?