Confluence
The Confluence integration lets a deployment read and write a user's Confluence. Every endpoint acts as the connected user, so what you can see and change is exactly what your Confluence account allows.
Connect Confluence with a site URL, username, and API token using Connect Confluence, or connect Confluence Cloud in the browser with Start a Confluence OAuth connection. To index Confluence content for agent search, see Index Confluence content on the knowledge index page.
- POST /confluence/connect Connect Confluence
- GET /integrations/confluence/oauth/auth-url Start a Confluence OAuth connection
- GET /confluence/status Check Confluence status
- DEL /confluence/connection Disconnect Confluence
- GET /confluence/spaces List spaces
- GET /confluence/spaces/{space_key}/pages List pages in a space
- GET /confluence/pages/{page_id} Retrieve a page
- POST /confluence/pages Create a page
- PUT /confluence/pages/{page_id} Update a page
- GET /confluence/search Search content
- POST /confluence/sync Sync Confluence
- GET /integrations/confluence/oauth/callback Confluence OAuth callback
Paths are relative to /api
Connect Confluence
POST /api/confluence/connect
Connects Confluence with a site URL, username, and API token.
Connects Confluence using basic authentication. The deployment verifies the credentials by listing a space before storing the connection against the caller. Set authType to basic; OAuth 2.0 connections are started with Start a Confluence OAuth connection instead.
- Authentication
- Bearer token How it works
Body parameters application/json
-
authTypestring RequiredConnection type. Must be
basic.Possible values-
basic
-
-
urlstring RequiredConfluence site URL or host. A bare subdomain is treated as an Atlassian Cloud site.
-
usernamestring RequiredAccount username, usually the account email address.
-
passwordstring RequiredAPI token for the account.
Returns
Returns success: true and a confirmation message.
Errors
- 400 A required field is missing,
authTypeis notbasic, or the credentials were rejected.
curl -X POST "$VDF_BASE_URL/api/confluence/connect" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"authType": "basic",
"url": "https://acme.example.com",
"username": "ada@example.com",
"password": "<API_TOKEN>"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/connect`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
authType: 'basic',
url: 'https://acme.example.com',
username: 'ada@example.com',
password: '<API_TOKEN>',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/api/confluence/connect",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"authType": "basic",
"url": "https://acme.example.com",
"username": "ada@example.com",
"password": "<API_TOKEN>",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"message": "Successfully connected to Confluence"
} Start a Confluence OAuth connection
GET /api/integrations/confluence/oauth/auth-url
Returns the Atlassian URL a user opens to connect Confluence Cloud by OAuth.
Begins the Atlassian OAuth 2.0 flow for Confluence Cloud. Open the returned auth_url in the browser; the user grants consent to Atlassian, which then redirects back to the deployment. The deployment exchanges the authorisation code and stores the tokens against the user who started the flow. When it finishes, confirm with Check Confluence status.
- Authentication
- Bearer token How it works
Query parameters
-
returnUrlstringAbsolute URL to return the browser to after the flow completes. Defaults to the deployment's integrations page.
Returns
Returns the Atlassian authorisation URL to open in the browser.
curl "$VDF_BASE_URL/api/integrations/confluence/oauth/auth-url?returnUrl=https%3A%2F%2Fexample.com%2Fconsultant%2Fapp%2Fintegrations" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/integrations/confluence/oauth/auth-url?returnUrl=https%3A%2F%2Fexample.com%2Fconsultant%2Fapp%2Fintegrations`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/integrations/confluence/oauth/auth-url",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
params={
"returnUrl": "https://example.com/consultant/app/integrations",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"auth_url": "https://auth.atlassian.com/authorize?audience=api.atlassian.com&client_id=..."
} Check Confluence status
GET /api/confluence/status
Returns whether the caller's Confluence connection is present and working.
Tests the caller's stored Confluence connection and reports whether it is connected. The site URL is returned as cloudId and url; the stored credentials are never returned.
- Authentication
- Bearer token How it works
Parameters
No parameters.
Returns
Returns the connection status.
curl "$VDF_BASE_URL/api/confluence/status" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/status`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/confluence/status",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"isConnected": true,
"message": "Successfully connected to Confluence",
"cloudId": "https://acme.example.com",
"url": "https://acme.example.com"
} Disconnect Confluence
DEL /api/confluence/connection
Disconnects the caller's Confluence connection.
Deactivates the caller's Confluence credentials.
- Authentication
- Bearer token How it works
Parameters
No parameters.
Returns
Returns success: true, a confirmation message, and isConnected: false.
curl -X DELETE "$VDF_BASE_URL/api/confluence/connection" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/connection`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.delete(
f"{os.environ['VDF_BASE_URL']}/api/confluence/connection",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"message": "Successfully disconnected from Confluence",
"isConnected": false
} List spaces
GET /api/confluence/spaces
Returns the Confluence spaces the caller can see.
Returns the spaces visible to the connected Confluence account.
- Authentication
- Bearer token How it works
Parameters
No parameters.
Returns
Returns the spaces the connected account can see, in spaces.
curl "$VDF_BASE_URL/api/confluence/spaces" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/spaces`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/confluence/spaces",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"spaces": [
{
"id": "98305",
"key": "ENG",
"name": "Engineering",
"type": "global",
"description": "Engineering docs"
}
]
} List pages in a space
GET /api/confluence/spaces/{space_key}/pages
Returns the current pages in a space, with paging.
- Authentication
- Bearer token How it works
Path parameters
-
space_keystring RequiredKey of the space whose pages to return.
Query parameters
-
startintegerIndex of the first page to return.
-
limitintegerMaximum number of pages to return.
Returns
Returns the pages in the space.
curl "$VDF_BASE_URL/api/confluence/spaces/ENG/pages?limit=25" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/spaces/ENG/pages?limit=25`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/confluence/spaces/ENG/pages",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
params={
"limit": 25,
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"space": "ENG",
"pages": [
{
"id": "163841",
"title": "Runbook",
"type": "page",
"status": "current",
"version": 4,
"createdDate": "2026-08-20T10:00:00Z"
}
]
} Retrieve a page
GET /api/confluence/pages/{page_id}
Returns the details of one Confluence page.
Returns a single page as Confluence represents it. Use expand to include the body, version, and space.
- Authentication
- Bearer token How it works
Path parameters
-
page_idstring RequiredID of the page to retrieve.
Query parameters
-
expandstringComma-separated Confluence expand options.
Returns
Returns the page in page.
Errors
- 404 No such page is visible to the caller.
curl "$VDF_BASE_URL/api/confluence/pages/163841" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/pages/163841`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/confluence/pages/163841",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"page": {
"id": "163841",
"title": "Runbook",
"type": "page"
}
} Create a page
POST /api/confluence/pages
Creates a Confluence page in the given space.
Creates a page in a space. Pass parentId to create the page beneath an existing page.
- Authentication
- Bearer token How it works
Body parameters application/json
-
spaceKeystring RequiredKey of the space to create the page in.
-
titlestring RequiredPage title.
-
contentstringPage body in Confluence storage format.
-
parentIdstringID of the parent page.
Returns
Returns the created page as Confluence represents it.
curl -X POST "$VDF_BASE_URL/api/confluence/pages" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"spaceKey": "ENG",
"title": "Incident review 2026-09-01",
"content": "<p>Summary…</p>"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/pages`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
spaceKey: 'ENG',
title: 'Incident review 2026-09-01',
content: '<p>Summary…</p>',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/api/confluence/pages",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"spaceKey": "ENG",
"title": "Incident review 2026-09-01",
"content": "<p>Summary…</p>",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"page": {
"id": "196610",
"title": "Incident review 2026-09-01"
}
} Update a page
PUT /api/confluence/pages/{page_id}
Updates the title or body of one Confluence page.
Updates a page. Provide title, content, or both; the page version is incremented automatically.
- Authentication
- Bearer token How it works
Path parameters
-
page_idstring RequiredID of the page to update.
Body parameters application/json
-
titlestringNew page title.
-
contentstringNew page body in Confluence storage format.
Returns
Returns the updated page in page, with a confirmation message.
Errors
- 400 Neither a title nor content was provided.
curl -X PUT "$VDF_BASE_URL/api/confluence/pages/163841" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "<p>Updated runbook…</p>"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/pages/163841`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: '<p>Updated runbook…</p>',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.put(
f"{os.environ['VDF_BASE_URL']}/api/confluence/pages/163841",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"content": "<p>Updated runbook…</p>",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"page": {
"id": "163841",
"title": "Runbook"
},
"message": "Page 163841 updated successfully"
} Search content
GET /api/confluence/search
Searches the connected Confluence for content matching the query text, optionally within a space and content type.
- Authentication
- Bearer token How it works
Query parameters
-
qstring RequiredText to search for.
-
spaceKeystringRestrict the search to this space.
-
typestringContent type to search.
Possible values-
page -
blogpost -
attachment
-
-
startintegerIndex of the first result to return.
-
limitintegerMaximum number of results to return.
Returns
Returns matching content in results, with total, start, and limit for paging.
Errors
- 400 No search query was provided.
curl "$VDF_BASE_URL/api/confluence/search?q=incident%20review&type=page" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/search?q=incident%20review&type=page`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/confluence/search",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
params={
"q": "incident review",
"type": "page",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"results": [
{
"id": "196610",
"title": "Incident review 2026-09-01",
"type": "page",
"space": "ENG",
"excerpt": "Summary of the incident…",
"url": "/wiki/spaces/ENG/pages/196610"
}
],
"total": 1,
"start": 0,
"limit": 25
} Sync Confluence
POST /api/confluence/sync
Counts the spaces and pages available to the caller for review.
Walks the caller's spaces and pages and returns how many were found, along with any per-space errors. Pass spaceKeys to limit the walk to specific spaces. This surveys what is available; to build the search index, use Index Confluence content.
- Authentication
- Bearer token How it works
Body parameters application/json
-
spaceKeysarray of stringsKeys of the spaces to survey. When omitted, all accessible spaces are surveyed.
Returns
Returns counts of spaces and pages surveyed.
curl -X POST "$VDF_BASE_URL/api/confluence/sync" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"spaceKeys": [
"ENG"
]
}' const response = await fetch(`${process.env.VDF_BASE_URL}/api/confluence/sync`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
spaceKeys: ['ENG'],
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/api/confluence/sync",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"spaceKeys": ["ENG"],
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"success": true,
"message": "Confluence sync completed",
"results": {
"spaces_synced": 1,
"pages_synced": 34,
"errors": []
}
} Confluence OAuth callback
GET /api/integrations/confluence/oauth/callback
Completes an Atlassian OAuth connection after the user returns from Atlassian.
The browser is sent here by Atlassian once the user has granted consent; clients never call it directly. The request is identified by the signed state created when the flow began with Start a Confluence OAuth connection. On success the deployment exchanges the authorisation code, stores the tokens against the user who started the flow, and redirects to the integrations page; on failure it redirects there with an error code. Confluence connections started this way may also complete through the shared Atlassian callback on the Jira page.
- Authentication
- None
Query parameters
-
codestringAuthorisation code returned by Atlassian on success.
-
statestringOpaque value that ties the callback to the connection that began it.
-
errorstringError code returned by Atlassian when the user declines or consent fails.
-
error_descriptionstringHuman-readable detail accompanying
error.
Returns
Redirects the browser back to the integrations page.
The response is an HTTP redirect; there is no JSON body.
curl -i "$VDF_BASE_URL/api/integrations/confluence/oauth/callback?code=%3CAUTHORIZATION_CODE%3E&state=%3CSTATE%3E" const response = await fetch(`${process.env.VDF_BASE_URL}/api/integrations/confluence/oauth/callback?code=%3CAUTHORIZATION_CODE%3E&state=%3CSTATE%3E`);
if (!response.ok) throw new Error(`Request failed with status ${response.status}`); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/api/integrations/confluence/oauth/callback",
params={
"code": "<AUTHORIZATION_CODE>",
"state": "<STATE>",
},
allow_redirects=False,
timeout=30,
)
response.raise_for_status()
print(response.headers["Location"])