Simple Python example for creating a new page using Rest API?
Asked by tony:

I've been searching for days and am finding page after page of useless information.

Searches for Python examples return examples in CURL, VB, javascript, and others but nothing that I can actually make work in Python.

I simply need to create a page and supply about 30K of auto-generated XHTML or Wiki-markup data to it.

This is a long-term project so I do not want to fall back to the old APIs that will be retired shortly.  
Can anyone point to an example or post something to get me started?

<br />

Thanks!


Answers:
author: Stephen Deutsch
body: Hi Tony,

I was also curious what would be the simplest possible thing that could work. I usually just use the XML-RPC api, but it would be nice to know how to use the REST api too, and I finally managed to get it going. Here you go:

```
import urllib2import base64conf_serverurl = "http://my-confluence:1990/confluence"username = "admin"password = "admin"stringToEncode = username + ":" + passwordencodedString = base64.b64encode(stringToEncode)url = conf_serverurl + "/rest/api/content?os_username=" + username + "&amp;os_password=" + passworddata = '{"type":"page","ancestors":[{"type":"page","id":98334}],"title":"new page","space":{"key":"ds"},"body":{"storage":{"value":"&lt;p&gt;This is a new page&lt;/p&gt;","representation":"storage"}}}'headers = { 'Authentication': 'Basic ' + encodedString, 'Content-type': 'application/json', 'Accept': 'application/json', 'X-Atlassian-Token': 'no-check' }req = urllib2.Request(url, data, headers=headers)response = urllib2.urlopen(req)data = response.read()print data
```

To choose which page will be the parent, just put the page id where it says 98334, put in the proper space key, and put the xhtml markup code where it says "\<p\>this is a new page\</p\>". Everything else should be pretty self-explanatory.


author: Stephen Deutsch
body: Hi Tony,

The code above is supposed to create a new page. The page ID that is in the request is for which page will be the **parent** for the new page, not which page is edited.

Also, you are right that the post is implicit; whenever you do a call to urllib2.Request which has data, it automatically sends it as a POST.

My guess is that either you put the wrong URL for the server URL (it should match the base URL and context path for your instance), either that or you are running Confluence version less than 5.5. Confluence 5.5 is the first version to have the new REST API.

You can use this slightly modified version of the above code to get a better error message:

```
import urllib2import base64conf_serverurl = "http://my-confluence.mycompany.com"username = "admin"password = "admin"stringToEncode = username + ":" + passwordencodedString = base64.b64encode(stringToEncode)url = conf_serverurl + "/rest/api/content?os_username=" + username + "&amp;os_password=" + passworddata = '{"type":"page","ancestors":[{"type":"page","id":98334}],"title":"new page","space":{"key":"ds"},"body":{"storage":{"value":"&lt;p&gt;This is a new page&lt;/p&gt;","representation":"storage"}}}'headers = { 'Authentication': 'Basic ' + encodedString, 'Content-type': 'application/json', 'Accept': 'application/json', 'X-Atlassian-Token': 'no-check' }req = urllib2.Request(url, data, headers=headers)try:    response = urllib2.urlopen(req)    data = response.read()except urllib2.HTTPError, error:    data = error.read()print data
```

comments: author: Jagruthi k
body: I tried the same. But I get the following error.{"statusCode":403,"data":{"authorized":false,"valid":true,"errors":\[\]},"message":"Could not create content with type page"}


author: Anjali Parate
body: I too tried this code but I am getting below output on the terminal.

Output -

\<!DOCTYPE html\>\<!--\[if IE 9\]\>\<html lang="en" class="ie9"\>\<!\[endif\]--\>\<!--\[if (gt IE 9)\|!(IE)\]\>\<!--\>\<html lang="en"\>\<!--\<!\[endif\]--\>\<head\>\<meta charset="utf-8"\>\<meta http-equiv="X-UA-Compatible" content="IE=edge"\>\<title\>Oops, you\&#39;ve made a malformed request. - Atlassian account\</title\>\<meta name="viewport" content="width=device-width, initial-scale=1.0"\>\<link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.9/css/aui.min.css" media="all"\>\<link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.9/css/aui-experimental.min.css" media="all"\>\<link rel="stylesheet" href="<https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/layout/base/base.less.css>" media="all"\>\<link rel="shortcut icon" href="[https://cpfs-cdn.atlassian.com/assets/shared/id-summit/id-summit-aa-favicon.ico"\>\<link]() rel="stylesheet" href="<https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/layout/error/error.less.css>" media="all"\>\<script\>window.baseUrl = 'https:\\/\\/aid-static-assets.prod.atl-paas.net\\/atlassian-id\\/14.6.40';\</script\>\<script src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/require.min.js"\>\</script\>\<script]() src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/require-config.js"\>\</script\>\<script]() src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/jquery/dist/jquery.min.js"\>\</script\>\<script]() src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/babel-polyfill/dist/polyfill.min.js"\>\</script\>\<script]() src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/@atlassian/herment/target/herment.min.js"\>\</script\>\<script]() src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/browser-metrics/dist/probe-min.js"\>\</script\>\<script]() src="<https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/browser-metrics/dist/collector-min.js>" async\>\</script\>\<script src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/browser-metrics-aa-beacon/dist/internal/browser-metrics-aa-beacon.js"\>\</script\>\<script]() src="<https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/lib/browser-metrics-aa-beacon/dist/internal/browser-metrics-aa-beacon/impl.js>" async\>\</script\>\<script\>window.AJS = {}; window.AJS.EventQueue = \[\]; require(\['internal/browser-metrics', 'herment'\], function (metrics, herment) {var config = {storage_key: 'aid', product: 'aid', subproduct: 'signup', save_interval: 20};herment(config).start();});\</script\>\</head\>\<body class="aui-page-focused aui-page-focused-medium aui-page-size-medium aid-page-minimal" data-rebranded\>\<div id="page"\>\<header id="header" role="banner"\>\<nav class="aui-header aui-dropdown2-trigger-group aui-header-logo-hires" role="navigation"\>\<div class="aui-header-inner"\>\<div class="aui-header-primary"\>\<h1 id="logo" class="aui-header-logo aui-header-logo-custom"\>\<a href="[https://id.atlassian.com/manage"\>\<img]() src="<https://cpfs-cdn.atlassian.com/assets/shared/id-summit/id-summit-aa-adg2-management-header.png>" alt="Atlassian account" /\>\</a\>\</h1\>\</div\>\</div\>\<!-- .aui-header-inner--\>\</nav\>\<!-- .aui-header --\>\</header\>\<!-- #header --\>\<section id="content" role="main"\>\<div class="aui-page-panel"\>\<div class="aui-page-panel-inner"\>\<section class="aui-page-panel-content"\>\<div class="aid-error aid-error-400"\>\<img class='errorLogo' width="180" src="[https://cpfs-cdn.atlassian.com/assets/shared/id-summit/id-summit-aa-adg2-login-header.svg"\>\<br/\>\<img]() class='errorImage' height="150" src="[https://aid-static-assets.prod.atl-paas.net/atlassian-id/14.6.40/images/forbidden.svg"\>\<h2]() class="errorTitle"\>Oops, you\&#39;ve made a malformed request.\</h2\>\<div class="errorContent"\>\<p\>Often, clearing your browsers cache and restarting your browser will solve this problem.\<br/\>If that doesn't work, please \<a href="<https://support.atlassian.com/>" target="_blank"\>contact support\</a\>.\</p\>\</div\>\</div\>\</section\>\<!-- .aui-page-panel-content --\>\</div\>\<!-- .aui-page-panel-inner --\>\</div\>\<!-- .aui-page-panel --\>\</section\>\<!-- #content --\>\<footer id="footer" role="contentinfo"\>\<div class="footer-body"\>\<ul\>\<li\>\<a target="_blank" href="[https://www.atlassian.com/end-user-agreement"\>Terms]() of Use\</a\>\</li\>\<li\>\<a target="_blank" href="[https://support.atlassian.com"\>Support\</a\>\</li\>\<li\>\<a]() target="_blank" href="[https://www.atlassian.com/company/privacy"\>Privacy]() Policy\</a\>\</li\>\</ul\>\<div id="footer-logo"\>\<a href="[http://www.atlassian.com/"\>Atlassian\</a\>\</div\>\</div\>\</footer\>\<!--]() #footer --\>\</div\>\<!-- #page --\>\</body\>\</html\>


author: tony
body: Hmm, didn't work for me.   

I edited an existing page and got its ID (although I would eventually like to create a new page). I noticed that the code does not specify a POST v.s. GET. Is that not necessary? (i.e. is POST assumed?)  

Yes, I did change the serverurl, username and password as well... :-)  

I get the following error with the above:

```
Traceback (most recent call last):  File "post_test.py", line 12, in &lt;module&gt;    response = urllib2.urlopen(req)  File "C:\Python27\lib\urllib2.py", line 127, in urlopen    return _opener.open(url, data, timeout)  File "C:\Python27\lib\urllib2.py", line 410, in open    response = meth(req, response)  File "C:\Python27\lib\urllib2.py", line 523, in http_response    'http', request, response, code, msg, hdrs)  File "C:\Python27\lib\urllib2.py", line 442, in error    result = self._call_chain(*args)  File "C:\Python27\lib\urllib2.py", line 382, in _call_chain    result = func(*args)  File "C:\Python27\lib\urllib2.py", line 629, in http_error_302    return self.parent.open(new, timeout=req.timeout)  File "C:\Python27\lib\urllib2.py", line 410, in open    response = meth(req, response)  File "C:\Python27\lib\urllib2.py", line 523, in http_response    'http', request, response, code, msg, hdrs)  File "C:\Python27\lib\urllib2.py", line 448, in error    return self._call_chain(*args)  File "C:\Python27\lib\urllib2.py", line 382, in _call_chain    result = func(*args)  File "C:\Python27\lib\urllib2.py", line 531, in http_error_default    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)urllib2.HTTPError: HTTP Error 404: Not Found
```


author: tony
body: Thanks. That would look like a great option.

Although adding more software to support what should be only a very small part of a very large end-to-end process is not optimal. Let alone the fact that it is highly unlikely that I would get approval for installing anything on our server. But I will keep a link to that, should it prove impossible to get this done with the built-in capabilities.  

<br />


author: Bob Swift (personal)
body: Or if you don't want to do programming, you can use the [Confluence Command Line Interface (CLI)](https://bobswift.atlassian.net/wiki/display/CSOAP).