Search Filters

The criteria on this page are the id values you put in a filter constraint node. The node shape, the
operators for each data type, and the configuration block are covered in
Advanced Search Overview.

{
  "type": "constraint",
  "id": "birth_date",
  "operator": "in_the_next",
  "value": { "period": "day", "units": 30, "anniversary": true },
  "invert": false
}
📘

These criteria are for individual search only

They apply to POST /search/individuals/results. The group, event-attendance, and scheduling
domains each have their own criteria set.

Get the live list for your integration

Criteria are filtered by the calling user's permissions and by the church's enabled modules, so the
set you can actually use is narrower than the full table below.

GET /search/individuals

Returns the criteria this caller may use, plus the search actions they may run. Call it once at
integration setup, or when a filter starts returning 412, instead of guessing from documentation.

It uses the same read:individuals scope as the results endpoint.

📘

GET /search/criteria/individuals is the older form of the same call and is deprecated. Use

GET /search/individuals.


Reading the table

Type determines which operators are valid and what shape value takes. text, number,
date, date_parts, boolean, boolean_strict, currency, and time are documented in
Data Types and Operators.

special means the criterion takes a structured value object of its own. Every special
criterion has a section under Special criteria giving its exact shape.

Access is the permission the calling user needs. A user who does not have it gets 403, not a
filtered result set — a single unpermitted constraint fails the whole request.

AccessMeaning
Any signed-in userNo specific people permission needed.
People readLimited people-read in at least one campus.
Full people readFull people-read in at least one campus.
FinancialFull financial access in at least one campus.
NotesMay view individual notes.
VirtusMay view Virtus data, and Virtus is connected for the church.
Significant eventsMaster administrator, or full people-read in at least one campus.
Sacrament adminSacrament admin in at least one campus. Falls back to People read when the church does not have sacrament visibility enabled.
ContextualChecked per constraint against the specific event or group named in the value — guest-list or member-list visibility for that record.

Master administrators and system users satisfy all of these.


Criteria

IdTypeAccessNotes
abilityspecialPeople readshape
agenumberPeople read
age_monthsnumberPeople read
allergiestextPeople read
anniversarydatePeople read
anniversary_date_partsdate_partsPeople read
anniversary_monthnumberPeople read
anointing_the_sick_sacramentspecialFull people readshape · Requires the Sacraments module
approval_statustextPeople read
approval_status_datedatePeople read
approval_status_modifier_idnumberPeople read
attendance_attendance_groupingspecialPeople readshape
attendance_departmentspecialPeople readshape
attendance_groupspecialPeople readshape
attendance_single_eventspecialPeople readshape
background_check_package_namespecialPeople readshape
baptism_sacramentspecialFull people readshape · Requires the Sacraments module
baptized_datedatePeople read
baptized_date_partsdate_partsPeople read
barcodetextPeople read
birth_datedatePeople read
birth_date_partsdate_partsPeople read
birth_date_parts_anniversary_modedate_partsPeople read
birth_monthnumberPeople read
campusnumberPeople read
child_work_approved_start_datedate_partsPeople read
child_work_approved_start_monthnumberPeople read
child_work_approved_stop_datedate_partsPeople read
child_work_approved_stop_monthnumberPeople read
church_servicenumberPeople read
commitment_datedatePeople read
commitment_date_partsdate_partsPeople read
commitment_storytextPeople read
confirmation_sacramentspecialFull people readshape · Requires the Sacraments module
contact_phone_numbertextPeople read
creator_first_nametextPeople read
creator_last_nametextPeople read
creator_namespecialPeople readshape
current_storytextPeople read
custom_fieldsspecialPeople readshape
date_createddatePeople read
date_created_monthnumberPeople read
date_created_partsdate_partsPeople read
date_deceaseddatePeople read
date_deceased_monthnumberPeople read
date_deceased_partsdate_partsPeople read
date_last_ran_own_giving_statementdatePeople read
date_last_ran_own_giving_statement_partsdate_partsPeople read
date_modifieddatePeople read
date_modified_monthnumberPeople read
date_modified_partsdate_partsPeople read
denied_status_reasontextPeople read
department_adminspecialPeople readshape
discussion_postsnumberPeople read
duplicatesspecialFull people readshape
emailtextPeople read
email_verification_date_opt_in_email_sentspecialPeople readshape
email_verification_date_verification_email_sentspecialPeople readshape
email_verification_date_verifiedspecialPeople readshape
email_verification_opt_in_datespecialPeople readshape
email_verification_opt_in_statusspecialPeople readshape
emergency_contact_nametextPeople read
emergency_contact_phone_numbertextPeople read
envelope_user_idspecialPeople readshape
ethnicity_idnumberPeople read
eventspecialContextualshape
event_attendancespecialContextualshape
event_legacyspecialPeople readshape
event_rsvpspecialContextualshape
external_diocesan_idtextPeople readRequires the Catholic vernacular module
external_fundraising_idtextPeople readRequires the Catholic vernacular module
external_safe_environment_idtextPeople readRequires the Catholic vernacular module
family_childspecialPeople readshape
family_headspecialPeople readshape
family_household_mailing_nametextPeople read
family_idnumberPeople read
family_otherspecialPeople readshape
family_phototextPeople read
family_positionspecialPeople readshape
family_spousespecialPeople readshape
fax_phone_numbertextPeople read
first_attended_datedatePeople read
first_communion_sacramentspecialFull people readshape · Requires the Sacraments module
first_nametextPeople read
form_question_answerspecialPeople readshape
funeral_system_significant_eventspecialSignificant eventsshape
gendertextPeople read
giving_numbertextPeople read
groupspecialContextualshape
group_custom_fieldsspecialPeople readshape
group_departmentspecialPeople readshape
group_interaction_typespecialPeople readshape
group_involvementspecialPeople readshape
group_member_start_datespecialPeople readshape
group_namespecialPeople readshape
group_relationshipspecialPeople readshape
group_searchspecialPeople readshape
group_statusspecialPeople readshape
group_typespecialPeople readshape
group_udf_pulldown_1numberPeople read
group_udf_pulldown_2numberPeople read
group_udf_pulldown_3numberPeople read
has_requested_background_checkspecialPeople readshape
holy_order_sacramentspecialFull people readshape · Requires the Sacraments module
home_addressspecialPeople readshape
home_areanumberPeople read
home_citytextPeople read
home_countrytextPeople read
home_phone_numbertextPeople read
home_statetextPeople read
home_streettextPeople read
home_ziptextPeople read
homebound_ministry_idnumberPeople read
how_joined_churchnumberFull people read
how_they_heardnumberFull people read
individual_idnumberSacrament admin
is_baptizedboolean_strictPeople read
is_confirmed_no_allergiesboolean_strictPeople read
is_home_listedbooleanPeople read
is_inactivebooleanPeople read
is_limited_access_userbooleanPeople read
is_listedbooleanPeople read
is_other_listedbooleanPeople read
is_work_listedbooleanPeople read
last_attended_datedate_partsPeople read
last_giving_datedate_partsPeople read
last_login_datedatePeople read
last_login_date_partsdate_partsPeople read
last_nametextPeople read
last_need_assigned_datedate_partsPeople read
legal_nametextPeople read
luna_assignmentspecialPeople readshape
luna_assignment_datedatePeople read
luna_assignment_date_partsspecialPeople readshape
luna_assignment_monthnumberPeople read
luna_assignment_statusspecialPeople readshape
luna_categorynumberPeople read
luna_category_involvementspecialPeople readshape
luna_organizerspecialPeople readshape
luna_positionspecialPeople readshape
luna_teamspecialPeople readshape
mailing_addressspecialPeople readshape
mailing_areanumberPeople read
mailing_carrier_routetextPeople read
mailing_citytextPeople read
mailing_countrytextPeople read
mailing_statetextPeople read
mailing_streettextPeople read
mailing_ziptextPeople read
marital_statustextPeople read
marriage_sacramentspecialFull people readshape · Requires the Sacraments module
membership_monthnumberPeople read
membership_start_datedatePeople read
membership_start_date_partsdate_partsPeople read
membership_stop_datedatePeople read
membership_stop_date_partsdate_partsPeople read
membership_typenumberFull people read
micr_scanspecialFinancialshape
middle_nametextPeople read
militarytextPeople read
mobile_carriernumberPeople read
mobile_phone_numbertextPeople read
modified_namespecialPeople readshape
modifier_first_nametextPeople read
modifier_last_nametextPeople read
namespecialAny signed-in usershape
name_fieldsspecialPeople readshape
new_giverspecialPeople readshape
notespecialNotesshape
other_addressspecialPeople readshape
other_areanumberPeople read
other_citytextPeople read
other_countrytextPeople read
other_idtextPeople read
other_statetextPeople read
other_streettextPeople read
other_ziptextPeople read
pager_phone_numbertextPeople read
passionspecialPeople readshape
personality_stylespecialPeople readshape
phone_numberspecialPeople readshape
phototextPeople read
pledgenumberPeople read
preferred_language_idnumberPeople read
privacy_settingsspecialPeople readshape
process_queuespecialPeople readshape
process_queue_added_datespecialPeople readshape
process_queue_completed_datespecialPeople readshape
process_queue_due_datespecialPeople readshape
reason_left_churchnumberFull people read
reconciliation_sacramentspecialFull people readshape · Requires the Sacraments module
religion_idnumberPeople readRequires the Catholic vernacular module
schoolnumberPeople read
school_gradenumberPeople read
significant_eventspecialFull people readshape
significant_event_datespecialFull people readshape
spiritual_giftspecialPeople readshape
spiritual_maturitynumberFull people read
sync_idnumberPeople read
udf_date_1datePeople read
udf_date_2datePeople read
udf_date_3datePeople read
udf_date_4datePeople read
udf_date_5datePeople read
udf_date_6datePeople read
udf_pulldown_1numberPeople read
udf_pulldown_2numberPeople read
udf_pulldown_3numberPeople read
udf_pulldown_4numberPeople read
udf_pulldown_5numberPeople read
udf_pulldown_6numberPeople read
udf_text_1textPeople read
udf_text_10textPeople read
udf_text_11textPeople read
udf_text_12textPeople read
udf_text_2textPeople read
udf_text_3textPeople read
udf_text_4textPeople read
udf_text_5textPeople read
udf_text_6textPeople read
udf_text_7textPeople read
udf_text_8textPeople read
udf_text_9textPeople read
virtus_statusspecialVirtusshape
virtus_status_expiration_timespecialVirtusshape
whos_includedinertPeople readListed by GET /search/individuals but not queryable — see Non-queryable criteria
work_addressspecialPeople readshape
work_areanumberPeople read
work_citytextPeople read
work_countrytextPeople read
work_job_titletextPeople read
work_phone_numbertextPeople read
work_statetextPeople read
work_streettextPeople read
work_ziptextPeople read

Ids that changed

Earlier revisions of this page listed ids that the API does not accept, and typed several criteria in
a way that produces 412 or an empty result set. If your integration uses one of these, update it.

Previously listedUse insteadWhy
udf_pulldow_1 … udf_pulldow_6udf_pulldown_1 … udf_pulldown_6The old ids were misspelled and are rejected.
areahome_area, work_area, other_area, mailing_areaThere is no single area criterion; each address block has its own.
emergency_contact_numberemergency_contact_phone_numberRejected id. emergency_contact_name also exists.
positionluna_positionRejected id. See Scheduling (Luna).
process_queue_dateprocess_queue_added_date, process_queue_completed_date, process_queue_due_dateRejected id. The date type is chosen by the criterion, not by a date_type value.

These are accepted, but were typed wrongly — the type in the table above is the one the API applies:

IdWas documented asActually
child_work_approved_start_date, child_work_approved_stop_datedatedate_parts
last_attended_date, last_giving_date, last_need_assigned_datedatedate_parts
is_baptizedbooleanboolean_strict — is_not_set means explicitly not baptized, not "unknown". Use unknown for unset.
ability, passion, personality_style, spiritual_giftnumberspecial — see My Fit
family_head, family_spouse, family_child, family_othertextspecial — see Family Members
family_positiontextspecial, but a plain string still works — see Family Position
group_nametextspecial — the value is a group id under equal/not_equal
group_relationshipnumberspecial — see Group: Relationship
virtus_statustextspecial — see Virtus Status

Special criteria

Each section gives the constraint's operator and the shape of value.

Where a section says the operator is ignored, send any string — the comparison logic lives
entirely inside value. invert still applies to the constraint as a whole.

Sub-operators inside a value (status_op, date_op, and so on) take the same operator names as the
matching data type. A sub-operator left null disables that part of the filter rather than failing.

Attendance

Covers attendance_attendance_grouping, attendance_department, and attendance_group. All three
share one value shape; type selects what id refers to.

Operator: ignored

{
  "type": "grouping",
  "id": 42,
  "group_id": null,
  "attended": "attended",
  "total_by": "week",
  "date_op": "in_the_last",
  "period": "month",
  "units": 3,
  "number_of_times_op": "greater_than_or_equal",
  "number_of_times_value": 4
}
FieldTypeDescription
typestringgrouping, group, department, or event. Determines what id means. event switches to per-event matching.
idnumberThe attendance grouping, group, or department id. 0 or omitted matches any.
group_idnumberOptional, and only with type: "grouping" — narrows the grouping's events to one group.
attendedstringattended, did_not_attend, did_not_attend_group, or pre_checked_did_not_attend.
total_bystringevent, day, or week — what counts as one occurrence. week uses the church's engagement-week definition.
date_opstringA date operator. The date window itself is expressed with the sibling keys below.
year, month, daynumberThe date for equal, not_equal, greater_than.
lbound, ubounddate stringThe range for between / not_between.
period, unitsstring, numberThe window for the in_the_last / in_the_previous / in_the_current families.
number_of_times_opstringA number operator applied to the occurrence count.
number_of_times_valuenumberThe occurrence count.
❗️

from_date / to_date and presence are not read

Earlier revisions of this page showed attendance_grouping_id, department_id, from_date,
to_date, and presence. None of those keys are read. The id goes in id, the window goes in
date_op plus its sibling keys, and presence goes in attended.

📘

Asking for "attended 0 times" is rewritten

attended: "attended" with number_of_times_op: "equal" and number_of_times_value: 0 (or
less_than 1) is converted to did_not_attend_group across all occurrences. A negative
number_of_times_value is clamped to 0.

Attendance: Single Event (legacy)

attendance_single_event. One event on one date.

Operator: ignored

{
  "presence": "present",
  "event_id": 8123,
  "event_date": "2026-08-16"
}
FieldTypeDescription
presencestringpresent matches attendees. Any other value matches non-attendees.
event_idnumberThe event.
event_datedate stringThe occurrence date.
❗️

total_by and number_of_times_* do nothing here

This criterion reads only the three keys above. Sending count or grouping keys is silently
ignored — the result is a plain "did / did not attend that occurrence" match. For counted
attendance use Attendance.

Event

event. check_type selects one of two completely different value shapes.

Operator: ignored
Access: contextual — the caller must be able to view that event's guest list.

Registration status:

{
  "check_type": "status",
  "status_op": "in",
  "status_value": [1, 2],
  "event_op": "equal",
  "event_id": 8123
}
FieldTypeDescription
check_type"status"Required.
status_opstringin, not_in, is, is_not, is_set, is_not_set, or is_not_any.
status_valuenumber | [number]Status id(s). Empty with in behaves as is_set; empty with not_in behaves as is_not_set.
event_opstringA number operator, or null to match across all events.
event_idnumberThe event.

Attendance:

{
  "check_type": "attendance",
  "attended": "attended",
  "event_op": "equal",
  "event_id": 8123,
  "date_op": "in_the_last",
  "date_value": { "period": "month", "units": 1 }
}
FieldTypeDescription
check_type"attendance"Required.
attendedstringattended, did_not_attend, or no_status.
event_op, event_idstring, numberThe event to look at.
date_op, date_valuestring, mixedThe occurrence-date window.
❗️

The status key is status_value, not status_id

A missing status_value is not a validation error — the constraint degrades to "has any status",
which quietly widens your result set.

Event (legacy)

event_legacy. The pre-event form. Prefer event with check_type: "status".

Operator: ignored

{
  "status_op": "is",
  "status_value": 2,
  "event_op": "equal",
  "event_id": 8123
}

status_op is is, is_not, is_any, or is_not_any. As with event, the key is
status_value — not status_id.

Form Question and Answer

form_question_answer. Matches a response to one question on one form.

Operator: ignored — the real operators are question_op and value_op inside the value.

{
  "form_id": 55,
  "question_id": 912,
  "question_op": "equal",
  "question_type": "single",
  "value": "Downtown",
  "value_op": "contains"
}
FieldTypeDescription
form_idnumberRequired. Omit question_id to match anyone who responded to the form at all.
question_idnumberThe question.
question_opstringequal to compare the answer, or is_set / is_not_set to test whether the person responded to the form.
question_typestringRequired when comparing an answer — it selects how value is interpreted. Values below.
value, value_opmixed, stringThe answer comparison.
choice_value, choice_opnumber, stringThe choice comparison, for question types that need both a choice and a value.

What value holds, by question_type:

question_typevalueAlso needs
single, paragraphtext—
checkbox, radio, selectchoice id (number)—
scaleoption id (number)choice_value, choice_op
prioritize, productnumberchoice_value, choice_op
number, donation_amountnumber—
datedate parts—
file_upload—Existence only; no value or operator is used.
❗️

form_question_id, option_value, and option_op are not read

The question id key is question_id. For scale, the option id goes in value / value_op and
the choice id in choice_value / choice_op. An unrecognized question_type is an error, so
omitting it is not a safe default.

Group

group. Membership in one group, optionally narrowed by member status.

Operator: ignored
Access: contextual — the caller must be able to view that group's member list.

{
  "group_id": 331,
  "group_op": "equal",
  "status_value": [1, 2],
  "status_op": "in"
}
FieldTypeDescription
group_idnumberThe group. 0 means any non-system group.
group_opstringA number operator. Defaults to equal.
status_valuenumber | [number]Relationship status. See Group statuses.
status_opstringDefaults to in.

Group: Department

group_department. Membership in any group in a department.

Operator: ignored

{
  "department_id": 12,
  "department_op": "equal",
  "status_value": ["LEADER"],
  "status_op": "in"
}
❗️

The key is department_id, not grouping_id

grouping_id is the underlying column name, not the filter key. department_id: 0 means any
group that is in a department and is not a system group.

Group: Type

group_type.

Operator: ignored

{
  "type_id": 4,
  "type_op": "equal",
  "status_value": ["MEMBER"],
  "status_op": "in"
}

Group: Search

group_search. Combines group name, department, type, and member status in one constraint.

Operator: ignored

{
  "group_name_value": "Youth",
  "group_name_op": "contains",
  "group_grouping_id": 12,
  "group_grouping_op": "equal",
  "group_type_id": 4,
  "group_type_op": "equal",
  "individual_status_id": ["LEADER", "MEMBER"],
  "individual_status_op": "in"
}
❗️

group_name_op: "equal" changes what group_name_value means

With equal, group_name_value is treated as a group id and matched against the group id.
With any other operator it is matched as text against the group name. This is the single most
common source of "my group search returns nothing".

Group: Name

group_name. The value's meaning depends on the operator.

Operator: any text operator, plus equal / not_equal

OperatorValueBehaviour
equalgroup id (number)In that group. 0 means in any group.
not_equalgroup id (number)Not in that group. 0 means in no group at all.
any text operatorstringMatched against the group's name.

Group: Relationship

group_relationship. Relationship status across all groups, with no group filter.

Operator: ignored

{ "status_value": ["LEADER", "COACH"], "status_op": "in" }

Group: Interaction Type

group_interaction_type.

Operator: a number operator, applied to interaction_type

{ "interaction_type": 3, "status_value": ["MEMBER"], "status_op": "in" }

Group: Status

group_status. Membership status with no group, type, or department filter.

Operator: a number operator
Value: the status value

Group: Member Start Date

group_member_start_date. When someone joined a specific group.

Operator: a date operator
Value: an object carrying group_id alongside the date parts the operator needs.

{ "group_id": 331, "year": 2026, "month": 1, "day": 15 }

Group: Involvement

group_involvement. The composite group filter used by current People Search. Every sub-filter is
optional; supply only the pairs you want applied.

Operator: ignored

{
  "group_name_selected_subfilter": "group_id",
  "group_id_value": 331,
  "group_id_op": "equal",
  "member_status_value": ["LEADER"],
  "member_status_op": "in",
  "member_start_date_value": { "period": "year", "units": 1 },
  "member_start_date_op": "in_the_last",
  "group_active_value": "active"
}
Field pairFilters on
group_id_value / group_id_opA specific group.
group_term_value / group_term_opFree text against the group name.
group_type_value / group_type_opGroup type.
group_department_value / group_department_opDepartment.
group_campus_value / group_campus_opThe group's campus.
member_status_value / member_status_opRelationship status.
member_start_date_value / member_start_date_opJoin date.
status_history_value / status_history_opPast status, not just current.
custom_field_id + custom_field_value / custom_field_opA group custom field.
group_active_valueactive or inactive.

group_name_selected_subfilter tells the filter which of the group-identifying pairs to honour.

Group statuses

status_value in the group criteria accepts these relationship values:

ValueMeaning
REQUESTINGRequested to join.
LEADERMain or assistant leader, or the group's owner.
MEMBERMember.
INVITEDInvited.
COACHGroup coach.
DIRECTORGroup director.
DEPT_ADMINAdministrator of the group's department.
📘

COACH, DIRECTOR, and DEPT_ADMIN are leadership roles from a permissions standpoint but are

not included in LEADER. Match them explicitly if you want every kind of leader.

Custom Fields

custom_fields for individual custom fields, group_custom_fields for group ones.

Operator: the operator for the field's own type

{ "field_id": "udf_text_3", "field_type": "TEXT", "field_value": "Alumni" }
FieldTypeDescription
field_idstringThe custom field's storage name, e.g. udf_text_3, udf_date_1, udf_pulldown_2.
field_typestringTEXT, DATE, or PULLDOWN.
field_valuemixedText, or a pulldown id.

For DATE, put the date parts on the value object itself alongside field_id and field_type:

{ "field_id": "udf_date_1", "field_type": "DATE", "year": 2026, "month": 3 }

group_custom_fields takes field_id and field_value only.

📘

The udf_text_1 … udf_text_12, udf_date_1 … udf_date_6, and udf_pulldown_1 …

udf_pulldown_6 criteria in the table above target the same columns directly and are simpler.
Reach for custom_fields when your integration discovers field names at runtime.

Name

name. Fuzzy matching across first and last name. This is the criterion the quick-search box uses.

Operator: space_to_wildcard, space_to_wildcard_space, any_order_like, or legacy
Value: string
Access: any signed-in user

OperatorBehaviour
space_to_wildcardRuns of whitespace become %, and the whole term is wrapped in %. Matched against first last. "jo sm" matches "John Smith".
space_to_wildcard_spaceRuns of whitespace become % % — wildcard, space, wildcard. Matched against first last.
any_order_likeSplits on whitespace; every word must match first name or last name, in any order. "smith john" matches "John Smith".
legacyPrefix matching across first, last, legal, maiden, alternate name and primary email. With two words, also first-word-on-first-name and second-word-on-last-name. If the term is all digits and separators, home phone, mobile phone, mailing street, and giving number are searched too.
❗️

The operator is space_to_wildcard, with one underscore

Earlier revisions of this page printed space_to__wildcard. An unrecognized name mode is an
error, not a fallback.

📘

legacy is much broader than a name search — it will match on email and, for numeric input, on

phone, street, and giving number. Use any_order_like when you want names only.

Name Fields

name_fields. One specific name field, with normal text operators.

Operator: any text operator

{ "type": "last_name", "search_term": "Smith" }

type is first_last_name (the default, which behaves like Name), first_name,
middle_name, last_name, legal_name, maiden_name, or alternate_name.

Address

home_address, work_address, mailing_address, other_address. One address block, one component.

Operator: any text operator

{ "type": "city", "search_term": "Colorado Springs" }

type is street, city, state, zip, or country.

📘

The home_city, work_zip, mailing_state-style criteria in the table target the same columns

and are simpler for a fixed query. The *_address form is useful when the component is chosen at
runtime.

Phone Number

phone_number. One phone field, or all of them.

Operator: any text operator

{ "type": "mobile", "search_term": "719-555-0134" }

type is home, mobile, work, emergency, fax, pager, or any.

📘

Formatting is handled for you

Punctuation is stripped from both the search term and the stored value before comparison, and the
term is also matched in the campus's locale format. With equal or not_equal and 10 or more
digits, the last 10 digits are matched as well, so a country code on either side does not break
the match.

My Fit: Ability, Passion, Spiritual Gift, Personality Style

ability, passion, spiritual_gift, personality_style.

Operator: in, not_in, is_set, or is_not_set
Value: an id, or an array of ids. Omit for is_set / is_not_set.

{ "type": "constraint", "id": "spiritual_gift", "operator": "in", "value": [3, 7], "invert": false }
❗️

Only those four operators work

These read as plain number criteria but they are not. equal, between, and the rest raise an
error rather than falling back to in.

Family Members

family_head, family_spouse, family_child, family_other. Matches on the name of another
member of the individual's family, by that member's position.

Operator: any text operator
Value: string — the related person's name

Family Position

family_position. Accepts either form.

A plain string, with the constraint's own operator:

{ "type": "constraint", "id": "family_position", "operator": "equal", "value": "PRIMARY_CONTACT" }

Or an object that pairs the position with a name, letting you ask "whose spouse is named Dana":

{
  "family_position_value": "SPOUSE",
  "family_position_op": "equal",
  "individual_name_value": "Dana",
  "individual_name_op": "contains"
}

Created / Modified By Name

creator_name, modified_name. Matches the full name of the user who created or last modified the
profile, rather than first and last name separately.

Operator: any text operator
Value: string

The creator_first_name, creator_last_name, modifier_first_name, and modifier_last_name
criteria remain available for single-field matching.

Note

note. Text of individual notes.

Operator: any text operator
Value: string
Access: Notes

Duplicates

duplicates. Individuals flagged as possible duplicates of the ids you pass.

Operator: ignored
Value: an individual id, or an array of ids
Access: Full people read

Matches both sides of each duplicate pair, applies the church's duplicate-score threshold, and
excludes the master administrator's profile.

Privacy Settings

privacy_settings. The visibility level a person has set on one field.

Operator: a number operator

{ "type": "phone_home", "selection_values": [1, 2] }

type names the field. email_primary checks the listed flag; every other value checks that
field's privacy level.

Process Queue

process_queue. Position in a process, by step and status.

Operator: ignored

{ "step_id": 17, "status_value": [1], "status_op": "in" }
FieldTypeDescription
step_idnumberThe step. 0 inverts the test — it matches every step other than step 0.
status_valuenumber | [number]Status id(s).
status_opstringin, not_in, is_set, or is_not_set. Anything else is an error.
❗️

The key is status_value, not status_id.

Process Queue: Date

process_queue_added_date, process_queue_completed_date, process_queue_due_date. The criterion
id chooses the date; there is no date_type value.

Operator: a date_parts operator
Value: the date parts, plus the process and step ids

{
  "process_name_id": 5,
  "queue_name_id": 17,
  "year": 2026,
  "month": 8
}
FieldTypeDescription
process_name_idnumberThe process. When set, both active and archived processes are searched.
queue_name_idnumberThe step. 0 matches every step in the process except step 0.
year, month, daynumberDate parts, as required by the operator.

is_not_set on the constraint drops the date comparison and inverts the match — it finds people who
have no such date on that step.

Significant Event

significant_event, and significant_event_date for a date-only query.

Operator: ignored (significant_event) · a date_parts operator (significant_event_date)
Access: Full people read

{
  "significant_event_id": [4, 9],
  "significant_event_op": "in",
  "significant_event_date_value": { "period": "year", "units": 1 },
  "significant_event_date_op": "in_the_last",
  "significant_event_note_value": "hospital",
  "significant_event_note_op": "contains"
}
FieldTypeDescription
significant_event_idnumber | [number]Event type id(s).
significant_event_opstringin, not_in, or is_not_set. Anything else leaves the event-type filter off.
significant_event_date_value / _opmixed, stringDate parts against when the event was recorded.
significant_event_note_value / _opstring, stringText search on the note.
❗️

The date keys are significant_event_date_value and significant_event_date_op

Not date_value / date_op. With the wrong keys the date filter is dropped and you get every
matching event type regardless of date.

Funeral

funeral_system_significant_event. Funerals recorded as system significant events.

Operator: ignored
Access: Significant events

Every pair below is optional; supply only what you want applied.

Field pairFilters on
date_of_service_value / date_of_service_opWhen the record was created. Date parts.
date_of_death_value / date_of_death_opDate of death. Date parts.
cemetery_value / cemetery_opCemetery.
location_of_funeral_service_value / _opService location.
service_locations_value / _opService locations.
primary_presider_value / _opPrimary presider.
presider_name_value / _opPresider name.
remains_value / _opDisposition of remains.
note_value / note_opNote text.

Sacraments

baptism_sacrament, reconciliation_sacrament, first_communion_sacrament,
confirmation_sacrament, marriage_sacrament, holy_order_sacrament,
anointing_the_sick_sacrament.

Operator: ignored
Access: Sacrament admin. Requires the Sacraments module.

Deleted and archived sacraments are always excluded. Every pair is optional — an empty value matches
anyone with a sacrament of that type.

Field pairFilters on
date_performed_value / date_performed_opDate performed.
diocese_value / diocese_opDiocese of reception.
subtype_value / subtype_opSacrament subtype.
religion_status_value / religion_status_opReligion status.
status_valueRecord status — verified values: COMPLETED, IN_PROGRESS, INCOMPLETE_PENDING.
received_here, convalidation, ocia, profession_of_faith, last_ritesBoolean flags on the record. Which flags apply depends on the sacrament type — see the Sacraments MCP tool for the per-type field map.
📘

Not every pair is meaningful for every sacrament type

subtype only has values on baptism_sacrament and holy_order_sacrament; religion_status and
convalidation only apply to marriage_sacrament; last_rites only applies to
anointing_the_sick_sacrament. Sending a sub-filter that criterion doesn't carry data for simply
never matches anyone, rather than erroring.

Virtus Status

virtus_status, and virtus_status_expiration_time for the expiry date.

Operator: in or not_in (virtus_status) · a date_parts operator (virtus_status_expiration_time)
Access: Virtus

{
  "type": "constraint",
  "id": "virtus_status",
  "operator": "in",
  "value": ["CERTIFIED", "EXPIRED", "ID_ERROR", "INACTIVE", "NOT_CERTIFIED"],
  "invert": false
}
ValueMeaning
CERTIFIEDActive, certified, and not past its expiry.
EXPIREDActive and certified, but past its expiry.
NOT_CERTIFIEDActive but not certified.
INACTIVENot active.
ID_ERRORNo Virtus id is stored on the profile.
❗️

Don't use not_in on this criterion at all — verified unreliable, even with one value

not_in does not behave like a simple negation here. To exclude a set of statuses, always send in with that set and "invert": true instead — verified to return the correct count.

📘

Virtus must be enabled and connected for the church. If it is not, the request returns

403 Forbidden.

New Giver

new_giver. Finds people by the date of their nth gift.

Operator: a date_parts operator
Value: the gift number in type, plus the date parts

{
  "type": "constraint",
  "id": "new_giver",
  "operator": "in_the_last",
  "value": { "type": 1, "period": "month", "units": 3 },
  "invert": false
}
FieldTypeDescription
typenumberWhich gift to look at. 1 is the person's first gift.
year, month, day / period, units / lbound, ubound—The date window, matching the constraint's operator.
❗️

The gift number key is type, and the operator is not ignored

Earlier revisions showed gift_number, date_value, and date_op with an ignored operator. None
of those are read. The constraint's own operator drives the date comparison.

Scheduling (Luna)

Scheduling criteria on the individual domain. For scheduling-first queries use the dedicated
scheduling search domains instead.

Operator: ignored, except where noted

IdValue
luna_position{ position_id, position_op, status_value, status_op }. status_op takes in, not_in, is, is_not, is_any, is_not_any.
luna_assignment{ status, status_op, date, date_op }
luna_assignment_status{ status_value, position_id, position_op, date_value, date_op }
luna_category_involvement{ category_id, position_value, position_op }. position_value is an array of involvement-role strings, not a position id — see below.
luna_teamThe team id. Uses the constraint's own operator.
luna_organizerThe organizer's individual id. Uses the constraint's own operator, including is_set / is_not_set.
luna_categoryA number criterion — the category id.
luna_assignment_date, luna_assignment_monthPlain date and number criteria.
luna_assignment_date_partsDate parts, using the constraint's own operator.
❗️

luna_position requires status_op — omit it and the whole request 500s

status_op is not an optional refinement here despite reading like one. Send it even if you only
want to filter by position_id (any valid value, e.g. "is_any", works) — without it the request
fails with a 500 regardless of what else is in the value object. position_id itself is
optional; omitting it (with status_op present) matches anyone holding any Luna position.

❗️

luna_category_involvement's position_value is a role list, not an id — sending the wrong type 500s

position_value takes an array of involvement-role strings: VOLUNTEER, CATEGORY ORGANIZER, PLAN ORGANIZER, SCHEDULE ORGANIZER, TEAM ORGANIZER. Sending a position id (a
number) here — the natural-looking guess — crashes with a 500, not a 412, because the
criterion checks the array unconditionally regardless of operator. position_op is in /
not_in (matches if any listed role applies) or is_set / is_not_set (any / no category
involvement at all — position_value can be [] for these). Omitting category_id (or setting
it to 0) also crashes unless the constraint node carries the separate
include_value key ({"include_value": ["ACTIVE", "ARCHIVED"]}) — with a specific category_id, that default is applied for you automatically.

{
  "type": "constraint",
  "id": "luna_category_involvement",
  "operator": "ignored",
  "value": { "category_id": 726, "position_op": "in", "position_value": ["VOLUNTEER"] },
  "invert": false
}

Department Admin

department_admin. Administrators of a department.

Operator: equal or not_equal
Value: the department id

Background Check Package Name

background_check_package_name matches people by their background checks — the package, and
optionally when the check completed, when it expires, who ordered it, and its report status.
has_requested_background_check distinguishes checks a person requested for themselves from checks
ordered on their behalf — send not_equal to match self-requested checks, anything else to match
checks ordered by someone else.

Operator: in — the node operator is not consulted; matching is controlled by the *_op keys
inside the value.

Checks expiring in the next 90 days under package 123:

{
  "package_op": "in",
  "package_value": [123],
  "expiration_date_op": "in_the_next",
  "expiration_date_value": { "period": "day", "units": 90 }
}
FieldTypeDescription
package_opstringNumber operator applied to the package id. is_not_set matches people with no background check at all; is_set matches a check of any package.
package_valuenumber | [number]Background check package id(s) — not the display name, despite the criterion's name. Package ids come from GET /individuals/background_check_types.
completed_date_op / completed_date_valuedate blockWhen the check completed (its status last changed).
expiration_date_op / expiration_date_valuedate blockWhen the check expires.
ordered_by_op / ordered_by_valuestring / number | [number]Number operator on the id of the person who ordered the check. Ids come from GET /individuals/background_check_creators.
report_status_op / report_status_valuestring / string | [string]Text operator on the report status. The supported statuses are PENDING, CLEAR, CONSIDER, DISPUTED, DISPUTED_CLEAR, SUSPENDED, CANCELED, CLEAR_CANCELED, CONSIDER_CANCELED, COMPLETE, PRE_ADVERSE_ACTION, POST_ADVERSE_ACTION — the same list for every integration, including vendor integrations; vendors do not define their own statuses.

Every block except the package is optional — include only the *_op / *_value pairs you need.

❗️

Do not put a comment key on this constraint

The optional comment node key documented under
Extra keys on a constraint node causes a
500 Internal Server Error when sent on a background_check_package_name constraint. The same
key on ordinary criteria in the same request works fine. Omit it here.

Date blocks. completed_date_* and expiration_date_* each accept four forms:

FormOperatorValue
Presenceis_set / is_not_setnone
Exact dateequal, not_equal, less_than, less_than_or_equal, greater_than, greater_than_or_equal{ "year": 2026, "month": 8, "day": 21 } — all three parts required, unlike a normal date_parts value.
Relative windowthe in_the_* relative operators (e.g. in_the_last, in_the_next){ "period": "day", "units": 90 }
Rangebetween / not_between{ "lbound": "2026-01-01", "ubound": "2026-03-31" }
❗️

An incomplete date block is skipped, not rejected

A date value that fits none of the forms above — for example an exact date missing day — drops
that date condition silently. The constraint still runs on its remaining conditions, typically
matching everyone with a live check of that package. Validate the date block yourself before
sending.

📘

Only live checks are searched

The criterion matches checks whose stored status is valid — pending, removed, and archived checks
are excluded. Date-expired checks still match, because expiry is derived from expiration_date
rather than the stored status, so both "expiring soon" (expiration_date_op: in_the_next) and
"lapsed" (in_the_last) filters work.

Email Verification

email_verification_opt_in_status, plus four date variants:
email_verification_opt_in_date, email_verification_date_verified,
email_verification_date_verification_email_sent, email_verification_date_opt_in_email_sent.

Operator: a text operator for the status · a date_parts operator for the dates

{ "type": "constraint", "id": "email_verification_opt_in_status", "operator": "in", "value": ["OPT_IN"] }
ValueMatches
OPT_INOpted in.
UNSUBSCRIBEDOpted out.
SUBSCRIBEDPre-opt-in or no response yet.
❗️

The date variants share the status value

The date criteria read the same value for both the status list and the date parts, so the value
must contain at least one of the three status strings as well as the date parts. With no
recognized status, no condition is applied and the constraint matches everyone who has an
email-verification record.

MICR Scan

micr_scan. Matches a scanned check's MICR line.

Operator: ignored
Value: the MICR string
Access: Financial

Envelope User Id

envelope_user_id. Giving envelope number.

Operator: the constraint's own operator
Value: the envelope id


Non-queryable criteria

whos_included is returned by GET /search/individuals as a filtering option for the People Search
UI, but it is not backed by a query. Do not send it in a filter tree — it has no valid comparison
and will fail the request rather than being ignored. Use configuration.filter_profile_type and the
include_* keys documented in
Population selection instead.


Extra keys on a constraint node

Beyond type, id, operator, value, and invert, a constraint node accepts:

KeyTypeDescription
commentstringFree text. Carried into the generated query as a comment. Useful for tracing a slow or surprising search back to the integration that sent it. Does not affect results. Exception: on a background_check_package_name constraint it causes a 500 — omit it there.
include_valueobject{ "include_value": ["ACTIVE", "INACTIVE"] }. Read by the group criteria to decide whether inactive groups and archived processes count. Defaults to active only.
value_typestringRead by group_name and the *_address criteria to say whether value should be treated as a number (an id) or as text.

Unrecognized keys are ignored.


Formula groups

A group node normally joins its children with a single and or or. A formula group lets you
express an arbitrary boolean expression over them instead, including NOT and parentheses, without
nesting groups by hand.

{
  "type": "group",
  "operator": "formula",
  "formula": "set1 AND (NOT set2 OR set3)",
  "invert": false,
  "conditions": [
    { "type": "constraint", "id": "campus", "operator": "equal", "value": 1, "invert": false },
    { "type": "constraint", "id": "is_inactive", "operator": "is_set", "invert": false },
    { "type": "constraint", "id": "membership_type", "operator": "in", "value": [2, 3], "invert": false }
  ]
}
FieldTypeRequiredDescription
type"group"yesFormula groups are group nodes.
operator"formula"yesWhat marks the group as a formula.
formulastringyesThe expression.
conditionsarrayyesThe referenced nodes, in order. At least one.

Grammar. SET<n>, AND, OR, NOT, and parentheses. Keywords are case-insensitive and
whitespace is ignored. set1 is the first entry in conditions, set2 the second, and so on —
the numbering is 1-based.

Each set may itself be a group node, so a formula can combine whole sub-trees rather than single
constraints.

❗️

A set number with no matching condition fails the request

set4 against a three-entry conditions array is an error. Keep the formula and the array in
step when you build the filter programmatically.

📘

AND and OR have no precedence here

The grammar binds left to right, so set1 OR set2 AND set3 is not the same as it would be in SQL.
Parenthesize anything non-trivial.


Examples

A single special criterion

Everyone whose mobile number contains a given exchange:

{
  "configuration": { "return_search_results": true },
  "filters": {
    "type": "constraint",
    "id": "phone_number",
    "operator": "contains",
    "value": { "type": "mobile", "search_term": "719555" },
    "invert": false
  }
}

Attendance

Adults who attended a weekend service at least twice in the last three months:

{
  "configuration": {
    "return_search_results": true,
    "order_by": [{ "column": "last_name", "direction": "asc" }]
  },
  "filters": {
    "type": "group",
    "operator": "and",
    "invert": false,
    "conditions": [
      {
        "type": "constraint",
        "id": "age",
        "operator": "greater_than_or_equal",
        "value": 18,
        "invert": false
      },
      {
        "type": "constraint",
        "id": "attendance_attendance_grouping",
        "operator": "ignored",
        "value": {
          "type": "grouping",
          "id": 42,
          "attended": "attended",
          "total_by": "week",
          "date_op": "in_the_last",
          "period": "month",
          "units": 3,
          "number_of_times_op": "greater_than_or_equal",
          "number_of_times_value": 2
        },
        "invert": false
      }
    ]
  }
}

Group leaders in a department

Everyone leading a group in department 12, including leaders of inactive groups:

{
  "configuration": { "return_search_results": true },
  "filters": {
    "type": "constraint",
    "id": "group_department",
    "operator": "ignored",
    "value": {
      "department_id": 12,
      "department_op": "equal",
      "status_value": ["LEADER", "COACH", "DIRECTOR"],
      "status_op": "in"
    },
    "include_value": { "include_value": ["ACTIVE", "INACTIVE"] },
    "invert": false
  }
}

A form response

Everyone who answered question 912 on form 55 with a specific choice:

{
  "configuration": { "return_search_results": true },
  "filters": {
    "type": "constraint",
    "id": "form_question_answer",
    "operator": "ignored",
    "value": {
      "form_id": 55,
      "question_id": 912,
      "question_op": "equal",
      "question_type": "select",
      "value": 4471,
      "value_op": "equal"
    },
    "invert": false
  }
}

To find everyone who responded to the form at all, drop question_id and keep only form_id.

First-time givers this quarter

{
  "configuration": {
    "return_search_results": true,
    "order_by": [{ "column": "last_name", "direction": "asc" }]
  },
  "filters": {
    "type": "constraint",
    "id": "new_giver",
    "operator": "in_the_previous",
    "value": { "type": 1, "period": "quarter", "units": 1 },
    "invert": false
  }
}

Excluding a set of Virtus statuses

Everyone who is neither expired nor uncertified — written as in plus invert, because not_in
with multiple statuses does not exclude the way it reads:

{
  "configuration": { "return_search_results": true },
  "filters": {
    "type": "constraint",
    "id": "virtus_status",
    "operator": "in",
    "value": ["EXPIRED", "NOT_CERTIFIED"],
    "invert": true
  }
}

A formula group

Members of campus 1 who are either leading a group or have a background check on file, but are not
inactive:

{
  "configuration": {
    "return_search_results": true,
    "filter_profile_type": ["active", "inactive"]
  },
  "filters": {
    "type": "group",
    "operator": "formula",
    "formula": "set1 AND NOT set2 AND (set3 OR set4)",
    "invert": false,
    "conditions": [
      { "type": "constraint", "id": "campus", "operator": "equal", "value": 1, "invert": false },
      { "type": "constraint", "id": "is_inactive", "operator": "is_set", "invert": false },
      {
        "type": "constraint",
        "id": "group_relationship",
        "operator": "ignored",
        "value": { "status_value": ["LEADER"], "status_op": "in" },
        "invert": false
      },
      {
        "type": "constraint",
        "id": "background_check_package_name",
        "operator": "is_set",
        "invert": false
      }
    ]
  }
}

When a filter is rejected

ResponseCause
412 with "<id> is not valid"The id is not a criterion on this domain, or is misspelled. Compare against GET /search/individuals.
412 with "id not currently set"A constraint node is missing id.
403The caller lacks the permission for one of the criteria used, or the OAuth token lacks the scope for the endpoint. Every criterion in the tree is checked before any results are produced.
403 on a Virtus criterionVirtus is not connected for the church.
📘

POST /search/individuals/results requires the read:individuals scope

The reference page for the endpoint currently lists read:advanced_searches. That scope covers the
saved-search endpoints; the results endpoint itself is gated on read:individuals. Request both if
your integration reads saved searches as well as running them.

📘

Validation is all-or-nothing

One unusable criterion fails the whole request; nothing is silently dropped. When a query stops
working after a permission change, look for the newest criterion in the tree first.