Please see http://www.opensocial.org/specs for the latest version of the OpenSocial specification.

OpenSocial RPC Protocol

1. Overview.

This proposal defines an RPC alternative to the RESTful API specification. The intent is to support the same data and operations as the RESTful API in a form that is more natural for the JSON data format. Any batch of RPCs should be programatically convertible to a sequence or batch of RESTful calls and maintain the same semantics, any exception to this will be called out explicitly.

It shares the following with the RESTful spec:
  1. The JSON/XML format of the OpenSocial data types for Person, Activity, Group & AppData are identical.
  2. HTTP status codes are used to represent common error cases where applicable
  3. OAuth is supported for authentication and authorization in addition to other authorization schemes a container may choose to support. A single OAuth token can be used for a batch of operations or each operation can specify its own OAuth token.
  4. Concurrency control is optional.

It differs from the RESTful spec in the following ways:

  1. All structural elements in the protocol are represented using the JSON or XML notation
  2. Batch support is required
  3. HTTP is used primarily as a transport and not to indicate the semantics of the request
  4. Automated discovery happens in two steps. XRDS can be used to discover the RPC endpoint. The service can then be introspected by executing an RPC for "system.listMethods" to discover the list of available services and operations using conventions defined by XML-RPC Introspection Within a running gadget the address of the RPC endpoint should be available as a Javascript variable (name and mechanism TBD). In general it is expected that a large percentage of consumers will bypass automated discovery and rely on simpy hardcoding references to the endpoints of various popular containers. 

This document presents all of its examples in the JSON format but the RPC protocol is equally applicable to an XML format. The data structure returned is equivalent in both formats; the only difference is in the encoding of the data. Singular fields are encoded as string key/value pairs in JSON and tags with text content in XML, e.g. "field": "value" and <field>value</field> respectively. Plural fields are encoded as arrays in JSON and repeated tags in XML, e.g. "fields": [ "value1", "value2" ] and<fields>value1</field><fields>value2</field> respectively. Nodes with multiple sub-nodes are represented as objects in JSON and tags with sub-tags in XML, e.g. "field": { "subfield1": "value1", "subfield2": "value2" } and<field><subfield1>value1</subfield1><subfield2>value2</subfield2></field> respectively.

2. Examples


2.1 Single element request & response for the Person associated with principal in the OAuth token

This maps to fetching /people/@me/@self using the RESTful API.
Notes:
  • The params groupId and userId are included here for completeness even though they are the default parameter values for the operation.
  • The "method" field identifies both the service "people" and the operation "get" which has the same semantics as an HTTP GET request in the RESTful spec. 
  • "json-rpc" as defined in JSON-RPC is not passed in the request but requests MUST be interpreted as if "json-rpc" : "2.0" was supplied
  • "id" is an optional identifier the caller may choose to associate with the call, this field is propagated to the response 
  • The "result" field in the response is the returned object, in this case an opensocial.Person object.
  • URL addressable equivalent is http://api.example.org/rpc?method=people.get&id=myself&userId=@me&groupId=@self

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <Auth token>
Content-Type: application/json
{
  "method" : "people.get",
  "id" : "myself"
  "params" : {
    "userId" : "@me",
    "groupId" : "@self"
  }
}


HTTP/1.x 207 Multi-Status
Content-Type: application/json
{
   "id" : "myself"
   "result" : {
     "id" : "example.org:34KJDCSKJN2HHF0DW20394",
     "name" : { "unstructured" : "Jane Doe"},
     "gender" : "female"
  }
}

2.2 Multi-element batch request & response for person associated with principal in the OAuth token and their friends

This maps to fetching /people/@me/@self & /people/@me/@friends using the RESTful API

Notes:
  • A batch request is detected by examining the request to see if it is a JSON array of requests. Any request id's specified in a batch SHOULD be unique
  • The request for "myself" succeeded but the one for "myfriends" failed because the OAuth token does not grant access to this resource. The failure of the "friends" request is indicated by the existence of an "error" object which contains a "code" field which uses the numerical value of the HTTP status code UNAUTHORIZED.  See JSON-RPC.Error 
  • The batch response elements are returned in an array in the same order as the corresponding batch request elements. The "id" of the corresponding request in the batch request is carried over to the response.
  • In this example parameters are omitted where they match the defaults. If the call has no parameters the "params" field can be omitted completely.

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <Auth token>
Content-Type: application/json
[
  {
    "method" : "people.get",
    "id" : "myself"
  },
  {
    "method" : "people.get",
    "id" : "myfriends"
    "params: {
      "groupId" : "@friends"
    }
  }
]

HTTP/1.x 207 Multi-Status
Content-Type: application/json
[
  {
    "id" : "myself",
    "result" : {
      "id" : "example.org:34KJDCSKJN2HHF0DW20394",
      "name" : { "unstructured" : "Jane Doe"},
      "gender" : "female"
    }
  },
  {
    "id" : "myfriends"
    "error" : {
      "code" : 401
    }
  }
]


2.3 Multi-element batch request & response with per-request auth-token override

This maps to fetching /people/@me/@self using the 1st auth-token and fetching /people/@me/@friends using the 2nd auth-token with RESTful API

Notes:
  • The auth token in the header is used for requests which do not specify an "auth" parameter explicitly.

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <1st Auth token>
Content-Type: application/json
[
  {
    "method" : "people.get",
    "id" : "a9fd76"
  },
  {
    "method" : "people.get",
    "id" : "e453a",
    "params: {
      "groupId" : "@friends",
      "auth" : "<2nd Auth token>"
    }
  }
]

HTTP/1.x 207 Multi-Status
Content-Type: application/json
[
   {
    "result" : {
      ...
    }
  },
  {
    "result" : {
      ...
    }
  }
]

2.4 Request & response for collection of Person objects

This example maps to fetching /people/@me/@friends with the RESTful API

Notes:
  • A response that contains a list of information will contain a "list" field in the result.
  • The result will also  include details about the number of elements returned in the "list" field as well as information about how to request additional elements using either paging or indexing. The example shown is for a list that is addressed by indexing.
  • Indices are always 0 based, so valid indices in the list are 0..totalResults-1
  • URL addressable equivalent is http://api.example.org/rpc?method=people.get&id=myfriends&userId=@me&groupId=@friends

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <auth token>
Content-Type: application/json
{
    "method" : "people.get",
    "id" : "myfriends"
    "params: {
      "userId" : "@me",
      "groupId" : "@friends"
    }
}

HTTP/1.x 207 Multi-Status
Content-Type: application/json
{
  "result" : {
    "totalResults" : 100,  
    "startIndex" : 0,
    "itemsPerPage" : 10,
    "list" : [
      {..},
      {..},
    ]
  }
}  

2.5 Updating application app-data for a user

This example maps to PUTing or POSTing a set of key-values to /appdata/@me/@self/app12345 with the RESTful API. This is a fairly simple example of an update.

Notes:
  • The userId and groupId params are omitted because they match the defaults
  • The appId param can be omitted if the auth-token used for the call can be used to derive the value for the appId.
  • The return value on success is VOID, represented by an empty JSON structure.
  • URL addressable equivalent is http://api.example.org/rpc?method=appdata.update&id=setMyData&appId=app12345&data.pokes=3&data.lastPoke=2008-02-13T18:30:02Z

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <auth token>
Content-Type: application/json
{
    "method" : "appdata.update",
    "id" : "setMyData"
    "params: {
      "appId" : "app12345",
      "data" : {
        "pokes" : 3,
        "lastPoke" : "2008-02-13T18:30:02Z"
      }
   }
}

HTTP/1.x 207 Multi-Status
Content-Type: application/json
{
  "result" : {
  }
}  

2.6 Creating a friend relationship to another user. 

This example maps to PUTing an opensocial.Person object /people/@me/@friends with the RESTful API. This example is a use-case not covered by the OpenSocial JS API and is given here to show how additional operations that a container may want to support can be defined within this framework. This effect of this call may be different based on how the container models the social graph. This may be interpreted as send an invite to the specified person to create a bi-drection friend relationship which may be accepted or rejected later. Depending on the semantics of the group the result of the call can vary and the person added may not be immediately visible in a subsequent person.get call on the same group.

Notes:
  • The return value on success is VOID, represented by an empty JSON structure. 
  • userId & groupId could be omitted as they match the operation default. Shown for completeness
  • URL addressable equivalent is http://api.example.org/rpc?method=people.create&id=createFriend&userId=@me&groupId=@friends&person.id=example.org:FF256337

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <auth token>
Content-Type: application/json
{
    "method" : "people.create",
    "id" : "createFriend"
    "params: {
      "userId" : "@me",
      "groupId" : "@friends",
      "person" : {
        "id" : "example.org:FF256337"
      }
    }
}

HTTP/1.x 207 Multi-Status
Content-Type: application/json
{
  "result" : {
  }
}  


2.7 Failed attempt to update profile information due to conflicting change

This example maps to POSTing an opensocial.Person object /people/@me/@self with the RESTful API. This example again is not one covered by the OpenSocial JS but may be supported by containers.  The example shown demonstrates the use of etags to detect an incompatible update to the profile of the user identified in the auth token. The request is attempting to update the 'books' field and passes the etag the client received when it retrieved the person object prior to update. The etag is added to the update request shown below but an inervening update from another client has made the change incompatible and so the update is rejected.

Notes
  • The error code 409 is the HTTP Conflict status code
  • The error object "data" field contains a limited representation of the latest version of the person object including an up-to-date etag value. Containers may choose to omit this data from conflict error responses.

POST /rpc HTTP/1.1
Host: api.example.org
Authorization: <auth token>
Content-Type: application/json
{
    "method" : "person.update",
    "id" : "setMyData"
    "params: {
      "userId" : "@me",
      "groupId" : "@self",
      "person" : {
        "etag" : "767ffdef7",
        "books" : ["The Prince", "Hotel New Hampshire"]
      }
    }
}

HTTP/1.x 207 Multi-Status
Content-Type: application/json
{
   "id" : "myself",
   "error" : {
     "code" : 409
     "message" : "Conflict detected",
     "data" : {
       "etag" : "8543de12",
       "books" : ["The Right Stuff", "About a boy"]
     }
   }
}


3. Naming Conventions

In addition to conforming with the JSON-RPC specification for a container to be an OpenSocial RPC provider they MUST conform to the following conventions

3.1 RPC Methods


The value of the "method" field in an OpenSocial RPC request uses a format of "<service-name>.<operation>". <service-name> is a string [A-Za-z0-9_]+ that identifies one of the services listed in [Services] and <operation> is a string [A-Za-z0-9_]+ that identifies an operation supported by that service.


All OpenSocial services MUST expose a "get" [TBD query, fetch are valid alternatives] operation. Operations with the names get, create, update and delete should map to the HTTP equivalent operations in the RESTful API of GET, PUT, POST & DELETE



3.2 Services


The names of the RPC services MUST match the names used in the OpenSocial namespace E.g http://ns.opensocial.org/messages/0.8


4. Batches

Calls to the RPC endpoint for batch execution MUST only be supported for HTTP POST requests. A batch of RPC's is an ordered array of requests and the return is an ordered array of responses in the same order. I.e


[ <rpc-request1>, <rpc-request2>, ...] -> [ <rpc-response1>,  <rpc-response2>, ...]

5. Lists

Many service operations return a list of OpenSocial resources. Lists are always returned in the "list" field of the result. Lists can either be the full set of resources or a pageable subset. If the returned list represents the entire set of resources the response is simply
{
  "result" : {
    "list" : [ ... ]
 }
}

If the operation supports random access indexing of the full list it will support the "startIndex" and "count" parameters which control what sublist of the full list is returned. If the response contains a sublist obtained via random access indexing it will have the general form:

{
  "result" : {
    "totalResults" : <total number of elements in the full list>,
    "startIndex" : <0 based offset in the full-list of the returned sublist>,
    "itemsPerPage" : <total number of elements in the returned sublist>,
    "list" : [ ... the sublist ...]
  }
}

If the operation supports access through an indexable list of pages of the full list it will support the "startPage" parameter that controls which page is selected. A response that contains a sublist obtained via indexed pages has the form:

{
  "result" : {
    "itemsPerPage" : <total number of elements in the returned sublist>,
    "firstPage" : <index of the first page. This field is optional but recommended>,
    "prevPage" : <index of the previous page. If this is the first page this field is omitted, otherwise it is required>,
    "nextPage" : <index of the next page. If this is the last page this field is omitted, otherwise it is required>,
    "lastPage" : <index of the last page. This field is optional but recommended>
    "list" : [ ... the sublist ...]
  }
}

The paging mechanisms described here are based on the OpenSearch standard with the additional requirement that all indexes are 0 based.

6. URL Addressing

Containers MUST give access to the RPC services using a URL addressing scheme to invoke a single RPC via HTTP GET. This encoding can also be used to support RPC execution via form posts including file-uploads as parameters to RPCs. It is recommended that only services that are idempotent are exported in this manner. Containers MUST use the following canonical transformation between the RPC structure and its URL encoding


  • The RPC method is defined by the 'method' query parameter
  • The RPC id is defined by the 'id' query parameter
  • All other query parameters are assumed to belong to the RPC params element and are encoded from JSON using <field path dot notation>=<scalar value> | <comma separated array of scalars>. When a field represents an array of non-scalars then elements of the array are identified by enclosing the index in parenthesis. Strings which match [0-9]+ MUST be single-quoted, Strings which match [A-Za-z_]+ MUST be unquoted, all other strings retain their original quoting.
    • { "field" : "value" } -> field=value
    • { "field" : [1,2,3,4,5]} -> field=1,2,3,4,5
    • { "field" : "12" } -> field='12'
    • { "field" : [identifier,anotheridentifier]} -> field=identifier,anotheridentifier
    • { "field" : ["value","another value"]} -> field=value,"another value"
    • { "field" : ['value','another value']} -> field=value,'another value'
    • {"field" : { "nested" : "value" }} -> field.nested=value
    • {"field" : [ { "nested1" : "value1" }, { "nested2" : "value2" }]} -> field(0).nested1=value1&field(1).nested2=value2


This scheme is intentionally verbose and is designed for simple representation of requests with a limited set of parameters. While more compact URL friendly encodings of JSON exist (e.g RISON ) this encoding seems more suitable for the intended use case.

Some examples:
  • { "method" : "people.get", "id" : "myfriends",  "params": {"userId" : "@me", "groupId" : "@friends" }} -> http://api.example.org/rpc?method=people.get&id=myfriends&params.userId=@me&params.groupId=@friends

7. Request Authentication and Authorization Context

This specification has the same requirements as the RESTful API for authentication and authorization. In addition Containers SHOULD also support a request context compatible with use by a gadget running the OpenSocial JS in the containers UI.

When OAuth is used for authorization on a single RPC the OAuth signature uses the URL Addressing representation of the request without the auth param to calculate the signature base string.
When OAuth is used for authorization on a batch of RPCs the generation of the OAuth signature base string uses the same technique asURL Addressing to convert a sub-request into a list of query parameters with the addition of adding the method field into the query parameter list. Each parameter in the query string is prepended with the id of the sub-request for which it was generated and '.' . The conversion for Example 2.2 would look like:

a9fd76.method=people.get&a9fd76.id=a9fd76&a9fd76.params.userId=@me&e453a.method=people.get&e453a.id=e453a&e453a.params.userId=@me&e453a.params.groupId=@friends

The remainder of the signing process is as per the OAuth spec i.e the query parameters are lexicographically sorted and a nonce and timestamp are added before the signing

This allows for singing the full content of the request. In the case where a sub-request specifies its own Auth then that whole subrequest is omitted from the OAuth signature and a separte signature calculated for that sub-request

8. Services

We use a hybrid method call syntax to document the operation supported by a service. The types of parameters are described using the same syntax used by the OpenSocial JavaScript documentation. Most parameter defaults are literal values such as "@me" and some are derived from the calling context and have the following definitions:

  • HttpRequest.Authorization - A parsed version of the authorization information stored in the HTTP Authorization header or that is associated with the request in a container specific manner
  • auth.AppId - The application id is derived from the authorization token if it is available.
  • User Ids - userId parameters to service operations MUST match the format described in http://code.google.com/apis/opensocial/docs/0.8/spec.html#people  or MUST be one of the reserved userId placeholders. All containers must support the @me placeholder value which is used to denote the user identified by the authorization token associated with the request. Any userId value that begins with '@' is reserved by the specification for future use. 
  • Group Ids - groupId parameters to service operations MAY be a simple string or one of the reserved groupId placeholders. All containers must support the @self & @friends placeholders values. Any groupId value that begins with '@' is reserved by the specification for future use as a placeholder. 


8.1 People

service-name = "people"

Operations summary:
Operation
Parameters
Return
get
AuthToken auth = HttpRequest.Authorization,  String or Array.<String> userId = "@me", String groupId = "@self", Array.<String> fields, int count,  int startIndex,  int startPage opensocial.Person or Array.<opensocial.Person>
create AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@friends", opensocial.Person person
opensocial.Person
update  AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self", opensocial.Person person opensocial.Person
delete
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self" Void


8.1.1 get


Retrieve a single person or list of opensocial.Person objects.  Supports returning a limited set of fields on returned Person objects and control of the order and paging in a returned list. 


8.1.2 create


Support creating opensocial.Activity objects as the targets of a relationship with the specified user, this is a generalization of many use cases including invitation, contact creation etc. Implementation of this method is not required to be OpenSocial compliant


8.1.3 udpate


Support updating the properties of an opensocial.Person object identified by its relationship to the specified user.Implementation of this method is not required to be OpenSocial compliant


8.1.4 delete


Support removing the relationship between an opensocial.Person and the specified userImplementation of this method is not required to be OpenSocial compliant




8.2 Activities

service-name = "activity"

Operations summary:
Operation
Parameters
Return
get
AuthToken auth = HttpRequest.Authorization,  String or Array<String> userId = "@me", String groupId = "@self",  String appId = auth.AppId,  Array<String> activityIds = [], Array.<String> fields,  int count,  int startIndex,  int startPage opensocial.Activity or Array.<opensocial.Activity>
create
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self",  String appId = auth.AppId,  opensocial.Activity activity opensocial.Activity
update
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self",  String appId = auth.AppId,  opensocial.Activity activity opensocial.Activity
delete
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self",  String appId = auth.AppId,  String activityId Void


8.2.1 get


Retrieve a one or list of opensocial.Activity objects.  Supports returning a limited set of fields on returned Activity objects and control of the order and paging in a returned list. 


8.2.2 create


Support creating opensocial.Activity objects as the targets of a relationship with the specified user, the specifically supported use case is posting a new activity to the stream of a single user i.e activity.create(userId="@me",groupId="@self", <some activity>) Support for other parameterizations is not required to be OpenSocial compliant.


8.2.3 udpate


Support updating opensocial.Activity objects as the targets of a relationship with the specified userImplementation of this method is not required to be OpenSocial compliant


8.2.4 delete


Support removing the relationship between an opensocial.Activity and the specified user. Implementation of this method is not required to be OpenSocial compliant




8.3 AppData

service-name = "appdata"

Operations summary:
Operation
Parameters
Return
get
AuthToken auth = HttpRequest.Authorization,  String or Array.<String> userId = "@me", String groupId = "@self",  String appId = auth.AppId, Array.<String> keys
Map.<String, String>
update
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self",  String appId = auth.AppId, Map.<String, String> data
Void
delete
AuthToken auth = HttpRequest.Authorization,  String userId = "@me", String groupId = "@self",  String appId = auth.AppId, Array.<String> keys Map.<String, String>

8.3.1 get


Retrieve a map of key-value pairs for the list of specified keys.


8.3.2 udpate


Add or replace key-value pairs stored in a users appdata with the key-vaues in the data parameter.


8.3.3 delete


Remove the specifed keys from a users appdata and returned the values associated with those removed keys.

8.4 Messaging

service-name = "messages"

Operations summary:
Operation
Parameters
Return
send AuthToken auth = HttpRequest.Authorization,  String userId = "@me", opensocial.Message message Void

Sample JSON for Message as one is not defined in the RESTful spec yet.
 

{
   "recipients" : ["example.org:AD38B3886625AAF", "example.org:997638BAA6F25AD"],
   "title" : "You have an invitation from Joe",
   "body" : "Some content",
   "type" : "EMAIL"
}


8.3.1 send


Send an opensocial.Message object to its defined recipients.




8.5 System

The system service is used to introspect the endpoint for the set of available services and operations and for metadata about those services.

service-name = "system"

Operations summary:
Operation
Parameters
Return
listMethods
Array.<String>
methodSignatures
String methodName
Signature
methodHelp
String methodName
Content


8.5.1 listMethods


Containers MUST imlpement this operation which takes no parameters and returns an array of all methods supported by the endpoint including the system methods. For a container which only supports read access to people & read and create access for activities the result would be


["people.get", "activities.get", "activities.create",  "system.listMethods", "system.methodSignatures", "system.methodHelp"]


8.5.2 methodSignatures


Containers MUST implement this operation that returns a method signature describing the types of the parameters, their default values and the type of the return value for a given operation. Note that this scheme does not match that used for XML-RPC definition of method signatures which only specifies a mapping for positional parameters. Type definitions used here match the scheme used in the OpenSocial Javascript API. The example below is the Signature response for people.get


{

    "return" : ["opensocial.Person", "Array.<opensocial.Person>"],

    "auth" : {

       "default" : null,

       "type" : "AuthToken"

     },

     "userId" : {

       "default" : "@me",

       "type" : ["String", "Array.<String>"]

     },

     "groupId" : {

       "default" : "@self",

       "type" : "String"

     },

     "fields" : {

       "default" : ["id","name","thumbnailUrl","profileUrl"],

       "type" : "Array.<String>"

     },

     "count" : {

       "type" : "int",

       "required" : false

     },

     "startIndex" : {

       "type" : "int",

       "required" : false

     }

     "startPage" : {

       "type" : "int",

       "required" : false

     }

}


The "return" field indicates the type of the result. If the service can return more than one type then the value is an array of the possible return types. Each named field in the response maps to a parameter of the operation and contains information about the types and values accepted for that parameter. The existence of "default" in the parameter detail indicates the parameter has a default value. The value of a default may be null which means that its not introspectable and usually means that it is some complex derivation. Parameters are assumed to be required unless otherwise indicated by the existence of the "required" field with a value of false. 


8.5.3 methodHelp


Containers MAY implement this operation that returns a textual description of the operation identified by the methodName parameter. A container can choose to return either plaintext or HTML as the response.


9. Standard Errors

A common set of error codes are used to represent failure modes that apply generally to operations and so are reserved for use by this specification

Code
Meaning
-32700 (Parse error)
 Invalid JSON. An error occurred on the server while parsing the JSON text.
-32600 (Invalid Request)
The received JSON not a valid JSON-RPC or batch of JSON-RPCs
-32601 (Method not found) The requested remote-procedure does not exist / is not available.
-32602 (Invalid params)
Invalid method parameters.
-32603 (Internal server error)
Internal server error
-32099..-32000 Reserved for implementation-defined server-errors.
401 (Unauthorized)
Access token does not grant access to the resource
404 (Not Found)
The requested resource was not found
409 (Conflict)
The requested update conflicts with a prior change
0-1000
Reserved for future use by this specification
 


10. Optimistic concurrency

Containers MAY choose to implement an optimistic concurrency scheme for updates. If this facility is supported by the container an "etag" field will be embedded in the updatable object when it is retrieved. When the container receives a request to update an object and an etag is present in the request the container MAY choose to deny the request because it has detected a conflicting update. Containers are free to allow updates even in the presence of conflicting etags at their own discretion but SHOULD document when such behavior is allowed.

11. Alternative Response Types

In situations where containers support the URL Addressing scheme to perform an RPC the container MAY return arbitrary content types in the response other than application/json. The system.methodHelp operation relies on this to provide browseable documentation.

12. Multi-part Uploads

A container MAY choose to support file uploads from browsers to the RPC endpoint and have the uploaded files be passed as parameters to the RPC. This is achieved by browsers posting a form which contains the files to the endpoint and including a form-parameter called "rpc" which contains the form-encoded RPC request. The form input element names for the uploaded files will be bound to the corresponding parameter names on execution.