3.0 REST API

From AlfrescoWiki

Jump to: navigation, search


This page represents on-going design of the 3.0 Repository Public RESTful API for use by any client. As each service is implemented and formally described it becomes self-documenting allowing for the generation of the published reference documentation (which will also be available from an installed Alfresco Repository).

The scope of services is heavily driven by the requirements of the Alfresco 3.0 Web Client.

Alfresco REST Design Guidelines

Contents

[edit] Node Service (TBD)

[edit] Data

[edit] Node

{
   "nodeRef" : "workspace://SpacesStore/123-123-123",
   "url" : "/services/api/node/workspace/SpacesStore/123-123-123"
}

[edit] Site Service

[edit] Data

[edit] Site Details

Details of the site that include:

  • short name (this must be unique and always present)
  • site preset (mandatory for create)
  • title
  • description
  • indication of whether the site is public
  • site node URL
  • tag scope URL for the site
  • site URL (provided when retrieving site details)


JSON example:

{
   "shortName" : "shortName",
   "sitePreset" : "sitePresetName",   
   "title" : "title",
   "description" : "description",
   "isPublic" : true,
   "node" : "/services/api/node/workspace/SpacesStore/123-123-123-123",
   "tagScope" : "/services/api/tagscopes/workspace/SpacesStore/123-123-123-123"
   "url" : "/services/api/sites/shortname"
}

[edit] MembershipDetails

Details of a site membership that includes:

  • role - the role that the person plays in the site
  • person - the person (see JSON defintion for person)
  • url - url to the membership resource


JSON example:

{
   "role" : "SiteManager",
   "person" :
   {
      "userName" : "userId",	
      "url" : "/alfresco/service/api/people/userId", 		   
      "firstName" : "Bob",
      "lastName" : "Smith"
   },
   "url" : "/alfresco/service/api/sites/mySite/memberships/userId"	 		    
}

[edit] Resources

[edit] Site Collection

The site collection contains a list of sites available across the repository. This collection may be filtered.

Methods:

GET /sites 
      ?nf={namefilter}&spf={sitepresetfilter}
      <= SiteDetails[]
POST /sites 
      => SiteDetails
      <= SiteDetails

[edit] Site

The site resource represents the site. This consists of a name, description and a list of memberships for that site. There will also be information about the 'owner' of the site and whether the site is public of not.

Methods:

GET /sites/{shortname} 
      <= SiteDetails
PUT /sites/{shortname}      
      => SiteDetails 
DELETE /sites/{shortname}

[edit] Site Membership Collection

The membership collection represents a list of all the membership details for a site. This collection may be filtered.

Methods:

GET /sites/{shortname}/memberships 
      ?nf={namefilter}&rf={rolefilter}
      <= MembershipDetails[]
POST /sites/{shortname}/memberships 
       => MembershipDetails 

[edit] Site Membership

The site membership resource represents a users membership to a site. This consists of a link to the site and the user concerned. It also contains information about the 'role' or permissions that user has on that site.

Methods:

GET /sites/{shortname}/memberships/{username} 
      <= MembershipDetails 
PUT /sites/{shortname}/memberships/{username} 
   => MembershipDetails 
DELETE /sites/{shortname}/memberships/{username}

[edit] Invite Service

NOTE - the API to this interface is subject to change - please use with care.

Note that throughout this section (and the code implementing it), the word 'invite' is used within the context of its informal usage as a noun - with the same meaning as 'invitation'.

[edit] Data

[edit] InviteInfo

Information pertaining to an invite:

  • Invite ID (this must be unique and always present)
  • User name of inviter (invite sender)
  • User name of invitee (invite recipient)
  • Site (the short name of the site that the inviter is inviting the invitee to join)
  • Invite URL (retrieves this InviteInfo instance)

Example of JSON representation of an InviteInfo object:

{
   "inviteId" : "jbpm$98",
   "inviterUserName" : "Bob.Lawrence",
   "inviteeUserName" : "Tom.Richards",
   "siteShortName" : "BobsBicycles",
   "inviteUrl" : "/api/invites?inviteId=jbpm$98"
} 

[edit] Resources

[edit] Invite Collection

An invite collection contains a list of pending invites, filtered by the parameters provided. Pending invites are those which haven't been cancelled by the inviter, or accepted or rejected by the invitee.

Methods:

Note that all the parameters for this method are optional, but at least one them must be provided

GET /invites?inviterUserName={inviterUserName}&inviteeUserName={inviteeUserName}&siteShortName={siteShortName}</url>
      returns InviteInfo[]

[edit] Invite

An invite resource represents an invite, the properties of which are outlined above in InviteInfo

Methods:

TODO: Note that the method below will probably in the future be superceded by something more RESTful like [GET /invites/{inviteId} returns InviteInfo]
GET /invites?inviteId={inviteId} 
      returns InviteInfo


TODO: Note that the method below will probably in the future be superceded by something more RESTful like [POST /invites input InviteInfo] (though the problem with this is that I need to find some way of passing in the invitee's first name, last name and email address, which are not part of InviteInfo (and shouldn't be). Perhaps this can be achieved by the client first calling [PUT /people/{inviteeUserName} input PersonDetails], with the invitee's first name, last name, and email address included in the updated person details)

GET /invite/start?inviteeFirstName={inviteeFirstName}&inviteeLastName={inviteeLastName}&inviteeEmail={inviteeEmailAddress}&siteShortName={siteShortName}
      returns InviteInfo 


TODO: Note that the method below will probably in the future be superceded by something more RESTful like [DELETE /invites/{inviteId} returns InviteInfo]

GET /invite/cancel?inviteId={inviteId}      
      returns InviteInfo 


TODO: Note that below, the parameters {inviteeUserName} and {siteShortName} shall be removed soon as they are redundant, and the values thereof should actually be looked up by the Web Script itself (as they can be looked up by using the {inviteId} parameter) Also note that the method below will probably in the future be superceded by something more RESTful like [PUT /invites/{inviteeUserName} input InviteDetails, and including the updated state of accepted in the InviteDetails. The problem with this however is that I don't know how to perform a PUT Web Script call from a URL within the body of the invite email]

GET /inviteresponse/accept?inviteId={inviteId}&inviteeUserName={inviteeUserName}&siteShortName={siteShortName}      
      returns InviteInfo 


TODO: The same change notifications from the previous method apply here too.

GET /invite/inviteresponse/reject      
      returns InviteInfo?inviteId={inviteId}&inviteeUserName={inviteeUserName}&siteShortName={siteShortName} 


Getting information about an invite if the id and ticket is known:

GET api/invite/{inviteId}/{inviteTicket}
   <= Invite

Note: This call does not require authentication

[edit] Person Service

[edit] Data

[edit] PersonQuery

A person query contains parameters to be used when querying the repository for people:

  • part of name
  • part of organisation
  • part of email address

[edit] Person

Person data includes:

  • unique identifier
  • title
  • first name
  • last name
  • organisation
  • job title
  • email address
  • bio
  • avatar URL
  • sites - url to the collection of sites the user is an explicit member of

JSON example:

{
   "userName" : "userId",	
   "url" : "/alfresco/service/api/people/userId", 		   
   "firstName" : "Bob",
   "lastName" : "Smith",
   "sites" : "/alfresco/service/api/people/userId/sites"
}

[edit] Resources

[edit] People Query

A query collection containing people in the repository that match the query parameters.

Methods:

 GET /query/people => PersonQuery <= Person[] 

[edit] People Collection

The people collection contains a list of all the people in the repository. This list may be filtered.

Methods:

 GET /people <= Person[] 
 POST /people 
=> Person
<= Person 

[edit] Person

The person resource represents an alfresco user.

Methods:

 GET /people/{userid} => Person 
 PUT /people/{userid} <= Person 
 DELETE /people/{userid} 

[edit] Persons Site Collection

A list of the sites that a person has an explicit memebership of.

Methods:

 GET /people/{userid}/sites 
   <= Site[]

[edit] Activities Service

[edit] Assumptions (TBC)

  • siteId (equivalent to site shortname) has a well-defined max length - note: activities service schema currently accommodates siteIds upto 255 characters
  • userId (equivalent to person username) has a well-defined max length - note: activities service schema currently accommodates userIds upto 255 characters

[edit] Data

[edit] Feed Control

Feed control data includes:

  • siteId (site shortname)
  • appToolId (app/tool id)

[edit] Resources

[edit] User Feed

Get user feed entries for currently logged in user. Optionally filter by site. Required authentication = "user".

Methods:

GET /activities/feed/user
GET /activities/feed/user?s={siteId}

As currently logged in admin, get user feed entries for specified user. Optionally filter by site. Required authentication = "admin".

Methods:

GET /activities/feed/user/{userId}
GET /activities/feed/user/{userId}?s={siteId} 

[edit] Site Feed

Get site feed entries for a given site. If site is private then currently logged in user must be a member of the site or an admin (else will get 401). Required authentication = "user".

Methods:

GET /activities/feed/site/{siteId} 

[edit] User Feed Control

Get user feed controls for currently logged in user. Required authentication = "user".

Methods:

GET /activities/feed/controls 
      <= FeedControl[]


Set user feed control for currently logged in user. Required authentication = "user".

Methods:

POST /activities/feed/control
      => FeedControl

Unset user feed control for currently logged in user, for given {siteId} or given {appToolId} or given combination (if both are supplied). Required authentication = "user".

Methods:

DELETE /activities/feed/control?s={siteId}&a={appToolId}

[edit] Rendition Service (TBD)

[edit] Data Dictionary Service (TBD)

  1. Read access to dictionary models

[edit] Properties Service (TBD)

  1. read/write of node
    1. properties
    2. assocs
    3. etc

[edit] Thumbnail Service

[edit] Data

[edit] Thumbnail Details

Contains the name of the thumbnail and the URL to the thumbnail content. Only the thumbnail name is madatory, other data is present if appropriate.

JSON Example:

{
   "thumbnailName" : "webpreview",
   "url" : "/alfresco/service/api/node/workspace/SpacesStore/43170404-5d87-4d90-8587-55113bf7ec4f/content/thumbnails/webpreview"
}

[edit] Resources

[edit] Thumbnail Collection

The collection of thumbnails for a given nodes content property.

Methods:

GET /node/{store_type}/{store_id}/{id}/content{property}/thumbnails 
      <= ThumbnailDetails[]

GET /path/{store_type}/{store_id}/{id}/content{property}/thumbnails
      <= ThumbnailDetails[]
POST /node/{store_type}/{store_id}/{id}/content{property}/thumbnails
      ?as={async?}      
      => ThumbnailDetails (only thumnbnail name is required)
      <= ThumbnailDetails

POST /path/{store_type}/{store_id}/{id}/content{property}/thumbnails
      ?as={async?}
      => ThumbnailDetails (only thumnbnail name is required)
      <= ThumbnailDetails

[edit] Thumbnail

GET /node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname} 
      ?qc={queuecreate?}&fc={forcecreate?}&ph={placeholder?}
      <= BinaryContent | 404

GET /path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}
      ?qc={queuecreate?}&fc={forcecreate?}&ph={placeholder?}
      <= BinaryContent | 404
      
PUT /node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}
        ?as={async?}

PUT /path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}
        ?as={async?}
DELETE /node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname} 

DELETE /path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}

[edit] Tagging Service

[edit] Data

Also see Node

[edit] Tag Scope

{
   "node" : "workspace://SpacesStore/123-123-123".
   "lastupdated" : { ... date ... },
   "tags" : "/../../tags"
}

[edit] Tag Map

{
   "tagName1" : 12,
   "tagName2" : 10,
   "tagName3" : 2,
}

[edit] Resources

[edit] Tag Collection

GET /api/tags/{store_type}/{store_id}
   ?tf={tag_filter?}
   <= String[]
GET /api/tags/{store_type}/{store_id}/{tag}/nodes
   <= Node[]
GET /api/tags/{store_type}/{store_id}/{id}/{tag}/nodes 
   <= Node[]

[edit] Node Tag Collection

GET /api/node/{store_type}/{store_id}/{id}/tags 
   <= String[]

GET /api/path/{store_type}/{store_id}/{id}/tags
   <= String[]     
POST /api/node/{store_type}/{store_id}/{id}/tags 
   => String[]
   <= String[]

POST /api/path/{store_type}/{store_id}/{id}/tags
   => String[]
   <= String[]  

[edit] Tag Scope

TODO: The node specific urls should probably use /api/tagscopes/node/... instead of /api/tagscopes/...

POST /api/tagscopes
   => Node
GET /api/tagscopes/{store_type}/{store_id}/{id}
   <= TagScope
DELETE /api/tagscopes/{store_type}/{store_id}/{id}
GET /api/tagscopes/{store_type}/{store_id}/{id}/tags
   ?tn={topN}
   <= TagMap

GET /api/tagscopes/site/{short_name}/tags
   ?tn={topN}
   <= TagMap

GET /api/tagscopes/site/{short_name}/{container}/tags
   ?tn={topN}
   <= TagMap

[edit] Preferences Service

[edit] Data

[edit] Preference Set

{
   "alfresco" :
   {
      "myComponent" : 
      {
         "StringPref" : "myPrefValue",
         "BooleanPref" : true
      },
      "myOtherComponent" :
      {
         "NumberPref" : 12
      }
   },
   "myPrefWithNoNamespace" : "someValue"
}

[edit] Resources

[edit] Users Preference Set

GET /api/people/{userid}/preferences
   ?pf={preferencefilter?}
   <= PreferenceSet

Gets all the preferences set for user. All preference values are returned in a preference set.

The name filter can be used to restrict the set of returned preferences. It can be a partial name, specifying part of the preferences namespace. (eg: ?nf=alfresco.myComponent will return just preference values for alfresco.myComponent) The full preference name can be specified to return only one preference value.

POST /api/people/{userid}/preferences
   => PreferenceSet
DELETE /api/people/{userid}/preferences
   ?pf={preferencefilter?}

[edit] Discussion Service

Provides methods to fetch, create and update forum posts. Posts are hierarchical, a post can be created as a reply to another post.


[edit] Data objects

=> Forum

{
   "name" : "name",
}


<= Forum

{
   "nodeRef" : "<nodeRef>",
   "postsURI" : "URI to fetch the posts",
   "name" : "myForum",
}


=> Post

{
   "title" : "title",
   "content" : "content",
   "tags" : [ "ECM", "Alfresco" ]
}

Notes:
 * "" or [] will be used for fields that are not specified
 * tags sets the set of tags, replacing the old set of tags


<= Post

{
   /* Top-level posts only data */
   "name" : "<name of the post>",
   "totalReplyCount" : 10,
   "lastReplyBy" : "<date>",    // only available if totalReplyCount > 0
   "lastReplyOn" : "<date>",    // only available if totalReplyCount > 0
   "tags" : [ "Alfresco", "ECM" ],

   /* Fields available for all posts */
   "url" : "/api/forum/post/node/{store_type}/{store_id}/{id}",
   "repliesUrl" : "/api/forum/post/node/{store_type}/{store_id}/{id}/replies",
   "nodeRef" : "<nodeRef>",
   "title" : "<title>",
   "createdOn" : "<date>",
   "modifiedOn" : "<date>",
   "author" : "<username>",
   "isUpdated" : true/false,
   "updatedOn" : "<date>", // only available if isUpdated==true
   "content" : "<content>",
   "replyCount" : 10,      // direct replies to this post
   "permissions" : [ "edit": true, "delete" : true, "reply" : true ]
}

Notes:
 * Only top-level posts support tagging for now
 * Only top-level posts have totalRepliesCount, lastReplyOn, lastReplyBy fields
 * In case there are no replies, lastReplyOn and lastReplyBy won't be returned
 * The "name" value of top-level posts can be used as part of the path in site/container/path urls to fetch the post


<= Reply

{
   /* Exactly the same information as in the post structure above */
   <post properties>

   /* If children are returned as well, they will be contained in following array */
   children: []
}


[edit] Methods

Use following methods to create and manage forums.

Fetch all forums in the system or forums located at a specific location

GET /api/forums
   <= Forum[]

GET /api/forum/node/{store_type}/{store_id}/{id}/forums
   <= Forum[]

GET /api/forum/site/{site}/{container}{path?}/forums
   <= Forum[]

GET /api/forum/{path}/forums
   <= Forum[]

POST /api/forum/node/{store_type}/{store_id}/{id}/forums
   => Forum
   <= Forum

Comment (MR): this could also be /api/node .... /forums


Get the forum details

GET /api/forum/node/{store_type}/{store_id}/{id}
   <= Forum

GET /api/forum/site/{site}/{container}{path?}
   <= Forum

GET /api/forum/{path}
   <= Forum


Use following methods to manage forum posts:

Get all posts (optinally filtered by a tag):

GET /api/forum/node/{store_type}/{store_id}/{id}/posts?tag={tag}
   <= Post[]

GET /api/forum/site/{site}/{container}{path?}/posts?tag={tag}
   <= Post[]


Get new posts:

GET /api/forum/node/{store_type}/{store_id}/{id}/posts/new?numdays={numdays}
   <= Post[]

GET /api/forum/site/{site}/{container}{path?}/posts/new?numdays={numdays}
   <= Post[]

Get hot posts:

GET /api/forum/node/{store_type}/{store_id}/{id}/posts/hot
   <= Post[]

GET /api/forum/site/{site}/{container}{path?}/posts/hot
   <= Post[]


Get posts for current user:

GET /api/forum/node/{store_type}/{store_id}/{id}/posts/myposts
   <= Post[]

GET /api/forum/site/{site}/{container}{path?}/posts/myposts
   <= Post[]

Notes:
 * All methods support pagination using startIndex and pageSize parameters


Adding a new post to a forum:

POST /api/forum/node/{store_type}/{store_id}/{id}/posts   (maps to a topic/post in the forum model)
   => Post
   <= Post


Fetch the replies for a post:

GET /api/forum/post/node/{store_type}/{store_id}/{id}/replies?levels={levels}
   <= Reply[]

GET /api/forum/post/site/{site}/{container}{path?}/replies?levels={levels}
   <= Reply[]

Notes
 * You can fetch several levels of replies at once, specified by the levels param.
 * If you don't specify the levels, only the direct replies are returned


Adding a reply to a post:

POST /api/forum/post/node/{store_type}/{store_id}/{id}/replies
   => Post
   <= Post


Get, update and delete a post (regardless whether it is a top-level post or a reply post):

GET /api/forum/post/node/{store_type}/{store_id}/{id}
   <= Post

PUT /api/forum/post/node/{store_type}/{store_id}/{id}
   => Post
   <= Post

DELETE /api/forum/post/node/{store_type}/{store_id}/{id}
   => Post
   <= 200|? 

[edit] Blogging Service

This API provides two kind of methods:

* Management of external blog configuration data as well as publishing/updating/unpublishing a post to it
* Management of blog posts (getting a list of posts in a space, creating, updating and deleting posts)

[edit] Data objects

=> ExternalBlogConfiguration

{
   "type" : "<blog type, currently either "typepad" or "wordpress">",
   "id" : "<id of the blog>",
   "name" : "<blog name>",
   "description" : "<blog description>",
   "username" : "<username>",
   "password" : "<password>",
}


<= ExternalBlogConfiguration

{
   "blogPostsUrl" : "/api/blog/node/{store_type}/{store_id}/{id}/posts",
   "type" : "<blog type, currently either "typepad" or "wordpress">",
   "id" : "<id of the blog>",
   "name" : "<blog name>",
   "description" : "<blog description>",
   "url" : "<url to the external blog>",
   "username" : "<username>",
   "password" : "<password>",
}


=> BlogPost

{
   "draft" : false/true,
   "title" : "title",
   "content" : "content",
   "tags" : [ "ECM", "Alfresco" ]
}

Notes:
 * Once a post change from draft to non-draft it cannot be changed back to draft
 * If any of the other fields is not specified, a default value ("" or []) will be used as value


<= BlogPost

{
   "url" : "/api/blog/post/node/{store_type}/{store_id}/{id}",
   "commentsUrl" : "/api/node/{store_type}/{store_id}/{id}/comments",
   "nodeRef" : "<nodeRef>",
   "name" : "<name>",
   "title" : "<title>",
   "content" : "<content>",
   "author" : "<username>",
   "createdOn" : "<date>",
   "modifiedOn" : "<date>",
   "permissions" : [ "edit" : true, "publishExt" : true, "delete" : true ],
   "commentCount" : 10,
   "tags" : [ "ECM", "Alfresco"],
   
   /* draft or internally published */
   "isDraft" : true/false,
   "releasedOn" : "<date>",     // only available if isDraft==false
   
   /* Updated flag - always false for draft posts */
   "isUpdated" : true/false,
   "updatedOn" : "<date>",      // only available if isUpdated==true
   
   /* External publishing information */
   "isPublished" : true/false,
   "publishedOn" : "<date>",    // only available if isPublished==true
   "updatedOn" : "<date>",      // only available if isPublished==true
   "postId" : "<id of the external post>",
   "postLink" : "<link to the post>",
   "outOfDate" : true/false,    // whether the external post is older than then internal post
}

Notes:
 * releasedOn is only available if isDraft==false
 * updatedOn is only available if isUpdated==true
 * updatedOn is always false for draft posts
 * publishedOn and updatedOn are only available if isPublished==true


<= PostsPerMonthData

{
   "beginOfMonth" : "<date>",      // date marking the begin of the month
   "endOfMonth" : "<date>",        // date marking the end of the month
   "year" : 2008,
   "month" : 6,                    // month index. Attention: January => 0
   "postCount" : 0                 // number of posts
   "firstPostInMonth" : "<date>"   // date of the first post
}

[edit] Methods

Get information about the external blog configuration

GET /api/blog/node/{store_type}/{store_id}/{id}
   <= ExternalBlogConfiguration

GET /api/blog/site/{site}/{container}{path?}
   <= ExternalBlogConfiguration


Update external blog configuration data:

PUT /api/blog/node/{store_type}/{store_id}/{id}
   => ExternalBlogConfiguration
   <= ExternalBlogConfiguration

PUT /api/blog/site/{site}/{container}{path?}
   => ExternalBlogConfiguration
   <= ExternalBlogConfiguration


Get a list of posts for a blog

Get all posts (optionally filtered by tag and date range):

GET /api/blog/node/{store_type}/{store_id}/{id}/posts?tag={tag}&fromDate={fromDate}&toDate={toDate}
   <= BlogPost[]

GET /api/blog/site/{site}/{container}{path?}/posts?tag={tag}&fromDate={fromDate}&toDate={toDate}
   <= BlogPost[]


Get new posts:

GET /api/blog/node/{store_type}/{store_id}/{id}/posts/new?numdays={numdays}
   <= BlogPost[]

GET /api/blog/site/{site}/{container}{path?}/posts/new?numdays={numdays}
   <= BlogPost[]


Get draft posts of the current user:

GET /api/blog/node/{store_type}/{store_id}/{id}/posts/mydrafts
   <= BlogPost[]

GET /api/blog/site/{site}/{container}{path?}/posts/mydrafts
   <= BlogPost[]


Get posts published by the current user:

GET /api/blog/node/{store_type}/{store_id}/{id}/posts/mypublished
   <= BlogPost[]

GET /api/blog/site/{site}/{container}{path?}/posts/mypublished
   <= BlogPost[]


Get externally published posts:

GET /api/blog/node/{store_type}/{store_id}/{id}/posts/publishedext
   <= BlogPost[]

GET /api/blog/site/{site}/{container}{path?}/posts/publishedext
   <= BlogPost[]


Get the number of posts per month:

GET /api/blog/node/{store_type}/{store_id}/{id}/postspermonth
   <= PostsPerMonthData[]

GET /api/blog/site/{site}/{container}{path?}/postspermonth
   <= PostsPerMonthData[]

Note:
 * If the blog does not contain posts yet, an empty month object for the current month is returned


Add a blog post:

POST /api/blog/node/{store_type}/{store_id}/{id}/posts
   => BlogPost
   <= BlogPost

POST /api/blog/site/{site}/{container}{path?}/posts
   => BlogPost
   <= BlogPost


Get, update and delete a blog post:

GET /api/blog/post/node/{store_type}/{store_id}/{id}
   <= BlogPost

GET /api/blog/post/site/{site}/{container}{path?}
   <= BlogPost

PUT /api/blog/post/node/{store_type}/{store_id}/{id}
   => BlogPost
   <= BlogPost

PUT /api/blog/post/site/{site}/{container}{path?}
   => BlogPost
   <= BlogPost

DELETE /api/blog/post/node/{store_type}/{store_id}/{id}
   => BlogPost
   <= 200|? 

DELETE /api/blog/post/site/{site}/{container}{path?}
   => BlogPost
   <= 200|? 

[edit] Comment Service

This API allows adding comments to any node in Alfresco.

The fm:forum model is currently used to store comments. The fm:discussable aspect is added to the node and then a topic called "Comments" added to it. All comments get stored as fm:post nodes into that topic.

The advantage is that comments will also be accessible from the standard webclient.

[edit] Data objects

=> Comment

{
   "title" : "title",
   "content" : "content"
}

<= Comment

{
   "url" : "/api/comment/node/workspace/SiteStore/fba4e60a-730b-487e-a5a1-e91d16fcc9da",
   "nodeRef" : "<nodeRef>",
   "name" : "<name of file representing comment>",
   "title" : "title",
   "content" : "Comment content, html",
   "author" : "username",
   "createdOn" : "<date>",
   "modifiedOn" : "<date>",
   "isUpdated" : true/false,
   "permissions" : [
      "edit": "true",
      "delete" : "true"
   ]
}


[edit] Methods

Fetching of comments for a node

GET /api/node/{store_type}/{store_id}/{id}/comments
   <= Comment[]

Adding a comment to a node

POST /api/node/{store_type}/{store_id}/{id}/comments
   => Comment
   <= Comment

Getting, updating and deleting a comment:

GET /api/comment/node/{store_type}/{store_id}/{id}
   <= Comment

PUT /api/comment/node/{store_type}/{store_id}/{id}
   => Comment
   <= Comment

DELETE /api/comment/node/{store_type}/{store_id}/{id}
   <= HTTP status