Skip to content

People and organizations ​

← Workspace APIs

Paging, updated_since, the deleted short form and the /ids endpoints work as described in Paging and Keeping a copy in sync. This page covers only what is specific to each resource.

People ​

A person is a contact in the workspace: a member, a customer contact, an instructor or anyone else Engagifii holds a record for. Inactive people are included with "status": "inactive". A person's id is the person_id used on registrations, invoices and payments.

EndpointMeaning
GET /peopleList people, one page at a time.
GET /people/idsThe id of every person that has not been deleted.
GET /people/{id}One person. 404 if the person does not exist or has been deleted.

Filters ​

ParameterTypeMeaning
organization_idUUIDOnly people whose primary organization is this one.
statusstringactive or inactive.

Example ​

json
{
  "id": "3f0c…",
  "salutation": "Ms.",
  "first_name": "Dana",
  "middle_name": null,
  "last_name": "Whitfield",
  "suffix": null,
  "pid": "100482",
  "title": "Director of Programs",
  "email": "dana.whitfield@example.org",
  "phone": "555-0142",
  "primary_organization_id": "9b21…",
  "status": "active",
  "time_zone": "Eastern Standard Time",
  "is_instructor": false,
  "date_of_birth": "1979-05-14",
  "gender": "female",
  "race": "Prefer not to say",
  "ethnicity": null,
  "emails": [
    { "email": "dana.whitfield@example.org", "type": "Work Email", "is_primary": true }
  ],
  "phones": [
    { "phone": "555-0142", "type": "Work Phone", "is_primary": true }
  ],
  "addresses": [
    {
      "type": "Mailing Address",
      "line_1": "100 Main Street",
      "line_2": "Suite 4",
      "city": "Springfield",
      "state": "IL",
      "postal_code": "62701",
      "country": "United States",
      "is_billing": true
    }
  ],
  "positions": [
    {
      "id": "c47e…",
      "organization_id": "9b21…",
      "position": { "id": "5d10…", "name": "Director" },
      "department": { "id": "e2a8…", "name": "Programs" },
      "is_current": true,
      "is_future": false,
      "start_date": "2022-03-01",
      "end_date": null,
      "terms": [
        {
          "id": "b6e2…",
          "name": "2024-2026 Term",
          "scenario": "elected",
          "region": { "id": "0f3a…", "name": "District 4" },
          "start_date": "2024-07-01",
          "end_date": "2026-06-30"
        }
      ]
    }
  ],
  "organizations": [
    { "organization_id": "9b21…", "is_contact_person": true }
  ],
  "member_types": [ { "id": "71f3…", "name": "Individual Member" } ],
  "member_type_history": [
    { "member_type_id": "71f3…", "name": "Individual Member", "start_date": "2021-01-01", "end_date": null, "is_current": true },
    { "member_type_id": "71f4…", "name": "Associate Member", "start_date": "2019-01-01", "end_date": "2020-12-31", "is_current": false }
  ],
  "tags": ["Board", "Volunteer"],
  "custom_fields": [
    { "field_id": "a90d…", "name": "Member Since", "group": "Membership", "type": "date", "value": "2015-06-01" }
  ],
  "email_opt_outs": [
    { "email": "dana.whitfield@example.org", "group_id": "4e7a…", "opted_out_at": "2026-03-02T16:40:12Z" }
  ],
  "last_login_at": "2026-10-28T14:02:51Z",
  "created_at": "2015-06-01T12:00:00Z",
  "updated_at": "2026-10-30T09:15:22Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe person's id.
salutationstring or nullFor example Ms. or Dr.
first_namestring or null
middle_namestring or null
last_namestring or null
suffixstring or nullFor example Jr.
pidstring or nullThe person ID Engagifii shows in the profile header. Workspaces often use it as the member number in other systems.
titlestring or nullThe person's job title.
emailstring or nullThe person's main email address.
phonestring or nullThe person's main phone number.
primary_organization_idUUID or nullThe person's primary organization. An id from /organizations.
statusstringactive or inactive.
time_zonestring or nullThe person's time zone as stored in Engagifii, for example Eastern Standard Time.
is_instructorbooleanWhether the person is an instructor.
date_of_birthdate or nullThe date of birth from the person's standard profile (Personal Details). null if none is entered.
genderstring or nullThe gender from the standard profile: male, female or not_specified. null if none is entered.
racestring or nullThe race from the standard profile, as the label in the workspace's own list of options. null if none is chosen.
ethnicityboolean or nullThe yes/no ethnicity answer from the standard profile. null if it was never answered.
emailsarrayEvery email address on the person. See Emails, phones and addresses.
phonesarrayEvery phone number on the person.
addressesarrayEvery address on the person.
positionsarrayThe person's positions at organizations, past, current and future. Current positions come first, then the most recent start date.
positions[].idUUIDThe position record's id.
positions[].organization_idUUID or nullThe organization the position is at.
positions[].positionobject or nullThe position held. null if none is set.
positions[].position.idUUIDThe position's id.
positions[].position.namestring or nullThe position's name, for example Director.
positions[].departmentobject or nullThe department. null if none is set.
positions[].department.idUUIDThe department's id.
positions[].department.namestring or nullThe department's name.
positions[].is_currentbooleanWhether the position is marked as current.
positions[].is_futurebooleanWhether the position is marked as a future position.
positions[].start_datedate or nullWhen the position started.
positions[].end_datedate or nullWhen the position ended.
positions[].termsarrayElection terms on a termed position, earliest first. Empty for other positions.
positions[].terms[].idUUIDThe term's id. The same term has the same id on every person.
positions[].terms[].namestring or nullThe term's name, for example 2024-2026 Term.
positions[].terms[].scenariostring or nullelected or appointed. null if not set.
positions[].terms[].regionobject or nullThe region the term is for. null if none is set.
positions[].terms[].region.idUUIDThe region's id.
positions[].terms[].region.namestring or nullThe region's name.
positions[].terms[].start_datedate or nullThe term's first day.
positions[].terms[].end_datedate or nullThe term's last day.
organizationsarrayEvery organization the person belongs to, in the order they were linked. Deleted organizations are left out. The positions the person holds there are in positions.
organizations[].organization_idUUIDThe organization. An id from /organizations.
organizations[].is_contact_personbooleanWhether the person is that organization's default contact.
member_typesarrayThe person's member types.
member_types[].idUUIDThe member type's id.
member_types[].namestring or nullThe member type's name.
member_type_historyarrayMember types with the dates Engagifii recorded for them, earliest first. See Member type history.
member_type_history[].member_type_idUUIDThe member type. Matches member_types[].id.
member_type_history[].namestring or nullThe member type's name.
member_type_history[].start_datedate or nullWhen the person got the member type.
member_type_history[].end_datedate or nullWhen the member type ended. null if Engagifii recorded no end.
member_type_history[].is_currentbooleantrue only when end_date is null and the member type is also in member_types.
tagsarray of stringsThe person's tags, in alphabetical order.
custom_fieldsarrayThe workspace's own fields that have a value for this person. See Custom fields.
email_opt_outsarrayThe person's email addresses that opted out of email, oldest first. Opting back in removes the entry.
email_opt_outs[].emailstring or nullThe address that opted out.
email_opt_outs[].group_idUUID or nullnull when the address opted out of all email from Engagifii. Otherwise the group whose mailing list it left, an id from /groups.
email_opt_outs[].opted_out_atdate-time or nullWhen the address opted out.
last_login_atdate-time or nullWhen the person last signed in to Engagifii. null if they never have.
created_atdate-timeWhen the person was added.
updated_atdate-timeWhen the person's own details last changed.

/people returns at most 200 people a page (page_size 1 to 200), because each person carries many details.

Member type history ​

Engagifii started recording member type dates when the workspace first changed a member type, so a member type held since before then has no history entry. Engagifii sometimes removes a member type from a person without closing its history entry. An end_date of null alone therefore does not mean the person still holds the type: use is_current, or member_types, for what the person holds today. Member types the workspace has deleted are left out.

Personal details ​

date_of_birth, gender, race and ethnicity are the standard profile fields. A workspace can also keep similar information in its own custom fields; those are in custom_fields. See the guidance under Custom fields on storing personal data.

Keeping people in sync ​

updated_at moves when the person's own details change. A change to only their positions, terms, organizations, member types, member type history, tags, custom fields, emails, phones, addresses or email opt-outs may not move it, and a removed member type or an opt-in leaves no trace for updated_since to find. Reload people in full from time to time.

Organizations ​

An organization is a company, agency, school or other body in the workspace. People link to it through primary_organization_id and positions[].organization_id, and invoices and payments use the same id. Inactive organizations are included with "status": "inactive".

EndpointMeaning
GET /organizationsList organizations, one page at a time.
GET /organizations/idsThe id of every organization that has not been deleted.
GET /organizations/{id}One organization. 404 if it does not exist or has been deleted.

Filters ​

ParameterTypeMeaning
statusstringactive or inactive.
qstringOnly organizations whose name contains this text. Up to 200 characters.

Example ​

json
{
  "id": "9b21…",
  "name": "Springfield Water District",
  "type": "Special District",
  "email": "info@example.org",
  "website": "https://www.example.org",
  "status": "active",
  "time_zone": "Central Standard Time",
  "is_parent": false,
  "is_child": true,
  "emails": [
    { "email": "info@example.org", "type": "General Email", "is_primary": true }
  ],
  "phones": [
    { "phone": "555-0100", "type": "Main Phone", "is_primary": false }
  ],
  "addresses": [
    {
      "type": "Billing Address",
      "line_1": "200 Lake Road",
      "line_2": null,
      "city": "Springfield",
      "state": "IL",
      "postal_code": "62702",
      "country": "United States",
      "is_billing": true
    }
  ],
  "tags": ["Utility"],
  "related_organizations": [
    { "organization_id": "0d4f…", "relation": "Parent" }
  ],
  "key_contacts": [
    { "person_id": "3f0c…", "type": "Billing" },
    { "person_id": "3f0c…", "type": "Member Organization Lead" }
  ],
  "group_ids": ["4e7a…"],
  "custom_fields": [
    { "field_id": "b3c1…", "name": "Population Served", "group": "Profile", "type": "number", "value": 48000 }
  ],
  "created_at": "2014-02-11T16:20:00Z",
  "updated_at": "2026-09-14T11:47:03Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe organization's id.
namestring or nullThe organization's name.
typestring or nullThe organization type set up in the workspace, for example Special District.
emailstring or nullThe organization's main email address.
websitestring or nullThe organization's website.
statusstringactive or inactive.
time_zonestring or nullThe organization's time zone as stored in Engagifii.
is_parentbooleanWhether the organization is marked as a parent organization.
is_childbooleanWhether the organization is marked as a child organization.
emailsarrayEvery email address on the organization. See Emails, phones and addresses.
phonesarrayEvery phone number on the organization. Organizations have no main phone, so is_primary is always false.
addressesarrayEvery address on the organization.
tagsarray of stringsThe organization's tags, in alphabetical order.
related_organizationsarrayOther organizations this one is related to. Only organizations that have not been deleted are listed.
related_organizations[].organization_idUUIDThe related organization. An id from /organizations.
related_organizations[].relationstring or nullThe kind of relation, as named in the workspace.
key_contactsarrayThe organization's key contacts, one entry per person and contact type, by the person's last name. Deleted people are left out.
key_contacts[].person_idUUIDThe contact. An id from /people.
key_contacts[].typestring or nullThe kind of key contact, as named in the workspace, for example Billing or Member Organization Lead.
group_idsarray of UUIDsThe groups associated with the organization (its Groups tab in Engagifii), by group name. Ids from /groups. Deleted groups are left out.
custom_fieldsarrayThe workspace's own fields that have a value for this organization. See Custom fields.
created_atdate-timeWhen the organization was added.
updated_atdate-timeWhen the organization's own details last changed.

Keeping organizations in sync ​

A change to only an organization's custom fields, tags, emails, phones, addresses, related organizations, key contacts or groups may not move updated_at. Reload organizations in full from time to time.

Emails, phones and addresses ​

People and organizations carry the same emails, phones and addresses arrays. Each entry comes from one of the contact fields the workspace has set up, such as "Work Email" or "Mailing Address". Entries are in the order the workspace arranges its fields. Empty values are left out.

FieldTypeMeaning
emails[].emailstringThe email address.
emails[].typestring or nullThe name of the field it is held in, for example Work Email.
emails[].is_primarybooleantrue when this address is the same as the record's email, ignoring case.
phones[].phonestringThe phone number, as entered.
phones[].typestring or nullThe name of the field it is held in, for example Mobile Phone.
phones[].is_primarybooleantrue when this number is the same as the person's phone. Always false for organizations.
addresses[].typestring or nullThe name of the field it is held in, for example Mailing Address.
addresses[].line_1string or nullFirst address line.
addresses[].line_2string or nullSecond address line.
addresses[].citystring or null
addresses[].statestring or null
addresses[].postal_codestring or null
addresses[].countrystring or null
addresses[].is_billingbooleanWhether this is the field the workspace uses as the billing address.

Custom fields ​

custom_fields lists the fields a workspace has added to people or organizations, with this record's value. Fields with no value for the record are left out. Entries are in the order the workspace arranges its fields.

FieldTypeMeaning
custom_fields[].field_idUUIDThe field's id. The same field has the same id on every record.
custom_fields[].namestring or nullThe field's name.
custom_fields[].groupstring or nullThe name of the section the field is in. null if it is in none.
custom_fields[].typestringThe kind of field. See below.
custom_fields[].valuestring, number, object or arrayThe value. Its shape depends on type.
typevalue
dateDate string, YYYY-MM-DD.
date_rangeObject { "from": date or null, "to": date or null }.
numberNumber, for example 12.5.
dropdown, smart_dropdownString with the chosen option, or an array of strings when several options can be chosen.
radioString with the chosen option.
htmlString of HTML, returned exactly as stored.
file{ "has_file": true }. The file itself is not returned.
text, position, department, position_dates, total_time_worked, terms, terms_scenario, region, otherString, or an array of strings when the field holds several choices.

Guidance for handling custom fields:

  • HTML is not sanitised. html values are returned as they were entered. If you display them, sanitise them first.
  • Values can be sensitive. Every custom field the workspace created is returned, including fields that may hold personal data such as a birth date or ethnicity. The same goes for a person's date_of_birth, gender, race and ethnicity. Store the data securely and limit who can see it.

Groups ​

A group is a named list of people in the workspace. A static group names its people; a dynamic group selects people by rules. The group record does not include its members; get them from /groups/{id}/members.

EndpointMeaning
GET /groupsList groups, one page at a time.
GET /groups/idsThe id of every group that has not been deleted.
GET /groups/{id}One group. 404 if it does not exist or has been deleted.
GET /groups/{id}/membersThe ids of the people in the group right now.

Filters ​

ParameterTypeMeaning
typestringstatic, dynamic or membership.

Example ​

json
{
  "id": "4e7a…",
  "name": "2026 Conference Speakers",
  "description": "Everyone presenting at the annual conference.",
  "type": "static",
  "email": "speakers@example.org",
  "time_zone": "Eastern Standard Time",
  "status": "active",
  "owner_person_ids": ["3f0c…"],
  "created_at": "2026-01-15T10:00:00Z",
  "updated_at": "2026-08-02T17:31:40Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe group's id.
namestring or nullThe group's name.
descriptionstring or nullThe group's description.
typestringstatic, dynamic, membership, or other for any other kind.
emailstring or nullThe group's email address.
time_zonestring or nullThe group's time zone as stored in Engagifii.
statusstringactive or inactive.
owner_person_idsarray of UUIDsThe people who own the group. Ids from /people. Deleted people are left out.
created_atdate-timeWhen the group was created.
updated_atdate-timeWhen the group's own details last changed.

GET /groups/{id}/members ​

Returns the ids of the people in the group right now, as Engagifii works them out from the group's rules. Deleted people are left out. A group with no rules yet has no members.

json
{ "data": ["0a1b…", "3f0c…"], "next_cursor": null }
  • Paging works like the /ids endpoints: page_size defaults to and maxes out at 5000, pass next_cursor back as cursor until it is null, and the ids are not in alphabetical order.
  • 404 if the group does not exist or has been deleted.
  • Each id is an id from /people.
  • A page for a large dynamic group can take several seconds.

Keeping groups in sync ​

  • Members have no change time, and membership changes whenever people change, without touching the group. To sync a group's members, fetch the full list again and replace what you hold.
  • A change to only a group's owners may not move updated_at. Reload groups in full from time to time.

Committees ​

A committee is a body in the workspace, such as a board or a working group, with a set of positions people can hold. Who holds them is in /committee-members.

EndpointMeaning
GET /committeesList committees, one page at a time.
GET /committees/idsThe id of every committee that has not been deleted.
GET /committees/{id}One committee. 404 if it does not exist or has been deleted.

There are no filters beyond paging.

Example ​

json
{
  "id": "d81b…",
  "name": "Board of Directors",
  "description": "Elected board of the association.",
  "type": { "id": "62c0…", "name": "Governance" },
  "organization_id": null,
  "uses_terms": true,
  "status": "active",
  "positions": [
    { "id": "f5a2…", "name": "Chair", "seat_limit": 1 },
    { "id": "f5a3…", "name": "Director", "seat_limit": null }
  ],
  "tags": ["Elected"],
  "created_at": "2019-04-01T08:00:00Z",
  "updated_at": "2026-06-20T13:12:09Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe committee's id.
namestring or nullThe committee's name.
descriptionstring or nullThe committee's description.
typeobject or nullThe committee type. null if none is set.
type.idUUIDThe committee type's id.
type.namestring or nullThe committee type's name.
organization_idUUID or nullThe organization the committee belongs to. An id from /organizations.
uses_termsbooleanWhether the committee uses terms.
statusstringactive or inactive.
positionsarrayThe committee's positions, in the order the workspace sets. Removed positions are left out.
positions[].idUUIDThe position's id. Matches position.id on /committee-members.
positions[].namestring or nullThe position's name, for example Chair.
positions[].seat_limitinteger or nullHow many people can hold the position at once. null means no limit.
tagsarray of stringsThe committee's tags, in alphabetical order. Tags the workspace has deleted are left out.
created_atdate-timeWhen the committee was created.
updated_atdate-timeThe later of the committee's own last change and the last change to one of its positions.

Keeping committees in sync ​

Removing a committee or one of its positions, renaming a committee type, or changing a committee's tags does not move updated_at, so updated_since misses these changes. A workspace has few committees: reload them in full on every sync and compare with /committees/ids.

Committee members ​

A committee member record is one seat: a person holding a position on a committee for a period. Past seats are included as well as current ones.

EndpointMeaning
GET /committee-membersList seats, one page at a time.
GET /committee-members/idsThe id of every seat that has not been deleted.
GET /committee-members/{id}One seat. 404 if it does not exist or has been deleted.

Filters ​

ParameterTypeMeaning
committee_idUUIDOnly seats on this committee.
person_idUUIDOnly seats held by this person.
currentstringtrue for seats that are current today (see is_current), false for seats that have ended.

Example ​

json
{
  "id": "8c66…",
  "committee_id": "d81b…",
  "person_id": "3f0c…",
  "position": { "id": "f5a2…", "name": "Chair" },
  "start_date": "2025-07-01",
  "end_date": "2027-06-30",
  "is_current": true,
  "status": "active",
  "created_at": "2025-06-12T15:40:00Z",
  "updated_at": "2025-06-12T15:40:00Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe seat's id.
committee_idUUIDThe committee. An id from /committees.
person_idUUIDThe person holding the seat. An id from /people.
positionobject or nullThe position held. null if none is set.
position.idUUIDThe position's id. Matches positions[].id on /committees, unless the position has since been removed from the committee.
position.namestring or nullThe position's name.
start_datedate or nullThe seat's first day.
end_datedate or nullThe seat's last day. null if it has no end date.
is_currentbooleantrue if the seat has no end date, or its end date has not passed (the seat is current through the whole of end_date, UTC). Only the end date counts, so a seat that starts in the future is also current.
statusstringactive or inactive.
created_atdate-timeWhen the seat was added.
updated_atdate-timeThe later of the seat's own last change and the last change to its position, such as a rename.

Keeping committee members in sync ​

  • is_current is worked out when you make the request. When a seat's end date passes, is_current changes but updated_at does not. Recompute it from end_date in your copy, or reload seats in full from time to time.
  • Seats of deleted committees and deleted people are left out of every endpoint. When a committee or person is deleted, its seats disappear without a deleted record in updated_since. Use /committee-members/ids to find them.

Profile change requests ​

A profile change request is a change to a person or organization record made through Engagifii's profile screens, the add-person flow or the deactivate-person flow. It lists each changed field with its old, requested and approved value, who made the change and, where an approval workflow applied, each approval step.

Most requests are approved the moment they are made, because no approval workflow applied or the editor may skip approval. These are staff edits recorded as approved requests. Engagifii changes the record only when a request is approved; the value it wrote is applied_value.

This is not a complete change history. Registration and sign-up forms, imports, member type and member status changes and some profile header edits update records without a request. Changes to sign-in roles are not returned.

EndpointMeaning
GET /profile-change-requestsList requests, one page at a time.
GET /profile-change-requests/idsThe id of every request.
GET /profile-change-requests/{id}One request. 404 if it does not exist.

Filters ​

ParameterTypeMeaning
person_idUUIDOnly requests on this person.
organization_idUUIDOnly requests on this organization.
statusstringpending, approved, denied or cancelled.
change_typestringedit, addition, deactivation or deletion.

Example ​

json
{
  "id": "e41c…",
  "number": "PCR-20931",
  "record": { "type": "person", "id": "3f0c…" },
  "change_type": "edit",
  "status": "approved",
  "requested_by_person_id": "3f0c…",
  "decided_by_person_id": "51ad…",
  "changes": [
    {
      "kind": "base",
      "name": "Title",
      "custom_field_id": null,
      "value_type": "text",
      "old_value": "Program Manager",
      "requested_value": "Director of Programs",
      "approved_value": null,
      "applied_value": "Director of Programs",
      "is_primary": false
    },
    {
      "kind": "custom",
      "name": "Member Since",
      "custom_field_id": "a90d…",
      "value_type": "date",
      "old_value": null,
      "requested_value": "06/01/2015",
      "approved_value": null,
      "applied_value": "06/01/2015",
      "is_primary": false
    }
  ],
  "steps": [
    {
      "sequence": 1,
      "name": "Membership review",
      "workflow": "Profile changes",
      "approver_person_id": "51ad…",
      "status": "approved",
      "acted_at": "2026-10-29T15:12:40Z",
      "acted_by_person_id": null,
      "deny_reason": null,
      "comment": "Confirmed with the member.",
      "decided_by_timeout": false,
      "is_backup_approver": false
    }
  ],
  "created_at": "2026-10-28T19:03:11Z",
  "decided_at": "2026-10-29T15:12:41Z",
  "updated_at": "2026-10-29T15:12:41Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe request's id.
numberstring or nullThe request number Engagifii shows. It is not unique: Engagifii has reused some numbers. Use id as the key.
recordobjectThe record the request changes.
record.typestringperson or organization.
record.idUUID or nullAn id from /people or /organizations. For an addition, the new person's id is set only once the request is approved, so it can be null before then.
change_typestringedit, addition (a new person), deactivation, deletion, or other for any other kind.
statusstringpending, approved, denied, cancelled, or other for any other status.
requested_by_person_idUUID or nullThe person who made the change in Engagifii, shown there as the requestor.
decided_by_person_idUUID or nullThe person who last changed the request after it was made, usually the one who decided it. null if no one has.
changesarrayThe changed fields.
changes[].kindstringbase for a standard profile field, custom for one of the workspace's custom fields, status for the record's active flag, other otherwise.
changes[].namestring or nullThe field's name. For status, always active. For custom, the field's current name.
changes[].custom_field_idUUID or nullFor custom, the field's id, as custom_fields[].field_id on people and organizations. null otherwise.
changes[].value_typestringWhat kind of value the field holds: text, html, date, dropdown, radio, location, email, phone, organizations or active_flag. See Change request values.
changes[].old_valuestring or nullThe value before the change.
changes[].requested_valuestring or nullThe value asked for.
changes[].approved_valuestring or nullThe value an approver entered in place of the requested one. null if the approver did not change it.
changes[].applied_valuestring or nullThe value Engagifii wrote to the record: approved_value if there is one, otherwise requested_value. "" when the approver cleared a dropdown. null unless status is approved.
changes[].is_primarybooleanFor email and phone fields, whether the value is marked as primary.
stepsarrayThe approval steps, in sequence order. Empty when no approval workflow applied.
steps[].sequenceintegerThe step's position in the workflow.
steps[].namestring or nullThe step's name.
steps[].workflowstring or nullThe name of the approval workflow.
steps[].approver_person_idUUID or nullThe person the step was assigned to.
steps[].statusstringpending, approved, denied, not_applicable, or other.
steps[].acted_atdate-time or nullWhen the step was approved or denied.
steps[].acted_by_person_idUUID or nullWhen an administrator acted in place of the assigned approver, that administrator. null otherwise.
steps[].deny_reasonstring or nullThe reason picked when the step was denied.
steps[].commentstring or nullThe approver's comment, exactly as typed.
steps[].decided_by_timeoutbooleantrue when Engagifii decided the step by its timeout rule.
steps[].is_backup_approverbooleantrue when the approver is a backup added after the step timed out.
created_atdate-timeWhen the request was made. See the note on older organization requests below.
decided_atdate-time or nullWhen the request was last changed after it was made, usually its decision. null while nothing has changed it.
updated_atdate-timedecided_at if set, otherwise created_at.

Change request values ​

Values are returned as strings, exactly as Engagifii stores them in the request. They are not converted to the formats used on /people and /organizations:

value_typeStored as
dateText in MM/dd/yyyy form, for example 06/01/2015.
phoneThe phone number as formatted text.
dropdown, radioJSON text such as {"id": "…", "value": "Gold"}.
locationJSON text of an address.
htmlHTML, as stored.
text, email, organizations, active_flagText as stored. The tags field is a comma-separated list, and its requested_value can hold only the tags added.
  • Text is not sanitised. Values, steps[].comment and steps[].deny_reason are returned as entered, and html values are HTML. Never render them unescaped.
  • Values can be sensitive. A request can change any field, including personal data. Store the data securely.

Keeping profile change requests in sync ​

  • Requests are never deleted, so the deleted short form never appears. /profile-change-requests/ids lists every request.
  • updated_at moves when a request is made and when it is decided. An approval step acted on before the final decision may not move it, so reload pending requests (status=pending) from time to time.
  • created_at on organization requests made before about 20 February 2025 is US Eastern time written as UTC, so those times are 4 or 5 hours early.

Files ​

A file is a document staff uploaded on the Documents tab of a person, organization, course, class or event, or a web link or hosted video added there instead. The API returns each file's name, type, size and the record it belongs to, never the file's content.

EndpointMeaning
GET /filesList files, one page at a time.
GET /files/idsThe id of every file that has not been deleted or moved to Trash.
GET /files/{id}One file. 404 if it does not exist, has been deleted or is in Trash.

Filters ​

ParameterTypeMeaning
record_idUUIDOnly files on this record, including its sub-folders. For example a person's id from /people or a class's id from /classes.

Example ​

json
{
  "id": "c2d9…",
  "file_name": "Signed membership agreement.pdf",
  "file_type": "pdf",
  "mime_type": "application/pdf",
  "size_bytes": 248113,
  "link_url": null,
  "video_host": null,
  "record": { "type": "organization", "id": "9b21…" },
  "created_at": "2026-02-03T14:21:07Z",
  "updated_at": "2026-02-03T14:21:07Z"
}

Fields ​

FieldTypeMeaning
idUUIDThe file's id.
file_namestring or nullThe name Engagifii shows for the file.
file_typestring or nullThe kind of file: pdf, doc, docx, png, jpg, jpeg, tiff, txt, wps, wpd, xls, xlsx, odf, mp4, zip or link. null for any other kind.
mime_typestring or nullThe file's media type, for example application/pdf.
size_bytesinteger or nullThe file's size in bytes. null for web links and hosted videos.
link_urlstring or nullFor a web link added instead of an upload, its address. null otherwise.
video_hoststring or nullFor a video kept on another site instead of an upload: youtube, vimeo or other. The video's address is not returned, as it can be a private link. null otherwise.
recordobjectThe record the file belongs to.
record.typestringperson, organization, course, class, event, venue, room, group, endorsement, or other when Engagifii cannot tell.
record.idUUID or nullThe record's id, for example an id from /people or /organizations. null when Engagifii cannot tell.
created_atdate-timeWhen the file was added.
updated_atdate-timeWhen the file last changed, including when it was moved to Trash.

Keeping files in sync ​

Moving a file to Trash in Engagifii deletes its content at once, so the API treats a file in Trash as deleted: it comes back in the deleted short form with updated_since, and leaves /files/ids.