REST API
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.
| Resource | Since | Does |
|---|---|---|
| POST /rest/wikis/{wiki}/releasenotes | 2.7 | Creates a release note for one version of one product. |
| GET /rest/wikis/{wiki}/releasenotes | 2.7 | Lists the release notes, of one product when product is passed. |
| GET /rest/wikis/{wiki}/releasenotes/{product}/{version} | 2.8 | Reads that release note. |
| PUT /rest/wikis/{wiki}/releasenotes/{product}/{version} | 2.8 | Replaces it, which is how a version is marked released. |
| POST /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes | 2.7 | Creates a change on that release note. |
| GET /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes | 2.7 | Lists the changes of that release note. |
| GET /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes/{entry} | 2.8 | Reads one change. |
| PUT /rest/wikis/{wiki}/releasenotes/{product}/{version}/changes/{entry} | 2.8 | Replaces 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
| Field | Required | Default | What it is |
|---|---|---|---|
| version | yes | The version the note is about, and what its page name is derived from. | |
| product | no | the product configured on ReleaseNotes.Code.ReleaseNotesConfig | Refused with a 400 when the wiki has no default product either. |
| date | no | empty | A day written yyyy-MM-dd. |
| released | no | false | A note that is not released yet still offers its "Add Change" buttons. |
| template | no | the template configured on ReleaseNotes.Code.ReleaseNotesConfig | The 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
| Field | Required | Default | What it is |
|---|---|---|---|
| title | yes | What the change is, as the release note lists it. | |
| summary | no | empty | The sentence or two shown under the title on the release note. |
| description | no | empty | The long form, shown on the change's own page. |
| audience | no | from the change template, user | One of user, administrator or developer; the release note has one section per audience. |
| importance | no | from the change template, medium | One of low, medium or high. |
| category | no | empty | Free text, offered to authors as a picker over the values already in use. |
| screenshots | no | empty | The 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
| Parameter | Default | Filters on |
|---|---|---|
| audience | every audience | user, administrator, developer. |
| category | every category | The category, as free text. |
| importance | every importance | low, medium, high. |
| containsScreenshots | both | true keeps only the changes carrying a screenshot, false only those carrying none. |
| aggregated | false | true adds the changes of the milestones and release candidates of the version. A final release note therefore reports none of them unless asked. |
| limit | 100 | How many changes at most; hasMore in the answer says whether a further page exists. |
| offset | 0 | Where 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
| Code | When |
|---|---|
| 200 | A listing, a read or a replacement was answered. Reading is not rights-checked, so a guest reads what an author reads. |
| 201 | The release note or the change was created. The Location header names it, and the body holds it with its reference. |
| 400 | The 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. |
| 401 | A guest made the call on a wiki that does not let guests edit. |
| 403 | The account the call authenticates as may not edit the page. |
| 404 | There 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. |
| 409 | The 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.