Documentation

Activities and audit

The activity timeline, automatic audit logging on contact and lead changes, and the comments thread.

Every change in the CRM — a contact tag added, a lead stage moved, an email opened, a ticket replied to — produces an activity record. Activities are the audit trail and the source of truth for the contact timeline a sales rep sees on the contact detail page. The system records them automatically; you rarely create activities by hand.

Surface

POST/crm/activity/manageJWT
GET/crm/activity/by-customer/:datatype?/:ownerId?JWT
GET/crm/activity/by-resource/:datatype/:ownerIdJWT

The two read endpoints differ in pivot: by-customer returns activities about a customer (contact, lead, merchant), by-resource returns activities about a non-customer resource (a ticket, a campaign, an order).

A typical contact-timeline call:

const activities = await fetch(
  `/api/crm/activity/by-customer/contact/${contactId}?page=1&pageSize=50`,
  { headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` } },
).then(r => r.json());

Auto-logged events

The CRM automatically writes activities for these events:

EventSourceActivity type
Contact createdPOST /repository/create/contactcontact_created
Contact taggedDB hookcontact_tagged
Lead stage movedPUT /crm/leads/detail/:idlead_stage_changed
Email sentbroadcast sendemail_sent
Email openedtracking pixelemail_opened
Email clickedtracking redirectemail_clicked
Page visitedanalytics ingestpage_visited
Form submittedPOST /crm/contact-form/post/:app/:nameform_submitted
Ticket createdPOST /crm/tickets/createticket_created
Ticket repliedPOST /crm/tickets/reply/:ticketIdticket_replied
Reservation bookedPOST /crm/reservations/createreservation_booked
Reservation cancelledDELETE /crm/reservations/cancel/...reservation_cancelled
Order placedstorefront checkoutorder_placed

Activities flow into the Sync notification processor which evaluates automation triggers (e.g. "if email_opened on contact tagged 'vip', notify rep"). They also feed the lead-scoring engine.

Manual activities

Use manage to add a custom activity — a logged call, an in-person meeting, a note pinned to a contact:

await fetch('/api/crm/activity/manage', {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    type: 'call_logged',
    datatype: 'contact',
    ownerId: 'contact-abc',
    summary: '15min discovery call. Interested in enterprise plan.',
    durationSeconds: 900,
    metadata: { phone: '+15551234567', outcome: 'positive' },
  }),
});

Comments

Comments are first-class on activities — internal-only threaded discussion attached to a record (a contact, a lead, a deal):

POST/crm/activity/comment/createJWT
GET/crm/activity/comment/get/:datatype/:ownerIdJWT
DELETE/crm/activity/comment/delete/:idJWT
// POST /crm/activity/comment/create
{
  "datatype": "lead",
  "ownerId": "lead-xyz",
  "text": "Procurement asked about SOC2 — need to send report.",
  "mentions": ["user-jane"]
}

Mentions create notifications via the Sync notification processor. Comments are visible only to staff (User principals) — never returned to customer-facing endpoints.

Audit reads

For broader audit (who edited what, when, from which IP), use the data layer's history endpoints rather than the activity log:

  • GET /repository/history/{collection}/:id returns the version history of a record.
  • The system fields on every BaseModel\<T\> (createdate, modifydate, createuser, modifyuser, version) carry the basic audit info inline.

The activity log is for narrative timeline; the data history is for forensic audit.

Activities are append-only by design. There's no edit endpoint — if a wrong activity is created, soft-delete it via the data layer. This keeps the audit trail tamper-evident.

Performance

Activities are scoped per ownerId, so reading a single contact's timeline is cheap. Reading "all activities for the org" is not — there's no global feed endpoint, and you should not build one against the raw data layer either; route through the Analytics module which materialises rollups.