Appearance
Interactions
Interactions are the calls, meetings and emails logged against people and organizations. Paging, updated_since and /ids work as described in Paging and Keeping a copy in sync, except where this page says otherwise.
An interaction can name thousands of people, for example one bulk email. So the people on an interaction and the organizations it is about are separate lists: /interaction-participants and /interaction-organizations. The note or email body is a separate call, GET /interactions/{id}/body.
Interactions
Most emails are logged by Engagifii itself when it sends a message. Those have no sender and no logged_by_person_id, and Engagifii shows them as "Notification" (is_notification: true). A scheduled email appears only once it has been sent.
| Endpoint | Meaning |
|---|---|
GET /interactions | List interactions, one page at a time. |
GET /interactions/ids | The id of every interaction. |
GET /interactions/{id} | One interaction. 404 if it does not exist or has been deleted. |
GET /interactions/{id}/body | The note or email body of one interaction. See below. |
Filters
| Parameter | Type | Meaning |
|---|---|---|
type | string | call, email or meeting. |
Example
json
{
"id": "7b3e…",
"type": "meeting",
"title": "Quarterly check-in",
"occurred_at": "2026-10-14T15:00:00Z",
"logged_by_person_id": "51ad…",
"is_notification": null,
"is_scheduled_email": null,
"from_person_id": null,
"recipient_count": null,
"participant_person_ids": ["3f0c…", "51ad…"],
"duration_minutes": 45,
"interaction_type": { "id": "2c91…", "label": "Member visit" },
"outcome": { "id": "8f04…", "label": "Follow-up needed" },
"organization_count": 1,
"attachments": [
{ "file_name": "Meeting notes.pdf" }
],
"created_at": "2026-10-14T16:02:18Z",
"updated_at": "2026-10-14T16:02:18Z"
}An email looks like this:
json
{
"id": "a40d…",
"type": "email",
"title": "Your 2027 membership renewal",
"occurred_at": "2026-11-02T13:30:05Z",
"logged_by_person_id": null,
"is_notification": true,
"is_scheduled_email": false,
"from_person_id": null,
"recipient_count": 1250,
"participant_person_ids": null,
"duration_minutes": null,
"interaction_type": null,
"outcome": null,
"organization_count": 310,
"attachments": [],
"created_at": "2026-11-02T13:30:05Z",
"updated_at": "2026-11-02T13:30:05Z"
}Fields
| Field | Type | Meaning |
|---|---|---|
id | UUID | The interaction's id. |
type | string | call, email, meeting, or other for any other kind. |
title | string or null | The call or meeting title, or the email subject. Returned as stored; it can contain HTML, so never render it unescaped. |
occurred_at | date-time or null | For calls and meetings, the date and time entered. For emails, when the email was sent. |
logged_by_person_id | UUID or null | The person who logged the interaction. An id from /people. null when Engagifii logged it itself. |
is_notification | boolean or null | Emails only: true when Engagifii sent the email without a sender. null for calls and meetings. |
is_scheduled_email | boolean or null | Emails only: true when the email was scheduled to send later. null for calls and meetings. |
from_person_id | UUID or null | Emails only: the sender. null for notifications, calls and meetings. |
recipient_count | integer or null | Emails only: the number of To, Cc and Bcc recipients. List them with /interaction-participants?interaction_id=…. null for calls and meetings. |
participant_person_ids | array of UUIDs or null | Calls and meetings only: the people who took part. null for emails. |
duration_minutes | integer or null | Calls and meetings only: how long it lasted. null for emails and when none is entered. |
interaction_type | object or null | The workspace's own type for the call or meeting. null if none is set. |
interaction_type.id | UUID | The type's id. |
interaction_type.label | string or null | The type's name, for example Member visit. |
outcome | object or null | The workspace's own outcome for the call or meeting. null if none is set. |
outcome.id | UUID | The outcome's id. |
outcome.label | string or null | The outcome's name. |
organization_count | integer | The number of organizations the interaction is about. List them with /interaction-organizations?interaction_id=…. |
attachments | array | Files attached to the interaction. Only the names are returned, not the files. |
attachments[].file_name | string | The attachment's file name. |
created_at | date-time | When the interaction was logged. |
updated_at | date-time | When the interaction was last edited, or logged if it was never edited. |
GET /interactions/{id}/body
Returns the note of a call or meeting, or the body of an email.
json
{
"data": {
"interaction_id": "a40d…",
"content_type": "text/html",
"body": "<p>Dear member,</p><p>Your membership renews on 1 January 2027.</p>"
}
}| Field | Type | Meaning |
|---|---|---|
interaction_id | UUID | The interaction. |
content_type | string | Always text/html. |
body | string | The body, exactly as Engagifii stores it, usually HTML. It is not sanitised: never render it unescaped. |
- This endpoint has its own rate limit of 600 requests per minute per integration, separate from the 120 per minute of every other endpoint, so a first full sync can read one body per interaction.
404when the interaction does not exist or has no body stored.503withRetry-Afterwhen the body could not be read. Retry after that many seconds.503with the detail"Interaction bodies are not available yet."and noRetry-Afterwhile Engagifii has not yet turned bodies on for the API. Try again on a later sync.- A body changes only when its interaction is edited. Read it for new interactions and whenever an interaction's
updated_atmoves.
Keeping interactions in sync
- Engagifii deletes interactions outright and records no deletion, so a deleted interaction never comes back in the deleted short form. Compare ids with
/interactions/idsto find them, and remove their participant and organization rows too. - An edit replaces an interaction's participants and organizations with new rows that have new ids. When an interaction's
updated_atmoves, read its rows again with?interaction_id=…and replace the ones you hold.
Interaction participants
One row per person on an interaction: the email's sender and its To, Cc and Bcc recipients, or a call or meeting participant.
| Endpoint | Meaning |
|---|---|
GET /interaction-participants | List participant rows, one page at a time. |
There is no /interaction-participants/ids and no /interaction-participants/{id}.
Parameters
| Parameter | Type | Meaning |
|---|---|---|
page_size | integer | Rows per page. Default 100, maximum 5000. |
cursor | UUID | The next_cursor from the previous page, passed back unchanged. |
interaction_id | UUID | Only rows of this interaction. |
person_id | UUID | Only rows for this person. |
updated_since | date or date-time | Only rows of interactions logged or edited at or after this time. Same format as on other lists. |
Example
json
{
"data": [
{ "id": "0c11…", "interaction_id": "a40d…", "person_id": "3f0c…", "role": "to" },
{ "id": "0c12…", "interaction_id": "7b3e…", "person_id": "51ad…", "role": "participant" }
],
"next_cursor": "0c12…"
}Fields
| Field | Type | Meaning |
|---|---|---|
id | UUID | The row's id. A new id is given each time the interaction is edited. |
interaction_id | UUID | The interaction. An id from /interactions. |
person_id | UUID or null | The person. An id from /people. null for an email recipient Engagifii could not match to a person. |
role | string | For emails: from, to, cc or bcc. For calls and meetings: participant. other for anything else. |
Interaction organizations
One row per organization an interaction is about. For emails, Engagifii fills these from the recipients' primary organizations.
| Endpoint | Meaning |
|---|---|
GET /interaction-organizations | List organization rows, one page at a time. |
There is no /interaction-organizations/ids and no /interaction-organizations/{id}.
Parameters
The same as interaction participants, with organization_id (UUID, only rows for this organization) in place of person_id.
Example
json
{
"data": [
{ "id": "5e70…", "interaction_id": "a40d…", "organization_id": "9b21…" }
],
"next_cursor": null
}Fields
| Field | Type | Meaning |
|---|---|---|
id | UUID | The row's id. A new id is given each time the interaction is edited. |
interaction_id | UUID | The interaction. An id from /interactions. |
organization_id | UUID or null | The organization. An id from /organizations. |
Paging and sync for participant and organization rows
These two lists work differently from the others:
- Rows are in a fixed order by
id, not by change time.next_cursoris the last row's id. Pass it back ascursoruntil it isnull. page_sizegoes up to 5000, because each row is small.- Rows have no change time of their own and no
updated_at.updated_sinceselects the rows of interactions logged or edited since that time. - Rows are never returned in the deleted short form. An edit replaces an interaction's rows with new ones, and a deleted interaction's rows disappear.
To keep a copy: on the first load, page through both lists in full. After that, for each interaction that comes back from /interactions?updated_since=…, fetch its rows with ?interaction_id=… and replace the rows you hold for it. When /interactions/ids shows an interaction is gone, delete its rows.
