How to Automate Vendor Onboarding Workflows
Streamline vendor onboarding with automated document collection and approval.
Jay Banlasan
The AI Systems Guy
Vendor onboarding involves collecting documents from multiple people across multiple systems. I built a system to automate vendor onboarding workflows that tracks document submissions, sends reminders for missing items, and only activates the vendor once everything is complete.
No vendor gets paid until compliance is verified.
What You Need Before Starting
- Python 3.8+
- SQLite for tracking
- Email notifications
- A document storage system
Step 1: Define Onboarding Requirements
VENDOR_REQUIREMENTS = {
"standard": {
"documents": [
{"name": "W-9 Tax Form", "required": True, "category": "tax"},
{"name": "Certificate of Insurance", "required": True, "category": "insurance"},
{"name": "Signed MSA", "required": True, "category": "legal"},
{"name": "Banking Information", "required": True, "category": "payment"},
{"name": "Business License", "required": False, "category": "compliance"}
],
"approvals": ["procurement", "legal", "finance"],
"sla_days": 14
}
}
Step 2: Create Vendor Onboarding Tracker
import sqlite3
from datetime import datetime, timedelta
def init_vendor_db(db_path="vendors.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS vendor_onboarding (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vendor_name TEXT,
vendor_email TEXT,
vendor_type TEXT,
status TEXT DEFAULT 'pending_documents',
initiated_at TEXT,
deadline TEXT,
activated_at TEXT
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS vendor_documents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vendor_id INTEGER,
document_name TEXT,
category TEXT,
required INTEGER,
received INTEGER DEFAULT 0,
file_path TEXT,
received_at TEXT
)
""")
conn.commit()
return conn
def start_vendor_onboarding(conn, vendor_name, vendor_email, vendor_type="standard"):
requirements = VENDOR_REQUIREMENTS[vendor_type]
deadline = (datetime.now() + timedelta(days=requirements["sla_days"])).strftime("%Y-%m-%d")
cursor = conn.execute(
"INSERT INTO vendor_onboarding (vendor_name, vendor_email, vendor_type, initiated_at, deadline) VALUES (?,?,?,?,?)",
(vendor_name, vendor_email, vendor_type, datetime.now().isoformat(), deadline)
)
vendor_id = cursor.lastrowid
for doc in requirements["documents"]:
conn.execute(
"INSERT INTO vendor_documents (vendor_id, document_name, category, required) VALUES (?,?,?,?)",
(vendor_id, doc["name"], doc["category"], int(doc["required"]))
)
conn.commit()
return vendor_id
Step 3: Track Document Submissions
def receive_document(conn, vendor_id, document_name, file_path):
conn.execute("""
UPDATE vendor_documents SET received=1, file_path=?, received_at=?
WHERE vendor_id=? AND document_name=?
""", (file_path, datetime.now().isoformat(), vendor_id, document_name))
conn.commit()
status = check_completion(conn, vendor_id)
if status["all_required_received"]:
conn.execute(
"UPDATE vendor_onboarding SET status='pending_approval' WHERE id=?",
(vendor_id,)
)
conn.commit()
return status
def check_completion(conn, vendor_id):
required_total = conn.execute(
"SELECT COUNT(*) FROM vendor_documents WHERE vendor_id=? AND required=1",
(vendor_id,)
).fetchone()[0]
required_received = conn.execute(
"SELECT COUNT(*) FROM vendor_documents WHERE vendor_id=? AND required=1 AND received=1",
(vendor_id,)
).fetchone()[0]
missing = conn.execute(
"SELECT document_name FROM vendor_documents WHERE vendor_id=? AND required=1 AND received=0",
(vendor_id,)
).fetchall()
return {
"all_required_received": required_received == required_total,
"progress": f"{required_received}/{required_total}",
"missing": [m[0] for m in missing]
}
Step 4: Send Reminder Notifications
def send_vendor_reminders(conn):
pending = conn.execute("""
SELECT v.id, v.vendor_name, v.vendor_email, v.deadline
FROM vendor_onboarding v
WHERE v.status = 'pending_documents'
""").fetchall()
for vendor_id, name, email, deadline in pending:
status = check_completion(conn, vendor_id)
days_left = (datetime.strptime(deadline, "%Y-%m-%d") - datetime.now()).days
if status["missing"] and days_left <= 7:
missing_list = ", ".join(status["missing"])
print(f"REMINDER to {name} ({email}): Missing documents: {missing_list}. Due in {days_left} days.")
Step 5: Activate Vendor
def activate_vendor(conn, vendor_id):
status = check_completion(conn, vendor_id)
if not status["all_required_received"]:
return {"error": f"Cannot activate. Missing: {status['missing']}"}
conn.execute(
"UPDATE vendor_onboarding SET status='active', activated_at=? WHERE id=?",
(datetime.now().isoformat(), vendor_id)
)
conn.commit()
return {"status": "activated", "vendor_id": vendor_id}
What to Build Next
Add annual re-certification that checks if insurance certificates and licenses are still current. Vendors expire. Your tracking system should catch that before you have a compliance gap.
Related Reading
- Building Your First Automation: A Complete Guide - automation step by step
- The Automation Decision Tree - prioritizing automations
- How to Audit Your Operations for AI Opportunities - audit for automation
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment