Skip to content

Data Models & Schemas

Table of Contents

Overview

The Engagifii CRM API uses a comprehensive set of data models that represent the core entities and their relationships within the CRM system. All models follow consistent naming conventions and validation rules.

Model Naming Conventions

  • Entity Models: Core business objects (Person, Organization, Committee)
  • View Models: Client-facing representations with *View or *ClientView suffix
  • Request Models: Input models for API operations with *Request suffix
  • Filter Models: Search and filtering models with *Filter suffix
  • Item Models: Lightweight representations with *Item suffix

Common Properties

Most entity models include these standard audit fields:

  • id: Unique GUID identifier
  • createdDate: ISO 8601 timestamp of creation
  • modifiedDate: ISO 8601 timestamp of last modification
  • isActive: Boolean indicating active status
  • tenantId: Multi-tenancy identifier (system managed)

Core Entity Models

Person Model

Represents an individual person within the CRM system.

json
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "firstName": "John",
  "middleName": "Michael",
  "lastName": "Doe",
  "suffix": "Jr.",
  "displayName": "John M. Doe Jr.",
  "email": "john.doe@example.com",
  "secondaryEmail": "john.doe.personal@gmail.com",
  "phone": "+1-555-123-4567",
  "mobilePhone": "+1-555-987-6543",
  "title": "Senior Software Engineer",
  "department": "Engineering",
  "organizationId": "org-123",
  "organizationName": "Acme Corporation",
  "addresses": [
    {
      "id": "addr-1",
      "type": "Primary",
      "street": "123 Main Street",
      "street2": "Suite 456",
      "city": "New York",
      "state": "NY",
      "zipCode": "10001",
      "country": "USA",
      "isActive": true
    }
  ],
  "positions": [
    {
      "id": "pos-1",
      "organizationId": "org-123",
      "title": "Senior Software Engineer",
      "department": "Engineering",
      "startDate": "2023-01-15T00:00:00Z",
      "endDate": null,
      "isActive": true,
      "isPrimary": true
    }
  ],
  "tags": [
    {
      "id": "tag-1",
      "name": "VIP",
      "color": "#FF5733",
      "category": "Status"
    }
  ],
  "customFields": {
    "birthDate": "1985-03-15T00:00:00Z",
    "linkedInProfile": "https://linkedin.com/in/johndoe",
    "emergencyContact": "Jane Doe",
    "notes": "Key stakeholder in platform architecture decisions"
  },
  "isActive": true,
  "createdDate": "2023-01-15T10:30:00Z",
  "modifiedDate": "2024-01-20T15:45:00Z"
}

Validation Rules:

  • firstName: Required, max 50 characters
  • lastName: Required, max 50 characters
  • email: Required, valid email format, unique per tenant
  • phone: Optional, valid phone format
  • addresses: At least one address required if specified
  • organizationId: Must reference valid organization

Organization Model

Represents a company, department, or other organizational entity.

json
{
  "id": "org-123",
  "name": "Acme Corporation",
  "shortName": "ACME",
  "description": "Leading provider of innovative software solutions",
  "organizationType": "Company",
  "organizationTypeId": "type-1",
  "parentOrganizationId": null,
  "website": "https://acme.com",
  "email": "info@acme.com",
  "phone": "+1-555-000-1234",
  "fax": "+1-555-000-1235",
  "addresses": [
    {
      "id": "addr-org-1",
      "type": "Headquarters",
      "street": "100 Corporate Boulevard",
      "city": "San Francisco",
      "state": "CA",
      "zipCode": "94105",
      "country": "USA",
      "isActive": true
    }
  ],
  "childOrganizations": [
    {
      "id": "org-124",
      "name": "Engineering Department",
      "organizationType": "Department",
      "memberCount": 25
    }
  ],
  "relatedOrganizations": [
    {
      "id": "org-200",
      "name": "Partner Corp",
      "relationshipType": "Strategic Partner",
      "relationshipStartDate": "2023-01-01T00:00:00Z"
    }
  ],
  "tags": [
    {
      "id": "tag-org-1",
      "name": "Fortune 500",
      "color": "#1E88E5"
    }
  ],
  "memberCount": 150,
  "isActive": true,
  "createdDate": "2023-01-01T00:00:00Z",
  "modifiedDate": "2024-01-20T12:00:00Z"
}

Validation Rules:

  • name: Required, max 200 characters, unique per tenant
  • organizationType: Required, must be valid type
  • website: Optional, valid URL format
  • email: Optional, valid email format
  • parentOrganizationId: Must reference valid organization, cannot create circular references

Committee Model

Represents committees, boards, or other governance structures.

json
{
  "id": "committee-123",
  "name": "Board of Directors",
  "description": "Executive oversight and strategic direction committee",
  "committeeType": "Board",
  "committeeTypeId": "ctype-1",
  "organizationId": "org-123",
  "organizationName": "Acme Corporation",
  "startDate": "2023-01-01T00:00:00Z",
  "endDate": null,
  "meetingFrequency": "Monthly",
  "positions": [
    {
      "id": "pos-1",
      "title": "Chairman",
      "description": "Committee chair and primary decision maker",
      "sequence": 1,
      "isRequired": true,
      "maxOccupants": 1
    },
    {
      "id": "pos-2",
      "title": "Secretary",
      "description": "Record keeping and meeting coordination",
      "sequence": 2,
      "isRequired": true,
      "maxOccupants": 1
    }
  ],
  "members": [
    {
      "id": "member-1",
      "personId": "person-456",
      "personName": "Jane Smith",
      "positionId": "pos-1",
      "positionTitle": "Chairman",
      "startDate": "2023-01-01T00:00:00Z",
      "endDate": null,
      "isActive": true
    }
  ],
  "tags": [
    {
      "id": "tag-com-1",
      "name": "Executive",
      "color": "#9C27B0"
    }
  ],
  "memberCount": 8,
  "isActive": true,
  "createdDate": "2023-01-01T00:00:00Z",
  "modifiedDate": "2024-01-15T09:30:00Z"
}

Validation Rules:

  • name: Required, max 200 characters
  • committeeType: Required, must be valid type
  • organizationId: Required, must reference valid organization
  • startDate: Required
  • endDate: Must be after startDate if specified
  • positions: At least one position required

Advocacy Relationship Model

Represents political or advocacy relationships between people and officials.

json
{
  "id": "relationship-123",
  "personId": "person-456",
  "personName": "John Doe",
  "relatedOfficialId": "official-789",
  "relatedOfficialName": "Senator Jane Smith",
  "relatedOfficialTitle": "U.S. Senator",
  "relatedOfficialOffice": "United States Senate",
  "relationshipType": "Constituent",
  "relationshipTypeId": "rel-type-1",
  "relationshipCategory": "Political",
  "startDate": "2023-01-01T00:00:00Z",
  "endDate": null,
  "strength": "Strong",
  "notes": "Active constituent relationship with regular communication",
  "lastContactDate": "2024-01-15T00:00:00Z",
  "nextFollowUpDate": "2024-02-15T00:00:00Z",
  "isActive": true,
  "createdDate": "2023-01-01T00:00:00Z",
  "modifiedDate": "2024-01-15T14:20:00Z"
}

Request/Response Models

ListViewRequest Model

Standard request model for paginated list endpoints.

json
{
  "pageIndex": 0,
  "pageSize": 50,
  "sortField": "lastName",
  "sortDirection": "asc",
  "searchText": "john",
  "filter": {
    // Endpoint-specific filter properties
  }
}

Properties:

  • pageIndex: Integer, zero-based page number, default 0
  • pageSize: Integer, records per page, range 1-500, default 50
  • sortField: String, field name to sort by
  • sortDirection: String, "asc" or "desc", default "asc"
  • searchText: String, general search query, max 200 characters
  • filter: Object, endpoint-specific filter criteria

ListViewResult Model

Standard response model for paginated list endpoints.

json
{
  "data": [
    // Array of result objects
  ],
  "totalCount": 1250,
  "pageIndex": 0,
  "pageSize": 50,
  "totalPages": 25,
  "hasNextPage": true,
  "hasPreviousPage": false,
  "firstItemOnPage": 1,
  "lastItemOnPage": 50
}

Properties:

  • data: Array of result objects
  • totalCount: Total number of records matching filter
  • pageIndex: Current page number (zero-based)
  • pageSize: Number of records per page
  • totalPages: Total number of pages
  • hasNextPage: Boolean, whether more pages exist
  • hasPreviousPage: Boolean, whether previous pages exist
  • firstItemOnPage: One-based index of first item on current page
  • lastItemOnPage: One-based index of last item on current page

Filter Models

PeopleListViewBodyFilter

Filter model for people list endpoints.

json
{
  "searchText": "john",
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "phone": "+1-555-123-4567",
  "organizationId": "org-123",
  "organizationName": "Acme",
  "personaTypeId": "type-456",
  "isActive": true,
  "hasEmail": true,
  "hasPhone": true,
  "hasAddress": true,
  "dateRange": {
    "startDate": "2023-01-01T00:00:00Z",
    "endDate": "2024-01-01T00:00:00Z",
    "dateField": "createdDate"
  },
  "locationFilter": {
    "country": "USA",
    "state": "CA",
    "city": "San Francisco",
    "zipCode": "94105",
    "radius": 50,
    "radiusUnit": "miles"
  },
  "tagIds": ["tag-1", "tag-2"],
  "excludeTagIds": ["tag-exclude-1"],
  "positionFilter": {
    "title": "Manager",
    "department": "Engineering",
    "hasActivePosition": true
  },
  "customFields": {
    "customField123": "value1",
    "customField456": ["value2", "value3"]
  }
}

OrganizationListViewBodyFilter

Filter model for organization list endpoints.

json
{
  "searchText": "acme",
  "name": "Acme Corporation",
  "organizationType": "Company",
  "organizationTypeId": "type-1",
  "parentOrganizationId": "parent-org-1",
  "hasParentOrganization": true,
  "hasChildOrganizations": true,
  "hasMembers": true,
  "memberCountRange": {
    "min": 10,
    "max": 500
  },
  "isActive": true,
  "dateRange": {
    "startDate": "2023-01-01T00:00:00Z",
    "endDate": "2024-01-01T00:00:00Z",
    "dateField": "createdDate"
  },
  "locationFilter": {
    "country": "USA",
    "state": "CA"
  },
  "tagIds": ["tag-org-1"],
  "customFields": {
    "industry": "Technology"
  }
}

DateRangeFilter

Common date range filter used across multiple endpoints.

json
{
  "startDate": "2023-01-01T00:00:00Z",
  "endDate": "2024-01-01T00:00:00Z",
  "dateField": "createdDate",
  "includeNullDates": false
}

Properties:

  • startDate: ISO 8601 date, inclusive start of range
  • endDate: ISO 8601 date, inclusive end of range
  • dateField: String, name of date field to filter on
  • includeNullDates: Boolean, whether to include records with null dates

Common Data Types

Address Type

json
{
  "id": "addr-1",
  "type": "Primary",
  "street": "123 Main Street",
  "street2": "Suite 456",
  "city": "New York",
  "state": "NY",
  "zipCode": "10001",
  "country": "USA",
  "latitude": 40.7128,
  "longitude": -74.0060,
  "isActive": true,
  "isPrimary": true
}

Address Types:

  • Primary: Main address
  • Secondary: Alternative address
  • Headquarters: Organization main office
  • Branch: Organization branch office
  • Billing: Billing address
  • Shipping: Shipping address

Tag Type

json
{
  "id": "tag-1",
  "name": "VIP",
  "description": "Very Important Person designation",
  "color": "#FF5733",
  "category": "Status",
  "isActive": true,
  "usageCount": 150
}

Position Type

json
{
  "id": "pos-1",
  "organizationId": "org-123",
  "title": "Senior Software Engineer",
  "department": "Engineering",
  "level": "Senior",
  "startDate": "2023-01-15T00:00:00Z",
  "endDate": null,
  "isActive": true,
  "isPrimary": true,
  "reportingManagerId": "person-manager-1",
  "salary": {
    "amount": 120000,
    "currency": "USD",
    "frequency": "Annual"
  }
}

Contact Information Type

json
{
  "emails": [
    {
      "type": "Primary",
      "address": "john.doe@company.com",
      "isActive": true
    },
    {
      "type": "Personal",
      "address": "john.doe@gmail.com",
      "isActive": true
    }
  ],
  "phones": [
    {
      "type": "Work",
      "number": "+1-555-123-4567",
      "extension": "1234",
      "isActive": true
    },
    {
      "type": "Mobile",
      "number": "+1-555-987-6543",
      "isActive": true
    }
  ]
}

Contact Types:

  • Email: Primary, Secondary, Personal, Work
  • Phone: Work, Mobile, Home, Fax

Validation Rules

General Validation Rules

String Fields:

  • All string fields are trimmed of leading/trailing whitespace
  • Empty strings are treated as null values
  • HTML content is sanitized for security

Date Fields:

  • Must be in ISO 8601 format: YYYY-MM-DDTHH:mm:ssZ
  • All dates stored in UTC
  • Historical dates allowed but cannot be in the future for creation dates

GUID Fields:

  • Must be valid GUID format with hyphens: 123e4567-e89b-12d3-a456-426614174000
  • Case insensitive
  • Cannot be empty GUID (00000000-0000-0000-0000-000000000000)

Email Fields:

  • Must be valid email format per RFC 5322
  • Maximum 254 characters
  • Case insensitive storage and comparison
  • Must be unique per tenant where specified

Phone Fields:

  • Supports international formats
  • Automatically formatted and validated
  • Can include extensions
  • Maximum 20 characters for base number

Entity-Specific Validation

Person Validation:

  • First name and last name required
  • Email required and must be unique per tenant
  • Phone number format validated if provided
  • At least one address required if addresses provided

Organization Validation:

  • Name required and must be unique per tenant
  • Cannot set self as parent organization
  • Circular parent-child relationships prevented
  • Website URL format validated if provided

Committee Validation:

  • Name required
  • Must belong to a valid organization
  • End date must be after start date if provided
  • At least one position required
  • Position titles must be unique within committee

JSON Schema Definitions

Person Schema

json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Person",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Unique identifier for the person"
    },
    "firstName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 50,
      "description": "Person's first name"
    },
    "lastName": {
      "type": "string", 
      "minLength": 1,
      "maxLength": 50,
      "description": "Person's last name"
    },
    "email": {
      "type": "string",
      "format": "email",
      "maxLength": 254,
      "description": "Primary email address"
    },
    "phone": {
      "type": "string",
      "pattern": "^[+]?[1-9]\\d{1,14}$",
      "description": "Primary phone number in international format"
    },
    "organizationId": {
      "type": "string",
      "format": "uuid",
      "description": "ID of associated organization"
    },
    "isActive": {
      "type": "boolean",
      "description": "Whether the person is active in the system"
    },
    "createdDate": {
      "type": "string",
      "format": "date-time",
      "description": "Date and time when person was created"
    }
  },
  "required": ["firstName", "lastName", "email"],
  "additionalProperties": true
}

Organization Schema

json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object", 
  "title": "Organization",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "organizationType": {
      "type": "string",
      "enum": ["Company", "Department", "NonProfit", "Government", "Educational"]
    },
    "website": {
      "type": "string",
      "format": "uri"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "parentOrganizationId": {
      "type": ["string", "null"],
      "format": "uuid"
    },
    "isActive": {
      "type": "boolean"
    }
  },
  "required": ["name", "organizationType"],
  "additionalProperties": true
}

List Request Schema

json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "ListViewRequest",
  "properties": {
    "pageIndex": {
      "type": "integer",
      "minimum": 0,
      "default": 0
    },
    "pageSize": {
      "type": "integer", 
      "minimum": 1,
      "maximum": 500,
      "default": 50
    },
    "sortField": {
      "type": "string",
      "maxLength": 50
    },
    "sortDirection": {
      "type": "string",
      "enum": ["asc", "desc"],
      "default": "asc"
    },
    "searchText": {
      "type": "string",
      "maxLength": 200
    },
    "filter": {
      "type": "object"
    }
  },
  "additionalProperties": false
}

For complete schema definitions and validation rules, refer to the OpenAPI Specification or test interactively using the Swagger Documentation.