REST API

Last modified by Vincent Massol on 2026/09/10 21:39

Reference

Release Notes Application 2.7+ Eight REST resources create, read, list and replace release notes and their changes. They exist alongside the generic XWiki REST API because creating one is more than a page write: the application allocates the next Entry001 page name, derives the page name of a release note from its version, applies the configured templates and saves once, so a half-created entry is never left behind.

ResourceSinceDoes
POST /rest/wikis/{wiki}/releasenotes2.7Creates a release note for one version of one product.
GET /rest/wikis/{wiki}/releasenotes2.7Lists the release notes, of one product when product is passed.
GET /rest/wikis/{wiki}/releasenotes/{product}/{version}2.8Reads that release note.
PUT /rest/wikis/{wiki}/releasenotes/{product}/{version}2.8Replaces it, which is how a version is marked released.
POST /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes2.7Creates a change on that release note.
GET /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes2.7Lists the changes of that release note.
GET /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes/{entry}2.8Reads one change.
PUT /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes/{entry}2.8Replaces it, which is how a change gets its screenshots.

{version} is the version the note is about, 18.0-milestone-1, and not the page name the application derives from it, 18.0M1. Both {product} and {version} are URL-encoded by the client. {entry} is the page a change lives in, Entry001, which the wiki allocates and answers.

Create a release note

FieldRequiredDefaultWhat it is
versionyes The version the note is about, and what its page name is derived from.
productnothe product configured on ReleaseNotes.Code.ReleaseNotesConfigRefused with a 400 when the wiki has no default product either.
datenoemptyA day written yyyy-MM-dd.
releasednofalseA note that is not released yet still offers its "Add Change" buttons.
templatenothe template configured on ReleaseNotes.Code.ReleaseNotesConfigThe page whose content and objects the new note starts from.
curl -u USER:PASSWORD -X POST 'http://localhost:8080/xwiki/rest/wikis/xwiki/releasenotes' \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"product": "MyProduct", "version": "3.0-milestone-1", "date": "2026-10-01"}'

The answer is a 201 whose Location header names the page resource of the new note, with the note itself in the body:

{"product":"MyProduct","version":"3.0-milestone-1","date":"2026-10-01","released":false,
 "template":null,"reference":"ReleaseNotes.Data.MyProduct.3\.0M1.WebHome"}

Create a change

FieldRequiredDefaultWhat it is
titleyes What the change is, as the release note lists it.
summarynoemptyThe sentence or two shown under the title on the release note.
descriptionnoemptyThe long form, shown on the change's own page.
audiencenofrom the change template, userOne of user, administrator or developer; the release note has one section per audience.
importancenofrom the change template, mediumOne of low, medium or high.
categorynoemptyFree text, offered to authors as a picker over the values already in use.
screenshotsnoemptyThe names of images or videos attached to the change page. They can only be named once that page exists, so a client posts the change first and names them with a PUT, as #HReplaceachange shows.
curl -u USER:PASSWORD -X POST \
  'http://localhost:8080/xwiki/rest/wikis/xwiki/releasenotes/MyProduct/3.0-milestone-1/changes' \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"title": "Live Data replaces the Live Table", "audience": "user", "importance": "high",
       "summary": "Every listing in the wiki is now a Live Data.", "category": "Live Data"}'

The 201 carries the page the wiki allocated, ReleaseNotes.Data.MyProduct.3\.0M1.Entry001.WebHome, and the entry that names it, Entry001; the next call gets Entry002. Change creation is not idempotent and there is no deduplication, so the same call twice creates two changes. A client that may run twice reads the changes first, or takes the 409 on the release note as the sign that it is re-running.

Replace a change

Release Notes Application 2.8+ A PUT on one change replaces it: the change becomes exactly what the request carries, and a property the request leaves out is emptied rather than kept. The change template has no say here, unlike when a change is created: a template gives a new change the values its author has not written yet, and a replacement is written in full. The fields are those of a posted change, and product and version are the ones in the URL whatever the body says, since they are the release note the change belongs to.

This is how a change gets its screenshots, which was impossible while a change was write-once: the names are attachments of the change's own page, and that page does not exist until the change has been created.

B='http://localhost:8080/xwiki/rest/wikis/xwiki'
# 1. Create the change. The answer names the entry the wiki allocated.
curl -u USER:PASSWORD -X POST "$B/releasenotes/MyProduct/3.0-milestone-1/changes" \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"title": "Live Data replaces the Live Table", "audience": "user", "importance": "high"}'
# 2. Attach the image to that page, with the generic XWiki REST API. The content type is what
#    tells the wiki this is the file and not a form, and a request without it is refused with a 400.
curl -u USER:PASSWORD -X PUT --data-binary @shot.png -H 'Content-Type: application/octet-stream' \
  "$B/spaces/ReleaseNotes/spaces/Data/spaces/MyProduct/spaces/3.0M1/spaces/Entry001/pages/WebHome/attachments/shot.png"
# 3. Replace the change with the screenshot it now has.
curl -u USER:PASSWORD -X PUT "$B/releasenotes/MyProduct/3.0-milestone-1/changes/Entry001" \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"title": "Live Data replaces the Live Table", "audience": "user", "importance": "high",
       "screenshots": ["shot.png"]}'

Step 3 sends the whole change and not only its screenshots, because a PUT replaces: the audience and the importance left out of it would be emptied. The change the POST answered is what a client sends back, with the names added.

A GET on the same URL reads that change back, and both answer a 404 when the entry holds none: the contributors of a release note live in an entry too, and it carries no change.

Replace a release note

Release Notes Application 2.8+ A PUT on one release note replaces the two properties that change over its life, released and date, which is how a version is marked released on the day it ships. The others are not replaced: product and version name the page, and the content, the title and the template are what the note was created with, so an administrator's edits to that content survive.

curl -u USER:PASSWORD -X PUT \
  'http://localhost:8080/xwiki/rest/wikis/xwiki/releasenotes/MyProduct/3.0-milestone-1' \
  -H 'Content-Type: application/json' -H 'Accept: application/json' \
  -d '{"released": true, "date": "2026-10-01"}'

Here too the request replaces, so a call carrying only released empties the date. A GET on the same URL reads the note back, and both answer a 404 when that version of that product has none.

List the changes

ParameterDefaultFilters on
audienceevery audienceuser, administrator, developer.
categoryevery categoryThe category, as free text.
importanceevery importancelow, medium, high.
containsScreenshotsbothtrue keeps only the changes carrying a screenshot, false only those carrying none.
aggregatedfalsetrue adds the changes of the milestones and release candidates of the version. A final release note therefore reports none of them unless asked.
limit100How many changes at most; hasMore in the answer says whether a further page exists.
offset0Where to start.

Each filter takes a comma-separated list, matched with like so % is a wildcard, and each item may carry one of the =, >=, >, <= or < prefixes. That is the same filter language as the getChanges macro.

B='http://localhost:8080/xwiki/rest/wikis/xwiki/releasenotes'
curl -u USER:PASSWORD "$B/MyProduct/3.0/changes?aggregated=true&importance=>=medium&limit=10"
curl -u USER:PASSWORD "$B?product=MyProduct"

Status codes

CodeWhen
200A listing, a read or a replacement was answered. Reading is not rights-checked, so a guest reads what an author reads.
201The release note or the change was created. The Location header names it, and the body holds it with its reference.
400The request is incomplete or malformed, and the message says how: a note with no version or no product, a date that is no day, a change with no title — including a replacement, which needs one as much as a creation does — an audience or an importance outside its values.
401A guest made the call on a wiki that does not let guests edit.
403The account the call authenticates as may not edit the page.
404There is no release note for that version of that product, or the entry named holds no change. A PUT never creates: the page of a change is the wiki's to allocate.
409The release note exists already. Its reference is in the body, which is what tells a client at its first call that it is re-running.

Rights

The account the call authenticates as needs edit right on the page being created. When the release-note template carries a script required right, it needs script as well, or the created note renders a "required right not granted" message in place of its changes. Listing is not rights-checked.

What these resources do not do

Deleting a release note or a change, writing the contributors list, and storing attachments. Each of those is a plain page, object or attachment write, with no name to allocate and no template to apply, so it is done with the generic XWiki REST API against the pages described in Release Note Structure. Those are deliberate non-goals — which is why illustrating a change takes the three calls above rather than one.

FAQ

How do I put a screenshot on a change?

Create the change, attach the image to the page the answer names, then PUT the change back with the file name in screenshots. The attachment cannot come first: its page is the one the creation allocates.

Do these calls need a form token?

No. XWiki's REST layer is not form-driven, so authenticating the request is enough.

How do I tell whether a release note is already there?

List the release notes first, or create it and read the 409: it carries the reference of the note that exists.

Why is my new change missing from the release note?

A release note shows the changes of its own version, plus those of its milestones and release candidates when it is a final one, so a change posted against a version the note does not cover is stored but not shown.

Related

Get Connected