XEP-0060: Publish-Subscribe

This specification defines an XMPP protocol extension for generic publish-subscribe functionality. The protocol enables XMPP entities to create nodes (topics) at a pubsub service and publish information at those nodes; an event notification (with or without payload) is then broadcasted to all entities that have subscribed to the node. Pubsub therefore adheres to the classic Observer design pattern and can serve as the foundation for a wide variety of applications, including news feeds, content syndication, rich presence, geolocation, workflow systems, network management systems, and any other application that requires event notifications.


NOTICE: The protocol defined herein is a Draft Standard of the XMPP Standards Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.


Document Information

Series: XEP
Number: 0060
Publisher: XMPP Standards Foundation
Status: Draft
Type: Standards Track
Version: 1.11
Last Updated: 2008-03-05
Approving Body: XMPP Council
Dependencies: XMPP Core, XEP-0004, XEP-0030, XEP-0068, XEP-0082, XEP-0131
Supersedes: None
Superseded By: None
Short Name: pubsub
XML Schema for pubsub namespace: <http://www.xmpp.org/schemas/pubsub.xsd>
XML Schema for pubsub#errors namespace: <http://www.xmpp.org/schemas/pubsub-errors.xsd>
XML Schema for pubsub#event namespace: <http://www.xmpp.org/schemas/pubsub-event.xsd>
XML Schema for pubsub#owner namespace: <http://www.xmpp.org/schemas/pubsub-owner.xsd>
Wiki Page: <http://wiki.jabber.org/index.php/Publish-Subscribe (XEP-0060)>


Author Information

Peter Millard

See Author Note

Peter Saint-Andre

JabberID: stpeter@jabber.org
URI: https://stpeter.im/

Ralph Meijer

Email: ralphm@ik.nu
JabberID: ralphm@ik.nu


Legal Notices

Copyright

This XMPP Extension Protocol is copyright (c) 1999 - 2008 by the XMPP Standards Foundation (XSF).

Permissions

Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the "Specification"), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.

Disclaimer of Warranty

## NOTE WELL: This Specification is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. In no event shall the XMPP Standards Foundation or the authors of this Specification be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification. ##

Limitation of Liability

In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising out of the use or inability to use the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.

IPR Conformance

This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which may be found at <http://www.xmpp.org/extensions/ipr-policy.shtml> or obtained by writing to XSF, P.O. Box 1641, Denver, CO 80201 USA).

Discussion Venue

The preferred venue for discussion of this document is the Standards discussion list: <http://mail.jabber.org/mailman/listinfo/standards>.

Errata may be sent to <editor@xmpp.org>.

Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the XMPP Standards Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this document has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.

Conformance Terms

The following keywords as used in this document are to be interpreted as described in RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".


Table of Contents


1. Introduction
    1.1. Overview
    1.2. How It Works
2. Glossary
3. Requirements
4. Preliminaries
    4.1. Affiliations
    4.2. Subscription States
    4.3. Event Types
    4.4. Node Types
    4.5. Node Access Models
    4.6. Addressing
       4.6.1. JID
       4.6.2. JID+NodeID
5. Entity Use Cases
    5.1. Discover Features
    5.2. Discover Nodes
    5.3. Discover Node Information
    5.4. Discover Node Meta-Data
    5.5. Discover Items for a Node
    5.6. Retrieve Subscriptions
    5.7. Retrieve Affiliations
6. Subscriber Use Cases
    6.1. Subscribe to a Node
       6.1.1. Request
       6.1.2. Success Case
       6.1.3. Error Cases
         6.1.3.1. JIDs Do Not Match
         6.1.3.2. Presence Subscription Required
         6.1.3.3. Not in Roster Group
         6.1.3.4. Not on Whitelist
         6.1.3.5. Payment Required
         6.1.3.6. Anonymous Subscriptions Not Allowed
         6.1.3.7. Subscription Pending
         6.1.3.8. Blocked
         6.1.3.9. Subscriptions Not Supported
         6.1.3.10. Node Has Moved
         6.1.3.11. Node Does Not Exist
       6.1.4. Approval Required
       6.1.5. Configuration Required
       6.1.6. Multiple Subscriptions
       6.1.7. Sending the Last Published Item
    6.2. Unsubscribe from a Node
       6.2.1. Request
       6.2.2. Success Case
       6.2.3. Error Cases
         6.2.3.1. No Subscription ID
         6.2.3.2. No Such Subscriber
         6.2.3.3. Insufficient Privileges
         6.2.3.4. Node Does Not Exist
         6.2.3.5. Bad Subscription ID
    6.3. Configure Subscription Options
       6.3.1. Advertising Support
       6.3.2. Request
       6.3.3. Success Case
       6.3.4. Error Cases
         6.3.4.1. Insufficient Privileges
         6.3.4.2. No Such Subscriber
         6.3.4.3. NodeID Required
         6.3.4.4. Subscription ID Required
         6.3.4.5. Invalid Subscription ID
         6.3.4.6. Subscription Options Not Supported
         6.3.4.7. Node Does Not Exist
       6.3.5. Form Submission
       6.3.6. Form Processing
         6.3.6.1. Success
         6.3.6.2. Failure
       6.3.7. Subscribe and Configure
    6.4. Retrieve Items from a Node
       6.4.1. Permissions
       6.4.2. Requesting All Items
       6.4.3. Returning All Items
       6.4.4. Returning the Last Published Item
       6.4.5. Returning Notifications Only
       6.4.6. Requesting Some Items
       6.4.7. Error Cases
         6.4.7.1. Subscription ID Required
         6.4.7.2. Invalid Subscription ID
         6.4.7.3. Entity Not Subscribed
         6.4.7.4. Persistent Items Not Supported
         6.4.7.5. Item Retrieval Not Supported
         6.4.7.6. Presence Subscription Required
         6.4.7.7. Not in Roster Group
         6.4.7.8. Not on Whitelist
         6.4.7.9. Payment Required
         6.4.7.10. Blocked
         6.4.7.11. Node Does Not Exist
7. Publisher Use Cases
    7.1. Publish an Item to a Node
       7.1.1. Request
       7.1.2. Success Case
         7.1.2.1. Notification With Payload
         7.1.2.2. Notification Without Payload
         7.1.2.3. Inclusion of Subscription ID
       7.1.3. Error Cases
         7.1.3.1. Insufficient Privileges
         7.1.3.2. Item Publication Not Supported
         7.1.3.3. Node Does Not Exist
         7.1.3.4. Payload Too Big
         7.1.3.5. Bad Payload
         7.1.3.6. Request Does Not Match Configuration
       7.1.4. Automatic Node Creation
       7.1.5. Publishing Options
    7.2. Delete an Item from a Node
       7.2.1. Request
       7.2.2. Success Case
         7.2.2.1. Delete And Notify
         7.2.2.2. Inclusion of Subscription ID
       7.2.3. Error Cases
         7.2.3.1. Insufficient Privileges
         7.2.3.2. Node Does Not Exist
         7.2.3.3. NodeID Required
         7.2.3.4. Item or ItemID Required
         7.2.3.5. Persistent Items Not Supported
         7.2.3.6. Item Deletion Not Supported
8. Owner Use Cases
    8.1. Create a Node
       8.1.1. General Considerations
       8.1.2. Create a Node With Default Configuration
       8.1.3. Create and Configure a Node
    8.2. Configure a Node
       8.2.1. Request
       8.2.2. Success Case
       8.2.3. Error Cases
         8.2.3.1. Node Configuration Not Supported
         8.2.3.2. Insufficient Privileges
         8.2.3.3. NodeID Required
         8.2.3.4. No Configuration Options
       8.2.4. Form Submission
       8.2.5. Form Processing
         8.2.5.1. Success
         8.2.5.2. Failure
         8.2.5.3. Success With Notifications
    8.3. Request Default Configuration Options
       8.3.1. Request
       8.3.2. Success Case
       8.3.3. Error Cases
         8.3.3.1. Node Configuration Not Supported
         8.3.3.2. Default Configuration Retrieval Not Supported
       8.3.4. Requesting Collection Node Configuration
    8.4. Delete a Node
       8.4.1. Request
       8.4.2. Success Case
       8.4.3. Error Cases
         8.4.3.1. Insufficient Privileges
         8.4.3.2. Root Collection Node
         8.4.3.3. Node Does Not Exist
    8.5. Purge All Node Items
       8.5.1. Request
       8.5.2. Success Case
       8.5.3. Error Cases
         8.5.3.1. Node Purging Not Supported
         8.5.3.2. Insufficient Privileges
         8.5.3.3. Node Does Not Persist Items
         8.5.3.4. Node Does Not Exist
    8.6. Manage Subscription Requests
    8.7. Process Pending Subscription Requests
       8.7.1. Request
       8.7.2. Success Case
       8.7.3. Error Cases
         8.7.3.1. Ad-Hoc Commands Not Supported
         8.7.3.2. Get-Pending Not Supported
         8.7.3.3. Insufficient Privileges
         8.7.3.4. Node Does Not Exist
       8.7.4. Per-Node Request
    8.8. Manage Subscriptions
       8.8.1. Retrieve Subscriptions List
         8.8.1.1. Request
         8.8.1.2. Success Case
         8.8.1.3. Error Cases
       8.8.2. Modify Subscriptions
         8.8.2.1. Request
         8.8.2.2. Success Case
         8.8.2.3. Error Cases
         8.8.2.4. Multiple Simultaneous Modifications
       8.8.3. Delete a Subscriber
       8.8.4. Notifying Subscribers
    8.9. Manage Affiliations
       8.9.1. Retrieve Affiliations List
         8.9.1.1. Request
         8.9.1.2. Success Case
         8.9.1.3. Error Cases
       8.9.2. Modify Affiliation
         8.9.2.1. Request
         8.9.2.2. Success Case
         8.9.2.3. Error Cases
         8.9.2.4. Multiple Simultaneous Modifications
       8.9.3. Delete an Entity
       8.9.4. Notifying Entities
9. Collection Nodes
    9.1. Subscribe to a Collection Node
    9.2. Root Collection Node
    9.3. Create a New Collection Node
    9.4. Create a Node Associated with a Collection
       9.4.1. Request
       9.4.2. Success Case
       9.4.3. Error Cases
         9.4.3.1. Only One Collection Node
         9.4.3.2. Insufficient Privileges
         9.4.3.3. No More Nodes
         9.4.3.4. Leaf Node
         9.4.3.5. Node Does Not Exist
    9.5. Associate an Existing Node with a Collection
    9.6. Disassociate a Node from a Collection
    9.7. Generating Publish Notifications for Collections
10. IM Account Integration
    10.1. Auto-Subscribe
       10.1.1. Account Owner
       10.1.2. Presence Subscriber
       10.1.3. Presence Sharer
    10.2. Filtered Notifications
11. Feature Summary
12. Error Conditions
13. Implementation Notes
    13.1. Notification Triggers
    13.2. Intended Recipients for Notifications
    13.3. Handling Notification-Related Errors
    13.4. Presence-Based Delivery of Events
    13.5. Not Routing Events to Offline Storage
    13.6. Including a Message Body
    13.7. Node ID and Item ID Uniqueness
    13.8. Item Caching
    13.9. Batch Processing
    13.10. Auto-Subscribing Owners and Publishers
    13.11. Authorizing Subscription Requests (Pending Subscribers)
    13.12. Notification of Subscription State Changes
    13.13. NodeID Semantics
    13.14. Multiple Node Discovery
    13.15. Inclusion of SHIM Headers
    13.16. Associating Events and Payloads with the Generating Entity
    13.17. Chaining
    13.18. Time-Based Subscriptions (Leases)
    13.19. Content-Based Pubsub Systems
    13.20. Singleton Nodes
14. Internationalization Considerations
    14.1. Field Labels
15. Security Considerations
16. IANA Considerations
17. XMPP Registrar Considerations
    17.1. Protocol Namespaces
    17.2. Service Discovery Category/Type
    17.3. Service Discovery Features
    17.4. Field Standardization
       17.4.1. pubsub#subscribe_authorization FORM_TYPE
       17.4.2. pubsub#subscribe_options FORM_TYPE
       17.4.3. pubsub#node_config FORM_TYPE
       17.4.4. pubsub#meta-data FORM_TYPE
       17.4.5. pubsub#publish-options FORM_TYPE
    17.5. SHIM Headers
    17.6. URI Query Types
18. XML Schemas
    18.1. http://jabber.org/protocol/pubsub
    18.2. http://jabber.org/protocol/pubsub#errors
    18.3. http://jabber.org/protocol/pubsub#event
    18.4. http://jabber.org/protocol/pubsub#owner
19. Acknowledgements
20. Author Note
Notes
Revision History


1. Introduction

1.1 Overview

As Jabber/XMPP technologies have matured, the need for a generic publish-subscribe ("pubsub") mechanism has arisen in a number of domains. These include (but are not limited to): news feeds, content syndication, extended presence, geolocation, avatar management, shared bookmarks, auction and trading systems, workflow systems, network management systems, NNTP gateways, profile management, and any other application that requires event notifications.

In all of these domains, it is desirable for data communication to follow the classic "publish-subscribe" or "observer" design pattern: a person or application publishes information, and an event notification (with or without payload) is broadcasted to all authorized subscribers. In general, the relationship between the publisher and subscriber is mediated by a service that receives publication requests, broadcasts event notifications to subscribers, and enables privileged entities to manage lists of people or applications that are authorized to publish or subscribe. In most pubsub services, the focal point for publication and subscription is a "topic" or "node" to which publishers send data and from which subscribers receive notifications. Additionally, some nodes may also maintain a history of events and provide other services that supplement the pure pubsub model.

This document defines a single, cohesive, generic protocol that all forms of pubsub can use. While compliant implementations are not required to implement all of the features defined herein, this document addresses most use cases that may be requested of a pubsub service. (For information about which features are required and which are recommended or optional, consult the Feature Summary.) Other specifications may define "subsets" or "profiles" of publish-subscribe for use in specialized contexts, but such profiles are out of scope for this document.

1.2 How It Works

This specification is large. However, the basic idea behind pubsub is rather simple (see Publish an Item to a Node):

  1. An entity publishes information to a node at a publish-subscribe service.
  2. The pubsub service pushes a notification to all entities that are authorized to learn about the published information.

Perhaps the most popular application of pubsub-like functionality is content syndication, which has become familiar from the RSS and Atom (RFC 4287 [1]) feeds associated with weblogs, news sites, and other frequently-updated information available on the Internet. Consider the example of a weblog published by <hamlet@denmark.lit>. When Hamlet writes a new weblog entry, his blogging software publishes the entry to a pubsub node hosted at <pubsub.shakespeare.lit>:

Example 1. Publisher Publishes a New Weblog Entry

<iq type='set'
    from='hamlet@denmark.lit/blogbot'
    to='pubsub.shakespeare.lit'
    id='pub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='princely_musings'>
      <item>
        <entry xmlns='http://www.w3.org/2005/Atom'>
          <title>Soliloquy</title>
          <summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
          </summary>
          <link rel='alternate' type='text/html'
                href='http://denmark.lit/2003/12/13/atom03'/>
          <id>tag:denmark.lit,2003:entry-32397</id>
          <published>2003-12-13T18:30:02Z</published>
          <updated>2003-12-13T18:30:02Z</updated>
        </entry>
      </item>
    </publish>
  </pubsub>
</iq>
    

So that is the "pub" part of publish-subscribe.

Now the pubsub service notifies all the subscribers about the new blog entry:

Example 2. Service Notifies Subscribers

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        [ ... ENTRY ... ]
      </item>
    </items>
  </event>
</message>

<message from='pubsub.shakespeare.lit' to='bernardo@denmark.lit' id='bar'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        [ ... ENTRY ... ]
      </item>
    </items>
  </event>
</message>

<message from='pubsub.shakespeare.lit' to='horatio@denmark.lit' id='baz'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        [ ... ENTRY ... ]
      </item>
    </items>
  </event>
</message>

<message from='pubsub.shakespeare.lit' to='bard@shakespeare.lit' id='fez'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        [ ... ENTRY ... ]
      </item>
    </items>
  </event>
</message>
    

Here is an even simpler example: a transient node that sends only notifications without a payload:

Example 3. A Transient Notification

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='elsinore/doorbell'/>
  </event>
</message>
    

Naturally, the entities involved may need to complete other use cases in order to enable full pubsub functionality -- for example, the publisher may need to create the node (see Create a Node) and subscribers may need to sign up for notifications (see Subscribe to a Node). These use cases are fully described in the remainder of this document. (For information about which features are required and which are recommended or optional, consult the Feature Summary.)

2. Glossary

The following terms are used throughout this document to refer to elements, objects, or actions that occur in the context of a pubsub service. (Note: Some of these terms are specified in greater detail within the body of this document.)

Table 1: Publish-Subscribe Terms

Authorize Access ModelA node access model under which an entity can subscribe only through having a subscription request approved by a node owner (subscription requests are accepted but only provisionally) and only subscribers may retrieve items.
Address(1) A JID as defined in XMPP Core [2], or (2) the combination of a JID and a Service Discovery [3] node.
Collection NodeA type of node that contains nodes and/or other collections but no published items. Collections make it possible to represent hierarchial node structures.
EntityA JID-addressable Jabber entity (client, service, application, etc.).
EventA change in the state of a node.
Instant NodeA node whose NodeID is automatically generated by a pubsub service.
ItemAn XML fragment which is published to a node, thereby generating an event.
ItemIDA unique identifier for an item in the context of a specific node.
Leaf NodeA type of node that contains published items only. It is NOT a container for other nodes.
NodeA virtual location to which information can be published and from which event notifications and/or payloads can be received (in other pubsub systems, this may be labelled a "topic").
NodeIDThe unique identifier for a node within the context of a pubsub service. The NodeID is either supplied by the node creator or generated by the pubsub service (if the node creator requests an Instant Node). The NodeID MAY have semantic meaning, but such meaning is OPTIONAL.
NotificationA message sent to a subscriber informing them of an event.
OutcastAn entity that is disallowed from subscribing or publishing to a node.
OwnerThe manager of a node, of which there may be more than one; often but not necessarily the node creator.
PayloadThe full data associated with an event rather than just the event notification itself.
Open Access ModelA node access model under which any entity may subscribe and retrieve items without approval.
Personal EventingA simplified subset of Publish-Subscribe for use in the context of instant messaging and presence applications, whereby each IM user's JID is a virtual pubsub service; for details, see Personal Eventing via Pubsub [4].
Presence Access ModelA node access model under which any entity that is subscribed to the owner's presence with a subscription of type "from" or "both" (see RFC 3921 [5]) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems.
PublisherAn entity that is allowed to publish items to a node.
Pubsub ServiceAn XMPP server or component that adheres to the protocol defined herein.
Roster Access ModelA node access model under which any entity that is subscribed to the owner's presence and in the specified roster group(s) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems.
SubscriberAn entity that is subscribed to a node.
Whitelist Access ModelA node access model under which an entity may subscribe and retrieve items only if explicitly allowed to do so by the node owner (subscription requests from unauthorized entities are rejected).

3. Requirements

Requirements for a pubsub service can be driven by end-user needs as well as the needs of other components and services which can use the service. First, a pubsub service implemented using Jabber MUST provide the basic features that implement a pure publish-subscribe pattern:

Some of the possible uses of a Jabber-based pubsub service will require other features, but these features are OPTIONAL and therefore not mandatory for compliance with this specification. However, if these features are implemented, they MUST adhere to the protocol described herein in to be compliant. These features include:

4. Preliminaries

4.1 Affiliations

To manage permissions, the protocol defined herein uses a hierarchy of affiliations, similiar to those introduced in Multi-User Chat [6].

All affiliations MUST be based on a bare JID (<localpart@domain.tld> or <domain.tld>) instead of a full JID (<localpart@domain.tld/resource> or <domain.tld/resource>).

Support for the "owner" and "none" affiliations is REQUIRED. Support for all other affiliations is RECOMMENDED. For each non-required affiliation supported by an implementation, it SHOULD return a service discovery feature of "name-affiliation" where "name" is the name of the affiliation, such as "member", "outcast", or "publisher" (see the Feature Summary). Particular kinds of pubsub services MAY enforce additional requirements (e.g., requiring support for a given non-required affiliation or for all affiliations).

Table 2: Affiliations and their Privileges

Affiliation Subscribe Retrieve Items Publish Item Delete Item Configure Node Delete Node Purge Node
Owner Yes Yes Yes Yes Yes Yes Yes
Publisher Yes Yes Yes Yes No No Yes/No *
Member Yes Yes No No No No No
None Yes No No No No No No
Outcast No No No No No No No

* Note: A service MAY allow any publisher to delete any item once it has been published to that node instead of allowing only the original publisher to remove it (this is discoverable via the "pubsub#delete-any" feature).

The ways in which an entity changes its affiliation with a node are well-defined. Typically, action by an owner is required to make an affiliation state transition. Affiliation changes and their triggering actions are specified in the following table.

Table 3: Affiliation State Chart

  Outcast None Member Publisher Owner
Outcast -- Owner removes ban Owner adds entity to member list Owner adds entity to publisher list Owner adds entity to owner list
None Owner bans entity -- Owner adds entity to member list Owner adds entity to publisher list Owner adds entity to owner list
Member Owner bans entity Owner removes entity from member list -- Owner adds entity to publisher list Owner adds entity to owner list
Publisher Owner bans entity Owner removes entity from publisher list n/a -- Owner adds entity to owner list
Owner n/a Owner resigns n/a n/a --

4.2 Subscription States

Subscriptions to a node may exist in several states.

Table 4: Subscription States

Subscription State Description
None The node MUST NOT send event notifications or payloads to the Entity.
Pending An entity has requested to subscribe to a node and the request has not yet been approved by a node owner. The node MUST NOT send event notifications or payloads to the entity while it is in this state.
Unconfigured An entity has subscribed but its subscription options have not yet been configured. The node MAY send event notifications or payloads to the entity while it is in this state. The service MAY timeout unconfigured subscriptions.
Subscribed An entity is subscribed to a node. The node MUST send all event notifications (and, if configured, payloads) to the entity while it is in this state (subject to subscriber configuration and content filtering).

4.3 Event Types

The requirements for the publish-subscribe protocol imply that there are two major dimensions along which we can measure events: persistent vs. transient, and pure notification vs. inclusion of payload. An implementation SHOULD enable an owner to configure a node along both of these dimensions.

No matter whether a node is configured for persistent or transient events, a service MAY cache the last item published to the node, in which case it SHOULD send that item to subscribers based on configuration of the "send_last_published_item" option (see the Item Caching section of this document); if the service supports the "http://jabber.org/protocol/pubsub#last-published" feature then the value of this option MUST default to "on_sub_and_presence" (though the service SHOULD allow the node owner to override the default).

A pubsub service MUST validate publish requests against the configuration of the node along both of these dimensions (see the Publish An Item to a Node section of this document for the relevant error conditions).

The node configuration and desired event type determine whether an item must be provided by the publisher, whether the item includes a payload in the publish request or notification, and whether an item ID is provided by the publisher or generated by the pubsub service. We can summarize the relevant rules as follows:

Table 5: Items, Payloads, and Item IDs

 Notification-Only Node *Payload-Included Node *
Persistent Node ** Publish request MUST include an <item/> element, which MAY be empty or MAY contain a payload; even if publish request contains a payload, pubsub service MUST NOT include the payload in notifications; if publish request did not include item ID, pubsub service MUST generate item ID Publish request MUST include an <item/> element, which SHOULD contain a payload; if publish request included a payload, notifications MUST include the payload; if publish request did not include item ID, pubsub service MUST generate item ID
Transient Node ** Publish request MUST NOT include an <item/> element; payload is not included in publish request or notifications, although notifications MUST include an empty <items/> element; item ID is neither provided in publish request nor generated by pubsub service Publish request MUST include an <item/> element, which SHOULD contain a payload; if publish request included a payload, notifications MUST include the payload; pubsub service MAY generate an item ID

* Note: Whether the node is notification-only or includes payloads is determined by the "pubsub#deliver_payloads" configuration field.

** Note: Whether the node is persistent or transient is determined by the "pubsub#persist_items" configuration field.

4.4 Node Types

There are two types of nodes:

Table 6: Node Types

Node Type Description
Leaf A node that contains published items only. It is NOT a container for other nodes. This is the most common node type.
Collection A node that contains nodes and/or other collections but no published items. Collections make it possible to represent hierarchial node structures.

4.5 Node Access Models

In order to make node creation simpler for clients, we define the following node access models (in order of openness):

Table 7: Node Access Models

Access Model Description
Open Any entity may subscribe to the node (i.e., without the necessity for subscription approval) and any entity may retrieve items from the node (i.e., without being subscribed); this SHOULD be the default access model for generic pubsub services.
Presence Any entity with a subscription of type "from" or "both" may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems (see RFC 3921).
Roster Any entity in the specified roster group(s) may subscribe to the node and retrieve items from the node; this access model applies mainly to instant messaging systems (see RFC 3921).
Authorize The node owner must approve all subscription requests, and only subscribers may retrieve items from the node.
Whitelist An entity may subscribe or retrieve items only if on a whitelist managed by the node owner. The node owner MUST automatically be on the whitelist. In order to add entities to the whitelist, the node owner SHOULD use the protocol specified in the Manage Affiliated Entities section of this document, specifically by setting the affiliation to "member".

A generic publish-subscribe implementation SHOULD support all of the defined access models, although specialized publish-subscribe implementations MAY support only a subset of the access models. Which access models are provided in a particular deployment is a matter of service provisioning (e.g., some restricted deployments may wish to lock down permissions so that only the "authorize" and "whitelist" access models are provided, or even only the "whitelist" access model).

A node creator or owner can override the default access model by specifying an appropriate value for the 'pubsub#access_model' configuration field (see the Create a Node With Default Configuration and Configure a Node sections of this document).

4.6 Addressing

If a pubsub node is addressable, it MUST be addressable either (1) as a JID or (2) as the combination of a JID and a node. [7]

4.6.1 JID

If a pubsub node is addressable as a JID, the NodeID MUST be the resource identifier, and MUST NOT be specified by the "user" portion (node identifier) of the JID (e.g. "domain.tld/NodeID" and "user@domain.tld/NodeID" are allowed; "NodeID@domain.tld" is not allowed [8]). JID addressing SHOULD be used when interacting with a pubsub node using a protocol that does not support the node attribute. For example, when a service makes it possible for entities to subscribe to nodes via presence, it would address nodes as JIDs. If a pubsub node is addressable as a JID, the pubsub service MUST ensure that the NodeID conforms to the Resourceprep profile of Stringprep as described in RFC 3920.

Consider the following example, in which the pubsub service is located at the hostname pubsub.shakespeare.lit.

Example 4. Node addressed as domain.tld/NodeID

<iq to='pubsub.shakespeare.lit/news announcements'>
  ...
</iq>
      

Now consider the following example, in which the pubsub service is located at pubsub@shakespeare.lit.

Example 5. Node addressed as user@domain.tld/NodeID

<iq to='pubsub@shakespeare.lit/news announcements'>
  ...
</iq>
      

4.6.2 JID+NodeID

If a pubsub node is addressable as a JID plus node, the NodeID MUST be the value of both the Service Discovery 'node' attribute and the pubsub 'node' attribute; i.e., for discovery purposes, a pubsub node is equivalent to a Service Discovery node. If a pubsub node is addressable as a JID plus node, the pubsub service SHOULD ensure that the NodeID conforms to the Resourceprep profile of Stringprep as described in RFC 3920.

Consider the following example, in which the (virtual) pubsub service is located at hamlet@denmark.lit.

Example 6. Node addressed as JID+NodeID

<iq to='hamlet@denmark.lit'>
  <query node='princely_musings'/>
</iq>
      

5. Entity Use Cases

This section defines the use cases for and protocols to be used by any entity that wishes to interact with a publish-subscribe service, mainly focused on Service Discovery use cases.

5.1 Discover Features

A service MUST respond to service discovery information requests qualified by the 'http://jabber.org/protocol/disco#info' namespace. The "disco#info" result returned by a pubsub service MUST indicate the identity of the service and indicate which pubsub features are supported.

Example 7. Entity Queries Pubsub Service Regarding Supported Features

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='feature1'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
    

Example 8. Pubsub Service Returns Set of Supported Features

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='feature1'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity category='pubsub' type='service'/>
    <feature var='http://jabber.org/protocol/pubsub'/>
  </query>
</iq>
    

The possible pubsub features are noted throughout this document and have been registered as described in the XMPP Registrar Considerations section of this document. For information regarding which features are required, recommended, and optional, see the Feature Summary section of this document.

5.2 Discover Nodes

If a service implements a hierarchy of nodes (by means of Collection Nodes), it MUST also enable entities to discover the nodes in that hierarchy by means of the Service Discovery protocol, subject to the recommendations in XEP-0030 regarding large result sets (for which Jabber Search [9] or some other protocol SHOULD be used). The following examples show the use of service discovery in discovering the nodes available at a hierarchical pubsub service.

Note: Node hierarchies and collection nodes are OPTIONAL. For details, refer to the NodeID Semantics and Collection Nodes sections of this document.

In the first example, an entity sends a service discovery items ("disco#items") request to the root node (i.e., the service itself), which is a Collection Node:

Example 9. Entity asks service for all first-level nodes

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='nodes1'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>
    

Example 10. Service returns all first-level nodes

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='nodes1'>
  <query xmlns='http://jabber.org/protocol/disco#items'>
    <item jid='pubsub.shakespeare.lit'
          node='blogs'
          name='Weblog updates'/>
    <item jid='pubsub.shakespeare.lit'
          node='news'
          name='News and announcements'/>
  </query>
</iq>
    

In the second example, an entity sends a disco#items request to one of the first-level nodes, which is also a collection node:

Example 11. Entity requests second-level nodes

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='nodes2'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='blogs'/>
</iq>
    

Example 12. Service returns second-level nodes

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='nodes2'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='blogs'>
    <item jid='pubsub.shakespeare.lit'
          node='princely_musings'/>
    <item jid='pubsub.shakespeare.lit'
          node='kingly_ravings'/>
    <item jid='pubsub.shakespeare.lit'
          node='starcrossed_stories'/>
    <item jid='pubsub.shakespeare.lit'
          node='moorish_meanderings'/>
  </query>
</iq>
    

If a node is a leaf node rather than a collection node and items have been published to the node, the service MAY return one <item/> element for each published item as described in the Discover Items for a Node section of this document, however such items MUST NOT include a 'node' attribute (since they are published items, not nodes).

5.3 Discover Node Information

A pubsub service MUST allow entities to query individual nodes for the information associated with that node. The Service Discovery protocol MUST be used to discover this information. The "disco#info" result MUST include an identity with a category of "pubsub" and a type of either "leaf" or "collection".

Note: If a node has an identity type of "leaf", then it MUST NOT contain other nodes or collections (only items); if a node has an identity type of "collection", then it MUST NOT contain items (only other nodes or collections).

Example 13. Entity queries collection node for information

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='info2'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='blogs'/>
</iq>
    

Example 14. Service responds with identity of pubsub/collection

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='meta1'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='blogs'>
    ...
    <identity category='pubsub' type='collection'/>
    ...
  </query>
</iq>
    

Example 15. Entity queries leaf node for information

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='princely_musings'/>
</iq>
    

Example 16. Service responds with identity of pubsub/leaf

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    ...
    <identity category='pubsub' type='leaf'/>
    ...
  </query>
</iq>
    

5.4 Discover Node Meta-Data

The "disco#info" result MAY include detailed meta-data about the node, encapsulated in the Data Forms [10] format as described in Service Discovery Extensions [11], where the data form context is specified by including a FORM_TYPE of "http://jabber.org/protocol/pubsub#meta-data" in accordance with Field Standardization for Data Forms [12]. If meta-data is provided, it SHOULD include values for all configured options as well as "automatic" information such as the node creation date, a list of publishers, and the like.

Example 17. Entity queries a node for information

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='meta1'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='princely_musings'/>
</iq>
    

Example 18. Service responds with information and meta-data

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='meta1'>
  <query xmlns='http://jabber.org/protocol/disco#info'
         node='princely_musings'/>
    <identity category='pubsub' type='leaf'/>
    <feature var='http://jabber.org/protocol/pubsub'/>
    <x xmlns='jabber:x:data' type='result'>
      <field var='FORM_TYPE' type='hidden'>
        <value>http://jabber.org/protocol/pubsub#meta-data</value>
      </field>
      <field var='pubsub#type' label='Payload type'>
        <value>http://www.w3.org/2005/Atom</value>
      </field>
      <field var='pubsub#creator' label='Node creator'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#creation_date' label='Creation date'>
        <value>2003-07-29T22:56Z</value>
      </field>
      <field var='pubsub#title' label='A short name for the node'>
        <value>Princely Musings (Atom)</value>
      </field>
      <field var='pubsub#description' label='A description of the node'>
        <value>Updates for Hamlet&apos;s Princely Musings weblog.</value>
      </field>
      <field var='pubsub#language' label='Default language'>
        <value>en</value>
      </field>
      <field var='pubsub#contact' label='People to contact with questions'>
        <value>bard@shakespeare.lit</value>
      </field>
      <field var='pubsub#owner' label='Node owners'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#publisher' label='Publishers to this node'>
        <value>hamlet@denmark.lit</value>
      </field>
      <field var='pubsub#num_subscribers' label='Number of subscribers to this node'>
        <value>1066</value>
      </field>
    </x>
  </query>
</iq>
    

Note: Node meta-data can be set in many ways. Some of it is based on node configuration (e.g., the owner's JID) whereas some of it may be dynamic (e.g., the number of subscribers). Any static information to be provided in the node meta-data SHOULD be provided as fields in the node configuration form.

Much of the meta-data provided about a node maps directly to selected Dublin Core Metadata Initiative (DCMI) [13] meta-data attributes; specifically:

Table 8: Dublin Core Meta-Data Mapping

Pubsub FieldDublin Core Meta-Data Attribute
pubsub#creation_dateDate [14]
pubsub#creatorCreator
pubsub#descriptionDescription
pubsub#languageLanguage
pubsub#publisherPublisher
pubsub#titleTitle
pubsub#typeType [15]

5.5 Discover Items for a Node

To discover the published items which exist on the service for a specific node, an entity MAY send a "disco#items" request to the node itself, and the service MAY return each item as a Service Discovery <item/> element. The 'name' attribute of each Service Discovery item MUST contain its ItemID and the item MUST NOT possess a 'node' attribute. This ItemID MAY then be used to retrieve the item using the protocol defined in the Retrieve Items from a Node section of this document.

Example 19. Entity requests all of the items for a node

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='items1'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='princely_musings'/>
</iq>

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='princely_musings'>
    <item jid='pubsub.shakespeare.lit' name='368866411b877c30064a5f62b917cffe'/>
    <item jid='pubsub.shakespeare.lit' name='3300659945416e274474e469a1f0154c'/>
    <item jid='pubsub.shakespeare.lit' name='4e30f35051b7b8b42abe083742187228'/>
    <item jid='pubsub.shakespeare.lit' name='ae890ac52d0df67ed7cfdf51b644e901'/>
  </query>
</iq>
    

5.6 Retrieve Subscriptions

An entity may want to query the service to retrieve its subscriptions for all nodes at the service. Support for this feature ("retrieve-subscriptions") is RECOMMENDED.

In order to make the request, the requesting entity MUST send an IQ-get whose <pubsub/> child contains an empty <subscriptions/> element with no attributes.

Example 20. Entity requests all current subscriptions

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
</iq>
    

If the service returns a list of subscriptions, it MUST return all subscriptions for all JIDs that match the bare JID (<localpart@domain.tld> or <domain.tld>) portion of the 'from' attribute on the request.

For each subscription, a <subscription/> element is returned specifying the NodeID, the JID that is affiliated (which MAY include a resource, depending on how the entity subscribed), and the current subscription state. If subscription identifiers are supported by the service, the 'subid' attribute MUST be present as well.

Example 21. Service returns all current subscriptions

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions>
      <subscription node='node1' jid='francisco@denmark.lit' subscription='subscribed'/>
      <subscription node='node2' jid='francisco@denmark.lit' subscription='subscribed'/>
      <subscription node='node5' jid='francisco@denmark.lit' subscription='unconfigured'/>
      <subscription node='node6' jid='francisco@denmark.lit' subscription='pending'/>
    </subscriptions>
  </pubsub>
</iq>
    

If the requesting entity has no subscriptions, the pubsub service MUST return an empty <subscriptions/> element.

Example 22. No subscriptions

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
</iq>
    

If the service does not support subscriptions retrieval, the service MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-subscriptions".

Example 23. Subscriptions retrieval not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='retrieve-subscriptions'/>
  </error>
</iq>
    

An entity MAY also request its subscriptions at a specific node (e.g., if it has subscriptions with multiple SubIDs) by including a 'node' attribute on the <subscriptions/> element.

Example 24. Entity requests current subscriptions from a specific node

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='subscriptions2'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions node='princely_musings'/>
  </pubsub>
</iq>
    

The service would then return only the subscriptions to that node.

Example 25. Service returns all current subscriptions

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions node='princely_musings'>
      <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='123-abc'/>
      <subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='004-yyy'/>
    </subscriptions>
  </pubsub>
</iq>
    

5.7 Retrieve Affiliations

An entity may want to query the service to retrieve its affiliations for all nodes at the service. Support for this feature ("retrieve-affiliations") is RECOMMENDED.

In order to make the request, the requesting entity includes an empty <affiliations/> element with no attributes.

Example 26. Entity requests all current affiliations

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
</iq>
    

If the service returns a list of affiliations, it MUST return all affiliations for all JIDs that match the bare JID (<localpart@domain.tld> or <domain.tld>) portion of the 'from' attribute on the request.

For each affiliation, an <affiliation/> element is returned containing the NodeID and the affiliation state (owner, publisher, or outcast).

Example 27. Service replies with all current affiliations

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations>
      <affiliation node='node1' affiliation='owner'/>
      <affiliation node='node2' affiliation='publisher'/>
      <affiliation node='node5' affiliation='outcast'/>
      <affiliation node='node6' affiliation='owner'/>
    </affiliations>
  </pubsub>
</iq>
    

If the requesting entity has no affiliations, the pubsub service MUST return an empty <affiliations/> element.

Example 28. No affiliations

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
</iq>
    

If the service does not support affiliations retrieval, the service MUST respond with a <feature-not-implemented/> error, specifying a pubsub-specific error condition of <unsupported/> and a feature of "retrieve-affiliations".

Example 29. Affiliations retrieval not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='affil1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <affiliations/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='retrieve-affiliations'/>
  </error>
</iq>
    

6. Subscriber Use Cases

This section defines the use cases for and protocols to be used by potential and actual subscribers. (Note: The Implementation Notes section of this document describes many important factors and business rules which a pubsub service MUST observe. In addition, the examples throughout assume the existence of a separate pubsub component and include any relevant 'from' addresses as stamped by a server or network edge.)

6.1 Subscribe to a Node

6.1.1 Request

When a Jabber entity wishes to subscribe to a node, it sends a subscription request to the pubsub service. The subscription request is an IQ-set where the <pubsub/> element contains one and only one <subscribe/> element. The <subscribe/> element SHOULD possess a 'node' attribute specifying the node to which the entity wishes to subscribe. The <subscribe/> element MUST also possess a 'jid' attribute specifying the exact XMPP address to be used as the subscribed JID -- often a bare JID (<localpart@domain.tld> or <domain.tld>) or full JID (<localpart@domain.tld/resource> or <domain.tld/resource>).

Here is an example of a subscription request.

Example 30. Entity subscribes to a node

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
</iq>
      

6.1.2 Success Case

If the subscription request is successfully processed, the server MUST inform the requesting entity that it is now subscribed (which MAY include a service-generated SubID).

Example 31. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription
        node='princely_musings'
        jid='francisco@denmark.lit'
        subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
        subscription='subscribed'/>
  </pubsub>
</iq>
      

6.1.3 Error Cases

There are several reasons why the subscription request might fail:

  1. The bare JID portions of the JIDs do not match.
  2. The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.
  3. The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.
  4. The node has an access model of "whitelist" and the requesting entity is not on the whitelist.
  5. The service requires payment for subscriptions to the node.
  6. The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.
  7. The requesting entity has a pending subscription.
  8. The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).
  9. The node does not support subscriptions.
  10. The node has moved.
  11. The node does not exist.

These error cases are described more fully in the following sections.

6.1.3.1 JIDs Do Not Match

If the specified JID is a bare JID or full JID, the service MUST at a minimum check the bare JID portion against the bare JID portion of the 'from' attribute on the received IQ request to make sure that the requesting entity has the same identity as the JID which is being requested to be added to the subscriber list.

If the bare JID portions of the JIDs do not match as described above and the requesting entity does not have some kind of admin or proxy privilege as defined by the implementation, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <invalid-jid/>.

Example 32. JIDs do not match

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='bernardo@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-jid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

Note: An implementation MAY enable the service administrator to configure a list of entities that are excluded from this check; those entities may be considered "trusted proxies" that are allowed to subscribe on behalf of other entities. In the same way, implementations MAY enable blacklisting of entities that are not allowed to perform specific operations (such as subscribing or creating nodes).

6.1.3.2 Presence Subscription Required

For nodes with an access model of "presence", if the requesting entity is not subscribed to the owner's presence then the pubsub service MUST respond with a <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <presence-subscription-required/>.

Example 33. Entity is not authorized to create a subscription (presence subscription required)

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <presence-subscription-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.1.3.3 Not in Roster Group

For nodes with an access model of "roster", if the requesting entity is not in one of the authorized roster groups then the pubsub service MUST respond with a <not-authorized/> error, which SHOULD also include a pubsub-specific error condition of <not-in-roster-group/>.

Example 34. Entity is not authorized to create a subscription (not in roster group)

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <not-in-roster-group xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.1.3.4 Not on Whitelist

For nodes with a node access model of "whitelist", if the requesting entity is not on the whitelist then the service MUST return a <not-allowed/> error, specifying a pubsub-specific error condition of <closed-node/>.

Example 35. Node has whitelist access model

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <closed-node xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.1.3.5 Payment Required

Commercial deployments may wish to link subscribers to a database of paying customers. If the subscriber needs to provide payment in order to subscribe to the node (e.g., if the subscriber is not in the customer database or the customer's account is not paid up), the service SHOULD return a <payment-required/> error to the subscriber.

Example 36. Payment is required for a subscription

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <payment-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
        

6.1.3.6 Anonymous Subscriptions Not Allowed

Some XMPP servers may allow authentication using SASL ANONYMOUS; however, because the resulting entity is unstable (the assigned JID may not be owned by the same principal in a persistent manner), a service MAY prevent anonymous entities from subscribing to nodes and SHOULD use service discovery to determine if an entity has an identity of "account/anonymous". If a requesting entity is anonymous but the service does not allow anonymous entities to subscribe, the service SHOULD return a <forbidden/> error to the subscriber.

Example 37. Requesting entity is anonymous

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='anonymous@denmark.lit/foo'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='anonymous@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
    

6.1.3.7 Subscription Pending

If the requesting entity has a pending subscription, the service MUST return a <not-authorized/> error to the subscriber, specifying a pubsub-specific error condition of <pending-subscription/>.

Example 38. Requesting entity has pending subscription

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <pending-subscription xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.1.3.8 Blocked

If the requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast), the service MUST return a <forbidden/> error to the subscriber.

Example 39. Requesting entity is blocked

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
        

6.1.3.9 Subscriptions Not Supported

If the node does not allow entities to subscribe, the service SHOULD return a <feature-not-implemented/> error to the subscriber, specifying a pubsub-specific error condition of <unsupported/> and a feature of "subscribe".

Example 40. Subscribing not supported

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='subscribe'/>
  </error>
</iq>
        

6.1.3.10 Node Has Moved

If the node has, the service SHOULD return a <gone/> error (if the node has moved permanently) or a <redirect/> error (if the node has moved temporarily).

Example 41. Node has moved

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
      xmpp:pubsub.shakespeare.lit?;node=some-other-node
    </gone>
  </error>
</iq>
        

6.1.3.11 Node Does Not Exist

If the node does not exist, the service SHOULD return an <item-not-found/> error to the subscriber.

Example 42. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
        

6.1.4 Approval Required

For nodes with an access model of "authorize", subscription requests MUST be approved by one of the node owners; therefore the pubsub service sends a message to the node owner(s) requesting authorization (see the Manage Subscription Requests section of this document). Because the subscription request may or may not be approved, the service MUST return a pending notification to the subscriber.

Example 43. Service replies with pending

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription
        node='princely_musings'
        jid='francisco@denmark.lit'
        subscription='pending'/>
  </pubsub>
</iq>
      

6.1.5 Configuration Required

If the entity must configure its subscription options (see the Configure Subscription Options section of this document) before receiving notifications, the service MUST so inform the entity. It SHOULD do so by returning an IQ-result to the requesting entity with a notation that configuration of subscription options is required.

Example 44. Service replies with success and indicates that subscription configuration is required

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription
        node='princely_musings'
        jid='francisco@denmark.lit'
        subscription='unconfigured'>
      <subscribe-options>
        <required/>
      </subscribe-options>
    </subscription>
  </pubsub>
</iq>
      

Note: The node shall include the <required/> child element only if the subscriber must configure the subscription before receiving any notifications. A service MAY time out subscription requests if configuration is required and a configuration request is not submitted within a reasonable amount of time (which shall be determined by the service or node configuration).

Alternatively, if the service is unable to create the subscription without simultaneous configuration, the service MAY return a <not-acceptable/> error, specifying a pubsub-specific error condition of <configuration-required/>.

Example 45. Service returns error specifying that subscription configuration is required

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe
        node='princely_musings'
        jid='francisco@denmark.lit'/>
    <options node='princely_musings' jid='francisco@denmark.lit'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
        </field>
        <field var='pubsub#deliver'><value>1</value></field>
        <field var='pubsub#digest'><value>0</value></field>
        <field var='pubsub#include_body'><value>false</value></field>
        <field var='pubsub#show-values'>
          <value>chat</value>
          <value>online</value>
          <value>away</value>
        </field>
      </x>
    </options>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <configuration-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
      

If the <required/> element is not included and no error is returned, the subscription takes effect immediately and the entity may configure the subscription at any time (the service MAY indicate that subscription options are supported by including an empty <subscribe-options/> element in the IQ-result, as shown in the following example).

Example 46. Service replies with success and indicates that subscription options are supported but not required

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='sub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription
        node='princely_musings'
        jid='francisco@denmark.lit'
        subscription='unconfigured'>
      <subscribe-options/>
    </subscription>
  </pubsub>
</iq>
      

6.1.6 Multiple Subscriptions

An entity may wish to subscribe using different subscription options, which it can do by subscribing multiple times to the same node. Support for this feature ("multi-subscribe") is OPTIONAL.

If multiple subscriptions for the same JID are allowed, the service MUST use the 'subid' attribute to differentiate between subscriptions for the same entity (therefore the SubID MUST be unique for each node+JID combination and the SubID MUST be present on the entity element any time it is sent to the subscriber). It is NOT RECOMMENDED for clients to generate SubIDs, since collisions might result; therefore a service SHOULD generate the SubID on behalf of the subscriber and MAY overwrite SubIDs if they are provided by subscribers. If the service does not allow multiple subscriptions for the same entity and it receives an additional subscription request, the service MUST return the current subscription state (as if the subscription was just approved).

6.1.7 Sending the Last Published Item

When a subscription request is successfully processed, the service MAY send the last published item to the new subscriber. The message containing this item SHOULD be stamped with extended information qualified by the 'urn:xmpp:delay' namespace (see Delayed Delivery [16]) to indicate it is sent with delayed delivery. (Note that in this example the message notification is sent to the bare JID since that is the subscribed JID.)

Example 47. Service sends last published item

<message from='pubsub.shakespeare.lit' to='francisco@denmark.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        <entry xmlns='http://www.w3.org/2005/Atom'>
          <title>Soliloquy</title>
          <summary>
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
          </summary>
          <link rel='alternate' type='text/html'
                href='http://denmark.lit/2003/12/13/atom03'/>
          <id>tag:denmark.lit,2003:entry-32397</id>
          <published>2003-12-13T18:30:02Z</published>
          <updated>2003-12-13T18:30:02Z</updated>
        </entry>
      </item>
    </items>
  </event>
  <delay xmlns='urn:xmpp:delay' stamp='2003-12-13T23:58:37Z'/>
</message>
      

If the service sends the last published item by default for all nodes (subject to overriding by node configuration), it MUST return a feature of "http://jabber.org/protocol/pubsub#last-published" in its responsess to disco#info requests.

6.2 Unsubscribe from a Node

6.2.1 Request

To unsubscribe from a node, the subscriber sends an IQ-set whose <pubsub/> child contains an <unsubscribe/> element that specifies the node and the subscribed JID.

Example 48. Entity unsubscribes from a node

<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         jid='francisco@denmark.lit'/>
  </pubsub>
</iq>
      

6.2.2 Success Case

If the request can be successfully processed, the service MUST return an IQ result.

Example 49. Service replies with success

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'/>
      

6.2.3 Error Cases

There are several reasons why the unsubscribe request might fail:

  1. The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.
  2. The request does not specify an existing subscriber.
  3. The requesting entity does not have sufficient privileges to unsubscribe the specified JID.
  4. The node does not exist.
  5. The request specifies a subscription ID that is not valid or current.

These error cases are described more fully in the following sections.

6.2.3.1 No Subscription ID

If the requesting entity has multiple subscriptions to the node but does not specify a subscription ID, the service MUST return a <bad-request/> error, which SHOULD also include a pubsub-specific error condition of <subid-required/>.

Example 50. Entity did not specify SubID

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <subid-required xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.2.3.2 No Such Subscriber

If the value of the 'jid' attribute does not specify an existing subscriber, the pubsub service MUST return an error stanza, which SHOULD be <unexpected-request/> and which SHOULD also include a pubsub-specific error condition of <not-subscribed/>.

Example 51. Requesting entity is not a subscriber

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <not-subscribed xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.2.3.3 Insufficient Privileges

If the requesting entity is prohibited from unsubscribing the specified JID, the service MUST return a <forbidden/> error. The service MUST validate that the entity making the request is authorized to unsubscribe the entity. If the subscriber's JID is of the form (<localpart@domain.tld/resource> or <domain.tld/resource>), a service MUST perform this check by comparing the (<localpart@domain.tld> or <domain.tld>) part of the two JIDs to ensure that they match. If the bare JID portions of the JIDs do not match and the requesting entity is not authorized to unsubscribe the JID (e.g., because it is not a service-wide admin or authorized proxy), the service MUST return a <forbidden/> error.

Example 52. Requesting entity is prohibited from unsubscribing entity

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         jid='bard@shakespeare.lit'/>
  </pubsub>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
        

6.2.3.4 Node Does Not Exist

If the node does not exist, the pubsub service MUST return an <item-not-found/> error.

Example 53. Node does not exist

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
        

6.2.3.5 Bad Subscription ID

If a subscription identifier is associated with the subscription, the unsubscribe request MUST include an appropriate 'subid' attribute. If the unsubscribe request includes a SubID but SubIDs are not supported for the node (or the subscriber did not subscribe using a SubID in the first place), the service SHOULD ignore the SubID and simply unsubscribe the entity. If the subscriber originally subscribed with a SubID but the unsubscribe request includes a SubID that is not valid or current for the subscriber, the service MUST return a <not-acceptable/> error, which SHOULD also include a pubsub-specific error condition of <invalid-subid/>.

Example 54. Invalid subscription identifier

<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='unsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     <unsubscribe
         node='princely_musings'
         subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
         jid='francisco@denmark.lit'/>
  </pubsub>
  <error type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-subid xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
        

6.3 Configure Subscription Options

An implementation MAY allow subscribers to configure subscription options. Implementations SHOULD use the Data Forms protocol to accomplish this configuration (however, an out-of-band mechanism such as a web interface could be offered as well).

6.3.1 Advertising Support

If a service supports subscription options it MUST advertise that fact in its response to a "disco#info" query by including a feature whose 'var' attribute is "pubsub#subscription-options".

Example 55. Pubsub service indicates support for subscription options

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='feature1'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    ...
    <feature var='http://jabber.org/protocol/pubsub#subscription-options'/>
    ...
  </query>
</iq>
      

6.3.2 Request

A subscriber requests the subscription options by including an <options/> element inside an IQ-get stanza.

Example 56. Subscriber requests subscription options form

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='options1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'/>
  </pubsub>
</iq>
      

6.3.3 Success Case

If the request can be successfully processed, the service MUST respond with the options.

Example 57. Service responds with the options form

<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='options1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <options node='princely_musings' jid='francisco@denmark.lit'>
      <x xmlns='jabber:x:data' type='form'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
        </field>
        <field var='pubsub#deliver' type='boolean'
               label='Enable delivery?'>
          <value>1</value>
        </field>
        <field var='pubsub#digest' type='boolean'
               label='Receive digest notifications (approx. one per day)?'>
          <value>0</value>
        </field>
        <field var='pubsub#include_body' type='boolean'
               label='Receive message body in addition to payload?'>
          <value>false</value>
        </field>
        <field
            var='pubsub#show-values'
            type='list-multi'
            label='Select the presence types which are
                   allowed to receive notifications'>
          <option label='Want to Chat'><value>chat</value></option>
          <option label='Available'><value>online</value></option>
          <option label='Away'><value>away</value></option>
          <option label='Extended Away'><value>xa</value></option>
          <option label='Do Not Disturb'><value>dnd</value></option>
          <value>chat</value>
          <value>online</value>
        </field>
      </x>
    </options>
  </pubsub>
</iq>
      

Note: The foregoing example shows some (but by no means all) of the possible configuration options that MAY be provided. If an implementation provides these options using the