CRM (Leads & People)
The CRM module manages your contacts, organizations, and sales pipeline. It's the core of any agent-driven sales or customer management system — track people, route leads, and move deals through configurable stages.
People
People are external individuals — customers, prospects, partners. They are the contacts your business interacts with.
| Field | Type | Description |
|---|---|---|
| id / uuid | ID! | Unique identifiers |
| firstname | String | First name |
| lastname | String | Last name |
| name | String | Full name (computed) |
| String | Primary email | |
| dob | Date | Date of birth |
| contacts | [Contact!] | Phone numbers, emails, etc. by type |
| address | [Address!] | Physical addresses |
| organizations | [Organization!] | Companies this person belongs to |
| tags | [Tag!] | Tags for categorization |
| files | [Filesystem!] | Attached documents |
| custom_fields | [CustomField!] | Custom key-value data |
# List people
query {
peoples(first: 20, orderBy: [{ column: CREATED_AT, order: DESC }]) {
data {
id uuid firstname lastname name email
contacts { type { name } value }
organizations { id name }
tags { name }
custom_fields { name value }
created_at
}
paginatorInfo { total hasMorePages }
}
}
# Create a person
mutation {
createPeople(input: {
firstname: "Jane"
lastname: "Doe"
email: "jane@example.com"
contacts: [{ contacts_types_id: 1, value: "+1-555-0100" }]
address: [{ address: "123 Main St", city: "New York", state: "NY", zip: "10001", country: "US" }]
company_id: 1
}) {
id uuid name email
}
}
# Search by email
query {
peoples(where: { column: EMAIL, operator: EQ, value: "jane@example.com" }) {
data { id name email }
}
}Organization
Organizations are external companies your business interacts with.
| Field | Type | Description |
|---|---|---|
| id / uuid | ID! | Unique identifiers |
| name | String! | Organization name |
| address | String | Address |
| tags | [Tag!] | Tags |
# Create an organization
mutation {
createOrganization(input: { name: "Acme Corp", address: "456 Business Ave" }) {
id uuid name
}
}
# Add person to organization
mutation {
addPeopleToOrganization(people_id: 1, organization_id: 1) { id }
}Lead
Leads are sales opportunities. They connect a person and organization to a pipeline stage, with routing, status tracking, and participant management.
| Field | Type | Description |
|---|---|---|
| id / uuid | ID! | Unique identifiers |
| title | String! | Lead title / deal name |
| firstname / lastname | String | Contact name (if no linked person) |
| email / phone | String | Contact info |
| description | String | Notes or description |
| reason_lost | String | Why the deal was lost (if applicable) |
| people | People | Linked contact |
| organization | Organization | Linked organization |
| owner | User | Assigned sales agent |
| receiver | LeadReceiver | Lead routing config |
| status | LeadStatus | Open, won, lost, etc. |
| type | LeadType | Lead type classification |
| source | LeadSource | Where the lead came from |
| pipeline | LeadPipeline | Sales pipeline |
| stage | LeadPipelineStage | Current stage in the pipeline |
| participants | [User!] | Team members involved |
| channels | [SocialChannel!] | Communication channels |
| tags | [Tag!] | Tags |
| files | [Filesystem!] | Attached files |
| custom_fields | [CustomField!] | Custom key-value data |
# List leads
query {
leads(first: 20, orderBy: [{ column: CREATED_AT, order: DESC }]) {
data {
id uuid title description
people { name email }
organization { name }
owner { displayname }
status { name }
source { name }
pipeline { name }
stage { name }
tags { name }
custom_fields { name value }
created_at
}
paginatorInfo { total currentPage lastPage }
}
}
# Create a lead
mutation {
createLead(input: {
title: "Enterprise deal"
people_id: 1
organization_id: 1
pipeline_stage_id: 1
description: "Potential enterprise contract"
custom_fields: [{ name: "deal_value", data: "50000" }]
}) {
id uuid title status { name } stage { name }
}
}
# Move lead to next stage
mutation {
updateLead(id: 1, input: { pipeline_stage_id: 3 }) {
id title stage { name }
}
}
# Mark lead as won
mutation {
leadWonOrLost(id: 1, input: { status: "won" }) {
id status { name }
}
}Pipelines & Stages
| Field | Type | Description |
|---|---|---|
| id | ID! | Unique identifier |
| name | String! | Pipeline name |
| slug | String! | URL-friendly name |
| is_default | Boolean | Whether this is the default pipeline |
| stage_count | Int | Number of stages |
| lead_count | Int | Total leads in pipeline |
| stages | [LeadPipelineStage!] | Ordered list of stages |
# List pipelines
query {
pipelines(first: 10) {
data {
id name is_default stage_count lead_count
stages { id name weight rotting_days }
}
}
}
# Create a pipeline with stages
mutation {
createPipeline(input: { name: "Sales Pipeline", weight: 1 }) { id name }
}
mutation {
createPipelineStage(input: { pipelines_id: 1, name: "Qualified", rotting_days: 14, weight: 2 }) { id name }
}Real-Time: Lead Subscription
subscription {
leadUpdate {
id title
status { name }
stage { name }
people { name }
updated_at
}
}