The RESTful API serves as a common protocol understood by all OpenSocial 0.8-compliant clients and servers. It replaces the November 2007 OpenSocial Data API proposal (which was based on the Google Data APIs).
This API defines a language- and platform- neutral protocol for clients to interact with OpenSocial container servers outside of gadgets on a web page. As a protocol, it is intended to be reasonably easy to implement in any language and on any platform. It should also be usable across a range of clients, from gadgets operating within a web page to servers communicating to synchronize data about a user.
The protocol operates primarily in terms of resources and operations on them. It is defined on top of the HTTP protocol, and uses the standard HTTP methods (GET, POST, PUT, DELETE, etc.) to retrieve and change server state.
No single data representation is ideal for every client. This protocol defines dual representations for each resource in two widely supported formats, JSON [RFC4627] and Atom/AtomPub [RFC4287][RFC5023], using a set of generic mapping rules. The mapping rules allow a server to write to a single interface rather than implementing the protocol twice.
OpenSocial container servers are free to define additional representations but MUST support at least the JSON and Atom formats defined in this document.
The protocol defines Activity, Person, Group, and AppData resources and collections (resources which consist of a set of other resources). Most operations consist of retrieving (GET), updating (PUT), creating (POST or PUT), or destroying (DELETE) these resources. The protocol provides an optional feature to batch multiple requests together in a pipeline to avoid multiple HTTP round trips. Finally, it specifies an optional partial update feature which avoids sending large resources over the wire to update just one field.
OpenSocial API Background details the underlying concepts used below; this document assumes familiarity with the OpenSocial model.
Each resource has a two representations, as JSON and Atom (XML). All data must be representable in both formats, but we do not attempt to map from generic XML or Atom to JSON. Instead, we define an internal data model using English and JSON syntax, and then define the mappings between this and Atom/JSON.
Each resource is represented as a hierarchical tree of elements. Ordering of elements within a parent element may or may not be significant, depending on the context. Mapping consists of converting between the internal hierarchy and the JSON / Atom protocol format.
The set of allowed fields in each type of data is the same as the set documented in the OpenSocial 0.8 API reference. The standard sets of fields are the same between the RESTful API and the JS APIs.
The general rules for mapping between the Atom and JSON formats are as follows. Each data type may add additional aliasing rules.
Examples of the primary types of data follow. Each example shows both representations, JSON and Atom, with the payload data highlighted for ease of comparison.
Collections are a useful abstraction for dealing generically with multiple things, whether those things are persons, groups, activities, or application data sets. They have both Atom and JSON representations; the Atom representation is simply a standard Atom feed whose entries are one of the entry types specified above. The default JSON collection representation is a JSON object containing an "entry" slot containing a list of JSON objects. Collections use the OpenSearch conventions for reporting totalResults (for complete unpaged feed), startIndex of current page, and itemsPerPage.
For example:
application/json representation:
{
"author" : "example.org:58UIDCSIOP233FDKK3HD44",
"link" : {"rel" : "next", "href" : "http://api.example.org/..." },
"totalResults" : 100,
"startIndex" : 1
"itemsPerPage" : 10
"entry" : [
{...first thingie...},
{...second thingie...}
...
]
}
application/atom+xml representation:
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:osearch="http://a9.com/-/spec/opensearch/1.1">
<author><uri>urn:guid:example.org:58UIDCSIOP233FDKK3HD44</uri></author>
<link rel="next" href="http://api.example.org/..." />
<osearch:totalResults>100</osearch:totalResults>
<osearch:startIndex>1</osearch:startIndex>
<osearch:itemsPerPage>10</osearch:itemsPerPage>
<entry>...first thingie...</entry>
<entry>...second thingie...</entry>
...
</feed>
Note: The standard "next" link in each case allows for paginated collections without the need to support full random access; collections MAY also support randomly accessed pages via query parameters.
Activity stream collections are ordered chronologically by default, most recent activities first; containers MAY by default order other collections arbitrarily. Other orderings can be requested for collections using query parameters.
A Person contains a social network oriented data about a single person. The same record is used for contacts/friends and for profiles.
See the Person Fields API doc for a full list of available fields and their (JS) types. See also the general mapping rules in section 2.
A minimal Person example:
application/json representation:
{
"id" : "example.org:34KJDCSKJN2HHF0DW20394",
"name" : {"unstructured" : "Jane Doe"},
"gender" : {"displayvalue" : "女性", "key" : "FEMALE"}
}
application/atom+xml representation:
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<person xmlns="http://ns.opensocial.org/2008/opensocial">
<name>
<unstructured>Jane Doe</unstructured>
</name>
<gender key="FEMALE">女性</gender>
</person>
</content>
<title/>
<updated>2003-12-13T18:30:02Z</updated>
<author/>
<id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</id>
</entry>
Note: In general clients can ask for a full representation of a resource, with all fields and sub-fields, or a partial representation, using query parameters; see below for details.
Note: The atom:summary element is the appropriate place to put a text or HTML representation of the structured data present in the content element, and the atom:title element is the appropriate place to copy a short descriptive name for the entry, such as name.unstructured. Servers MAY choose to add these or other fields to make their feeds more useful for generic aggregators or tools.
OpenSocial Groups are owned by people, and are used to tag or categorize people and their relationships. The RESTful API supports querying for the available groups for a given user. The groups are returned as a collection. Each group has a display name, an identifier which is unique within the groups owned by that person, and a URI link.
A Group example:
application/json representation:
{
"id" : "example.org:34KJDCSKJN2HHF0DW20394/friends",
"title" : "Peeps",
"link" : {rel : "alternate", "href" : "http://api.example.org/people/example.org:34KJDCSKJN2HHF0DW20394/@friends" }
}
application/atom+xml representation:
<entry xmlns="http://www.w3.org/2005/Atom">
<link rel="alternate" href="http://api.example.org/people/example.org:34KJDCSKJN2HHF0DW20394/@friends" />
<title>Peeps</title>
<updated>2003-12-13T18:30:02Z</updated>
<id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394/friends</id>
</entry>
Groups only appear within Group Collections and are used to retrieve a list of available groups for a given person.
An OpenSocial Activity represents a short summary or notification of a timestamped event, often with pointers for more information.
See the Activity Fields API doc for a full list of available fields and their (JS) types. Activities have extensive hoisting rules to ensure maximum compatibility with standard feed processing code:
A minimal Activity example:
application/json representation:
{
"id" : "http://example.org/activities/example.org:87ead8dead6beef/self/af3778",
"title" : { "type" : "html",
"value" : "<a href=\"foo\">some activity</a>"
}
"updated" : "2008-02-20T23:35:37.266Z",
"body" : "Some details for some activity",
"bodyId" : "383777272"
"url" : "http://api.example.org/activity/feeds/.../af3778"
"userId" : "example.org:34KJDCSKJN2HHF0DW20394"
}
application/atom+xml representation:
<entry xmlns="http://www.w3.org/2005/Atom">
<category term="status"/>
<id>http://example.org/activities/example.org:87ead8dead6beef/self/af3778</id>
<title type="html"><a href="foo">some activity</a></title>
<summary>Some details for some activity</summary>
<updated>2008-02-20T23:35:37.266Z</updated>
<link rel="self" type="application/atom+xml" href="http://api.example.org/activity/feeds/.../af3778"/>
<author><uri>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</uri></author>
<content>
<activity xmlns="http://ns.opensocial.org/2008/opensocial">
<body_id>383777272</body_id>
</activity>
</content>
</entry>
AppData stores uninterpreted key/value pairs on behalf of an application. The standard unit of AppData is all of the key/value pairs stored for a given app on behalf of a given user; however, the API supports other types of queries (detailed below). To retrieve a subset of fields, use the fields= selector syntax (detailed below).
An isolated AppData example
The first example is of a collection of key/value pairs for a particular application/user pair:
application/json representation:
{
"pokes" : 3,
"last_poke" : "2008-02-13T18:30:02Z"
}
application/atom+xml representation:
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="text/xml">
<appdata xmlns="http://opensocial.org/2008/opensocial">
<pokes>3</pokes>
<last_poke>2008-02-13T18:30:02Z</last_poke>
</appdata>
</content>
<title/>
<updated>2003-12-13T18:30:02Z</updated>
<author><uri>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</uri></author>
<id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</id>
</entry>
An AppData Collection Example
In this example, a client has requested a collection of data that spans multiple users. The result is a collection which, by default, is given a special default JSON representation as a mapping from users to their data. It's also possible to get a generic representation as an array using a query parameter:
application/json default array representation:
{
"entry" :
[
{ "id" : "example.org:34KJDCSKJN2HHF0DW20394", "pokes" : 3, "last_poke" : "2008-02-13T18:30:02Z" },
{ "id" : "example.org:58UIDCSIOP233FDKK3HD44", "pokes" : 2, "last_poke" : "2007-12-16T18:30:02Z" }
]
}
application/json representation (with indexBy=id):
{
"entry" : {
"example.org:34KJDCSKJN2HHF0DW20394" : {"pokes" : 3, "last_poke" : "2008-02-13T18:30:02Z" },
"example.org:58UIDCSIOP233FDKK3HD44" : {"pokes" : 2, "last_poke" : "2007-12-16T18:30:02Z" }
}
}
application/atom+xml representation:
<feed xmlns="http://www.w3.org/2005/Atom>
<id>...</id>
<title>...</title>
<entry>
<content type="text/xml">
<appdata xmlns="http://opensocial.org/2008/opensocial">
<pokes>3</pokes>
<last_poke>"2008-02-13T18:30:02Z"</last_poke>
</appdata>
</content>
<title/>
<updated>2008-02-13T18:30:02Z</updated>
<author><uri>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</uri></author>
<id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</id>
</entry>
<entry>
<content type="text/xml">
<appdata xmlns="http://opensocial.org/2008/opensocial">
<pokes>2</pokes>
<last_poke>"2007-12-16T18:30:02Z"</last_poke>
</appdata>
</content>
<title/>
<updated>2007-12-16T18:30:02Z</updated>
<author><uri>urn:guid:example.org:58UIDCSIOP233FDKK3HD44</uri></author>
<id>urn:guid:example.org:58UIDCSIOP233FDKK3HD44</id>
</entry>
</entry>
The default representation of a collection is simply a JSON list of records ([ {...}, {....}, ...]). The special type "index" means that the collection is instead to be represented as a mapping, using the index field; this is requested by supplying a query parameter "indexBy" (see above).
The data within each field is assumed to be in JSON format and is otherwise uninterpreted.
OpenSocial uses standard HTTP methods: GET to retrieve, PUT to update in place, POST to create new, and DELETE to remove. POST is special; it operates on collections and creates new activities, persons, or app data within those collections, and returns the base URI for the created resource in the Location: header, per AtomPub semantics.
Restricted clients, or clients behind restricted clients, which cannot use PUT or DELETE SHOULD translate PUT and DELETE to POST operations with an additional X-HTTP-Method-Override: header:
POST /... HTTP/1.1
...
X-HTTP-Method-Override: PUT
Servers SHOULD respond to POST+X-HTTP-Method-Override as if the content of the header were the actual operation sent.
Note: OpenSocial 0.8 does not support cross-domain JSONP (GET with callback), but servers MAY offer this as an extension. It is RECOMMENDED that such servers implement appropriate security and authorization controls.
Each RESTful operation has a request context that usually includes authentication and authorization information. Typically, the context information includes the requestor id (the user initiating the request) and app ID (the application, or whatever is acting as the user's agent). It may include other container-specific information.
Containers MUST be an OAuth Core 1.0 Service Provider (a web application that allows access via OAuth). Containers MAY also support other ways to establish a request context. Containers MUST also support the Consumer Request OAuth extension, in which the end user has not directly authorized the operation. Applications SHOULD ensure that the users have given prior consent, implicitly or explicitly, to the operation or class of operations. However, containers MAY require an additional prior trust relationship be established by the app in order to allow use of Consumer Request OAuth.
If a Consumer has a user identifier and wishes to indicate that the operation is being done on behalf of that particular user, it SHOULD provide the OAuth extension parameter xoauth_requestor_id with the OAuth signed parameters. Consumers SHOULD only provide this if the user has given prior consent, implicitly or explicitly, to the operation or class of operations, as it indicates that the operation is being done on behalf of the user. Container SPs MUST either honor the parameter or ignore it as if it were not provided.
Thus, a request context usually includes the requesting application (the OAuth Consumer), and may include the requesting user, either implicitly via an oauth_token or explicitly via xoauth_requestor_id. It may also include additional information via extensions or other channels (cookies, URI parameters, client SSL certificates, etc.) A container may also accept requests with no authentication or authorization (authnz) information at all for public data. A container may provide a public version (e.g., of a profile) if no authnz information is provided.
Note that the data provided for a given RESTful URI MAY vary per requestor or app. Thus, the meaning of the resource at a given URI is "the view of the information available to the current requestor/app combination". In the case where no information is available due to lack of authorization, an HTTP 401 Unauthorized response SHOULD be returned to the client. In the case where at least some view of the information is available, it SHOULD be returned using a 200 status, with a standard OAuth WWW-Authenticate: header indicating that additional information may be available when using a different authnz context.
A container declares what collection and features it supports, and provides templates for discovering them, via a simple discovery document. A client starts the discovery process at the container's identifier URI (e.g., example.org). The full flow is available at http://xrds-simple.net/core/1.0/; in a nutshell:
The discovery document is an XML file in the same format used for OpenID and OAuth discovery, defined at http://xrds-simple.net/core/1.0/:
<XRDS xmlns="xri://$xrds">
<XRD xmlns:simple="http://xrds-simple.net/core/1.0" xmlns="xri://$XRD*($v*2.0)" xmlns:os="http://ns.opensocial.org/" version="2.0">
<Type>xri://$xrds*simple</Type>
<Service>
<Type>http://ns.opensocial.org/people/0.8</Type>
<os:URI-Template>http://api.example.org/people/{guid}/{selector}{-prefix|/|pid}</URI-Template>
</Service>
<Service>
<Type>http://ns.opensocial.org/activities/0.8</Type>
<os:URI-Template>http://api.example.org/activities/{guid}/{selector}</URI-Template>
</Service>
<Service>
<Type>http://ns.opensocial.org/appdata/0.8</Type>
<os:URI-Template>http://api.example.org/appdata/{guid}/{selector}</URI-Template>
</Service>
</XRD>
</XRDS>
Each Service advertises a service provided by the container. Each container MUST support the service Types documented below and MAY support others by advertising them in the discovery document. Each service comprises a set of resources defined by the given URI Template (or URI, if there is only a single resource). Clients follow the URIs and instantiate the templates to find and operate on specific resources. (URI Template syntax is documented at http://www.ietf.org/internet-drafts/draft-gregorio-uritemplate-03.txt.)
The set of substitution variables is fixed for each service Type. The core set of service Types and their substitution variables is documented below. Extensions to OpenSocial SHOULD document their substitution variables; note that a reasonable place to put human readable documentation is at the namespace URI.
This section defines the core types that every OpenSocial container MUST support, their XRDS types, and their semantics. Unless otherwise specified, all HTTP operations are generally allowed for any URI endpoint; a container which wishes to specify the allowed operations SHOULD provide an HTTP Allow: header for each resource listing the allowed operations.
XRDS Type: http://ns.opensocial.org/people/0.8
guid : Container-globally-unique user identifier; identifies owner of the people data, or @me to indicate the requestor should be used selector : One ofPeople URI examples:
/people/{guid}/@all -- Collection of all people connected to user {guid}
/people/{guid}/@friends -- Collection of all friends of user {guid}; subset of @all
/people/{guid}/{groupid} -- Collection of all people connected to user {guid} in group {groupid}
/people/{guid}/@all/{pid} -- Individual person record for a specific person known to {guid}; shows {guid}'s view of {pid}.
/people/{guid}/@self -- Profile record for user {guid}
/people/@me/@self -- Profile record for requestor
Note that a given container may use alternative URI formats; for example,
/people.cgi?guid={guid}&groupid={groupid}
is a valid URI pattern given the appropriate XRDS discovery document which allows clients to map the parameters to a concrete URI.
Friends may be added by POSTing to the appropriate collection (e.g., /people/{guid}/@friends). Containers MAY require a dual opt-in process before the friend record appears in the collection, and in this case SHOULD return a 202 Accepted response, indicating that the request is 'in flight' and may or may not be ultimately successful.
XRDS Type: http://ns.opensocial.org/groups/0.8
guid : Container-globally-unique user identifier; identifies owner of the people data; can be @me to indicate auth[nz] requestor should be used.
Groups URI examples: /groups/{guid} -- Collection of groups associated with user {guid}
XRDS Type: http://ns.opensocial.org/activities/0.8
guid : Container-globally-unique user identifier; owner or recipient of the activity data, or @me to indicate the requestor should be used
selector : One ofActivity URI examples:
/activities/{guid}/@self -- Collection of activities generated by given user
/activities/{guid}/@friends -- Collection of activities for friends of the given user {guid}
/activities/{guid}/{groupid} -- Collection of activities for people in group {groupid} belonging to given user {uid}
/activities/{guid}/@self/{activityid} -- Individual activity resource; usually discovered from collection
guid : Container-globally-unique user identifier, or @me to indicate the requestor should be used
selector : One ofAppData URI examples:
/appdata/{guid}/@self/{appid} -- All app data for user {guid}, app {appid}
/appdata/{guid}/@friends/{appid} -- All app data for friends of user {guid} and app {appid}; read-only (only GET and HEAD supported)
/appdata/{guid}/@self/{appid}?fields=count -- Just the count field for user {guid}, app {appid}
These additional query parameters may be used with any URI above. The parameters startIndex and count are interpreted according to the OpenSearch spec.
format={format} -- Format desired; one of (atom, json); default is json if not provided
fields={-join|,|field} -- List of fields to include in representation or in the members of a collection. Default is to include all available fields.
startIndex={startIndex} -- Index into a paged collection
count={count} -- Requests page size for paged collection
networkDistance={networkDistance} -- Modifies group-relative requests (@friends, etc.) to include the transitive closure of all friends up to {networkDistance} links away. May not be honored by the container.
indexBy={fieldname} -- For a collection, return a JSON mapping which uses the named field (must be unique key) to the rest of the fields.
orderBy={fieldname} -- For a collection, return entries sorted by the given field.
Containers SHOULD carefully consider security. Containers MUST support OAuth but SHOULD use appropriate policies to determine allowed operations on a per-Consumer and per-user basis. Per the OAuth spec, Containers SHOULD document how a Consumer can direct a user to a Container web page to obtain an oauth_token for future use. Note that this is a vector for phishing if the user is required to enter their credentials.
Containers SHOULD support SSL connections for sensitive data as OAuth on its own does not provide encryption or message body integrity checking. Containers should base their security decisions on the type of client in use; a generally available desktop client, for example, cannot effectively protect a Consumer Secret that is installed with each client. The security of communications with a partner service, on the other hand, is dependent on the effectiveness of that service's security procedures. Containers may wish to rate limit requests from unknown clients, or require registration, in order to mitigate risk.
Containers should scope oauth_tokens as narrowly as possible (e.g., allow reading but not writing if a client only performs reads).
This feature allows a container and client to cooperate in order to prevent multiple containers from overwriting each other's data. It uses the standard HTTP/AtomPub optimistic concurrency mechanism based on ETags (see section 9.5 of [RFC5023] for details; the same mechanism applies regardless of the data format used for the body of the PUT).
Concurrency control is available on a resource-by-resource basis. When an updateable resource supports concurrency control, the container SHOULD supply an ETag encoding the resource's current state when supplying a representation to clients. If a resource does not support optimistic concurrency, it MUST respond to an update request containing an If-Match: header with a 403 Not Implemented error.
A server which chooses not to support optimistic concurrency SHOULD omit ETags on its responses for updateable resources. A client SHOULD assume that optimistic concurrency is not available if no ETag is present.
When a client is given an ETag, it MAY supply that ETag in an If-Match: header on subsequent updates. The semantics are that the client can supply the new representation and the previous ETag; the server inspects the current state of the resource and applies the update if the client supplied ETag matches (meaning no intervening updates have happened), otherwise responds with a 409 Conflict error and the new ETag. Clients may then take appropriate actions to resolve the conflict, or fail the operation, depending on their needs. Clients are also free to use PUT to simply overwrite a resource with a new state at any time, ignoring possible overwriting problems.
If partial updates are supported (see below), a server MUST accept an ETag given for either a base resource or a projection of that resource upon a subsequent PUT for that resource. That is, it is legal to supply an ETag you received when GETting the full representation of a resource even if you are only PUTting back a single field. If you intend to simply overwrite that single field, then you skip sending any ETag.
There are use cases where clients want to send several operations, in a specified sequence, to a server to execute in turn, but do not want to incur the overhead of multiple HTTP round trips. A specific use case is a gadget which first adds a new friend, then retrieves the 5th page of friends (what it's currently viewing). These are two ad hoc requests from the point of view of the server involved, but for optimization purposes the gadget wants to batch up the requests and responses to minimize latency. It is also possible that the requests and responses would be to different types of data (activities, people, or persistence) and/or to different servers. In the most general case it is useful to be able to batch any type of request, including requests to third party servers (e.g., "phone home" requests) that need to be executed in sequence with container-local requests; in this case the container API is acting as a proxy (and should take appropriate security precautions to avoid abuse).
This optional feature allows a container to accept an arbitrary sequence of operations while using only one HTTP round trip between server and client for the overall set of requests and response.
If a container supports batching, it advertises a "batch-proxy" Service in its discovery document:
<Service>
<Type>http://ns.opensocial.org/batch-proxy/0.8</Type>
<URI simple:method="POST">http://api.example.org/batch-proxy</URI>
</Service>
The method may be either POST or BATCH. Containers SHOULD support the BATCH method if possible, but MUST support the POST method. Clients SHOULD support the BATCH method but MUST be able to fall back to the POST method.
The semantics of a set of batched requests in this proposal are exactly the same as sending the same requests individually. In particular, the server does not provide any atomicity guarantees. The server is not allowed to reorder or parallelize the requests unless it can do so without client-visible side effects. The simplest server implementation is to loop over the requests, executing each in turn, and appending responses into a batch response to send to the client.
The batch interface is an optional part of OpenSocial. If a server does not support it, a client falls back to using individual requests and responses with no changes in semantics. Depending on the exact situation, it may be more efficient to use individual requests which can be parallelized and cached, or to use batch serial requests; a goal with this API is to make it simple for a client to switch between the two mechanisms and to keep the semantics consistent and straightforward.
To this end, a batch request is represented by an envelope HTTP request sent to a batching proxy resource. The client POSTs the document described below to the proxy URI, which returns 200 OK when the contents have been processed (successfully or not) and returns a response sequence document.
Both request and response sequence documents are represented by standard multipart/mixed documents; the individual requests and responses are represented by standard application/http;version=1.1 documents (see RFC2616, section 19.1). These documents encapsulate what would be sent over the wire for a standard, stand-alone HTTP request. An example request with two parts:
POST /batch-proxy HTTP/1.1
Host: api.example.org
Authorization: OAuth ...request auth[nz] context elided...
Content-Type: multipart/mixed; boundary=batch-a73hdj3dy3mm347ddjjdf
-batch-a73hdj3dy3mm347ddjjdf
Content-Type: application/http;version=1.1
Content-Transfer-Encoding: binary
POST /people/@me/@friends HTTP/1.1
Host: api.example.org
Content-Type: application/json
...representation of new Person elided...
-batch-a73hdj3dy3mm347ddjjdf
Content-Type: application/http;version=1.1
Content-Transfer-Encoding: binary
GET /people/@me/@friends?startPage=5&count=10&format=json
Host: api.example.org
If-None-Match: "837dyfkdi39df"
The response:
HTTP/1.1 200 OK
Content-Type: multipart/mixed; boundary=batch-a73hdj3dy3mm347ddjjdf
-batch-a73hdj3dy3mm347ddjjdf
Content-Type: application/http;version=1.1
Content-Transfer-Encoding: binary
201 Created
Location: http://api.example.org/people/example.org:38ge838389993/@all/api.example.org:5ea3gh838kjk34834
ETag: "993hhhgjgkkd"
-batch-a73hdj3dy3mm347ddjjdf
Content-Type: application/http;version=1.1
Content-Transfer-Encoding: binary
304 Not Modified
ETag: "837dyfkdi39df"
In this case, the friend add succeeded and the response to the retrieval of page 5 of the friends list indicates that page 5 didn't change (the friend was added below that page's last entry). If the resource had changed, of course, there would be a list of the friends in the response.
Only the top level request can specify overall request related things such as keepalives and content transfer encoding. The top level request response code is:
Individual responses use the HTTP response codes they would have used had they been executed individually. Requests and responses are matched by position, and the server guarantees that if it sends back a response, the nth response is for the nth request. It does not guarantee that the number of responses matches the number of requests; in particular, network problems might truncate a response document or drop a connection, and in this case clients are left not knowing the status of the remaining responses. If a server needs to indicate that a particular sub-request timed out without any indication of whether it succeeded or failed, it should use "X-Batch-Status: 504 Gateway Timeout" to indicate that it has a known unknown. Clients seeing a 504 sub-response should be advised that the request may have completed before timing out.
Note that a container MAY support proxying to foreign servers (via the Host: header); however, servers are not required to support this and clients SHOULD NOT assume the capability.
In general, HTTP fields may be added to either the envelope request or sub-requests. For example, a client may add an Authorization: header to the envelope request (to authorize itself to the proxy service) and also add Authorization: header(s) to different sub-requests (to authorize itself to other services).
(This extension generally follows the proposal at http://www.snellspace.com/wp/?p=886, which is also the semantics used by Astoria.)
Partial updates avoid the need to send full representations of data on updates, especially for People and App Data. The primary use case is when a client has retrieved a full representation and subsequently wishes to send a small update to a server. In the most general case, the client my have a series of small updates (e.g., changing tags on a large number of contacts) scattered across many resources. It should also allow for concurrency control. We wish to have a generalized partial update / patching mechanism to handle such cases. As with the batching mechanism, it should be optional on the server side; clients can always fall back to sending full representations back to the server if it does not support the mechanism.
The exact syntax is TBD at this point.
A social network service may optionally expose a mechanism for sending short messages between users. The functionality and policies are parallel to those of the JS API's requestSendMessage.
If a container supports messaging, it advertises a "messages" Service in its discovery document:
<Service>
<Type>http://ns.opensocial.org/messages/0.8</Type>
<os:URI-Template>http://api.example.org/messages/{guid}/outbox/{msgid}</URI-Template>
</Service>
To create a message and place it in a queue, a client PUTs a message to an 'outbox' collection resource discovered from the XRDS document:
PUT /messages/{guid}/outbox/{msgid}
The outbox is owned by the source user. Placing a message in the outbox requests that the message be delivered to one or more recipients. Containers are free to filter or alter the message according to their own policies (such as security or rate limiting policies).
The format of the message is the same as an activity, but with an additional set of recipients (osapi:recipient):
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:osapi="http://opensocial.org/2008/opensocialapi">
<osapi:recipient>example.org:AD38B3886625AAF</osapi:recipient>
<osapi:recipient>example.org:997638BAA6F25AD</osapi:recipient>
<title>You have an invitation from Joe</title>
<id>{msgid}</id>
<link rel="alternate" href="http://app.example.org/invites/{msgid}"/>
<content>Click <a href="http://app.example.org/invites/{msgid}">here</a> to review your invitation.</content>
</entry>
The {msgid} is client generated and SHOULD be globally unique. If a client does not care about failure cases, it can alternatively use a standard AtomPub POST to /messages/{source-uid}/outbox and leave generation of the ID to the container. In either case, the response is 201 Created on success.
If not supported, the response code should be 403 Not Implemented.
Typically a container would choose to only allow a PUT to an outbox where the {guid} equals the requestor id, but this is a container security policy decision. Containers may choose to allow messaging only between friends or user other heuristics to prevent spam.
The copyrights in this specification are licensed under the Creative Commons Attribution 2.5 license | Terms of Service