DataSync API for Swift SDK

DataSync is PubNub's data layer for storing application state (users, channels, memberships, and any custom object type) and keeping every connected client current through real-time events. Use it to model the objects your application works with and to react the moment they change.

DataSync is the successor to App Context.

DataSync entities and SDK entities are different things

This page is about DataSync entities, the records the service stores and treats as the source of truth for your application state. They are created and read through the pubnub.dataSync.* methods documented here.

An SDK entity is a local client-side handle such as pubnub.channel("room-1"). It carries no stored state of its own, it just gives you a scoped surface for subscribing and calling APIs. Refer to SDK entities in Publish and subscribe.

The two meet in the DataSync SDK entities: SDK entities whose only job is to subscribe to a DataSync object's real-time updates.

The classes that your objects conform to (their types and schemas) are defined through the Admin API or the Admin Portal, not through this SDK:

  • Entity classes, which back users, channels, and custom entities: list, read, create, replace, and delete. Partial updates aren't implemented; replace the complete class version instead.
  • Relationship classes, which back memberships and custom relationships: list, read, create, replace, and delete.

User and Channel entity classes and the Membership relationship class are predefined on every keyset, so you only need to define classes for your own custom entities and relationships.

A class definition is what decides, for every object of that class, which payload fields are filterable and sortable, which projection each field belongs to, and how long the object lives before it expires. Refer to managing classes for more information.

Every DataSync method reports through its completion closure, which receives a Result. A successful call returns the typed object (PubNubDataSyncUser, PubNubDataSyncChannel, PubNubDataSyncMembership, PubNubDataSyncEntity, or PubNubDataSyncRelationship). A list method returns a tuple holding the array of objects and an optional PubNubDataSyncPage, and the remove* methods return Void. The Response blocks on this page show the JSON the service sends, which the SDK decodes for you. It surfaces neither the HTTP status nor the HATEOAS links. A stored object carries its free-form status and its expiresAt auto-deletion timestamp (ISO 8601) whenever those are set on it. You pass payload as any JSONCodable value, such as a Codable struct or a dictionary, and decode it back with payload?.decode(_:).

Every DataSync request must be authorized with a token or signature. A request with no credential fails with a 401; an invalid credential or a credential that doesn't permit the operation fails with a 403.

The Swift SDK is a client-side SDK, so it doesn't sign requests with a secret key. Never put a secret key in a client-side application. Give the client a token that a server SDK granted, as described in grant structured data access, and set it with set(token:).

Asynchronous calls and errors

Every DataSync method is asynchronous and delivers its outcome to the completion closure. The SDK has no async or await variant, so wrap a call in a continuation if you need one.

A failed call arrives in the .failure case as an Error that you cast with error.pubNubError. Its reason follows the HTTP status, for example .badRequest, .unauthorized, .forbidden, .resourceNotFound, .conflict, or .preconditionFailed, and its details hold the messages the service returned.

Requires Access Manager

DataSync requires that the Access Manager add-on is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.

Users​

Users are built-in objects. There are no top-level name or email fields, all application data lives in the free-form payload. Refer to users for the concept.

A user is an entity of the built-in User entity class, which the service provides at the Global class level. To give your users their own declared, filterable properties, define a subclass of User with Create a new entity class and pass its name as className.

Create user​

Creates a user. Supply an id to control the identifier, or omit it to let the server generate one.

Method(s)​

1func createUser(
2 className: String? = nil,
3 classVersion: Int,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 id: String? = nil,
6 status: String? = nil,
7 payload: JSONCodable? = nil,
8 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
9 completion: ((Result<PubNubDataSyncUser, Error>) -> Void)?
10)
* required
ParameterDescription
id
Type: String
Default:
server-generated
User identifier. Omit to let the server generate a UUID. Max 255 characters.
className
Type: String
Default:
User
Name of the entity class this user belongs to. Must be User or one of its subclasses. Defaults to User on the server if omitted. Set at creation and immutable afterward.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate classes with the same name defined at different levels. Set at creation and immutable afterward.
classVersion *
Type: Int
Default:
n/a
Version of the user class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncUser. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice",
5 "entityClass": "User",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"fullName": "Alice Summers", "email": "alice@example.com", "loginCount": 0, "isEmailVerified": false},
10 "createdAt": "2026-07-13T09:00:00.000Z",
11 "updatedAt": "2026-07-13T09:00:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "AbQdEfGhIjKlMn"
14 }
15}

Get user​

Returns a single user by id.

Method(s)​

1func getUser(
2 id: String,
3 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
4 completion: ((Result<PubNubDataSyncUser, Error>) -> Void)?
5)
* required
ParameterDescription
id *
Type: String
Default:
n/a
User identifier.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncUser. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice",
5 "entityClass": "User",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"fullName": "Alice Summers", "email": "alice@example.com", "loginCount": 0, "isEmailVerified": false},
10 "createdAt": "2026-07-13T09:00:00.000Z",
11 "updatedAt": "2026-07-13T09:00:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "AbQdEfGhIjKlMn"
14 }
15}

Get all users​

Returns a paginated list of users. All parameters other than completion are optional, so you can call getUsers with only a completion closure. For pagination, filtering, and sorting, refer to sorting and pagination.

Method(s)​

1func getUsers(
2 className: String? = nil,
3 classVersion: Int? = nil,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 cursor: String? = nil,
6 limit: Int? = nil,
7 filterFast: String? = nil,
8 filter: String? = nil,
9 sort: [PubNub.DataSyncSortField] = [],
10 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
11 completion: ((Result<(users: [PubNubDataSyncUser], next: PubNubDataSyncPage?), Error>) -> Void)?
12)
* required
ParameterDescription
className
Type: String
Default:
all user classes
User class to list. Omit to list the Global User class and all of its subclasses.
classVersion
Type: Int
Default:
all versions
User class version to list. Omit to list users across every version of the class.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate a class name defined at both levels.
cursor
Type: String
Default:
n/a
Opaque pagination cursor. Omit for the first page.
limit
Type: Int
Default:
20
Maximum number of users per page. Max 100.
filterFast
Type: String
Default:
n/a
Filter expression evaluated against strongly consistent storage, so it reflects the latest writes. Accepts up to 10 conditions by default (raisable per keyset), over properties declared with filtering mode simple or full. Cannot be combined with filter.
filter
Type: String
Default:
n/a
Filter expression evaluated against eventually consistent storage, so results can briefly lag writes. Supports the full expression language, over properties declared with filtering mode full. Cannot be combined with filterFast.
sort
Type: [PubNub.DataSyncSortField]
Default:
[]
Order results. Each PubNub.DataSyncSortField names a property and sets ascending (default true), for example .init(property: "createdAt", ascending: false).
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a tuple of the users array and the optional next page. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": [
4 {
5 "id": "alice",
6 "entityClass": "User",
7 "entityClassVersion": 1,
8 "entityClassLevel": "Global",
9 "status": "active",
10 "payload": {"fullName": "Alice Summers", "email": "alice@example.com", "loginCount": 0, "isEmailVerified": false},
11 "createdAt": "2026-07-13T09:00:00.000Z",
12 "updatedAt": "2026-07-13T09:00:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "AbQdEfGhIjKlMn"
15 }
show all 22 lines

Other examples​

Filter with filterFast​

filterFast is evaluated against strongly consistent storage, so it matches an object you just wrote. It runs over properties declared with filtering mode simple or full and accepts up to 10 conditions by default (raisable per keyset). Reference a declared property by its name, not its path. It shares the same expression language as filter, so only one of the two can be sent per call.

1

Filter with filter​

filter runs over properties declared with filtering mode full and is evaluated against eventually consistent storage, so a very recent write may not be matched yet. Reference a declared property by its name, not its path. It shares the same expression language as filterFast, so only one of the two can be sent per call.

1

Page through results with cursor​

Pass no cursor on the first call. Take next.cursor from the response and pass it back as cursor on the next call. Stop when next.hasNext is false.

1

Set user​

Replaces a user in full (PUT). Send the complete set of fields, any field you omit is cleared. className and classLevel are immutable after creation and cannot be sent. Refer to optimistic concurrency with ETags for ifMatchesEtag. For a partial update, use Update user.

Method(s)​

1func setUser(
2 id: String,
3 classVersion: Int,
4 status: String? = nil,
5 payload: JSONCodable? = nil,
6 ifMatchesEtag: String? = nil,
7 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
8 completion: ((Result<PubNubDataSyncUser, Error>) -> Void)?
9)
* required
ParameterDescription
id *
Type: String
Default:
n/a
User identifier.
classVersion *
Type: Int
Default:
n/a
Version of the user class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The update succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncUser. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice",
5 "entityClass": "User",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"fullName": "Alice R. Summers", "email": "alice.summers@example.com", "loginCount": 12, "isEmailVerified": true},
10 "createdAt": "2026-07-13T09:00:00.000Z",
11 "updatedAt": "2026-07-13T10:15:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "CdEfGhIjKlMnOp"
14 }
15}

Update user​

Applies a partial update to a user with raw JSON Patch operations. Refer to partial update for the operation model.

Method(s)​

1func updateUser(
2 id: String,
3 operations: [PubNubDataSyncPatchOperation],
4 ifMatchesEtag: String? = nil,
5 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
6 completion: ((Result<PubNubDataSyncUser, Error>) -> Void)?
7)
* required
ParameterDescription
id *
Type: String
Default:
n/a
User identifier.
operations *
Type: [PubNubDataSyncPatchOperation]
Default:
n/a
One or more JSON Patch operations. Must contain at least one item.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The patch succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncUser. Pass nil to ignore the result.

Use a JSON Pointer that starts with /payload/ to target payload fields, or a root pointer (for example /status) to target a top-level field.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice",
5 "entityClass": "User",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"fullName": "Alice R. Summers", "email": "alice.summers@example.com", "loginCount": 13, "isEmailVerified": true, "nickname": "Ali"},
10 "createdAt": "2026-07-13T09:00:00.000Z",
11 "updatedAt": "2026-07-13T10:20:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "EfGhIjKlMnOpQr"
14 }
15}

Remove user​

Deletes a user by id.

Method(s)​

1func removeUser(
2 id: String,
3 ifMatchesEtag: String? = nil,
4 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
5 completion: ((Result<Void, Error>) -> Void)?
6)
* required
ParameterDescription
id *
Type: String
Default:
n/a
User identifier.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The delete succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds Void. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200
3}

Channels​

Channels work like users. They have no top-level name field, all application data lives in payload, and they support the same operations. Refer to channels for the concept.

A channel is an entity of the built-in Channel entity class, which the service provides at the Global class level. Subclass it with Create a new entity class to add declared properties, then pass the subclass name as className.

Create channel​

Creates a channel. Supply an id to control the identifier, or omit it to let the server generate one.

Method(s)​

1func createChannel(
2 className: String? = nil,
3 classVersion: Int,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 id: String? = nil,
6 status: String? = nil,
7 payload: JSONCodable? = nil,
8 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
9 completion: ((Result<PubNubDataSyncChannel, Error>) -> Void)?
10)
* required
ParameterDescription
id
Type: String
Default:
server-generated
Channel identifier. Omit to let the server generate a UUID. Max 255 characters.
className
Type: String
Default:
Channel
Name of the entity class this channel belongs to. Must be Channel or one of its subclasses. Defaults to Channel on the server if omitted. Set at creation and immutable afterward.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate classes with the same name defined at different levels. Set at creation and immutable afterward.
classVersion *
Type: Int
Default:
n/a
Version of the channel class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncChannel. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general",
5 "entityClass": "Channel",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"name": "General", "topic": "Company-wide announcements", "retentionDays": 30, "isPrivate": false},
10 "createdAt": "2026-07-13T09:05:00.000Z",
11 "updatedAt": "2026-07-13T09:05:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "GhIjKlMnOpQrSt"
14 }
15}

Get channel​

Returns a single channel by id.

Method(s)​

1func getChannel(
2 id: String,
3 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
4 completion: ((Result<PubNubDataSyncChannel, Error>) -> Void)?
5)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Channel identifier.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncChannel. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general",
5 "entityClass": "Channel",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"name": "General", "topic": "Company-wide announcements", "retentionDays": 30, "isPrivate": false},
10 "createdAt": "2026-07-13T09:05:00.000Z",
11 "updatedAt": "2026-07-13T09:05:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "GhIjKlMnOpQrSt"
14 }
15}

Get all channels​

Returns a paginated list of channels. All parameters other than completion are optional, so you can call getChannels with only a completion closure. For pagination, filtering, and sorting, refer to sorting and pagination.

Method(s)​

1func getChannels(
2 className: String? = nil,
3 classVersion: Int? = nil,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 cursor: String? = nil,
6 limit: Int? = nil,
7 filterFast: String? = nil,
8 filter: String? = nil,
9 sort: [PubNub.DataSyncSortField] = [],
10 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
11 completion: ((Result<(channels: [PubNubDataSyncChannel], next: PubNubDataSyncPage?), Error>) -> Void)?
12)
* required
ParameterDescription
className
Type: String
Default:
all channel classes
Channel class to list. Omit to list the Global Channel class and all of its subclasses.
classVersion
Type: Int
Default:
all versions
Channel class version to list. Omit to list channels across every version of the class.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate a class name defined at both levels.
cursor
Type: String
Default:
n/a
Opaque pagination cursor. Omit for the first page.
limit
Type: Int
Default:
20
Maximum number of channels per page. Max 100.
filterFast
Type: String
Default:
n/a
Filter expression evaluated against strongly consistent storage, so it reflects the latest writes. Accepts up to 10 conditions by default (raisable per keyset), over properties declared with filtering mode simple or full. Cannot be combined with filter.
filter
Type: String
Default:
n/a
Filter expression evaluated against eventually consistent storage, so results can briefly lag writes. Supports the full expression language, over properties declared with filtering mode full. Cannot be combined with filterFast.
sort
Type: [PubNub.DataSyncSortField]
Default:
[]
Order results. Each PubNub.DataSyncSortField names a property and sets ascending (default true).
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a tuple of the channels array and the optional next page. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": [
4 {
5 "id": "general",
6 "entityClass": "Channel",
7 "entityClassVersion": 1,
8 "entityClassLevel": "Global",
9 "status": "active",
10 "payload": {"name": "General", "topic": "Company-wide announcements", "retentionDays": 30, "isPrivate": false},
11 "createdAt": "2026-07-13T09:05:00.000Z",
12 "updatedAt": "2026-07-13T09:05:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "GhIjKlMnOpQrSt"
15 }
show all 22 lines

Other examples​

Filter with filterFast​

filterFast is evaluated against strongly consistent storage, so it matches an object you just wrote. It runs over properties declared with filtering mode simple or full and accepts up to 10 conditions by default (raisable per keyset). Reference a declared property by its name, not its path. It shares the same expression language as filter, so only one of the two can be sent per call.

1

Filter with filter​

filter runs over properties declared with filtering mode full and is evaluated against eventually consistent storage, so a very recent write may not be matched yet. Reference a declared property by its name, not its path. It shares the same expression language as filterFast, so only one of the two can be sent per call.

1

Page through results with cursor​

Pass no cursor on the first call. Take next.cursor from the response and pass it back as cursor on the next call. Stop when next.hasNext is false.

1

Set channel​

Replaces a channel in full (PUT). Send the complete set of fields, any field you omit is cleared. className and classLevel are immutable after creation and cannot be sent. Refer to optimistic concurrency with ETags for ifMatchesEtag. For a partial update, use Update channel.

Method(s)​

1func setChannel(
2 id: String,
3 classVersion: Int,
4 status: String? = nil,
5 payload: JSONCodable? = nil,
6 ifMatchesEtag: String? = nil,
7 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
8 completion: ((Result<PubNubDataSyncChannel, Error>) -> Void)?
9)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Channel identifier.
classVersion *
Type: Int
Default:
n/a
Version of the channel class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The update succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncChannel. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general",
5 "entityClass": "Channel",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"name": "General", "topic": "All-hands announcements", "retentionDays": 90, "isPrivate": false},
10 "createdAt": "2026-07-13T09:05:00.000Z",
11 "updatedAt": "2026-07-13T11:00:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "IjKlMnOpQrStUv"
14 }
15}

Update channel​

Applies a partial update to a channel with raw JSON Patch operations. Refer to partial update for the operation model.

Method(s)​

1func updateChannel(
2 id: String,
3 operations: [PubNubDataSyncPatchOperation],
4 ifMatchesEtag: String? = nil,
5 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
6 completion: ((Result<PubNubDataSyncChannel, Error>) -> Void)?
7)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Channel identifier.
operations *
Type: [PubNubDataSyncPatchOperation]
Default:
n/a
One or more JSON Patch operations. Must contain at least one item.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The patch succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncChannel. Pass nil to ignore the result.

Use a JSON Pointer that starts with /payload/ to target payload fields, or a root pointer (for example /status) to target a top-level field.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general",
5 "entityClass": "Channel",
6 "entityClassVersion": 1,
7 "entityClassLevel": "Global",
8 "status": "active",
9 "payload": {"name": "General", "topic": "Company announcements", "retentionDays": 365, "isPrivate": true, "archivedAt": "2026-08-11"},
10 "createdAt": "2026-07-13T09:05:00.000Z",
11 "updatedAt": "2026-07-13T11:05:00.000Z",
12 "expiresAt": "2026-08-13T00:00:00.000Z",
13 "eTag": "KlMnOpQrStUvWx"
14 }
15}

Remove channel​

Deletes a channel by id.

Method(s)​

1func removeChannel(
2 id: String,
3 ifMatchesEtag: String? = nil,
4 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
5 completion: ((Result<Void, Error>) -> Void)?
6)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Channel identifier.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The delete succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds Void. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200
3}

Memberships​

A membership links a user to a channel and carries its own payload. In the running example, Alice is a member of general with the payload { "role": "moderator" }. Refer to memberships for the concept.

A membership is a relationship of the built-in Global Membership relationship class, whose two sides are surfaced as channelId and userId. Every membership response includes both relationshipClass and relationshipClassVersion. The class is assigned by the service, so the createMembership and setMembership methods take no class parameter.

Relationship classes don't support inheritance, and only the Global Membership class produces memberships, so relationshipClass is always Membership and relationshipClassVersion is the only part that varies.

Create membership​

Creates a membership linking a user to a channel. The userId and channelId pair must be unique for the membership class. A membership that duplicates an existing pair is rejected with a 409.

Method(s)​

1func createMembership(
2 channelId: String,
3 userId: String,
4 classVersion: Int,
5 id: String? = nil,
6 status: String? = nil,
7 payload: JSONCodable? = nil,
8 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
9 completion: ((Result<PubNubDataSyncMembership, Error>) -> Void)?
10)
* required
ParameterDescription
channelId *
Type: String
Default:
n/a
Identifier of the channel in the membership.
userId *
Type: String
Default:
n/a
Identifier of the user in the membership.
id
Type: String
Default:
server-generated
Membership identifier. Omit to let the server generate a UUID. Max 255 characters.
classVersion *
Type: Int
Default:
n/a
Version of the membership class schema. Sent to the service as relationshipClassVersion.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncMembership. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general-alice",
5 "channelId": "general",
6 "userId": "alice",
7 "relationshipClass": "Membership",
8 "relationshipClassVersion": 1,
9 "status": "active",
10 "payload": {"role": "moderator", "unreadCount": 0, "isMuted": false},
11 "createdAt": "2026-07-13T09:10:00.000Z",
12 "updatedAt": "2026-07-13T09:10:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "MnOpQrStUvWxYz"
15 }
show all 16 lines

Get membership​

Returns a single membership by id.

Method(s)​

1func getMembership(
2 id: String,
3 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
4 completion: ((Result<PubNubDataSyncMembership, Error>) -> Void)?
5)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Membership identifier.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncMembership. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general-alice",
5 "channelId": "general",
6 "userId": "alice",
7 "relationshipClass": "Membership",
8 "relationshipClassVersion": 1,
9 "status": "active",
10 "payload": {"role": "moderator", "unreadCount": 0, "isMuted": false},
11 "createdAt": "2026-07-13T09:10:00.000Z",
12 "updatedAt": "2026-07-13T09:10:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "MnOpQrStUvWxYz"
15 }
show all 16 lines

Get all memberships​

Returns a paginated list of memberships. All parameters other than completion are optional, so you can call getMemberships with only a completion closure. userId and channelId can be set independently, together, or omitted entirely. Filter by userId to list a user's memberships or by channelId to list a channel's members. For pagination, filtering, and sorting, refer to sorting and pagination.

Method(s)​

1func getMemberships(
2 channelId: String? = nil,
3 userId: String? = nil,
4 classVersion: Int? = nil,
5 cursor: String? = nil,
6 limit: Int? = nil,
7 filterFast: String? = nil,
8 filter: String? = nil,
9 sort: [PubNub.DataSyncSortField] = [],
10 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
11 completion: ((Result<(memberships: [PubNubDataSyncMembership], next: PubNubDataSyncPage?), Error>) -> Void)?
12)
* required
ParameterDescription
channelId
Type: String
Default:
n/a
List only memberships for this channel.
userId
Type: String
Default:
n/a
List only memberships for this user.
classVersion
Type: Int
Default:
all versions
Membership class version to list. Omit to list memberships across every version of the class.
cursor
Type: String
Default:
n/a
Opaque pagination cursor. Omit for the first page.
limit
Type: Int
Default:
20
Maximum number of memberships per page. Max 100.
filterFast
Type: String
Default:
n/a
Filter expression evaluated against strongly consistent storage, so it reflects the latest writes. Accepts up to 10 conditions by default (raisable per keyset), over properties declared with filtering mode simple or full. Cannot be combined with filter.
filter
Type: String
Default:
n/a
Filter expression evaluated against eventually consistent storage, so results can briefly lag writes. Supports the full expression language, over properties declared with filtering mode full. Cannot be combined with filterFast.
sort
Type: [PubNub.DataSyncSortField]
Default:
[]
Order results. Each PubNub.DataSyncSortField names a property and sets ascending (default true).
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a tuple of the memberships array and the optional next page. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": [
4 {
5 "id": "general-alice",
6 "channelId": "general",
7 "userId": "alice",
8 "relationshipClass": "Membership",
9 "relationshipClassVersion": 1,
10 "status": "active",
11 "payload": {"role": "moderator", "unreadCount": 0, "isMuted": false},
12 "createdAt": "2026-07-13T09:10:00.000Z",
13 "updatedAt": "2026-07-13T09:10:00.000Z",
14 "expiresAt": "2026-08-13T00:00:00.000Z",
15 "eTag": "MnOpQrStUvWxYz"
show all 23 lines

Other examples​

List a user's memberships with userId​

Pass userId instead of channelId to list the memberships of a user rather than the members of a channel.

1

Filter with filterFast​

filterFast is evaluated against strongly consistent storage, so it matches an object you just wrote. It runs over properties declared with filtering mode simple or full and accepts up to 10 conditions by default (raisable per keyset). Reference a declared property by its name, not its path. It shares the same expression language as filter, so only one of the two can be sent per call.

1

Filter with filter​

filter runs over properties declared with filtering mode full and is evaluated against eventually consistent storage, so a very recent write may not be matched yet. Reference a declared property by its name, not its path. It shares the same expression language as filterFast, so only one of the two can be sent per call.

1

Page through results with cursor​

Pass no cursor on the first call. Take next.cursor from the response and pass it back as cursor on the next call. Stop when next.hasNext is false.

1

Set membership​

Replaces a membership in full (PUT). Send the complete set of fields, any field you omit is cleared. The linked user and channel are immutable, so setMembership doesn't take channelId or userId, there is nothing to resend. Refer to optimistic concurrency with ETags for ifMatchesEtag. For a partial update, use Update membership.

Method(s)​

1func setMembership(
2 id: String,
3 classVersion: Int,
4 status: String? = nil,
5 payload: JSONCodable? = nil,
6 ifMatchesEtag: String? = nil,
7 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
8 completion: ((Result<PubNubDataSyncMembership, Error>) -> Void)?
9)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Membership identifier.
classVersion *
Type: Int
Default:
n/a
Version of the membership class schema. Sent to the service as relationshipClassVersion.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The update succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncMembership. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general-alice",
5 "channelId": "general",
6 "userId": "alice",
7 "relationshipClass": "Membership",
8 "relationshipClassVersion": 1,
9 "status": "active",
10 "payload": {"role": "member", "unreadCount": 7, "isMuted": true},
11 "createdAt": "2026-07-13T09:10:00.000Z",
12 "updatedAt": "2026-07-13T12:00:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "OpQrStUvWxYzAb"
15 }
show all 16 lines

Update membership​

Applies a partial update to a membership with raw JSON Patch operations. Refer to partial update for the operation model.

Method(s)​

1func updateMembership(
2 id: String,
3 operations: [PubNubDataSyncPatchOperation],
4 ifMatchesEtag: String? = nil,
5 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
6 completion: ((Result<PubNubDataSyncMembership, Error>) -> Void)?
7)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Membership identifier.
operations *
Type: [PubNubDataSyncPatchOperation]
Default:
n/a
One or more JSON Patch operations. Must contain at least one item.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The patch succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncMembership. Pass nil to ignore the result.

Use a JSON Pointer that starts with /payload/ to target payload fields, or a root pointer (for example /status) to target a top-level field.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "general-alice",
5 "channelId": "general",
6 "userId": "alice",
7 "relationshipClass": "Membership",
8 "relationshipClassVersion": 1,
9 "status": "active",
10 "payload": {"role": "admin", "unreadCount": 0, "isMuted": false, "lastReadAt": "2026-07-13T12:05:00.000Z"},
11 "createdAt": "2026-07-13T09:10:00.000Z",
12 "updatedAt": "2026-07-13T12:05:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "QrStUvWxYzAbCd"
15 }
show all 16 lines

Remove membership​

Deletes a membership by id.

Method(s)​

1func removeMembership(
2 id: String,
3 ifMatchesEtag: String? = nil,
4 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
5 completion: ((Result<Void, Error>) -> Void)?
6)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Membership identifier.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The delete succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds Void. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200
3}

Entities​

Entities are instances of the custom entity classes you define on your keyset. In the running example, course is a class and course-swift-basics is an instance. Use Create a new entity class to declare a class, and Get entity class by ID to read the property, filtering, and projection declarations that govern its instances.

Entity classes can extend one another. Listing a class also returns the entities of its subclasses, so getEntities(className: "course") returns every course plus every instance of a class that extends course.

Create entity​

Creates an entity of a given class and version.

Method(s)​

1func createEntity(
2 className: String,
3 classVersion: Int,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 id: String? = nil,
6 status: String? = nil,
7 payload: JSONCodable? = nil,
8 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
9 completion: ((Result<PubNubDataSyncEntity, Error>) -> Void)?
10)
* required
ParameterDescription
id
Type: String
Default:
server-generated
Entity identifier. Omit to let the server generate a UUID. Max 255 characters.
className *
Type: String
Default:
n/a
Name of the entity class this instance belongs to. Set at creation and immutable afterward.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate classes with the same name defined at different levels. Set at creation and immutable afterward.
classVersion *
Type: Int
Default:
n/a
Version of the entity class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncEntity. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "course-swift-basics",
5 "entityClass": "course",
6 "entityClassVersion": 1,
7 "entityClassLevel": "SubKey",
8 "status": "draft",
9 "payload": {"title": "Swift Basics", "lessonCount": 24, "isPublished": false},
10 "createdAt": "2026-07-13T09:15:00.000Z",
11 "updatedAt": "2026-07-13T09:15:00.000Z",
12 "expiresAt": "2026-08-14T00:00:00.000Z",
13 "eTag": "StUvWxYzAbCdEf"
14 }
15}

Get entity​

Returns a single entity by id.

Method(s)​

1func getEntity(
2 id: String,
3 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
4 completion: ((Result<PubNubDataSyncEntity, Error>) -> Void)?
5)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Entity identifier.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncEntity. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "course-swift-basics",
5 "entityClass": "course",
6 "entityClassVersion": 1,
7 "entityClassLevel": "SubKey",
8 "status": "draft",
9 "payload": {"title": "Swift Basics", "lessonCount": 24, "isPublished": false},
10 "createdAt": "2026-07-13T09:15:00.000Z",
11 "updatedAt": "2026-07-13T09:15:00.000Z",
12 "expiresAt": "2026-08-14T00:00:00.000Z",
13 "eTag": "StUvWxYzAbCdEf"
14 }
15}

Get all entities​

Returns a paginated list of entities within a class. The className parameter is required, entities are always listed within the context of their class. For pagination, filtering, and sorting, refer to sorting and pagination.

Method(s)​

1func getEntities(
2 className: String,
3 classVersion: Int? = nil,
4 classLevel: PubNubDataSyncClassLevel? = nil,
5 cursor: String? = nil,
6 limit: Int? = nil,
7 filterFast: String? = nil,
8 filter: String? = nil,
9 sort: [PubNub.DataSyncSortField] = [],
10 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
11 completion: ((Result<(entities: [PubNubDataSyncEntity], next: PubNubDataSyncPage?), Error>) -> Void)?
12)
* required
ParameterDescription
className *
Type: String
Default:
n/a
Name of the entity class to list.
classVersion
Type: Int
Default:
all versions
Entity class version to list. Omit to list entities across every version of the class.
classLevel
Type: PubNubDataSyncClassLevel
Default:
service default
Class hierarchy level of className, either .global for a class the service provides or .subKey for one defined on your keyset. Used to disambiguate a class name defined at both levels.
cursor
Type: String
Default:
n/a
Opaque pagination cursor. Omit for the first page.
limit
Type: Int
Default:
20
Maximum number of entities per page. Max 100.
filterFast
Type: String
Default:
n/a
Filter expression evaluated against strongly consistent storage, so it reflects the latest writes. Accepts up to 10 conditions by default (raisable per keyset), over properties declared with filtering mode simple or full. Cannot be combined with filter.
filter
Type: String
Default:
n/a
Filter expression evaluated against eventually consistent storage, so results can briefly lag writes. Supports the full expression language, over properties declared with filtering mode full. Cannot be combined with filterFast.
sort
Type: [PubNub.DataSyncSortField]
Default:
[]
Order results. Each PubNub.DataSyncSortField names a property and sets ascending (default true).
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a tuple of the entities array and the optional next page. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": [
4 {
5 "id": "course-swift-basics",
6 "entityClass": "course",
7 "entityClassVersion": 1,
8 "entityClassLevel": "SubKey",
9 "status": "draft",
10 "payload": {"title": "Swift Basics", "lessonCount": 24, "isPublished": false},
11 "createdAt": "2026-07-13T09:15:00.000Z",
12 "updatedAt": "2026-07-13T09:15:00.000Z",
13 "expiresAt": "2026-08-14T00:00:00.000Z",
14 "eTag": "StUvWxYzAbCdEf"
15 }
show all 22 lines

Other examples​

Filter with filterFast​

filterFast is evaluated against strongly consistent storage, so it matches an object you just wrote. It runs over properties declared with filtering mode simple or full and accepts up to 10 conditions by default (raisable per keyset). Reference a declared property by its name, not its path, and combine conditions with && and ||. It shares the same expression language as filter, so only one of the two can be sent per call.

1

Filter with filter​

filter runs over properties declared with filtering mode full and is evaluated against eventually consistent storage, so a very recent write may not be matched yet. Reference a declared property by its name, not its path, and combine conditions with && and ||. It shares the same expression language as filterFast, so only one of the two can be sent per call.

1

Page through results with cursor​

Pass no cursor on the first call. Take next.cursor from the response and pass it back as cursor on the next call. Stop when next.hasNext is false.

1

Set entity​

Replaces an entity in full (PUT). Send the complete set of fields, any field you omit is cleared. className and classLevel are immutable after creation and cannot be sent. Refer to optimistic concurrency with ETags for ifMatchesEtag. For a partial update, use Update entity.

Method(s)​

1func setEntity(
2 id: String,
3 classVersion: Int,
4 status: String? = nil,
5 payload: JSONCodable? = nil,
6 ifMatchesEtag: String? = nil,
7 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
8 completion: ((Result<PubNubDataSyncEntity, Error>) -> Void)?
9)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Entity identifier.
classVersion *
Type: Int
Default:
n/a
Version of the entity class schema.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The update succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncEntity. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "course-swift-basics",
5 "entityClass": "course",
6 "entityClassVersion": 1,
7 "entityClassLevel": "SubKey",
8 "status": "published",
9 "payload": {"title": "Swift Basics", "lessonCount": 30, "isPublished": true, "summary": "An introduction to Swift for new developers"},
10 "createdAt": "2026-07-13T09:15:00.000Z",
11 "updatedAt": "2026-07-13T13:00:00.000Z",
12 "expiresAt": "2026-08-14T00:00:00.000Z",
13 "eTag": "UvWxYzAbCdEfGh"
14 }
15}

Update entity​

Applies a partial update to an entity with raw JSON Patch operations. Refer to partial update for the operation model.

Method(s)​

1func updateEntity(
2 id: String,
3 operations: [PubNubDataSyncPatchOperation],
4 ifMatchesEtag: String? = nil,
5 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
6 completion: ((Result<PubNubDataSyncEntity, Error>) -> Void)?
7)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Entity identifier.
operations *
Type: [PubNubDataSyncPatchOperation]
Default:
n/a
One or more JSON Patch operations. Must contain at least one item.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The patch succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncEntity. Pass nil to ignore the result.

Use a JSON Pointer that starts with /payload/ to target payload fields, or a root pointer (for example /status) to target a top-level field.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "course-swift-basics",
5 "entityClass": "course",
6 "entityClassVersion": 1,
7 "entityClassLevel": "SubKey",
8 "status": "published",
9 "payload": {"title": "Swift Basics (2026)", "lessonCount": 32, "isPublished": true},
10 "createdAt": "2026-07-13T09:15:00.000Z",
11 "updatedAt": "2026-07-13T13:05:00.000Z",
12 "expiresAt": "2026-08-14T00:00:00.000Z",
13 "eTag": "WxYzAbCdEfGhIj"
14 }
15}

Other examples​

Combine patch operations, and guard the write with ifMatchesEtag​

A single updateEntity call can mix add, replace, remove, move, copy, and test, in one operations array. All operations in the call apply together or not at all. Add ifMatchesEtag (the eTag from a prior read) to reject the patch with a 412 if the entity changed since you read it, instead of silently overwriting a concurrent change.

1

Remove entity​

Deletes an entity by id.

Method(s)​

1func removeEntity(
2 id: String,
3 ifMatchesEtag: String? = nil,
4 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
5 completion: ((Result<Void, Error>) -> Void)?
6)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Entity identifier.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The delete succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds Void. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200
3}

Relationships​

A relationship links two entities and carries its own payload. In the running example, the enrollment relationship links student-alice to course-swift-basics.

Relationships are instances of the relationship classes you define on your keyset. A relationship class declares the cardinality the service enforces (one-to-one, one-to-many, or many-to-many) and, optionally, which entity class each side must belong to. Use Create a new relationship class to declare a class, and Get relationship class by name and version to read it back.

Create relationship​

Creates a relationship between two entities. The relationship class's cardinality (one-to-one, one-to-many, or many-to-many) is enforced on create. A relationship that violates its class's cardinality is rejected with a 409.

Method(s)​

1func createRelationship(
2 className: String,
3 classVersion: Int,
4 entityAId: String,
5 entityBId: String,
6 id: String? = nil,
7 status: String? = nil,
8 payload: JSONCodable? = nil,
9 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
10 completion: ((Result<PubNubDataSyncRelationship, Error>) -> Void)?
11)
* required
ParameterDescription
id
Type: String
Default:
server-generated
Relationship identifier. Omit to let the server generate a UUID. Max 255 characters.
className *
Type: String
Default:
n/a
Name of the relationship class this instance belongs to. Set at creation and immutable afterward.
entityAId *
Type: String
Default:
n/a
Identifier of the first linked entity. Immutable after creation.
entityBId *
Type: String
Default:
n/a
Identifier of the second linked entity. Immutable after creation.
classVersion *
Type: Int
Default:
n/a
Version of the relationship class schema. Sent to the service as relationshipClassVersion.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncRelationship. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice-course-swift-basics",
5 "relationshipClass": "enrollment",
6 "relationshipClassVersion": 1,
7 "entityAId": "student-alice",
8 "entityBId": "course-swift-basics",
9 "status": "active",
10 "payload": {"role": "student", "completedLessons": 0, "isActive": true},
11 "createdAt": "2026-07-13T09:20:00.000Z",
12 "updatedAt": "2026-07-13T09:20:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "YzAbCdEfGhIjKl"
15 }
show all 16 lines

Get relationship​

Returns a single relationship by id.

Method(s)​

1func getRelationship(
2 id: String,
3 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
4 completion: ((Result<PubNubDataSyncRelationship, Error>) -> Void)?
5)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Relationship identifier.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncRelationship. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice-course-swift-basics",
5 "relationshipClass": "enrollment",
6 "relationshipClassVersion": 1,
7 "entityAId": "student-alice",
8 "entityBId": "course-swift-basics",
9 "status": "active",
10 "payload": {"role": "student", "completedLessons": 0, "isActive": true},
11 "createdAt": "2026-07-13T09:20:00.000Z",
12 "updatedAt": "2026-07-13T09:20:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "YzAbCdEfGhIjKl"
15 }
show all 16 lines

Get all relationships​

Returns a paginated list of relationships within a class. The className parameter is required. Filter by entityAId or entityBId to list a specific entity's links. For pagination, filtering, and sorting, refer to sorting and pagination.

Method(s)​

1func getRelationships(
2 className: String,
3 classVersion: Int? = nil,
4 entityAId: String? = nil,
5 entityBId: String? = nil,
6 cursor: String? = nil,
7 limit: Int? = nil,
8 filterFast: String? = nil,
9 filter: String? = nil,
10 sort: [PubNub.DataSyncSortField] = [],
11 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
12 completion: ((Result<(relationships: [PubNubDataSyncRelationship], next: PubNubDataSyncPage?), Error>) -> Void)?
13)
* required
ParameterDescription
className *
Type: String
Default:
n/a
Name of the relationship class to list.
classVersion
Type: Int
Default:
all versions
Relationship class version to list. Omit to list relationships across every version of the class.
entityAId
Type: String
Default:
n/a
List only relationships whose first entity is this id.
entityBId
Type: String
Default:
n/a
List only relationships whose second entity is this id.
cursor
Type: String
Default:
n/a
Opaque pagination cursor. Omit for the first page.
limit
Type: Int
Default:
20
Maximum number of relationships per page. Max 100.
filterFast
Type: String
Default:
n/a
Filter expression evaluated against strongly consistent storage, so it reflects the latest writes. Accepts up to 10 conditions by default (raisable per keyset), over properties declared with filtering mode simple or full. Cannot be combined with filter.
filter
Type: String
Default:
n/a
Filter expression evaluated against eventually consistent storage, so results can briefly lag writes. Supports the full expression language, over properties declared with filtering mode full. Cannot be combined with filterFast.
sort
Type: [PubNub.DataSyncSortField]
Default:
[]
Order results. Each PubNub.DataSyncSortField names a property and sets ascending (default true).
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a tuple of the relationships array and the optional next page. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": [
4 {
5 "id": "alice-course-swift-basics",
6 "relationshipClass": "enrollment",
7 "relationshipClassVersion": 1,
8 "entityAId": "student-alice",
9 "entityBId": "course-swift-basics",
10 "status": "active",
11 "payload": {"role": "student", "completedLessons": 0, "isActive": true},
12 "createdAt": "2026-07-13T09:20:00.000Z",
13 "updatedAt": "2026-07-13T09:20:00.000Z",
14 "expiresAt": "2026-08-13T00:00:00.000Z",
15 "eTag": "YzAbCdEfGhIjKl"
show all 23 lines

Other examples​

Pass entityAId to list relationships where the entity is on the first side of the link.

1

Pass entityBId instead of entityAId to list relationships where the entity is on the second side of the link.

1

Filter with filterFast​

filterFast is evaluated against strongly consistent storage, so it matches an object you just wrote. It runs over properties declared with filtering mode simple or full and accepts up to 10 conditions by default (raisable per keyset). Reference a declared property by its name, not its path. It shares the same expression language as filter, so only one of the two can be sent per call.

1

Filter with filter​

filter runs over properties declared with filtering mode full and is evaluated against eventually consistent storage, so a very recent write may not be matched yet. Reference a declared property by its name, not its path. It shares the same expression language as filterFast, so only one of the two can be sent per call.

1

Page through results with cursor​

Pass no cursor on the first call. Take next.cursor from the response and pass it back as cursor on the next call. Stop when next.hasNext is false.

1

Set relationship​

Replaces a relationship in full (PUT). Send the complete set of fields, any field you omit is cleared. The linked entities are immutable, so setRelationship doesn't take entityAId or entityBId, there is nothing to resend. Refer to optimistic concurrency with ETags for ifMatchesEtag. For a partial update, use Update relationship.

Method(s)​

1func setRelationship(
2 id: String,
3 classVersion: Int,
4 status: String? = nil,
5 payload: JSONCodable? = nil,
6 ifMatchesEtag: String? = nil,
7 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
8 completion: ((Result<PubNubDataSyncRelationship, Error>) -> Void)?
9)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Relationship identifier.
classVersion *
Type: Int
Default:
n/a
Version of the relationship class schema. Sent to the service as relationshipClassVersion.
status
Type: String
Default:
n/a
Free-form lifecycle status. Max 100 characters.
payload
Type: JSONCodable
Default:
n/a
Free-form JSON object holding your application data.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The update succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncRelationship. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice-course-swift-basics",
5 "relationshipClass": "enrollment",
6 "relationshipClassVersion": 1,
7 "entityAId": "student-alice",
8 "entityBId": "course-swift-basics",
9 "status": "active",
10 "payload": {"role": "student", "completedLessons": 12, "isActive": true, "grade": "A"},
11 "createdAt": "2026-07-13T09:20:00.000Z",
12 "updatedAt": "2026-07-13T14:00:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "AbCdEfGhIjKlMn"
15 }
show all 16 lines

Update relationship​

Applies a partial update to a relationship with raw JSON Patch operations. Refer to partial update for the operation model.

Method(s)​

1func updateRelationship(
2 id: String,
3 operations: [PubNubDataSyncPatchOperation],
4 ifMatchesEtag: String? = nil,
5 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
6 completion: ((Result<PubNubDataSyncRelationship, Error>) -> Void)?
7)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Relationship identifier.
operations *
Type: [PubNubDataSyncPatchOperation]
Default:
n/a
One or more JSON Patch operations. Must contain at least one item.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The patch succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds a PubNubDataSyncRelationship. Pass nil to ignore the result.

Use a JSON Pointer that starts with /payload/ to target payload fields, or a root pointer (for example /status) to target a top-level field.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200,
3 "data": {
4 "id": "alice-course-swift-basics",
5 "relationshipClass": "enrollment",
6 "relationshipClassVersion": 1,
7 "entityAId": "student-alice",
8 "entityBId": "course-swift-basics",
9 "status": "active",
10 "payload": {"role": "student", "completedLessons": 24, "isActive": false},
11 "createdAt": "2026-07-13T09:20:00.000Z",
12 "updatedAt": "2026-07-13T14:05:00.000Z",
13 "expiresAt": "2026-08-13T00:00:00.000Z",
14 "eTag": "CdEfGhIjKlMnOp"
15 }
show all 16 lines

Remove relationship​

Deletes a relationship by id.

Method(s)​

1func removeRelationship(
2 id: String,
3 ifMatchesEtag: String? = nil,
4 custom requestConfig: PubNub.RequestConfiguration = PubNub.RequestConfiguration(),
5 completion: ((Result<Void, Error>) -> Void)?
6)
* required
ParameterDescription
id *
Type: String
Default:
n/a
Relationship identifier.
ifMatchesEtag
Type: String
Default:
n/a
The eTag from a prior read. The delete succeeds only if it still matches, otherwise the server returns 412.
custom
Type: PubNub.RequestConfiguration
Default:
PubNub.RequestConfiguration()
Per-request overrides for the PubNub configuration or network session. Refer to request configuration for details.
completion *
Type: Closure
Default:
n/a
Receives the Result of the call. On success it holds Void. Pass nil to ignore the result.

Sample code​

Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
1

Response​

1{
2 "status": 200
3}

Real-time updates​

DataSync objects can publish create, update, and delete events that you receive in real time with the onDataSync listener. Create a subscription for the object's channel, assign onDataSync on the Subscription, a SubscriptionSet, or the PubNub client, and call subscribe(), as described in Add DataSync listener.

1

Each event names the change in change (entityCreated, entityUpdated, entityDeleted, relationshipCreated, relationshipUpdated, or relationshipDeleted), identifies the object kind in kind, and carries the object state in entity or relationship. For a delete event, removed carries the id, the class details, and the deletedAt timestamp. A change the SDK doesn't recognize arrives as unknown, with the raw metadata and payload attached.

kind names the object kind, while the state always arrives in one of the two containers:

Change tokindState arrives in
A useruserPubNubDataSyncEntityEvent (entity)
A channelchannelPubNubDataSyncEntityEvent (entity)
An entitycustomPubNubDataSyncEntityEvent (entity)
A membershipmembershipPubNubDataSyncRelationshipEvent (relationship)
A relationshipcustomPubNubDataSyncRelationshipEvent (relationship)

Dispatch on kind rather than on which container is populated, because PubNubDataSyncEntityEvent is shared by three kinds and PubNubDataSyncRelationshipEvent by two. Read object on either container to get the state narrowed to PubNubDataSyncUser, PubNubDataSyncChannel, PubNubDataSyncMembership, or the general entity and relationship types. className tells you the specific class within a kind, for example which subclass of User an event belongs to.

Where each event is delivered​

The channels that receive an event depend on the changed object. A relationship or membership never publishes on a channel named after its own id:

Change toOn createOn update or delete
A userThe user's idThe user's id, plus the id of every entity, user, or channel connected to it by a relationship or membership
A channelThe channel's idThe channel's id, plus the id of every entity, user, or channel connected to it by a relationship or membership
An entityThe entity's idThe entity's id, plus the id of every entity, user, or channel connected to it by a relationship or membership
A membershipBoth the userId and the channelId of the membershipSame as create
A relationshipBoth the entityAId and the entityBId of the relationshipSame as create
Update and delete also fan out to connected objects

An update or delete on a user, channel, or entity is also delivered on the id channel of every other object connected to it by a relationship or membership, in either direction, at the time of the change. A client subscribed to a connected object's channel receives the event too, even though that object itself did not change. A create does not fan out this way, because nothing can be connected to a brand new object yet.

The connected channels are entity, user, and channel ids. Relationships and memberships never get an id channel of their own, so they never appear in this fan-out as a channel name.

So to see memberships appear and disappear for Alice, subscribe to alice rather than the membership id. A client subscribed to both sides of the same link receives the change twice, once per channel. Deduplicate create and update events on the object's id and updatedAt, and delete events on id and deletedAt.

For a membership event, relationship.entityAId is the channel id and relationship.entityBId is the user id. The service sends these as channelId and userId, and the SDK maps them onto the A and B sides so that one PubNubDataSyncRelationship type serves both memberships and your own relationships. The narrowed PubNubDataSyncMembership surfaces them as channelId and userId again.

Projection channels​

Each projection declared on the class gets its own event, published to its own channel, and carrying only that projection's view of the payload:

ProjectionChannelPayload
__default__ (the base projection)The object's own id, for example course-swift-basicsThe fields tagged __default__
Any named projection, for example admin__<projection>__<id>, for example __admin__course-swift-basicsThe fields tagged with that projection

A projection name must start with a letter or digit, so a leading __ marks a projection channel, with __default__ as the only exception.

Avoid ids that start with two underscores

A projection channel is named __<projection>__<id>, so an object id in that form can collide with another object's projection channel. The service doesn't reject such ids today, so avoid any id that starts with __.

Filtering applies to payload and to status: each is included in a given projection's event only if the class declares it under that projection, falling back to __default__ when the class never declares status. id, eTag, createdAt, updatedAt, and expiresAt are never filtered. Every projection's event carries them unchanged.

So one change to an object whose class declares a stats projection publishes two events, and a client subscribed only to course-swift-basics never sees the stats-only fields. The SDK builds the channel name for you: call subscription() for the base projection, or subscription(projection:) with the projection name for a named one.

1

If the class declares no properties at all there is nothing to filter, so a single unfiltered event is published to the object's own id channel.

Projection channels need channel grants

Publishing to __<projection>__<id> is an ordinary channel publish, and it isn't gated by the dataSyncProjections entries in a token. Use Access Manager channels grants to control who can subscribe to a projection channel. Anyone who can subscribe there receives the restricted fields. Refer to grant structured data access.

Delete events are never filtered by a projection.

Events are off by default and are enabled per class in the Admin Portal. Refer to enabling events for how to turn them on, and receiving events for the listener flow.

Was this page useful?

Last updated on