---
source_url: https://www.pubnub.com/docs/data-storage/structured-data/grant-structured-data-access
title: Grant DataSync access
updated_at: 2026-09-30T07:20:08.000Z
---

# Grant DataSync access

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

This guide shows you how to issue Access Manager tokens that authorize DataSync operations and optionally scope field-level access with projection grants. Token issuance is a server-side operation. Your client application then uses the token to make DataSync requests.

The examples issue one token for each of three roles in a marketplace:

* A catalog service that creates and deletes the objects.
* A shopper, Alice, who reads products through the `public` projection.
* A support agent who reads Alice's `admin`-only fields.

They use the classes from [Define an entity class](https://www.pubnub.com/docs/data-storage/structured-data/define-entity-class.md) and the objects from [Create entities and relationships](https://www.pubnub.com/docs/data-storage/structured-data/create-entities-and-relationships.md).

## Before you start

* Access Manager must be enabled on your keyset. Refer to [Enable DataSync](https://www.pubnub.com/docs/data-storage/structured-data/enable-structured-data.md).
* You need server-side signing credentials. Do not issue tokens from a client.
* Refer to [Access control and permissions management](https://www.pubnub.com/docs/security/access-control/overview.md) for the general Access Manager model.

## DataSync resource types

DataSync adds three resource types: `datasync:entities`, `datasync:relationships`, and `datasync:memberships`. User and channel entities reuse the existing `users` and `channels` resource types.

:::warning Use users, not uuids, for DataSync user entities
DataSync checks the `users` resource type for user entities. A token that only grants `uuids` permissions does not authorize DataSync operations on the corresponding user entity. Refer to [DataSync access control](https://www.pubnub.com/docs/data-storage/structured-data/access-control.md#permissions-and-resource-types).
:::

## Grant a service write access

The catalog service creates, reads, and deletes each object by exact ID.

### JavaScript

```javascript
const catalogToken = await pubnub.grantToken({
    ttl: 15,
    authorizedUserId: 'catalog-service',
    resources: {
        dataSync: {
            entities: { 'product-sneaker-42': { create: true, get: true, delete: true } },
            relationships: { 'wishlist-alice-sneaker': { create: true, get: true, delete: true } },
            memberships: { 'membership-alice-summer-sale': { create: true, get: true, delete: true } },
        },
        users: { 'user-alice': { create: true, get: true, delete: true } },
        channels: { 'channel-summer-sale': { create: true, get: true, delete: true } },
    },
})
```

### C#

```csharp
PNResult<PNAccessManagerTokenResult> catalogGrant = await pubnub.GrantToken()
    .TTL(15)
    .AuthorizedUserId("catalog-service")
    .Resources(new PNTokenResources
    {
        DataSync = new PNDataSyncTokenScopes
        {
            Entities = new Dictionary<string, PNTokenAuthValues> { { "product-sneaker-42", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
            Relationships = new Dictionary<string, PNTokenAuthValues> { { "wishlist-alice-sneaker", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
            Memberships = new Dictionary<string, PNTokenAuthValues> { { "membership-alice-summer-sale", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
        },
        Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
        Channels = new Dictionary<string, PNTokenAuthValues> { { "channel-summer-sale", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
    })
    .ExecuteAsync();
```

A token without a projection grant reads and writes the `__default__` view. The catalog service can't create a user with `email`, because `email` belongs only to the `admin` projection. The request fails with a `403` and error code `DS-0202`. Set admin-only fields from your server.

## Grant a shopper read access

Alice reads her own user, her memberships, and every product, and subscribes to product updates. Pattern grants cover every ID that matches the regular expression, so `product-.*` covers `product-sneaker-42` and any product added later. The projection grant makes every product read return the `public` view.

### JavaScript

```javascript
const aliceToken = await pubnub.grantToken({
    ttl: 15,
    authorizedUserId: 'user-alice',
    resources: {
        users: { 'user-alice': { get: true, update: true } },
        channels: {
            'channel-summer-sale': { get: true, read: true },
            '__public__product-sneaker-42': { read: true },
        },
    },
    patterns: {
        dataSync: {
            entities: { 'product-.*': { get: true } },
            memberships: { 'membership-alice-.*': { get: true } },
        },
    },
    dataSyncProjections: {
        patterns: { entities: { 'product-.*': 'public' } },
    },
})
```

### C#

```csharp
PNResult<PNAccessManagerTokenResult> aliceGrant = await pubnub.GrantToken()
    .TTL(15)
    .AuthorizedUserId("user-alice")
    .Resources(new PNTokenResources
    {
        Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Get = true, Update = true } } },
        Channels = new Dictionary<string, PNTokenAuthValues>
        {
            { "channel-summer-sale", new PNTokenAuthValues { Get = true, Read = true } },
            { "__public__product-sneaker-42", new PNTokenAuthValues { Read = true } },
        },
    })
    .Patterns(new PNTokenPatterns
    {
        DataSync = new PNDataSyncTokenScopes
        {
            Entities = new Dictionary<string, PNTokenAuthValues> { { "product-.*", new PNTokenAuthValues { Get = true } } },
            Memberships = new Dictionary<string, PNTokenAuthValues> { { "membership-alice-.*", new PNTokenAuthValues { Get = true } } },
        },
    })
    .DataSyncProjections(new PNDataSyncProjections
    {
        Patterns = new PNDataSyncProjectionScope
        {
            Entities = new Dictionary<string, string> { { "product-.*", "public" } },
        },
    })
    .ExecuteAsync();
```

User entities use the `users` resource type and channels use `channels`. Reading a user or channel entity uses `get`. `read` on a channel gates subscribe access.

Alice can read products but can't create them. A create with this token fails with a `403`.

:::warning ID channels carry the default view
An object's ID channel, such as `product-sneaker-42`, carries the `__default__` view in every event, whatever projection the subscriber's token has. It also carries events about the entities linked to that object. That's why Alice gets `read` on `__public__product-sneaker-42` rather than on `product-sneaker-42`: the ID channel would send her `stock`. Grant `read` on an ID channel only to clients that may see the `__default__` view of the object and of everything linked to it. Refer to [Events](https://www.pubnub.com/docs/data-storage/structured-data/events.md).
:::

## Grant a support agent the admin projection

The support agent reads Alice's `email`, which only the `admin` projection includes. The token assigns `admin` to `user-alice` and grants `read` on the projection channel `__admin__user-alice`, so the agent also receives `email` changes in real time.

### JavaScript

```javascript
const supportToken = await pubnub.grantToken({
    ttl: 15,
    authorizedUserId: 'support-agent',
    resources: {
        users: { 'user-alice': { get: true } },
        channels: { '__admin__user-alice': { read: true } },
    },
    dataSyncProjections: {
        resources: { users: { 'user-alice': 'admin' } },
    },
})
```

### C#

```csharp
PNResult<PNAccessManagerTokenResult> supportGrant = await pubnub.GrantToken()
    .TTL(15)
    .AuthorizedUserId("support-agent")
    .Resources(new PNTokenResources
    {
        Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Get = true } } },
        Channels = new Dictionary<string, PNTokenAuthValues> { { "__admin__user-alice", new PNTokenAuthValues { Read = true } } },
    })
    .DataSyncProjections(new PNDataSyncProjections
    {
        Resources = new PNDataSyncProjectionScope
        {
            Users = new Dictionary<string, string> { { "user-alice", "admin" } },
        },
    })
    .ExecuteAsync();
```

A read with this token returns only the fields in the `admin` projection, so `getUser` for `user-alice` returns `email` without `name` or `display_name`. Permission on `user-alice` doesn't cover the projection channel. Grant `read` on `__admin__user-alice` separately.

Refer to [Grant token (JavaScript)](https://www.pubnub.com/docs/sdks/javascript/api-reference/access-manager.md#grant-token) and [Grant token (C#)](https://www.pubnub.com/docs/sdks/c-sharp/api-reference/access-manager.md#grant-token) for the full parameter reference.

## Choose permissions per operation

| Operation | Resource type | Permission |
| --- | --- | --- |
| Read a DataSync object | `datasync:entities`, `datasync:relationships`, `datasync:memberships`, `users`, `channels` | `get` |
| Create a DataSync object | Same | `create` |
| Replace or patch a DataSync object | Same | `update` |
| Delete a DataSync object | Same | `delete` |
| Subscribe to an entity's ID channel or projection channel for events | `channels` | `read` |

Last updated at: 2026-09-30T07:20:08.000Z
