# Events ## Create object **post** `/v2/prism/{teamId}/event` Creates a record. For `document`, writing `content` (or HTML) stores the property and reads back, but the in-app editor is CRDT-backed and will render a blank page until that document has been opened and saved in the app. Treat API-created docs as data records, not as collaboratively edited pages, unless you only need the stored property values. ### Path Parameters - `teamId: optional string` ### Header Parameters - `"Idempotency-Key": optional string` ### Body Parameters - `default: optional map[unknown]` Properties keyed by property slug. Values can be strings, numbers, booleans, arrays, or null. For select/multiselect properties, values may be option slugs or option UUIDs on write; option slugs are returned on read. - `list: optional unknown` ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event \ -X POST \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "id": "11111111-1111-4111-8111-111111111111", "default": { "full_name": "Sarah Chen", "email": "sarah@example.com", "title": "Partner", "organization": "Acme Ventures" } } ``` ## List records of an object type **get** `/v2/prism/{teamId}/event` Convenience list endpoint. Equivalent to `POST /v2/prism/{teamId}/{objectType}/query` with an empty body, plus query-string sugar for the common cases. Any unrecognized query parameter is interpreted as an equality filter on a property of that name; pass arrays for `in`. Values are received as strings, so non-string property filters via this endpoint may not work — use the `query` endpoint for typed comparisons or anything beyond simple equality. ### Path Parameters - `teamId: optional string` ### Query Parameters - `cursor: optional string` Opaque cursor from a previous response's `next_cursor`. Pass it back unchanged to fetch the next page. - `deleted: optional boolean` Include soft-deleted records. Pass the literal string `true`. - `include_total: optional boolean` When set to `true`, the response includes a `total` field with the unpaginated row count. Costs an extra pass; prefer `GET .../count` for the unfiltered total. - `limit: optional number` Maximum number of rows to return. Capped server-side at 50. - `list_id: optional string` Scope properties to a specific list/app. - `select: optional string` Comma-separated property slugs to return. Use dot notation for relationships. `id` is always returned at the top level. Defaults to all properties. - `sort: optional string` Comma-separated list of slugs. Prefix with `-` for descending. Example: `sort=-updated_at,name`. ### Returns - `data: array of object { id, is_user_object, properties, source }` - `id: string` - `is_user_object: optional boolean` - `properties: optional map[unknown]` Selected property values keyed by property slug. For select/multiselect properties, option slugs are returned. For reference properties, values are nested `{ id, properties }` objects. - `source: optional array of string` - `has_more: boolean` Accurate end-of-data signal — false on the last page, never forces clients to overshoot. - `next_cursor: optional string` - `total: optional number` Populated only when `?include_total=true` was passed. ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "data": [ { "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "is_user_object": true, "properties": { "foo": "bar" }, "source": [ "string" ] } ], "has_more": true, "next_cursor": "next_cursor", "total": 0 } ``` ## Get object **get** `/v2/prism/{teamId}/event/{eventId}` Get object ### Path Parameters - `teamId: optional string` - `eventId: string` ### Query Parameters - `select: optional string` Comma-separated property slugs to return. Use dot notation for relationships. `id` is always returned at the top level. Defaults to all properties. ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "id": "11111111-1111-4111-8111-111111111111", "default": { "full_name": "Sarah Chen", "email": "sarah@example.com", "title": "Partner", "organization": "Acme Ventures" } } ``` ## Patch object **patch** `/v2/prism/{teamId}/event/{eventId}` Patch object ### Path Parameters - `teamId: optional string` - `eventId: string` ### Header Parameters - `"Idempotency-Key": optional string` - `"If-Match": optional string` ### Body Parameters - `default: optional map[unknown]` Properties keyed by property slug. Values can be strings, numbers, booleans, arrays, or null. For select/multiselect properties, values may be option slugs or option UUIDs on write; option slugs are returned on read. - `list: optional unknown` ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID \ -X PATCH \ -H 'Content-Type: application/json' \ -H "x-api-key: $MICRO_API_KEY" \ -d '{}' ``` #### Response ```json { "id": "11111111-1111-4111-8111-111111111111", "default": { "full_name": "Sarah Chen", "email": "sarah@example.com", "title": "General Partner", "organization": "Acme Ventures" } } ``` ## Delete object **delete** `/v2/prism/{teamId}/event/{eventId}` Delete object ### Path Parameters - `teamId: optional string` - `eventId: string` ### Header Parameters - `"If-Match": optional string` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID \ -X DELETE \ -H "x-api-key: $MICRO_API_KEY" ``` ## Query **post** `/v2/prism/{teamId}/event/query` Query ### Path Parameters - `teamId: optional string` ### Header Parameters - `"Idempotency-Key": optional string` ### Body Parameters - `query: object { select, combinator, cursor, 5 more }` - `select: array of string` Property slugs to select. Use dot notation for relationships (e.g. attendee.contact.first_name). `id` is always returned at the top level of each row and does not need to be selected. - `combinator: optional "AND" or "OR"` Logical operator for combining filters - `"AND"` - `"OR"` - `cursor: optional string` Opaque cursor from a previous response's `next_cursor`. Pass it back unchanged to fetch the next page. When set, `page` and `limit` are derived from the cursor and any explicit values are ignored. - `filter: optional array of map[object { "=" } or object { "!=" } or object { "<" } or 14 more]` Filters as [{ slug: { operator: value } }]. For select/multiselect properties, values may be option slugs or option UUIDs. - `PrismQueryFilterEq object { "=" }` - `"=": string or boolean` - `string` - `boolean` - `PrismQueryFilterNe object { "!=" }` - `"!=": string or boolean` - `string` - `boolean` - `PrismQueryFilterLt object { "<" }` - `"<": string` - `PrismQueryFilterGt object { ">" }` - `">": string` - `PrismQueryFilterLte object { "<=" }` - `"<=": string` - `PrismQueryFilterGte object { ">=" }` - `">=": string` - `Contains object { contains }` - `contains: string or boolean or array of string` - `string` - `boolean` - `array of string` - `BeginsWith object { begins_with }` - `begins_with: string` - `EndsWith object { ends_with }` - `ends_with: string` - `NotContains object { not_contains }` - `not_contains: string` - `Exists object { exists }` - `exists: boolean` - `NotExists object { not_exists }` - `not_exists: boolean` - `IsNull object { is_null }` - `is_null: string or boolean or array of string` - `string` - `boolean` - `array of string` - `IsNotNull object { is_not_null }` - `is_not_null: string or boolean or array of string` - `string` - `boolean` - `array of string` - `Between object { between }` - `between: string or boolean or array of string` - `string` - `boolean` - `array of string` - `In object { in }` - `in: array of string` - `NotIn object { not_in }` - `not_in: array of string` - `limit: optional number` Maximum number of rows to return. Capped server-side at 50; requests above the cap are rejected. - `list_id: optional string` - `page: optional number` Page number (1-based). Prefer `cursor`. Page-number pagination drifts under concurrent writes; use it only for one-shot exports. - `sort: optional array of map["asc" or "desc"]` Sort order as [{ slug: direction }]. Array order determines sort priority - `"asc"` - `"desc"` - `id: optional string or array of string` - `string` - `array of string` - `boxes: optional array of string` - `cursor: optional string` Alternative location for the opaque cursor (a sibling of `query`). Use whichever feels more natural; if both are present, `query.cursor` wins. - `deleted: optional boolean` - `include_total: optional boolean` When true, the response includes a `total` field with the unpaginated row count. Costs an additional pass over the result set — for unfiltered totals prefer `GET /v2/prism/{teamId}/{objectType}/count` instead. - `sources: optional array of string` ### Returns - `data: array of object { id, is_user_object, properties, source }` - `id: string` - `is_user_object: optional boolean` - `properties: optional map[unknown]` Selected property values keyed by property slug. For select/multiselect properties, option slugs are returned. For reference properties, values are nested `{ id, properties }` objects. - `source: optional array of string` - `has_more: boolean` Accurate end-of-data signal. False when this page contains the last record; true only when at least one more record exists. (Implementation note: the server fetches one extra row internally to determine this — clients never need to overshoot to discover the end.) - `next_cursor: optional string` Opaque cursor pointing at the next page. Pass it back unchanged. Do not parse it. The current encoding is offset-based (page + limit), so it has the same concurrent-write drift the deprecated `page` parameter has; treat it as a black box so a future keyset cursor is a drop-in. Null when `has_more` is false. - `total: optional number` Only populated when the request set `include_total: true`. Total number of records matching the query, ignoring pagination. Opt-in because it costs an additional pass over the result set. ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/query \ -H 'Content-Type: application/json' \ -H "x-api-key: $MICRO_API_KEY" \ -d '{ "query": { "select": [ "full_name", "email", "title", "organization" ], "filter": [ { "full_name": { "=": "Sarah Chen" } } ], "limit": 10 } }' ``` #### Response ```json { "data": [ { "id": "11111111-1111-4111-8111-111111111111", "properties": { "full_name": "Sarah Chen", "email": "sarah@example.com", "title": "Partner", "organization": "Acme Ventures" }, "is_user_object": false, "source": null } ], "has_more": false, "next_cursor": null, "total": 1 } ``` ## Total record count for an object type **get** `/v2/prism/{teamId}/event/count` Returns the total number of records of this object type that the caller can see. Avoids the page-overshoot anti-pattern — clients no longer need to keep paging until `has_more` flips false to discover the total. Currently does not apply query filters; for a filtered total, pass `include_total: true` in a POST `/query` body. Unfiltered counts on high-cardinality types (especially `engagement`) scan the full access-scoped set and can take tens of seconds or time out; prefer a filtered `include_total` query or accept that this endpoint is expensive there. ### Path Parameters - `teamId: optional string` ### Query Parameters - `list_id: optional string` Scope the count to a specific list/app. ### Returns - `total: number` Number of records matching the access scope. ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/count \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "total": 0 } ``` ## Find a record by property value **get** `/v2/prism/{teamId}/event/by/{slug}/{value}` Returns the single record whose property `{slug}` equals `{value}`. 404 if nothing matches; 409 if more than one record matches. ### Path Parameters - `teamId: optional string` - `slug: string` - `value: string` ### Query Parameters - `list_id: optional string` Scope the lookup to a specific list/app. ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/by/$SLUG/$VALUE \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "default": { "foo": "bar" }, "list": {} } ``` ## Upsert by property value **put** `/v2/prism/{teamId}/event/by/{slug}/{value}` Idempotent create-or-update keyed on `{slug}={value}`. If exactly one record matches, it is patched and 200 is returned. If none match, a new record is created (with the lookup property set if absent) and 201 is returned. If multiple records match, 409 is returned and you should patch by id instead. ### Path Parameters - `teamId: optional string` - `slug: string` - `value: string` ### Query Parameters - `list_id: optional string` Scope the upsert to a specific list/app. Required to match or write list-scoped properties, including `app_stage`. ### Header Parameters - `"Idempotency-Key": optional string` ### Body Parameters - `default: optional map[unknown]` Properties keyed by property slug. Values can be strings, numbers, booleans, arrays, or null. For select/multiselect properties, values may be option slugs or option UUIDs on write; option slugs are returned on read. - `list: optional unknown` ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/by/$SLUG/$VALUE \ -X PUT \ -H 'Content-Type: application/json' \ -H "x-api-key: $MICRO_API_KEY" \ -d '{}' ``` #### Response ```json { "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "default": { "foo": "bar" }, "list": {} } ``` ## Duplicate object **post** `/v2/prism/{teamId}/event/{eventId}/duplicate` Duplicate object ### Path Parameters - `teamId: optional string` - `eventId: string` ### Header Parameters - `"Idempotency-Key": optional string` ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID/duplicate \ -X POST \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "default": { "foo": "bar" }, "list": {} } ``` ## Restore object **post** `/v2/prism/{teamId}/event/{eventId}/restore` Restore object ### Path Parameters - `teamId: optional string` - `eventId: string` ### Header Parameters - `"Idempotency-Key": optional string` ### Returns - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID/restore \ -X POST \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "default": { "foo": "bar" }, "list": {} } ``` ## Domain Types ### Event - `Event object { default, list }` - `default: optional map[unknown]` Properties keyed by property slug. Values can be strings, numbers, booleans, arrays, or null. For select/multiselect properties, values may be option slugs or option UUIDs on write; option slugs are returned on read. - `list: optional unknown` ### Event Create Response - `EventCreateResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event List Response - `EventListResponse object { data, has_more, next_cursor, total }` - `data: array of object { id, is_user_object, properties, source }` - `id: string` - `is_user_object: optional boolean` - `properties: optional map[unknown]` Selected property values keyed by property slug. For select/multiselect properties, option slugs are returned. For reference properties, values are nested `{ id, properties }` objects. - `source: optional array of string` - `has_more: boolean` Accurate end-of-data signal — false on the last page, never forces clients to overshoot. - `next_cursor: optional string` - `total: optional number` Populated only when `?include_total=true` was passed. ### Event Get Response - `EventGetResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event Update Response - `EventUpdateResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event Query Response - `EventQueryResponse object { data, has_more, next_cursor, total }` - `data: array of object { id, is_user_object, properties, source }` - `id: string` - `is_user_object: optional boolean` - `properties: optional map[unknown]` Selected property values keyed by property slug. For select/multiselect properties, option slugs are returned. For reference properties, values are nested `{ id, properties }` objects. - `source: optional array of string` - `has_more: boolean` Accurate end-of-data signal. False when this page contains the last record; true only when at least one more record exists. (Implementation note: the server fetches one extra row internally to determine this — clients never need to overshoot to discover the end.) - `next_cursor: optional string` Opaque cursor pointing at the next page. Pass it back unchanged. Do not parse it. The current encoding is offset-based (page + limit), so it has the same concurrent-write drift the deprecated `page` parameter has; treat it as a black box so a future keyset cursor is a drop-in. Null when `has_more` is false. - `total: optional number` Only populated when the request set `include_total: true`. Total number of records matching the query, ignoring pagination. Opt-in because it costs an additional pass over the result set. ### Event Count Response - `EventCountResponse object { total }` - `total: number` Number of records matching the access scope. ### Event Find Response - `EventFindResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event Upsert Response - `EventUpsertResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event Duplicate Response - `EventDuplicateResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` ### Event Restore Response - `EventRestoreResponse object { id, default, list }` Object returned by reads (get/create/patch/restore). id is always present. - `id: string` - `default: optional map[unknown]` Properties keyed by property slug. - `list: optional unknown` # Grant ## Get grant **get** `/v2/prism/{teamId}/event/{eventId}/grant` Get grant ### Path Parameters - `teamId: optional string` - `eventId: string` ### Returns - `contact_ids: optional array of string` - `group_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `identity_ids: optional array of string` - `organization_ids: optional array of string` - `share_level: optional "metadata" or "full"` How much of the record the grant exposes. `metadata` shares only the record's headers and participants; `full` shares its contents. Currently recorded on the access row and returned on read — it is not yet enforced by the read path. Applies to `message` grants; ignored for other object types. - `"metadata"` - `"full"` - `team_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `user_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID/grant \ -H "x-api-key: $MICRO_API_KEY" ``` #### Response ```json { "contact_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "group_id": { "foo": "a" }, "identity_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "organization_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "share_level": "metadata", "team_id": { "foo": "a" }, "user_id": { "foo": "a" } } ``` ## Update grant **put** `/v2/prism/{teamId}/event/{eventId}/grant` Update grant ### Path Parameters - `teamId: optional string` - `eventId: string` ### Header Parameters - `"Idempotency-Key": optional string` ### Body Parameters - `share_level: optional "metadata" or "full"` How much of the record the grant exposes. `metadata` shares only the record's headers and participants; `full` shares its contents. Currently recorded on the access row and returned on read — it is not yet enforced by the read path. Applies to `message` grants; ignored for other object types. - `"metadata"` - `"full"` - `team_group_id: optional array of map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `team_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `user_id: optional array of map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` ### Returns - `contact_ids: optional array of string` - `group_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `identity_ids: optional array of string` - `organization_ids: optional array of string` - `share_level: optional "metadata" or "full"` How much of the record the grant exposes. `metadata` shares only the record's headers and participants; `full` shares its contents. Currently recorded on the access row and returned on read — it is not yet enforced by the read path. Applies to `message` grants; ignored for other object types. - `"metadata"` - `"full"` - `team_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `user_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` ### Example ```http curl https://developers.micro.so/v2/prism/$TEAM_ID/event/$EVENT_ID/grant \ -X PUT \ -H 'Content-Type: application/json' \ -H "x-api-key: $MICRO_API_KEY" \ -d '{}' ``` #### Response ```json { "contact_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "group_id": { "foo": "a" }, "identity_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "organization_ids": [ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e" ], "share_level": "metadata", "team_id": { "foo": "a" }, "user_id": { "foo": "a" } } ``` ## Domain Types ### Grant Get Response - `GrantGetResponse object { contact_ids, group_id, identity_ids, 4 more }` The grants on a record. For `message`, also carries the entity ids of everyone on the message, resolved from its address headers when the grant was written. The id arrays are read-only and are null when participant resolution was unavailable (for example the mailbox had no Gmail token at the time). - `contact_ids: optional array of string` - `group_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `identity_ids: optional array of string` - `organization_ids: optional array of string` - `share_level: optional "metadata" or "full"` How much of the record the grant exposes. `metadata` shares only the record's headers and participants; `full` shares its contents. Currently recorded on the access row and returned on read — it is not yet enforced by the read path. Applies to `message` grants; ignored for other object types. - `"metadata"` - `"full"` - `team_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `user_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` ### Grant Update Response - `GrantUpdateResponse object { contact_ids, group_id, identity_ids, 4 more }` The grants on a record. For `message`, also carries the entity ids of everyone on the message, resolved from its address headers when the grant was written. The id arrays are read-only and are null when participant resolution was unavailable (for example the mailbox had no Gmail token at the time). - `contact_ids: optional array of string` - `group_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `identity_ids: optional array of string` - `organization_ids: optional array of string` - `share_level: optional "metadata" or "full"` How much of the record the grant exposes. `metadata` shares only the record's headers and participants; `full` shares its contents. Currently recorded on the access row and returned on read — it is not yet enforced by the read path. Applies to `message` grants; ignored for other object types. - `"metadata"` - `"full"` - `team_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"` - `user_id: optional map["a" or "r" or "w"]` - `"a"` - `"r"` - `"w"`