WP Annotations
Create a new annotation.
Request body
Post ID.
Parent ID, if it’s a reply.
Author’s user ID. Requires ability to edit_others_annotations
. Default is that of the authenticated user.
Author’s name. Default is that of the authenticated user.
Author’s email address. Default is that of the authenticated user.
Author’s URL. Default is that of the authenticated user.
Author’s IP address. Requires ability to edit_others_annotations
. Default is auto-detected using $_SERVER['REMOTE_ADDR']
.
Author’s user-agent (browser). Requires ability to edit_others_annotations
. Default is auto-detected using $_SERVER['HTTP_USER_AGENT']
.
Comment content. Back-end annotations are not spam or flood checked. However, they do have a maximum length.
W3C annotation selector. Max JSON-encoded size is 16kb. SVG selectors allow up to 128kbs, but those are currently disabled, pending a security review. Regarding selectors in JavaScript, see suggestion here: https://jsfiddle.net/jaswrks/1cLaeyfd/
{
"type": "CssSelector",
"value": "#foo > .bar"
}
{
"type": "CssSelector",
"value": "#foo > ul:nth-child(2) > li:nth-child(3)",
"refinedBy": {
"type": "TextPositionSelector",
"start": 412,
"end": 667
}
}
{
"type": "RangeSelector",
"startSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 0,
"end": 0
}
},
"endSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 100,
"end": 100
}
}
}
Type of selector.
Can select text nodes!
Pending a security review.
Required for CSS and XPath types. Other properties apply to other types.
The default status for a new annotation is approve
. To create an annotation with a restricted status (hold
, 0
, spam
, trash
) you must be able to edit_others_annotations
.
Held for moderation. Same as ‘0’.
Same as ‘1’ and ‘approve’.
Same as ‘1’ and ‘approved’.
Archived as resolved.
Archived as rejected.
Archived for another reason.
Annotation spam.
In the trash.
Any comment meta properties registered using register_meta().
{
"my_key": "my value",
"another_key": {
"another": "value"
}
}
Any value.
Examples
i.e., Also supports all the same arguments as the REST API for comments.
{
"post": 1,
"content": "Hello world!",
"via": "gutenberg"
}
{
"post": 1,
"content": "Hello world!",
"via": "gutenberg",
"selector": {
"type": "CssSelector",
"value": "#foo > .bar"
}
}
{
"post": 1,
"author": 1,
"author_name": "John Smith",
"author_email": "john@example.com",
"author_url": "https://john.example.com/",
"author_ip": "127.0..0.1",
"author_user_agent": "Mozilla/5.0",
"content": "Hello world!",
"via": "gutenberg",
"selector": {
"type": "CSSSelector",
"value": "#foo > ul:nth-child(2) > li:nth-child(3)",
"refinedBy": {
"type": "TextPositionSelector",
"start": 412,
"end": 667
}
}
}
{
"post": 1,
"author": 1,
"author_name": "John Smith",
"author_email": "john@example.com",
"author_url": "https://john.example.com/",
"author_ip": "127.0..0.1",
"author_user_agent": "Mozilla/5.0",
"content": "Hello world!",
"via": "gutenberg",
"selector": {
"type": "RangeSelector",
"startSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 0,
"end": 0
}
},
"endSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 100,
"end": 100
}
}
},
"meta": {
"my_key": "my value",
"another_key": {
"another": "value"
}
}
}
{id}
Get a single annotation by ID.
Path variables
Annotation ID.
Request parameters
REST API context.
?context=view
{
"id": 1,
"post": 1,
"parent": 0,
"author": 1,
"author_name": "John",
"author_url": "https://example.john.com/",
"date": "2018-01-11T11:09:03",
"date_gmt": "2018-01-11T11:09:03",
"content": {
"rendered": "<p>Hello world!</p>\n"
},
"link": "https://example.com/hello-world/#comment-1",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": {
"type": "CssSelector",
"value": "#foo > .bar"
},
"_links": {
"self": [
{
"href": "https://example.com/wp-json/wp/v2/annotations/1"
}
],
"collection": [
{
"href": "https://example.com/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://example.com/wp-json/wp/v2/users/1"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://example.com/wp-json/wp/v2/posts/1"
}
]
}
}
?context=edit
{
"id": 1,
"post": 1,
"parent": 0,
"author": 1,
"author_name": "John",
"author_email": "john@example.com",
"author_url": "https://example.john.com/",
"author_ip": "192.168.42.1",
"author_user_agent": "Mozilla/5.0",
"date": "2018-01-11T11:09:03",
"date_gmt": "2018-01-11T11:09:03",
"content": {
"rendered": "<p>Hello world!</p>\n",
"raw": "Hello world!"
},
"link": "https://example.com/hello-world/#comment-1",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": {
"type": "CssSelector",
"value": "#foo > .bar"
},
"_links": {
"self": [
{
"href": "https://example.com/wp-json/wp/v2/annotations/1"
}
],
"collection": [
{
"href": "https://example.com/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://example.com/wp-json/wp/v2/users/1"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://example.com/wp-json/wp/v2/posts/1"
}
]
}
}
{id}
Update annotation properties.
Path variables
Annotation ID.
Request body
Author’s user ID. Requires ability to edit_others_annotations
.
Author’s name. Requires ability to edit_others_annotations
.
Author’s email address. Requires ability to edit_others_annotations
.
Author’s URL. Requires ability to edit_others_annotations
.
Author’s IP address. Requires ability to edit_others_annotations
.
Author’s user-agent (browser). Requires ability to edit_others_annotations
.
Comment content. Back-end annotations are not spam or flood checked. However, they do have a maximum length.
W3C annotation selector. Max JSON-encoded size is 16kb. SVG selectors allow up to 128kbs, but those are currently disabled, pending a security review. Regarding selectors in JavaScript, see suggestion here: https://jsfiddle.net/jaswrks/1cLaeyfd/
{
"type": "CssSelector",
"value": "#foo > .bar"
}
{
"type": "CssSelector",
"value": "#foo > ul:nth-child(2) > li:nth-child(3)",
"refinedBy": {
"type": "TextPositionSelector",
"start": 412,
"end": 667
}
}
{
"type": "RangeSelector",
"startSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 0,
"end": 0
}
},
"endSelector": {
"type": "XPathSelector",
"value": "//*[@id='c9xi4jhi']/text()[1]",
"refinedBy": {
"type": "TextPositionSelector",
"start": 100,
"end": 100
}
}
}
Type of selector.
Can select text nodes!
Pending a security review.
Required for CSS and XPath types. Other properties apply to other types.
To set a restricted status (hold
, 0
, spam
, trash
) you must be able to edit_others_annotations
. However, if the authenticated user is the annotation author, and they can delete_annotation
, trash
becomes available.
Held for moderation. Same as ‘0’.
Same as ‘1’ and ‘approve’.
Same as ‘1’ and ‘approved’.
Archived as resolved.
Archived as rejected.
Archived for another reason.
Annotation spam.
In the trash.
Any comment meta properties registered using register_meta().
{
"my_key": "my value",
"another_key": {
"another": "value"
}
}
Any value.
Examples
i.e., Also supports all the same arguments as the REST API for comments, except that post
and parent
are currently readonly in annotation comment types.
{
"content": "Hello world!"
}
{
"status": "resolve"
}
{
"status": "reject"
}
{
"status": "archive"
}
{
"author": 1,
"author_name": "John Smith",
"author_email": "john@example.com",
"author_url": "https://john.example.com/",
"author_ip": "127.0..0.1",
"author_user_agent": "Mozilla/5.0",
"content": "Hello world!",
"status": "approved",
"via": "gutenberg",
"selector": {
"type": "CSSSelector",
"value": "#foo > ul:nth-child(2) > li:nth-child(3)",
"refinedBy": {
"type": "TextPositionSelector",
"start": 412,
"end": 667
}
},
"meta": {
"my_key": "my value",
"another_key": {
"another": "value"
}
}
}
Also supports all the same arguments as the REST API for comments; e.g., pagination, order.
Request parameters
REST API context.
Post ID. Array or comma-delimited string.
Parent annotation ID. Array or comma-delimited string. If hierarchical
is given, parent
defaults to 0
unless defined explicitly. This way hiearchical queries start from top-level annotations by default.
Author ID. Requires ability to edit_others_annotations
. However, any authenticated user can set this to their own user ID, which allows them to query their own annotations.
Status. Array or comma-delimited string. To query a restricted status (hold
, 0
, spam
, trash
) you must be able to edit_others_annotations
. However, if author
is given, and the authenticated user is that author, and they can delete_annotations
, trash
becomes available.
Annotation client identifier. Array or comma-delimited string.
Hierarchical response format?
All children (deeply) are simply appended.
Each annotation includes a children
property containing an array of any replies.
?context=view&hierarchical=threaded
[
{
"id": 1,
"post": 1,
"parent": 0,
"author": 1,
"author_name": "John",
"author_url": "https://john.example.com",
"date": "2018-01-11T12:21:10",
"date_gmt": "2018-01-11T12:21:10",
"content": {
"rendered": "<p>Hello world!</p>\n"
},
"link": "https://example.com/hello-world/#comment-1",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": {
"type": "CssSelector",
"value": "#foo"
},
"_links": {
"self": [
{
"href": "https://example.com/wp-json/wp/v2/annotations/1"
}
],
"collection": [
{
"href": "https://example.com/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://example.com/wp-json/wp/v2/users/1"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://example.com/wp-json/wp/v2/posts/1"
}
]
},
"children": [
{
"id": 2,
"post": 1,
"parent": 1,
"author": 2,
"author_name": "Mary",
"author_url": "https://mary.example.com",
"date": "2018-01-11T12:21:10",
"date_gmt": "2018-01-11T12:21:10",
"content": {
"rendered": "<p>Hello world!</p>\n"
},
"link": "https://example.com/hello-world/#comment-2",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": null,
"_links": {
"self": [
{
"href": "https://example.com/wp-json/wp/v2/annotations/2"
}
],
"collection": [
{
"href": "https://example.com/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://example.com/wp-json/wp/v2/users/2"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://example.com/wp-json/wp/v2/posts/1"
}
]
},
"children": []
}
]
}
]
?context=edit&hierarchical=flat
[
{
"id": 1,
"post": 1,
"parent": 0,
"author": 1,
"author_name": "John",
"author_email": "john@example.com",
"author_url": "https://john.example.com",
"author_ip": "192.168.42.1",
"author_user_agent": "Mozilla/5.0",
"date": "2018-01-11T12:21:10",
"date_gmt": "2018-01-11T12:21:10",
"content": {
"rendered": "<p>Hello world!</p>\n",
"raw": "Hello world!"
},
"link": "https://wp.vm/hello-world/#comment-1",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": {
"type": "CssSelector",
"value": "#foo"
},
"_links": {
"self": [
{
"href": "https://wp.vm/wp-json/wp/v2/annotations/1"
}
],
"collection": [
{
"href": "https://wp.vm/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://wp.vm/wp-json/wp/v2/users/1"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://wp.vm/wp-json/wp/v2/posts/1"
}
]
}
},
{
"id": 2,
"post": 1,
"parent": 1,
"author": 2,
"author_name": "Mary",
"author_email": "mary@example.com",
"author_url": "https://mary.example.com",
"author_ip": "192.168.42.1",
"author_user_agent": "Mozilla/5.0",
"date": "2018-01-11T12:21:10",
"date_gmt": "2018-01-11T12:21:10",
"content": {
"rendered": "<p>Hello world!</p>\n",
"raw": "Hello world!"
},
"link": "https://wp.vm/hello-world/#comment-2",
"status": "approved",
"type": "annotation",
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=24&d=mm&r=g",
"48": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=48&d=mm&r=g",
"96": "https://secure.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=96&d=mm&r=g"
},
"meta": [],
"via": "gutenberg",
"selector": null,
"_links": {
"self": [
{
"href": "https://wp.vm/wp-json/wp/v2/annotations/2"
}
],
"collection": [
{
"href": "https://wp.vm/wp-json/wp/v2/annotations"
}
],
"author": [
{
"embeddable": true,
"href": "https://wp.vm/wp-json/wp/v2/users/2"
}
],
"up": [
{
"embeddable": true,
"post_type": "post",
"href": "https://wp.vm/wp-json/wp/v2/posts/1"
}
]
}
}
]
Meta-caps check specific annotations by ID.
current_user_can( 'edit_annotation', 53254 )
read_annotation
edit_annotation
delete_annotation
This custom meta-cap checks a post by ID.
current_user_can( 'create_annotation', 123 )
create_annotation
General pseudo-caps that optionally support a post ID arg.
current_user_can( 'read_annotations', 123 )
current_user_can( 'read_annotations' )
read_annotations
Other general pseudo-caps.
current_user_can( 'edit_others_annotations' )
create_annotations
delete_annotations
delete_others_annotations
delete_private_annotations
delete_published_annotations
edit_annotations
edit_others_annotations
edit_private_annotations
edit_published_annotations
publish_annotations
read_private_annotations