From a26fe3bb65dda1a9a141ca4ec64c21af43aa66fc Mon Sep 17 00:00:00 2001
From: nitin <142569587+ehconitin@users.noreply.github.com>
Date: Wed, 20 May 2026 14:52:58 +0530
Subject: [PATCH] docs(sdk): document DatabaseEventPayload and simplify its
type (#20754)
closes
https://discord.com/channels/1130383047699738754/1505967920163983502
Update logic-function docs to match the real `DatabaseEventPayload`
shape.
The docs now show database event payloads as record-level events with
`recordId` and `properties.before/after/diff/updatedFields`, including
compact examples for created, updated, and destroyed events. Route
payload type imports now use the preferred `twenty-sdk/logic-function`
surface.
Also clean up the shared payload type wrapper so it models event
metadata without over-promising actor fields; `userId`,
`userWorkspaceId`, and `workspaceMemberId` remain optional through the
underlying event type.
---
.../extend/apps/logic/logic-functions.mdx | 117 +++++++++++++++++-
.../database-event-payload.type.ts | 14 +--
2 files changed, 116 insertions(+), 15 deletions(-)
diff --git a/packages/twenty-docs/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/developers/extend/apps/logic/logic-functions.mdx
index 6edf3a9530..f0f83e0845 100644
--- a/packages/twenty-docs/developers/extend/apps/logic/logic-functions.mdx
+++ b/packages/twenty-docs/developers/extend/apps/logic/logic-functions.mdx
@@ -13,8 +13,8 @@ Each function file uses `defineLogicFunction()` to export a configuration with a
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk/define';
-import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
-import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
+import type { RoutePayload } from 'twenty-sdk/logic-function';
+import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
const client = new CoreApiClient();
@@ -79,10 +79,10 @@ yarn twenty logs
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
-Import the `RoutePayload` type from `twenty-sdk`:
+Import the `RoutePayload` type from `twenty-sdk/logic-function`:
```ts
-import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
+import type { RoutePayload } from 'twenty-sdk/logic-function';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -141,6 +141,115 @@ const handler = async (event: RoutePayload) => {
Header names are normalized to lowercase. Access them using lowercase keys (e.g., `event.headers['content-type']`).
+#### Database event trigger payload
+
+When a database event trigger invokes your logic function, it receives one `DatabaseEventPayload` per changed record. The payload combines metadata about the source workspace and object with the record-level event.
+
+```ts
+import type {
+ DatabaseEventPayload,
+ ObjectRecordCreateEvent,
+ ObjectRecordDestroyEvent,
+ ObjectRecordUpdateEvent,
+} from 'twenty-sdk/logic-function';
+
+type Person = {
+ id: string;
+ emails?: { primaryEmail?: string };
+};
+```
+
+The payload includes:
+
+| Property | Description |
+|----------|-------------|
+| `name` | Event name, such as `person.updated`. |
+| `workspaceId` | Workspace where the event happened. |
+| `objectMetadata` | Metadata for the object that changed. |
+| `recordId` | Id of the changed record. |
+| `userId`, `userWorkspaceId`, `workspaceMemberId` | Actor fields when the event was caused by a workspace user. |
+| `properties` | Record data for the event, with `before`, `after`, `diff`, and `updatedFields` depending on the operation. |
+
+| Event | Record data |
+|-------|-------------|
+| `person.created` | `event.properties.after` |
+| `person.updated` | `event.properties.before`, `event.properties.after`, `event.properties.diff`, `event.properties.updatedFields` |
+| `person.destroyed` | `event.properties.before` |
+
+For soft deletes, `.deleted` follows the update-style shape because the record's `deletedAt` field changes.
+For permanent deletes, use `.destroyed`.
+
+
+`databaseEventTriggerSettings.updatedFields` filters which update events trigger the function.
+`event.properties.updatedFields` tells you which fields actually changed on the current event.
+
+
+Created event example:
+
+```ts
+type PersonCreatedEvent = DatabaseEventPayload<
+ ObjectRecordCreateEvent
+>;
+
+const handler = async (event: PersonCreatedEvent) => {
+ const person = event.properties.after;
+
+ return {
+ personId: event.recordId,
+ email: person.emails?.primaryEmail,
+ };
+};
+```
+
+Updated event example:
+
+```ts
+type PersonUpdatedEvent = DatabaseEventPayload<
+ ObjectRecordUpdateEvent
+>;
+
+const handler = async (event: PersonUpdatedEvent) => {
+ const { before, after, diff, updatedFields } = event.properties;
+
+ return {
+ personId: event.recordId,
+ updatedFields,
+ previousEmail: before.emails?.primaryEmail,
+ currentEmail: after.emails?.primaryEmail,
+ emailDiff: diff.emails,
+ };
+};
+```
+
+Trigger only on email updates:
+
+```ts
+export default defineLogicFunction({
+ ...,
+ databaseEventTriggerSettings: {
+ eventName: 'person.updated',
+ updatedFields: ['emails'],
+ },
+});
+```
+
+Destroyed event example:
+
+```ts
+type PersonDestroyedEvent = DatabaseEventPayload<
+ ObjectRecordDestroyEvent
+>;
+
+const handler = async (event: PersonDestroyedEvent) => {
+ const personBeforeDestroy = event.properties.before;
+
+ return {
+ personId: event.recordId,
+ email: personBeforeDestroy.emails?.primaryEmail,
+ };
+};
+```
+
#### Exposing a function as an AI tool or workflow action
Logic functions can be exposed on two surfaces, each with its own trigger:
diff --git a/packages/twenty-shared/src/database-events/database-event-payload.type.ts b/packages/twenty-shared/src/database-events/database-event-payload.type.ts
index 46ac94f982..07f7ce204a 100644
--- a/packages/twenty-shared/src/database-events/database-event-payload.type.ts
+++ b/packages/twenty-shared/src/database-events/database-event-payload.type.ts
@@ -37,19 +37,11 @@ type SimplifiedFlatObjectMetadata = {
viewUniversalIdentifiers: string[];
};
-type WorkspaceEventBatch = {
+type DatabaseEventMetadata = {
name: string;
workspaceId: string;
objectMetadata: SimplifiedFlatObjectMetadata;
- userId: string;
- userWorkspaceId: string;
- workspaceMemberId: string;
- recordId: string;
- events: WorkspaceEvent[];
};
-export type DatabaseEventPayload = Omit<
- WorkspaceEventBatch,
- 'events'
-> &
- T;
+export type DatabaseEventPayload =
+ DatabaseEventMetadata & T;