WP Annotation Posts

Front and back-end annotations implemented as a custom post type. Conforms to the W3C annotation data model for annotation selectors and maintains some parity with the W3C annotation object model and protocol — while still doing things the WordPress way, which maximizes compatibility with WP REST API utilities, including those in JavaScript.
Pull Request

https://github.com/WordPress/gutenberg/pull/4385
This is an alternative to annotations as a custom comment type in #4386

Create Annotation
POST /wp-json/wp/v2/annotations

Create a new annotation.

Note: While the API supports both front and back-end annotations, as a security precaution, front-end annotations are disabled for now. At this time, the main focus is on back-end annotations only.

Request parameters

parent_post_password
string optional

Parent post password (if protected and authenticated user is unable to edit it, but is allowed to annotate; e.g., edge case for front-end annotations). Defaults to current password cookie.

Default:
[cookie value]

Request body

Object
properties
parent_post
integer required

Non-annotation post ID.

parent_post_target
One of

A front or back-end annotation?

string
Enumeration:
[empty string]

Front-end (default).

admin

Back-end annotation.

Default:
[empty string]
parent
integer

Parent ID; i.e., to create a reply.

Default:
0
author
integer

User ID. Default is that of the authenticated user. Setting this to anything other than the authenticated user’s ID requires edit_others_annotations.

Example:
1
creator
string

Non-numeric creator ID/slug; i.e., if created by a specific feature or plugin.

Max length: 250
Pattern: [a-z0-9_-]+
Example:
yoast
creator_meta
Object

Required only if the creator field is given.

display_name
string

Display name.

Max length: 250
Example:
Yoast
image_url
string

Square image/icon URL.

Max length: 2,000
Example:
https://example.com/96x96.png
content
string required

Post content markup. @TODO: Front-end annotation content should be scrutinized; i.e., treated like a comment instead of like a post in that respect.

Min length: 1
Example:
Hello world!
via
string
Max length: 250
Pattern: [a-zA-Z0-9:_-]+
Example:
gutenberg
selector
Object

W3C annotation selector. Max JSON-encoded size is 16kb. SVG selectors allow up to 128kbs, but those are currently disabled, pending a security review. See also: https://jsfiddle.net/jaswrks/jpcL1t8a/

Examples:
{
    "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": "CssSelector",
          "value": "#foo > ul:nth-child(2) > li:nth-child(2)"
    },
    "endSelector": {
          "type": "CssSelector",
          "value": "#foo > ul:nth-child(2) > li:nth-child(8)"
    }
}
type
string

Type of selector.

Enumeration:
FragmentSelector
CssSelector
XPathSelector

Can select text nodes!

TextQuoteSelector
TextPositionSelector
DataPositionSelector
SvgSelector

Pending a security review.

RangeSelector
value
string

Required for CssSelector type. Other properties apply to other types.

status
string

Annotation post status.

Enumeration:
publish

Published.

private

Published (private access only).

future

Pending future publication.

draft

Draft, unpublished.

auto-draft

Draft revision, unpublished.

pending

Needs review, unpublished.

inherit

Revisions inherit parent status.

trash

In the trash.

Default:
draft
substatus
string

Annotation substatus. For example, a published annotation can be archived (via substatus) and therefore tucked away, but still visible to others in one way or another. This is possible because the annotation’s main status is still publish, whereas substatus can be one of the following.

Enumeration:
[empty string]

Open (default).

resolve

Archived as resolved.

reject

Archived as rejected.

archive

Archived for another reason.

Default:
[empty string]
meta
Object

Any meta properties registered using register_meta().

Example:
{
    "my_key": "my value",
    "another_key": {
        "another": "value"
    }
}
pattern properties
[a-z0-9_-]+
Any of

Any value.

string
number
Array of unknown
Object
additional properties
Object
Examples

i.e., Also supports all properties associated with post types in the REST API.

Example 1
Example 2
Example 3
Example 4
{
	"parent_post": 1,
	"parent_post_target": "admin",

	"content": "Hello world!",
	"status": "publish",

    "via": "gutenberg"
}
{
	"parent_post": 1,
	"parent_post_target": "admin",

	"content": "Hello world!",
	"status": "publish",

    "via": "gutenberg",
    "selector": {
        "type": "CssSelector",
        "value": "#foo > .bar"
    }
}
{
    "parent_post": 1,
    "parent_post_target": "admin",

    "author": 1,
    "creator": "yoast",
    "creator_meta": {
        "display_name": "Yoast",
        "image_url": "https://example.com/96x96.png"
    },
    "via": "gutenberg",

    "content": "Hello world!",
    "selector": {
        "type": "CSSSelector",
        "value": "#foo > ul:nth-child(2) > li:nth-child(3)",
        "refinedBy": {
              "type": "TextPositionSelector",
              "start": 412,
              "end": 667
        }
    }

    "status": "publish",
    "substatus": ""
}
{
    "parent_post": 1,
    "parent_post_target": "admin",

    "author": 1,
    "creator": "yoast",
    "creator_meta": {
        "display_name": "Yoast",
        "image_url": "https://example.com/96x96.png"
    },
    "via": "gutenberg",

    "content": "Hello world!",
    "selector": {
        "type": "RangeSelector",
        "startSelector": {
              "type": "CssSelector",
              "value": "#foo > ul:nth-child(2) > li:nth-child(2)"
        },
        "endSelector": {
              "type": "CssSelector",
              "value": "#foo > ul:nth-child(2) > li:nth-child(8)"
        }
    },

    "status": "publish",
    "substatus": "",

    "meta": {
        "my_key": "my value",
        "another_key": {
            "another": "value"
        }
    }
}
Get Annotation
GET /wp-json/wp/v2/annotations/{id}

Get a single annotation by ID.

Path variables

id
integer required

Annotation ID.

Request parameters

context
string optional

REST API context.

Enumeration:
view
edit
embed
Default:
view
parent_post_password
string optional

Parent post password (if protected and authenticated user is unable to edit it, but is allowed to view). Defaults to current password cookie.

Default:
[cookie value]
Example 1
Example 2

?context=view

{
    "id": 1,
    "date": "2018-01-11T20:23:33",
    "date_gmt": "2018-01-11T20:23:33",
    "guid": {
        "rendered": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/"
    },
    "modified": "2018-01-11T20:23:33",
    "modified_gmt": "2018-01-11T20:23:33",
    "slug": "a5a57c7c5a5f0c",
    "status": "publish",
    "type": "wp_annotation",
    "link": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
    "content": {
        "rendered": "<p>Hello world!</p>\n",
        "protected": false
    },
    "author": 1,
    "parent": 0,
    "template": "",
    "meta": [],
    "revisions": null,
    "parent_post": 1,
    "parent_post_target": "admin",
    "via": "gutenberg",
    "author_meta": {
        "display_name": "John Smith",
        "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
    },
    "creator": "yoast",
    "creator_meta": {
        "display_name": "Yoast",
        "image_url": "https://example.com/96x96.png"
    },
    "selector": {
		"type": "CssSelector",
		"value": "#foo"
	},
    "substatus": "archive",
    "last_substatus_time": 1515741301,
    "substatus_history": [
        {
            "identity": "yoast",
            "identity_meta": {
                "display_name": "Yoast",
                "image_url": "https://example.com/96x96.png"
            },
            "time": 1515741301,
            "old": "",
            "new": "archive"
        }
    ],
    "_links": {
        "self": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/annotations/1"
            }
        ],
        "collection": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/annotations"
            }
        ],
        "about": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https://wp.vm/wp-json/wp/v2/users/1"
            }
        ],
        "wp:attachment": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/media?parent=1"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
            }
        ]
    }
}

?context=edit

{
    "id": 1,
    "date": "2018-01-11T20:23:33",
    "date_gmt": "2018-01-11T20:23:33",
    "guid": {
        "rendered": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
        "raw": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/"
    },
    "modified": "2018-01-12T07:15:01",
    "modified_gmt": "2018-01-12T07:15:01",
    "password": "",
    "slug": "a5a57c7c5a5f0c",
    "status": "publish",
    "type": "wp_annotation",
    "link": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
    "content": {
        "raw": "Hello world!",
        "rendered": "<p>Hello world!</p>\n",
        "protected": false
    },
    "author": 1,
    "parent": 0,
    "template": "",
    "meta": [],
    "revisions": null,
    "parent_post": 1,
    "parent_post_target": "admin",
    "via": "gutenberg",
    "author_meta": {
        "display_name": "John Smith",
        "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
    },
    "creator": "yoast",
    "creator_meta": {
        "display_name": "Yoast",
        "image_url": "https://example.com/96x96.png"
    },
    "selector": {
		"type": "CssSelector",
		"value": "#foo"
	},
    "substatus": "archive",
    "last_substatus_time": 1515741301,
    "substatus_history": [
        {
            "identity": "yoast",
            "identity_meta": {
                "display_name": "Yoast",
                "image_url": "https://example.com/96x96.png"
            },
            "time": 1515741301,
            "old": "",
            "new": "archive"
        }
    ],
    "_links": {
        "self": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/annotations/1"
            }
        ],
        "collection": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/annotations"
            }
        ],
        "about": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https://wp.vm/wp-json/wp/v2/users/1"
            }
        ],
        "wp:attachment": [
            {
                "href": "https://wp.vm/wp-json/wp/v2/media?parent=1"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
            }
        ]
    }
}
Update Annotation
PUT /wp-json/wp/v2/annotations/{id}

Update annotation properties.

Path variables

id
integer required

Annotation ID.

Request parameters

parent_post_password
string optional

Parent post password (if protected and authenticated user is unable to edit it, but is allowed to annotate; e.g., edge case for front-end annotations). Defaults to current password cookie.

Default:
[cookie value]

Request body

Object
properties
parent_post
integer

Non-annotation post ID.

parent_post_target
One of

A front or back-end annotation?

Default:
annotation
string
Enumeration:
[empty string]

Front-end.

admin

Back-end.

parent
integer

Parent ID; i.e., to make it a reply.

Example:
1
author
integer

User ID. Setting this to anything other than the authenticated user’s ID requires the ability to edit_others_annotations.

Example:
1
creator
string

Non-numeric creator ID/slug; i.e., if created by a specific feature or plugin.

Max length: 250
Pattern: [a-z0-9_-]+
Example:
yoast
creator_meta
Object

Required only if the creator field is given.

display_name
string

Display name.

Max length: 250
Example:
Yoast
image_url
string

Square image/icon URL.

Max length: 2,000
Example:
https://example.com/96x96.png
content
string

Post content markup. @TODO: Front-end annotation content should be scrutinized; i.e., treated like a comment instead of like a post in that respect.

Min length: 1
Example:
Hello world!
via
string
Max length: 250
Pattern: [a-zA-Z0-9:_-]+
Example:
gutenberg
selector
Object

W3C annotation selector. Max JSON-encoded size is 16kb. SVG selectors allow up to 128kbs, but those are currently disabled, pending a security review. See also: https://jsfiddle.net/jaswrks/jpcL1t8a/

Examples:
{
    "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": "CssSelector",
          "value": "#foo > ul:nth-child(2) > li:nth-child(2)"
    },
    "endSelector": {
          "type": "CssSelector",
          "value": "#foo > ul:nth-child(2) > li:nth-child(8)"
    }
}
type
string

Type of selector.

Enumeration:
FragmentSelector
CssSelector
XPathSelector

Can select text nodes!

TextQuoteSelector
TextPositionSelector
DataPositionSelector
SvgSelector

Pending a security review.

RangeSelector
value
string

Required for CssSelector type. Other properties apply to other types.

status
string

Annotation post status.

Enumeration:
publish

Published.

private

Published (private access only).

future

Pending future publication.

draft

Draft, unpublished.

auto-draft

Draft revision, unpublished.

pending

Needs review, unpublished.

inherit

Revisions inherit parent status.

trash

In the trash.

substatus
string

Annotation substatus. For example, a published annotation can be archived (via substatus) and therefore tucked away, but still visible to others in one way or another. This is possible because the annotation’s main status is still publish, whereas substatus can be one of the following.

Enumeration:
[empty string]

Open (default).

resolve

Archived as resolved.

reject

Archived as rejected.

archive

Archived for another reason.

meta
Object

Any meta properties registered using register_meta().

Example:
{
    "my_key": "my value",
    "another_key": {
        "another": "value"
    }
}
pattern properties
[a-z0-9_-]+
Any of

Any value.

string
number
Array of unknown
Object
additional properties
Object
Examples

i.e., Also supports all properties associated with post types in the REST API.

Example 1
Example 2
Example 3
Example 4
Example 5
{
    "content": "Hello world!"
}
{
    "substatus": "resolve"
}
{
    "substatus": "reject"
}
{
    "substatus": "archive"
}
{
    "author": 1,
    "parent_post": 1,
    "parent_post_target": "admin",
    "parent": 0,
    "slug": "a5a57c7c5a5f0c",
    "status": "publish",
    "substatus": "archive",
    "content": "<p>Hello world!</p>\n",
    "creator": "yoast",
    "creator_meta": {
        "display_name": "Yoast",
        "image_url": "https://example.com/96x96.png"
    },
    "via": "gutenberg",
    "selector": {
		"type": "CssSelector",
		"value": "#foo"
	},
    "meta": {
        "my_key": "my value",
        "another_key": {
            "another": "value"
        }
    }
}
Delete Annotation
DELETE /wp-json/wp/v2/annotations/{id}

Delete a single annotation by ID.

Path variables

id
integer required

Annotation ID.

Request parameters

force
integer optional

Bypass trash and force deletion?

Enumeration:
0

Trash (default).

1

Permanently delete.

Default:
0
parent_post_password
string optional

Parent post password (if protected and the authenticated user is unable to edit it, but is allowed to delete — edge case).

Default:
[cookie value]
Query Annotations
GET /wp-json/wp/v2/annotations

Also supports all the same properties as the REST API for post types; e.g., pagination, order.

Request parameters

context
string optional

REST API context.

Enumeration:
view
edit
embed
Default:
view
parent_post
string required

Parent post ID. Array or comma-delimited string.

Example:
1,2,3
parent_post_target
string required

Parent post target. Array or comma-delimited string.

Example:
,admin
parent_post_password
string optional

Parent post password; i.e., if protected and the authenticated user is unable to edit it, but is allowed to view. Array or comma-delimited string. In the case of multiple passwords use an array, and the order given must match that of the parent_post parameter.

parent
string optional

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.

Example:
4,5,6
status
string optional

Annotation status. Array or comma-delimited string.

Default:
publish
Example:
publish,private
substatus
string optional

Annotation substatus. Array or comma-delimited string.

Default:
[empty string] (open)
Example:
,resolve,reject,archive
creator
string optional

Annotation creator. Array or comma-delimited string.

Example:
yoast
via
string optional

Annotation client identifier. Array or comma-delimited string.

Example:
gutenberg,other
hierarchical
string optional

Hierarchical response format? Array or comma-delimited string.

Enumeration:
flat

All children (deeply) are simply appended.

threaded

Each annotation includes a children property containing an array of any replies.

Example 1
Example 2

?context=view&hierarchical=threaded

[
    {
        "id": 1,
        "date": "2018-01-11T20:23:33",
        "date_gmt": "2018-01-11T20:23:33",
        "guid": {
            "rendered": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/"
        },
        "modified": "2018-01-11T20:23:33",
        "modified_gmt": "2018-01-11T20:23:33",
        "slug": "a5a57c7c5a5f0c",
        "status": "publish",
        "type": "wp_annotation",
        "link": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
        "content": {
            "rendered": "<p>Hello world!</p>\n",
            "protected": false
        },
        "author": 1,
        "parent": 0,
        "template": "",
        "meta": [],
        "revisions": null,
        "parent_post": 1,
        "parent_post_target": "admin",
        "via": "gutenberg",
        "author_meta": {
            "display_name": "John Smith",
            "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
        },
        "creator": "yoast",
        "creator_meta": {
            "display_name": "Yoast",
            "image_url": "https://example.com/96x96.png"
        },
        "selector": {
    		"type": "CssSelector",
    		"value": "#foo"
    	},
        "substatus": "archive",
        "last_substatus_time": 1515741301,
        "substatus_history": [
            {
                "identity": "yoast",
                "identity_meta": {
                    "display_name": "Yoast",
                    "image_url": "https://example.com/96x96.png"
                },
                "time": 1515741301,
                "old": "",
                "new": "archive"
            }
        ],
        "_links": {
            "self": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations/1"
                }
            ],
            "collection": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations"
                }
            ],
            "about": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
                }
            ],
            "author": [
                {
                    "embeddable": true,
                    "href": "https://wp.vm/wp-json/wp/v2/users/1"
                }
            ],
            "wp:attachment": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/media?parent=1"
                }
            ],
            "curies": [
                {
                    "name": "wp",
                    "href": "https://api.w.org/{rel}",
                    "templated": true
                }
            ]
        },
        "children": [
            {
                "id": 2,
                "date": "2018-01-11T20:23:33",
                "date_gmt": "2018-01-11T20:23:33",
                "guid": {
                    "rendered": "https://wp.vm/wp_annotation/axtr7c7c5a55cv/"
                },
                "modified": "2018-01-11T20:23:33",
                "modified_gmt": "2018-01-11T20:23:33",
                "slug": "axtr7c7c5a55cv",
                "status": "publish",
                "type": "wp_annotation",
                "link": "https://wp.vm/wp_annotation/axtr7c7c5a55cv/",
                "content": {
                    "rendered": "<p>Hello world!</p>\n",
                    "protected": false
                },
                "author": 2,
                "parent": 1,
                "template": "",
                "meta": [],
                "revisions": null,
                "parent_post": 1,
                "parent_post_target": "admin",
                "via": "gutenberg",
                "author_meta": {
                    "display_name": "Mary Jane",
                    "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
                },
                "creator": "yoast",
                "creator_meta": {
                    "display_name": "Yoast",
                    "image_url": "https://example.com/96x96.png"
                },
                "selector": null,
                "substatus": "",
                "last_substatus_time": 0,
                "substatus_history": [],
                "_links": {
                    "self": [
                        {
                            "href": "https://wp.vm/wp-json/wp/v2/annotations/2"
                        }
                    ],
                    "collection": [
                        {
                            "href": "https://wp.vm/wp-json/wp/v2/annotations"
                        }
                    ],
                    "about": [
                        {
                            "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
                        }
                    ],
                    "author": [
                        {
                            "embeddable": true,
                            "href": "https://wp.vm/wp-json/wp/v2/users/2"
                        }
                    ],
                    "wp:attachment": [
                        {
                            "href": "https://wp.vm/wp-json/wp/v2/media?parent=2"
                        }
                    ],
                    "curies": [
                        {
                            "name": "wp",
                            "href": "https://api.w.org/{rel}",
                            "templated": true
                        }
                    ]
                },
                "children": []
            }
        ]
    }
]

?context=edit&hierarchical=flat

[
    {
        "id": 1,
        "date": "2018-01-11T20:23:33",
        "date_gmt": "2018-01-11T20:23:33",
        "guid": {
            "rendered": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
            "raw": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/"
        },
        "modified": "2018-01-11T20:23:33",
        "modified_gmt": "2018-01-11T20:23:33",
        "password": "",
        "slug": "a5a57c7c5a5f0c",
        "status": "publish",
        "type": "wp_annotation",
        "link": "https://wp.vm/wp_annotation/a5a57c7c5a5f0c/",
        "content": {
            "raw": "Hello world!",
            "rendered": "<p>Hello world!</p>\n",
            "protected": false
        },
        "author": 1,
        "parent": 0,
        "template": "",
        "meta": [],
        "revisions": null,
        "parent_post": 1,
        "parent_post_target": "admin",
        "via": "gutenberg",
        "author_meta": {
            "display_name": "John Smith",
            "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
        },
        "creator": "yoast",
        "creator_meta": {
            "display_name": "Yoast",
            "image_url": "https://example.com/96x96.png"
        },
        "selector": {
    		"type": "CssSelector",
    		"value": "#foo"
    	},
        "substatus": "archive",
        "last_substatus_time": 1515741301,
        "substatus_history": [
            {
                "identity": "yoast",
                "identity_meta": {
                    "display_name": "Yoast",
                    "image_url": "https://example.com/96x96.png"
                },
                "time": 1515741301,
                "old": "",
                "new": "archive"
            }
        ],
        "_links": {
            "self": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations/1"
                }
            ],
            "collection": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations"
                }
            ],
            "about": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
                }
            ],
            "author": [
                {
                    "embeddable": true,
                    "href": "https://wp.vm/wp-json/wp/v2/users/1"
                }
            ],
            "wp:attachment": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/media?parent=1"
                }
            ],
            "curies": [
                {
                    "name": "wp",
                    "href": "https://api.w.org/{rel}",
                    "templated": true
                }
            ]
        }
    },
    {
        "id": 2,
        "date": "2018-01-11T20:23:33",
        "date_gmt": "2018-01-11T20:23:33",
        "guid": {
            "rendered": "https://wp.vm/wp_annotation/axtr7c7c5a55cv/",
            "raw": "https://wp.vm/wp_annotation/axtr7c7c5a55cv/"
        },
        "modified": "2018-01-11T20:23:33",
        "modified_gmt": "2018-01-11T20:23:33",
        "password": "",
        "slug": "axtr7c7c5a55cv",
        "status": "publish",
        "type": "wp_annotation",
        "link": "https://wp.vm/wp_annotation/axtr7c7c5a55cv/",
        "content": {
            "raw": "Hello world!",
            "rendered": "<p>Hello world!</p>\n",
            "protected": false
        },
        "author": 2,
        "parent": 1,
        "template": "",
        "meta": [],
        "revisions": null,
        "parent_post": 1,
        "parent_post_target": "admin",
        "via": "gutenberg",
        "author_meta": {
            "display_name": "Mary Jane",
            "image_url": "https://secure.gravatar.com/avatar/e50c12f18247416a1f46f102c5c826c2?s=96&d=mm&r=g"
        },
        "creator": "yoast",
        "creator_meta": {
            "display_name": "Yoast",
            "image_url": "https://example.com/96x96.png"
        },
        "selector": null,
        "substatus": "",
        "last_substatus_time": 0,
        "substatus_history": [],
        "_links": {
            "self": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations/2"
                }
            ],
            "collection": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/annotations"
                }
            ],
            "about": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/types/wp_annotation"
                }
            ],
            "author": [
                {
                    "embeddable": true,
                    "href": "https://wp.vm/wp-json/wp/v2/users/2"
                }
            ],
            "wp:attachment": [
                {
                    "href": "https://wp.vm/wp-json/wp/v2/media?parent=2"
                }
            ],
            "curies": [
                {
                    "name": "wp",
                    "href": "https://api.w.org/{rel}",
                    "templated": true
                }
            ]
        }
    }
]
Capabilities

Annotation permissions sometimes resemble those associated with comments, but at other times (e.g., back-end annotations) not so much. So these offer a standard method by which to check annotation permissions.

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 parent post by ID and the would-be parent post target.

current_user_can( 'create_annotation', 123, 'admin' )
  • create_annotation

General pseudo-caps that optionally support args: parent post ID, target.

current_user_can( 'read_annotations', 123, 'admin' )
current_user_can( 'read_annotations' )
  • read_annotations

General pseudo-caps that optionally support: parent post target.

current_user_can( 'edit_others_annotations', 'admin' )
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