CRM (Customer Relationship Management)
The Ravenmask CRM is a lightweight customer lifecycle management system for tracking leads, accounts, and sales opportunities.
Overview
| Component | URL | Description |
|---|---|---|
| Web UI | https://crm.ravenhelm.dev | Main CRM interface |
| API | https://crm.ravenhelm.dev/api/v1 | REST API |
| API Docs | https://crm.ravenhelm.dev/api/docs | Swagger documentation |
Architecture
Frontend (React) --> Backend (FastAPI) --> PostgreSQL (crm db)
|
v
Traefik (*.ravenhelm.dev)
^
|
Bifrost MCP --> Norns Agent
Stack:
- Frontend: React + TypeScript + Vite + TanStack Query
- Backend: Python + FastAPI + SQLAlchemy
- Database: PostgreSQL (
crmdatabase) - Proxy: Traefik
- MCP Integration: Bifrost (CRM executor)
Data Model
Leads
Pre-qualified prospects. Flow: New -> Contacted -> Qualified -> Converted
| Field | Description |
|---|---|
| first_name, last_name | Contact name (required) |
| email, phone | Contact info |
| company, title | Company details |
| status | new, contacted, qualified, unqualified, converted |
| source | Origin (website, linkedin, referral, etc.) |
| estimated_value | Potential deal size |
| notes | Free-form notes |
Accounts
Companies/organizations you do business with.
| Field | Description |
|---|---|
| name | Company name (required) |
| domain | Website domain |
| industry | Industry sector |
| segment | SMB, Mid-Market, Enterprise |
Opportunities
Active deals in the sales pipeline.
| Field | Description |
|---|---|
| name | Deal name (required) |
| account_id | Linked account |
| stage | Pipeline stage (Lead -> Discovery -> Proposal -> Negotiation -> Closed Won/Lost) |
| amount | Deal value |
| close_date | Expected close date |
| probability | Win probability (0-100%) |
| pipeline_id | Which pipeline this belongs to |
Pipeline Stages (Default)
- Lead (10%)
- Discovery (25%)
- Proposal (50%)
- Negotiation (75%)
- Closed Won (100%)
- Closed Lost (0%)
MCP Tools (Bifrost)
The CRM is integrated with Bifrost MCP, allowing AI agents (like Norns) to interact with CRM data programmatically.
Available Tools
Lead Management
| Tool | Description |
|---|---|
crm_list_leads | List all leads, optionally filter by status |
crm_get_lead | Get details of a specific lead by UUID |
crm_create_lead | Create a new lead (requires first_name, last_name) |
crm_update_lead | Update lead fields or status |
crm_convert_lead | Convert qualified lead to opportunity |
Account Management
| Tool | Description |
|---|---|
crm_list_accounts | List all accounts, optionally search by name |
crm_get_account | Get account details including linked opportunities |
crm_create_account | Create a new account (requires name) |
crm_update_account | Update account fields |
Opportunity Management
| Tool | Description |
|---|---|
crm_list_opportunities | List opportunities, filter by account/stage/pipeline |
crm_get_opportunity | Get opportunity details |
crm_create_opportunity | Create a new opportunity (requires name) |
crm_update_opportunity | Update opportunity stage, amount, or close date |
Pipeline
| Tool | Description |
|---|---|
crm_get_pipeline | Get pipeline stages configuration |
crm_get_pipeline_summary | Get pipeline summary with counts and values per stage |
Tool Parameters
crm_create_lead
{
"first_name": "John", // required
"last_name": "Doe", // required
"email": "john@example.com",
"phone": "+1-555-1234",
"company": "Acme Corp",
"title": "CTO",
"source": "linkedin",
"estimated_value": "$50,000",
"notes": "Met at conference"
}
crm_update_lead
{
"lead_id": "uuid", // required
"status": "qualified", // new, contacted, qualified, unqualified
"notes": "Follow up scheduled"
}
crm_convert_lead
{
"lead_id": "uuid", // required
"opportunity_name": "Acme Corp - Enterprise Deal",
"amount": 50000,
"close_date": "2025-03-31",
"create_account": true // create account from company name
}
crm_create_opportunity
{
"name": "New Deal", // required
"account_id": "uuid",
"stage": "Discovery",
"amount": 25000,
"close_date": "2025-06-30",
"probability": 25
}
crm_get_pipeline_summary
Returns pipeline overview:
{
"pipeline_id": "uuid",
"stages": {
"Lead": {"count": 5, "value": 100000, "weighted_value": 10000, "probability": 10},
"Discovery": {"count": 3, "value": 75000, "weighted_value": 18750, "probability": 25},
"Proposal": {"count": 2, "value": 50000, "weighted_value": 25000, "probability": 50}
},
"totals": {
"opportunities": 10,
"pipeline_value": 225000,
"weighted_value": 53750
}
}
Example Agent Interactions
List qualified leads:
"Show me all qualified leads"
Tool: crm_list_leads
Args: {"status": "qualified"}
Create a lead from a conversation:
"Add a lead for Sarah Chen from TechCorp, she's interested in our enterprise plan"
Tool: crm_create_lead
Args: {
"first_name": "Sarah",
"last_name": "Chen",
"company": "TechCorp",
"source": "conversation",
"notes": "Interested in enterprise plan"
}
Get pipeline status:
"What does our sales pipeline look like?"
Tool: crm_get_pipeline_summary
Args: {}
Advance an opportunity:
"Move the TechCorp deal to proposal stage"
Tool: crm_update_opportunity
Args: {"opportunity_id": "uuid", "stage": "Proposal"}
Implementation Details
- Executor:
~/ravenhelm/services/bifrost/api/executors/crm.py - Executor Type:
crm - Internal URL:
http://crm-backend:8000(Docker network) - Tools registered in:
tool_definitionstable (ravenmaskos database)
Webhooks API
Public endpoints for external integrations (marketing forms, LinkedIn, etc.)
Create Single Lead
Endpoint: POST /api/v1/webhooks/leads
Request:
{
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "+1-555-1234",
"company": "Acme Corp",
"title": "CTO",
"source": "linkedin",
"source_detail": "Q1 Lead Gen Campaign",
"estimated_value": "$50,000",
"notes": "Met at AWS re:Invent"
}
Response:
{
"success": true,
"lead_id": "uuid-here",
"message": "Lead created: John Doe"
}
Create Multiple Leads (Batch)
Endpoint: POST /api/v1/webhooks/leads/batch
Request:
{
"leads": [
{"first_name": "Jane", "last_name": "Smith", "email": "jane@corp.com", "source": "trade_show"},
{"first_name": "Bob", "last_name": "Wilson", "email": "bob@inc.com", "source": "trade_show"}
]
}
Response:
{
"success": true,
"total": 2,
"created": 2,
"failed": 0,
"lead_ids": ["uuid-1", "uuid-2"],
"errors": null
}
Webhook Fields Reference
| Field | Required | Type | Description |
|---|---|---|---|
first_name | Yes | string | First name (max 100 chars) |
last_name | Yes | string | Last name (max 100 chars) |
email | No | string | Email address |
phone | No | string | Phone number |
company | No | string | Company name |
title | No | string | Job title |
source | No | string | Lead source identifier |
source_detail | No | string | Campaign name, form ID, etc. |
estimated_value | No | string | Potential deal size |
notes | No | string | Additional notes |
custom_data | No | object | Any extra JSON fields |
Optional Headers
| Header | Description |
|---|---|
X-Source | Override lead source for all leads in request |
X-Webhook-Signature | HMAC-SHA256 signature for security verification |
Common Source Values
| Source | Use Case |
|---|---|
website | Contact forms on website |
linkedin | LinkedIn Lead Gen Forms |
referral | Customer/partner referrals |
trade_show | Conference badge scans |
cold_call | Outbound prospecting |
email_campaign | Marketing email responses |
social_media | Social media inquiries |
webinar | Webinar registrations |
Integration Examples
cURL
curl -X POST https://crm.ravenhelm.dev/api/v1/webhooks/leads \
-H "Content-Type: application/json" \
-d '{
"first_name": "Test",
"last_name": "Lead",
"email": "test@example.com",
"source": "api_test"
}'
n8n Workflow
Use HTTP Request node:
- Method: POST
- URL:
https://crm.ravenhelm.dev/api/v1/webhooks/leads - Headers:
Content-Type: application/json - Body: JSON with lead fields
JavaScript/Fetch
await fetch('https://crm.ravenhelm.dev/api/v1/webhooks/leads', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
first_name: 'John',
last_name: 'Doe',
email: 'john@example.com',
source: 'website_form'
})
});
Python
import requests
response = requests.post(
'https://crm.ravenhelm.dev/api/v1/webhooks/leads',
json={
'first_name': 'John',
'last_name': 'Doe',
'email': 'john@example.com',
'source': 'python_script'
}
)
print(response.json())
Service Management
Location
odin:/Users/ravenhelm/ravenhelm/services/crm/
├── backend/ # FastAPI application
├── frontend/ # React application
└── docker-compose.yml
Commands
# View logs
ssh ravenhelm@100.115.101.81 "docker logs -f crm-backend"
ssh ravenhelm@100.115.101.81 "docker logs -f crm-frontend"
# Restart services
ssh ravenhelm@100.115.101.81 "cd ~/ravenhelm/services/crm && docker compose restart"
# Rebuild after code changes
ssh ravenhelm@100.115.101.81 "cd ~/ravenhelm/services/crm && docker compose build && docker compose up -d"
Database
# Connect to CRM database
ssh ravenhelm@100.115.101.81 "docker exec -it postgres psql -U ravenhelm -d crm"
# Check data counts
ssh ravenhelm@100.115.101.81 "docker exec -i postgres psql -U ravenhelm -d crm -c \"
SELECT 'leads', COUNT(*) FROM leads
UNION ALL SELECT 'accounts', COUNT(*) FROM accounts
UNION ALL SELECT 'opportunities', COUNT(*) FROM opportunities;
\""
Workflows
Lead to Opportunity Conversion
- Lead enters system (webhook, manual, import)
- Sales qualifies lead (status: new -> contacted -> qualified)
- Convert qualified lead to opportunity
- Creates opportunity in pipeline
- Optionally creates account from company name
- Links opportunity to account
- Work opportunity through pipeline stages
- Close won/lost
Creating Opportunities from Accounts
- Navigate to account detail page
- Click "New Opportunity"
- Fill in deal details
- Opportunity auto-linked to account
See Also
- Automation - n8n workflows for CRM automation
- Bifrost - MCP gateway service
- Reference - Port mappings and URLs