# Search customers Search customers using OpenSearch-powered full-text and field-specific search. This endpoint provides fast, indexed search across customer data with support for: - Full-text search across multiple fields - Field-specific filtering with various operators - Sorting and pagination - Saved search preferences Note: Only active (non-deleted) customers are searchable. Soft-deleted records are automatically excluded from all search results. Response Formats: - flat (default): Returns indexed fields only for faster performance - full: Returns complete customer objects with all relationships Endpoint: POST /customers/search Version: 1.0.0 Security: BearerAuth ## Request fields (application/json): - `criteria` (object) Search criteria to filter customers - `criteria.id` (object) Search criteria for UUID fields - `criteria.id.operator` (string, required) Search operator: - EQUALS: Exact match - NOT_EQUALS: Not equal to - ONE_OF: Matches any UUID in array - NOT_ONE_OF: Does not match any UUID in array - EXISTS: Field has a value (not null) - DOES_NOT_EXIST: Field is null Enum: "EQUALS", "NOT_EQUALS", "ONE_OF", "NOT_ONE_OF", "EXISTS", "DOES_NOT_EXIST" - `criteria.id.values` (array) Array of UUIDs for ONE_OF or NOT_ONE_OF operators Example: ["550e8400-e29b-41d4-a716-446655440000","550e8400-e29b-41d4-a716-446655440001"] - `criteria.friendlyId` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.friendlyId.operator` (string, required) Search operator: - EQUALS: Exact match - NOT_EQUALS: Not equal to - ONE_OF: Matches any value in array - NOT_ONE_OF: Does not match any value in array - EXISTS: Field has a value (not null) - DOES_NOT_EXIST: Field is null Enum: "EQUALS", "NOT_EQUALS", "ONE_OF", "NOT_ONE_OF", "EXISTS", "DOES_NOT_EXIST" - `criteria.friendlyId.values` (array) Array of values for ONE_OF or NOT_ONE_OF operators Example: ["ACTIVE","PENDING"] - `criteria.name` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.name.operator` (string, required) Search operator: - EQUALS: Exact match - NOT_EQUALS: Not equal to - STARTS_WITH: Begins with prefix - ENDS_WITH: Ends with suffix - INCLUDES: Contains substring - ONE_OF: Matches any value in array - NOT_ONE_OF: Does not match any value in array - EXISTS: Field has a value (not null) - DOES_NOT_EXIST: Field is null Enum: "EQUALS", "NOT_EQUALS", "STARTS_WITH", "ENDS_WITH", "INCLUDES", "ONE_OF", "NOT_ONE_OF", "EXISTS", "DOES_NOT_EXIST" - `criteria.dbaName` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.status` (object) Customer status (ACTIVE, INACTIVE, PENDING, SUSPENDED, ARCHIVED) - `criteria.city` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.state` (object) State/Province code (uppercase) - `criteria.location` (object) Computed field "city, state" - `criteria.zip` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.country` (object) Country code (uppercase) - `criteria.teamId` (object) Team ID (internal field groupId) - `criteria.teamName` (object) Team name (internal field groupName) - `criteria.userIds` (object) IDs of users associated with this customer - `criteria.userNames` (object) Names of users associated with this customer - `criteria.accountOwnerId` (object) Primary account owner user ID - `criteria.accountOwnerName` (object) Primary account owner name - `criteria.operatedById` (object) Operations representative user ID - `criteria.operatedByName` (object) Operations representative name - `criteria.primaryContactName` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.primaryContactEmail` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.primaryContactPhone` (object) Search criteria for text fields (supports wildcards and partial matching) - `criteria.serviceTier` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.yearsInBusiness` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.numberOfEmployees` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.industry` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.sic` (object) Standard Industrial Classification code - `criteria.naics` (object) North American Industry Classification System code - `criteria.paymentTermName` (object) Search criteria for keyword fields (exact match, no partial matching) - `criteria.creditLimit` (object) Search criteria for float/decimal fields - `criteria.creditLimit.operator` (string, required) Search operator: - EQUALS: Exact match - NOT_EQUALS: Not equal to - GREATER_THAN: Greater than value - LESS_THAN: Less than value - BETWEEN: Between min and max (inclusive) - NOT_BETWEEN: Not between min and max - EXISTS: Field has a value (not null) - DOES_NOT_EXIST: Field is null Enum: "EQUALS", "NOT_EQUALS", "GREATER_THAN", "LESS_THAN", "BETWEEN", "NOT_BETWEEN", "EXISTS", "DOES_NOT_EXIST" - `criteria.creditLimit.value` (number) Single value for EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN - `criteria.creditLimit.min` (number) Minimum value for BETWEEN or NOT_BETWEEN - `criteria.creditLimit.max` (number) Maximum value for BETWEEN or NOT_BETWEEN - `criteria.outstandingBalance` (object) Search criteria for float/decimal fields - `criteria.totalRevenue` (object) Search criteria for float/decimal fields - `criteria.totalTransportationCost` (object) Search criteria for float/decimal fields - `criteria.totalGrossProfit` (object) Computed as totalRevenue - totalTransportationCost - `criteria.ordersCount` (object) Number of non-canceled/rejected shipments - `criteria.quotesCount` (object) Search criteria for integer fields - `criteria.quotesWon` (object) Search criteria for integer fields - `criteria.quoteWinRate` (object) Computed win rate (quotesWon / quotesCount) - `criteria.mostRecentOrderCreationAt` (object) Date of the most recent order - `criteria.mostRecentOrderCreationAt.operator` (string, required) Search operator: - EQUALS: Exact match - NOT_EQUALS: Not equal to - BEFORE: Before datetime - AFTER: After datetime - BETWEEN: Between min and max (inclusive) - NOT_BETWEEN: Not between min and max - EXISTS: Field has a value (not null) - DOES_NOT_EXIST: Field is null Enum: "EQUALS", "NOT_EQUALS", "BEFORE", "AFTER", "BETWEEN", "NOT_BETWEEN", "EXISTS", "DOES_NOT_EXIST" - `criteria.mostRecentOrderCreationAt.value` (string) Absolute datetime for EQUALS, NOT_EQUALS Example: "2025-01-15T10:00:00Z" - `criteria.mostRecentOrderCreationAt.min` (string) Minimum datetime for BETWEEN or NOT_BETWEEN Example: "2025-01-01T00:00:00Z" - `criteria.mostRecentOrderCreationAt.max` (string) Maximum datetime for BETWEEN or NOT_BETWEEN Example: "2025-12-31T23:59:59Z" - `criteria.mostRecentOrderCreationAt.valueRelative` (integer) Relative time from now (negative for past, positive for future). Example: -7 with WEEK unit means 7 weeks ago. - `criteria.mostRecentOrderCreationAt.valueRelativeUnit` (string) Time unit for relative time calculations: - YEAR: Years - MONTH: Months - WEEK: Weeks - DAY: Days - HOUR: Hours - MINUTE: Minutes - SECOND: Seconds Enum: "YEAR", "MONTH", "WEEK", "DAY", "HOUR", "MINUTE", "SECOND" - `criteria.mostRecentOrderCreationAt.minRelative` (integer) Relative time for min boundary - `criteria.mostRecentOrderCreationAt.minRelativeUnit` (string) Time unit for relative time calculations: - YEAR: Years - MONTH: Months - WEEK: Weeks - DAY: Days - HOUR: Hours - MINUTE: Minutes - SECOND: Seconds Enum: "YEAR", "MONTH", "WEEK", "DAY", "HOUR", "MINUTE", "SECOND" - `criteria.mostRecentOrderCreationAt.maxRelative` (integer) Relative time for max boundary - `criteria.mostRecentOrderCreationAt.maxRelativeUnit` (string) Time unit for relative time calculations: - YEAR: Years - MONTH: Months - WEEK: Weeks - DAY: Days - HOUR: Hours - MINUTE: Minutes - SECOND: Seconds Enum: "YEAR", "MONTH", "WEEK", "DAY", "HOUR", "MINUTE", "SECOND" - `criteria.nextFollowUp` (object) Search criteria for date fields (no time component). Supports both absolute date values and relative time expressions. - `criteria.nextFollowUp.operator` (string, required) Search operator (same as DatetimeSearchCriteria) Enum: "EQUALS", "NOT_EQUALS", "BEFORE", "AFTER", "BETWEEN", "NOT_BETWEEN", "EXISTS", "DOES_NOT_EXIST" - `criteria.nextFollowUp.value` (string) Absolute date for EQUALS, NOT_EQUALS Example: "2025-01-15" - `criteria.nextFollowUp.min` (string) Minimum date for BETWEEN or NOT_BETWEEN Example: "2025-01-01" - `criteria.nextFollowUp.max` (string) Maximum date for BETWEEN or NOT_BETWEEN Example: "2025-12-31" - `criteria.nextFollowUp.valueRelative` (integer) Relative time from now - `criteria.nextFollowUp.minRelative` (integer) - `criteria.nextFollowUp.maxRelative` (integer) - `criteria.lastOutreach` (object) Search criteria for datetime fields. Supports both absolute datetime values and relative time expressions. - `criteria.quickbooksCustomerId` (object) QuickBooks Online customer ID (internal field qboCustomerId) - `criteria.tags` (object) Tag labels associated with the customer - `criteria.createdAt` (object) Search criteria for datetime fields. Supports both absolute datetime values and relative time expressions. - `criteria.updatedAt` (object) Search criteria for datetime fields. Supports both absolute datetime values and relative time expressions. - `pagination` (object) Pagination options for search requests - `pagination.pageNumber` (integer) Page number (1-based) Example: 1 - `pagination.pageSize` (integer) Number of results per page (max 250) Example: 50 - `sort` (array) Sort options for the search results Example: [{"field":"createdAt","order":"desc"}] - `sort.field` (string, required) Field name to sort by (must be an indexed field) Example: "createdAt" - `sort.order` (string, required) Sort direction (ascending or descending) Enum: "asc", "desc" - `savedSearch` (object) Optional saved search to load preferences from. When provided, the saved search criteria will be loaded and merged with any explicit criteria. - `savedSearch.id` (string) Saved search UUID Example: "550e8400-e29b-41d4-a716-446655440000" - `savedSearch.key` (string) Client-defined key for the saved search Example: "my-carrier-search" - `format` (string) Response format: - flat: Returns only indexed fields (default, faster) - full: Returns complete customer objects Enum: "flat", "full" ## Response 200 fields (application/json): - `data` (array, required) Search results - either flat rows or full customer objects based on format parameter - `pagination` (object, required) Pagination information for search results - `pagination.pageNumber` (integer, required) Current page number Example: 1 - `pagination.pageSize` (integer, required) Number of results returned on this page Example: 50 - `pagination.totalPages` (integer, required) Total number of pages available Example: 25 - `totalResults` (integer, required) Total number of matching results (excluding soft-deleted records) ## Response 400 fields (application/json): - `error` (string, required) Error code - `message` (string, required) Human-readable error message ## Response 401 fields (application/json): - `error` (string, required) Error code - `message` (string, required) Human-readable error message ## Response 422 fields (application/json): - `error` (string, required) Error code Example: "validation_error" - `message` (string, required) Human-readable error message - `details` (array, required) Validation error details - `details.field` (string, required) Field name that failed validation - `details.message` (string, required) Validation error message ## Response 429 fields (application/json): - `error` (string, required) Error code - `message` (string, required) Human-readable error message