> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription Types

> Real-time update payloads

Subscription types represent the payloads received when subscribing to real-time updates via WebSocket.

## ContentUpdate

Payload for content subscription updates.

```graphql theme={null}
type ContentUpdate {
  contentId: ID!
  content: Content
  resolvedRef: ResolvedPackageRef!
  action: String!
  timestamp: DateTime!
}
```

| Field         | Type                | Description                                 |
| ------------- | ------------------- | ------------------------------------------- |
| `contentId`   | ID!                 | ID of the updated content                   |
| `content`     | Content             | Full content object (null if exceeds 100KB) |
| `resolvedRef` | ResolvedPackageRef! | Package IDs for caching                     |
| `action`      | String!             | `"CREATED"`, `"UPDATED"`, or `"DELETED"`    |
| `timestamp`   | DateTime!           | When the update occurred                    |

### Handling ContentUpdate

```javascript theme={null}
subscription.on('data', (update) => {
  if (update.action === 'DELETED') {
    removeContent(update.contentId);
    return;
  }

  // Content may be null if payload exceeds 100KB
  if (update.content) {
    refreshContent(update.content, update.resolvedRef);
  } else {
    // Fetch separately
    fetchContent(update.contentId).then(content => {
      refreshContent(content, update.resolvedRef);
    });
  }
});
```

## ComponentUpdate

Payload for component subscription updates.

```graphql theme={null}
type ComponentUpdate {
  componentId: ID!
  component: Component
  resolvedRef: ResolvedPackageRef!
  action: String!
  timestamp: DateTime!
}
```

| Field         | Type                | Description                                             |
| ------------- | ------------------- | ------------------------------------------------------- |
| `componentId` | ID!                 | ID of the updated component                             |
| `component`   | Component           | Full component object (null if exceeds 100KB)           |
| `resolvedRef` | ResolvedPackageRef! | Package IDs for caching                                 |
| `action`      | String!             | `"CREATED"`, `"UPDATED"`, `"PUBLISHED"`, or `"DELETED"` |
| `timestamp`   | DateTime!           | When the update occurred                                |

## PackageUpdate

Payload for package subscription updates.

```graphql theme={null}
type PackageUpdate {
  packageId: ID!
  resolvedRef: ResolvedPackageRef!
  action: String!
  timestamp: DateTime!
}
```

| Field         | Type                | Description                                             |
| ------------- | ------------------- | ------------------------------------------------------- |
| `packageId`   | ID!                 | ID of the updated package                               |
| `resolvedRef` | ResolvedPackageRef! | Package IDs for caching                                 |
| `action`      | String!             | `"CREATED"`, `"UPDATED"`, `"PUBLISHED"`, or `"DELETED"` |
| `timestamp`   | DateTime!           | When the update occurred                                |

## PreviewUpdate

Payload for preview subscription updates.

```graphql theme={null}
type PreviewUpdate {
  preview: PreviewResult!
  action: String!
  timestamp: DateTime!
}
```

| Field       | Type           | Description                  |
| ----------- | -------------- | ---------------------------- |
| `preview`   | PreviewResult! | Component or content preview |
| `action`    | String!        | `"UPDATED"` or `"DELETED"`   |
| `timestamp` | DateTime!      | When the update occurred     |

### PreviewResult Union

```graphql theme={null}
union PreviewResult = ComponentPreview | ContentPreview
```

## ComponentPreview

Preview data for a component.

```graphql theme={null}
type ComponentPreview {
  componentId: ID!
  componentName: String!
  component: Component
  resolvedRef: ResolvedPackageRef!
}
```

| Field           | Type                | Description                            |
| --------------- | ------------------- | -------------------------------------- |
| `componentId`   | ID!                 | Component ID                           |
| `componentName` | String!             | Component name for display/recents     |
| `component`     | Component           | Component data (null if exceeds 100KB) |
| `resolvedRef`   | ResolvedPackageRef! | Package IDs for caching                |

## ContentPreview

Preview data for content.

```graphql theme={null}
type ContentPreview {
  contentId: ID!
  contentName: String!
  contentTypeName: String!
  content: Content
  resolvedRef: ResolvedPackageRef!
}
```

| Field             | Type                | Description                           |
| ----------------- | ------------------- | ------------------------------------- |
| `contentId`       | ID!                 | Content ID                            |
| `contentName`     | String!             | Content name for display/recents      |
| `contentTypeName` | String!             | Content type name for display/recents |
| `content`         | Content             | Content data (null if exceeds 100KB)  |
| `resolvedRef`     | ResolvedPackageRef! | Package IDs for caching               |

## Handling Preview Updates

```javascript theme={null}
subscription.on('data', (update) => {
  const { preview, action } = update;

  if (action === 'DELETED') {
    if (preview.__typename === 'ComponentPreview') {
      removeComponentPreview(preview.componentId);
    } else {
      removeContentPreview(preview.contentId);
    }
    return;
  }

  // Handle component preview
  if (preview.__typename === 'ComponentPreview') {
    if (preview.component) {
      refreshComponentPreview(preview.component, preview.resolvedRef);
    } else {
      fetchComponent(preview.componentId).then(component => {
        refreshComponentPreview(component, preview.resolvedRef);
      });
    }
  }

  // Handle content preview
  if (preview.__typename === 'ContentPreview') {
    if (preview.content) {
      refreshContentPreview(preview.content, preview.resolvedRef);
    } else {
      fetchContent(preview.contentId).then(content => {
        refreshContentPreview(content, preview.resolvedRef);
      });
    }
  }
});
```

## 100KB Payload Limit

AWS WebSocket has a payload limit. When data exceeds 100KB:

1. The `content` or `component` field will be `null`
2. The `resolvedRef` field is always included
3. Use the ID to fetch the full data separately

```javascript theme={null}
if (!update.content) {
  // Payload exceeded 100KB, fetch separately
  const content = await fetchContent(update.contentId);
  refreshContent(content, update.resolvedRef);
}
```

## Related

* [Subscriptions](/graphql/subscriptions/overview) - How to set up WebSocket subscriptions
* [Resolved Package](/graphql/types/resolved-package) - Package resolution types
