DataSync event format reference

Showing JavaScript examples.

DataSync events are PubNub messages with message type 5. This distinguishes them from ordinary messages. Each event carries a versioned envelope with a metadata section and a data section.

Envelope schema​

{
"version": "1.0",
"metadata": {
"event": "create" | "update" | "delete",
"source": "data-sync",
"type": "user" | "channel" | "membership" | "entity" | "relationship",
"className": "Product",
"classLevel": "Global" | "SubKey",
"classVersion": 1
},
"data": { ... }
}

Metadata fields​

FieldTypeDescription
versionstringEnvelope version. Always 1.0 for DataSync events
metadata.eventstringcreate, update, or delete
metadata.sourcestringAlways data-sync
metadata.typestringThe object kind: user, channel, membership, entity, or relationship
metadata.classNamestringThe class name, for example Product or User. Read together with classLevel to distinguish a built-in class from a same-named keyset-level class
metadata.classLevelstringGlobal (PubNub-owned) or SubKey (keyset-level)
metadata.classVersionnumberThe class version the object pins to

metadata.type is derived from the Global class the class descends from, not from its name. A keyset-level class extending the built-in User reports type: "user" alongside its own className and classLevel: "SubKey". A keyset-level class merely named User that extends nothing reports type: "entity".

Data field shapes​

For create and update events, data carries the object's current state, scoped to the projection for the channel it's delivered on:

FieldPresent on
idAll object kinds
createdAtAll object kinds
updatedAtAll object kinds
expiresAtAll object kinds (omitted if not set)
eTagAll object kinds
statusAll object kinds (omitted if not set or outside projection)
payloadAll object kinds (omitted if empty or outside projection)
entityAIdRelationships only
entityBIdRelationships only
channelIdMemberships only
userIdMemberships only

For delete events, data is exactly { id, deletedAt } for every object kind alike. No payload or status is included.

Fields that have no value are omitted from data rather than sent as null. Read every field except id defensively.

Example events​

{
"version": "1.0",
"metadata": {
"event": "update",
"source": "data-sync",
"type": "entity",
"className": "Product",
"classLevel": "SubKey",
"classVersion": 1
},
"data": {
"id": "product-sneaker-42",
"status": "active",
"eTag": "a1b2c3",
"createdAt": "2026-06-01T10:00:00Z",
show all 20 lines

How the event is received per SDK​

1subscription.onDataSync = (event) => {
2 const change = event.message
3 console.log(change.event, change.className, change.data.payload?.price)
4}

The JavaScript SDK flattens the wire envelope: metadata.event arrives as event.message.event, metadata.className as event.message.className, and so on. event.message.data is the raw data object.

Using the REST subscribe endpoint directly, the raw response carrying an event looks like:

1curl -N 'https://ps.pndsn.com/v2/subscribe/{subKey}/product-sneaker-42/0?tt=0&auth=<token>'
[
[
{
"version": "1.0",
"metadata": {
"event": "update",
"source": "data-sync",
"type": "entity",
"className": "Product",
"classLevel": "SubKey",
"classVersion": 1
},
"data": {
"id": "product-sneaker-42",
"status": "active",
show all 25 lines

Refer to Add DataSync listener (JavaScript) and Add DataSync listener (C#) for the full SDK field reference.

Comparison with App Context events​

DataSync events use a different format from App Context events. Existing App Context event consumers are unaffected.

AspectApp ContextDataSync
Message type25
sourceobjectsdata-sync
Verbsset, deletecreate, update, delete
Envelope version2.01.0

Was this page useful?

Last updated on