I'm trying to use the rest API to create pages in my confluence instance, however, the API isn't working as intended.
I tried with Js, postman, even python script, none work.
I got the 200 ok code but the response is in HTML and when I look at my confluence, there's no page created.
JS
const req = require('request')
//This creates a page in a space.
var username = "admin";
var password = "admin";
var jsondata = {"type":"page",
"title":"My Test Page",
"space":{"key":"TEST"},
"body":{"storage":{"value":"<p>This is a new page</p>","representation":"storage"}}};
req.post("http://localhost:8090/confluence/rest/api/content/", {
'contentType': "application/json; charset=utf-8",
'dataType': "json",
'auth': {
'user': username,
'pass': password
},
data: {"type":"page",
"title":"My Test Page",
"space":{"key":"TEST"},
"body":{"storage":{"value":"<p>This is a new page</p>","representation":"storage"}}},
}, (err, httpResponse, body)=> {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', httpResponse);
});
Python
# This script bulk generates spaces and pages in Confluence.
import click
import grequests as greqs
import requests as reqs
from requests.auth import HTTPBasicAuth
from tqdm import tqdm
import itertools
SPACES_URL = "http://{hostname}:{port}/rest/api/space"
PAGES_URL = "http://{hostname}:{port}/rest/api/content"
@click.command()
@click.option("-u", "--username", default="admin", show_default=True, show_envvar=True, prompt=True)
@click.password_option("-p", "--password", default="admin", show_default=True, show_envvar=True, prompt=True)
@click.option("-h", "--hostname", default="localhost", show_default=True, show_envvar=True, prompt=True)
@click.option("-P", "--port", default=8090, show_default=True, show_envvar=True, prompt=True)
@click.option("-t", "--threads", default=8, show_default=True, show_envvar=True, prompt=True)
@click.option("-s", "--space-count", show_envvar=True, prompt=True)
@click.option("-c", "--page-count", show_envvar=True, prompt=True)
@click.option("-r", "--prefix", default="CONFLUENCE", show_default=True, show_envvar=True, prompt=True)
@click.option("-d", "--disable-progress", default=False, show_default=True, show_envvar=True, prompt=True)
def cli(username, password, hostname, port, threads, space_count, page_count, prefix, disable_progress):
global SPACES_URL, PAGES_URL
SPACES_URL = SPACES_URL.format(hostname=hostname, port=port)
PAGES_URL = PAGES_URL.format(hostname=hostname, port=port)space_count = int(space_count)
page_count = int(page_count)spaces_generator = (greqs.post(SPACES_URL,
json={"key": f"{prefix}SpaceStation{i}",
"name": f"{prefix}_Space{i}"},
auth=HTTPBasicAuth(username, password)) for i in range(space_count))spaces_reqs = greqs.imap(spaces_generator, size=threads,
exception_handler=lambda r, e: print("Request failed. Reason: " + str(e)))spaces_responses = []
print(f"Generating {space_count} spaces...")
for _ in tqdm(range(space_count), disable=disable_progress):
try:
spaces_responses.append(next(spaces_reqs))
except:
# Silently ignore the exception
continueif len(spaces_responses) == space_count:
pages_reqs = []
count = 0for response in spaces_responses:
# 200 OK (HTTP Status Code)
if response.status_code == reqs.codes.ok:
count += 1
space_key = response.json()["key"]
pages_generator = (greqs.post(PAGES_URL,
json={
"type": "page",
"title": f"{prefix}_Page{j}",
"space": {"key": space_key},
"body": {
"storage": {
"value": "<p>This is a new page</p>",
"representation": "storage"
}
}
},
auth=HTTPBasicAuth(username, password)) for j in range(page_count))pages_reqs.append(greqs.imap(pages_generator, size=threads,
exception_handler=lambda r, e: print("Request failed. Reason: " + str(e))))pages_reqs = itertools.chain(*pages_reqs)
print(f"Generating {page_count} pages for each newly created space...")
for _ in tqdm(range(page_count * count), disable=disable_progress):
try:
next(pages_reqs)
except:
# Silently ignore the exception
continue
if __name__ == "__main__":
cli(auto_envvar_prefix="CONF")
Is there anything i should do differenty? thank you
The endpoint I was using was the issue. In production, you should use this endpoint http://localhost:8090/rest/api/content/, but I was using this one http://localhost:8090/confluence/rest/api/content/ which is used for development, so that was it.
Remember this:
For production use this endpoint http://localhost:8090/rest/api/content/
For development use this endpoint http://localhost:8090/confluence/rest/api/content/
Hi @Mamadou Barry ,
Please notice that the different endpoint has nothing to do with Development or Production environments but it depends on how you configured the Context-path in server.xml configuration file:
<Context path=""
<Context path="confluence"
I hope this explains.
Cheers,
Dario
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
In order to try to help we may need a bit more details:
What is the HTML you get in response saying?
Also, is this working if you send the same request to the same endpoint using curl?
Cheers,
Dario
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for replying. Actually, I have figured out the issue and solved it.
The endpoint I was using was the issue. In production, you should use this endpoint http://localhost:8090/rest/api/content/, but I was using this one http://localhost:8090/confluence/rest/api/content/ which is used for development, so that was it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.