Open Source CRM developed on Django framework with REST API for contact, lead, account, and opportunity management
Lead tracking and qualification system for potential customers. Leads represent prospective business opportunities that need to be qualified and potentially converted to accounts and opportunities.
Create leads from external websites using API key authentication.
def create_lead_from_site(lead_data: dict, api_key: str) -> dict:
"""
Create lead from external website or system.
Args:
lead_data (dict): Lead information
api_key (str): API key for authentication (passed as query parameter)
Returns:
dict: Created lead details
Authentication:
API Key (query parameter: apikey)
Example:
POST /api/leads/create-from-site/?apikey=your-api-key
{
"first_name": "John",
"last_name": "Prospect",
"email": "john@prospect.com",
"phone": "+1234567890",
"account_name": "Prospect Company",
"source": "Website Form",
"title": "Interested in Product Demo"
}
Response:
{
"id": "new-lead-uuid",
"first_name": "John",
"last_name": "Prospect",
...lead details...
}
"""List leads with comprehensive filtering, excluding converted leads.
def list_leads(name: str = None, title: str = None, source: str = None,
assigned_to: str = None, status: str = None, tags: str = None,
city: str = None, email: str = None,
limit: int = 10, offset: int = 0) -> dict:
"""
List leads with filtering (excludes converted leads).
Args:
name (str, optional): Filter by first or last name
title (str, optional): Filter by lead title
source (str, optional): Filter by lead source
assigned_to (str, optional): Filter by assigned user UUID
status (str, optional): Filter by status ('assigned', 'in process', 'recycled', 'closed')
tags (str, optional): Filter by tags
city (str, optional): Filter by city
email (str, optional): Filter by email
limit (int): Results per page (default: 10)
offset (int): Results to skip (default: 0)
Returns:
dict: Paginated leads with metadata
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
GET /api/leads/?status=assigned&source=website&limit=5
Response:
{
"open_leads": [
{
"id": "lead-uuid",
"title": "Product Demo Request",
"first_name": "Jane",
"last_name": "Prospect",
"email": "jane@prospect.com",
"phone": "+1987654321",
"status": "assigned",
"source": "Website Form",
"account_name": "Prospect Corp",
"opportunity_amount": "50000.00",
"created_on": "2023-01-15T10:30:00Z",
"assigned_to": ["user1-uuid"],
"tags": ["demo", "qualified"]
}
],
"closed_leads": [],
"open_leads_count": 15,
"closed_leads_count": 3,
"contacts": [...],
"users": [...],
"source_list": ["Website Form", "Cold Call", "Referral", "Trade Show"],
"tags": [...],
"status": [...available status options...]
}
"""Create leads with optional automatic conversion to accounts.
def create_lead(lead_data: dict, auto_convert: bool = False) -> dict:
"""
Create new lead with optional auto-conversion to account.
Args:
lead_data (dict): Lead information and associations
auto_convert (bool): Whether to automatically convert to account
Returns:
dict: Created lead (and account if auto-converted)
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Content-Type: multipart/form-data (if including attachments)
Example:
POST /api/leads/
{
"title": "Enterprise Software Inquiry",
"first_name": "Robert",
"last_name": "Johnson",
"email": "robert@bigcorp.com",
"phone": "+1555987654",
"status": "assigned",
"source": "Cold Call",
"account_name": "Big Corp Industries",
"website": "https://bigcorp.com",
"description": "Interested in enterprise solution for 500+ users",
"opportunity_amount": "75000.00",
"contacts": ["contact1-uuid"],
"assigned_to": ["user1-uuid"],
"teams": ["sales-team-uuid"],
"tags": ["enterprise", "qualified"],
"address_line": "789 Corporate Blvd",
"city": "Dallas",
"state": "TX",
"postcode": "75201",
"country": "USA"
}
Response:
{
"id": "new-lead-uuid",
"title": "Enterprise Software Inquiry",
...lead details...,
"converted_account": null # or account details if auto-converted
}
"""Get comprehensive lead information and perform updates.
def get_lead(pk: str) -> dict:
"""
Get detailed lead information.
Args:
pk (str): Lead UUID
Returns:
dict: Complete lead details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
GET /api/leads/lead-uuid/
Response:
{
"lead_obj": {
"id": "lead-uuid",
"title": "Product Demo Request",
"first_name": "Jane",
"last_name": "Prospect",
"email": "jane@prospect.com",
"phone": "+1987654321",
"status": "in process",
"source": "Website Form",
"account_name": "Prospect Corp",
"website": "https://prospect.com",
"description": "Interested in our premium features",
"opportunity_amount": "50000.00",
"address_line": "456 Business St",
"city": "Seattle",
"state": "WA",
"postcode": "98101",
"country": "USA",
"created_on": "2023-01-15T10:30:00Z",
"created_by": "user-uuid"
},
"address_obj": {...address details...},
"assigned_to": [...assigned users...],
"teams": [...assigned teams...],
"comments": [...lead comments...],
"attachments": [...lead attachments...],
"contacts": [...associated contacts...],
"users_mention": [...users for @mentions...],
"tags": ["demo", "qualified"]
}
"""
def update_lead(pk: str, lead_data: dict) -> dict:
"""
Update lead information.
Args:
pk (str): Lead UUID
lead_data (dict): Updated lead information
Returns:
dict: Updated lead details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
PUT /api/leads/lead-uuid/
{
"status": "in process",
"opportunity_amount": "60000.00",
"description": "Updated after discovery call"
}
"""
def delete_lead(pk: str) -> None:
"""
Delete a lead.
Args:
pk (str): Lead UUID
Returns:
None: 204 No Content on success
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
DELETE /api/leads/lead-uuid/
"""Manage lead activity and documentation.
def add_lead_comment_or_attachment(pk: str, comment: str = None,
attachment: file = None) -> dict:
"""
Add comment or attachment to lead.
Args:
pk (str): Lead UUID
comment (str, optional): Comment text
attachment (file, optional): File to attach
Returns:
dict: Success response
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Content-Type: multipart/form-data (for attachments)
Example:
POST /api/leads/lead-uuid/
{
"comment": "Discovery call scheduled for next Tuesday"
}
"""
def edit_lead_comment(pk: str, comment: str) -> dict:
"""Edit a lead comment."""
def delete_lead_comment(pk: str) -> None:
"""Delete a lead comment."""
def delete_lead_attachment(pk: str) -> None:
"""Delete a lead attachment."""Import multiple leads from file upload.
def upload_leads(leads_file: file) -> dict:
"""
Bulk upload leads from file.
Args:
leads_file (file): CSV or Excel file containing lead data
Returns:
dict: Import results and statistics
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Content-Type: multipart/form-data
Example:
POST /api/leads/upload/
Form Data:
leads_file: <file_object>
Response:
{
"status": "success",
"imported_count": 25,
"failed_count": 2,
"errors": [...validation errors for failed rows...]
}
"""Manage companies associated with leads.
def list_companies() -> dict:
"""
List companies from leads.
Returns:
dict: Companies list
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
GET /api/leads/companies/
Response:
{
"companies": [
{
"id": "company-uuid",
"name": "Tech Corp",
"industry": "Technology",
"website": "https://techcorp.com"
}
]
}
"""
def create_company(company_data: dict) -> dict:
"""
Create new company.
Args:
company_data (dict): Company information
Returns:
dict: Created company details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/leads/companies/
{
"name": "New Tech Startup",
"industry": "Software",
"website": "https://newtechstartup.com"
}
"""
def get_company(pk: str) -> dict:
"""
Get company details.
Args:
pk (str): Company UUID
Returns:
dict: Company information
Headers Required:
Authorization: Bearer <access_token>
Example:
GET /api/leads/company/company-uuid/
"""class Lead:
"""Lead model for potential customers"""
id: str # UUID
title: str # Lead title/subject
first_name: str # Required
last_name: str # Required
email: str # Contact email
phone: str # Contact phone
status: str # Lead status
source: str # How lead was acquired
account_name: str # Prospective company name
website: str # Company website
description: str # Lead details
opportunity_amount: decimal # Potential deal value
# Address information
address_line: str
street: str
city: str
state: str
postcode: str
country: str
# Metadata
created_on: datetime
created_by: str # User UUID
org: str # Organization UUID
# Associations
contacts: list[str] # Contact UUIDs
assigned_to: list[str] # User UUIDs
teams: list[str] # Team UUIDs
tags: list[str] # Tag names
class LeadStatus:
"""Lead status options"""
ASSIGNED: str = "assigned"
IN_PROCESS: str = "in process"
CONVERTED: str = "converted" # Converted to account (filtered from lists)
RECYCLED: str = "recycled"
CLOSED: str = "closed"
class LeadSource:
"""Common lead sources"""
WEBSITE: str = "Website Form"
COLD_CALL: str = "Cold Call"
REFERRAL: str = "Referral"
TRADE_SHOW: str = "Trade Show"
EMAIL_CAMPAIGN: str = "Email Campaign"
SOCIAL_MEDIA: str = "Social Media"
ADVERTISEMENT: str = "Advertisement"
class Company:
"""Company information from leads"""
id: str # UUID
name: str # Company name
industry: str # Industry type
website: str # Company website
created_from_lead: str # Lead UUID that created companyConverted leads are filtered out of standard lead lists but remain in the system for historical tracking.
Install with Tessl CLI
npx tessl i tessl/pypi-django-crm