Custom GPT - Action to Confluence API

Hi - I am attempting to add an action to one of my custom GPTs in ChatGPT to connect to the Atlassian Confluence cloud to read content on the site. I’ve set up the oAuth 2.0 authentication/authorization, scopes, etc. I have also been building out the OpenAI schema for the API; however, I believe I am receiving errors in parsing. Any guidance would be appreciated.


{
  "openapi": "3.1.0",
  "info": {
    "title": "Confluence",
    "description": "API integration with Confluence Cloud for accessing and managing content within Confluence spaces at XXXX.",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://XXXXX.atlassian.net/wiki/rest/api"
    }
  ],
  "paths": {

    "/labels/{id}/pages": {
      "get": {
        "summary": "Get pages for label",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier for the label",
            "schema": {
              "type": "string"
            }
          }],
        "responses": {
          "200": {
            "description": "Successful response with pages for the label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponse"
                }
              }
            }
          }
        }
      }
    },
    "/pages": {
      "get": {
        "summary": "Get pages",
        "responses": {
          "200": {
            "description": "Successful response with list of pages",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponse"
                }
              }
            }
          }
        }
      }
    },
    "/pages/{id}": {
      "get": {
        "summary": "Get page by id",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier for the page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response with page details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          }
        }
      }
    },
    "/spaces/{id}/pages": {
      "get": {
        "summary": "Get pages in space",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier for the space",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response with pages in the space",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponse"
                }
              }
            }
          }
        }
      }
    },
  "/attachments/{id}/footer-comments": {
    "get": {
      "summary": "Get attachment comments",
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "description": "The unique identifier for the attachment",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "Successful response with comments for the attachment",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentResponse"
              }
            }
          }
        }
      }
    }
  },
  "/spaces": {
    "get": {
      "summary": "Get spaces",
      "description": "Returns all spaces. The results will be sorted by id ascending.",
      "responses": {
        "200": {
          "description": "Successful response with list of spaces",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Space"
              }
            }
          }
        }
      }
    }
  },
  "/spaces/{id}": {
    "get": {
      "summary": "Get space by id",
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "description": "The unique identifier for the space",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "Successful response with space details",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Space"
              }
            }
          }
        }
      }
    }
  },

  "/footer-comments/{comment-id}": {
    "get": {
      "summary": "Get footer comment by id",
      "parameters": [
        {
          "name": "comment-id",
          "in": "path",
          "required": true,
          "description": "The unique identifier for the footer comment",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "Successful response with footer comment details",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Comment"
              }
            }
          }
        }
      }
    }
  },

  "components": {
    "schemas": {

      "PageResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          },
          "_links": {
            "type": "object",
            "properties": {
              "next": {
                "type": "string"
              }
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "status": { "type": "string" },
          "title": { "type": "string" },
          "spaceId": { "type": "string" },
          "parentId": { "type": "string" },
          "parentType": { "type": "string" },
          "position": { "type": "integer" },
          "authorId": { "type": "string" },
          "ownerId": { "type": "string" },
          "lastOwnerId": { "type": "string" },
          "createdAt": { "type": "string" },
          "version": {
            "type": "object",
            "properties": {
              "createdAt": { "type": "string" },
              "message": { "type": "string" },
              "number": { "type": "integer" },
              "minorEdit": { "type": "boolean" },
              "authorId": { "type": "string" }
            }
          },
          "body": {
            "type": "object",
            "properties": {
              "storage": { "type": "object" },
              "atlas_doc_format": { "type": "object" }
            }
          },
          "_links": {
            "type": "object",
            "properties": {
              "webui": { "type": "string" },
              "editui": { "type": "string" },
              "tinyui": { "type": "string" }
            }
          }
        }
      }
    },
    "/pages/{id}": {
      "get": {
        "summary": "Get page by id",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier for the page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response with page details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          }
        }
      }
    },
    "/spaces/{id}/pages": {
      "get": {
        "summary": "Get pages in space",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique identifier for the space",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response with pages in the space",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageResponse"
                }
              }
            }
          }
        }
      }
    },

    "CommentResponse": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/Comment"
          }
        },
        "_links": {
          "type": "object",
          "properties": {
            "next": {
              "type": "string"
            }
          }
        }
      }
    },
    "Comment": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "status": { "type": "string" },
        "title": { "type": "string" },
        "parentCommentId": { "type": "string" },
        "version": {
          "type": "object",
          "properties": {
            "createdAt": { "type": "string" },
            "message": { "type": "string" },
            "number": { "type": "integer" },
            "minorEdit": { "type": "boolean" },
            "authorId": { "type": "string" }
          }
        },
        "body": {
          "type": "object",
          "properties": {
            "storage": { "type": "object" },
            "atlas_doc_format": { "type": "object" }
          }
        },
        "resolutionStatus": { "type": "string" },
        "properties": {
          "type": "object",
          "properties": {
            "inline-marker-ref": { "type": "string" },
            "inline-original-selection": { "type": "string" }
          }
        },
        "_links": {
          "type": "object",
          "properties": {
            "webui": { "type": "string" }
            }
          }
        }
      },
  "Space": {
    "type": "object",
    "properties": {
      "id": { "type": "string" },
      "key": { "type": "string" },
      "name": { "type": "string" },
      "type": { "type": "string" },
      "status": { "type": "string" },
      "authorId": { "type": "string" },
      "createdAt": { "type": "string" },
      "homepageId": { "type": "string" },
      "description": {
        "type": "object",
        "properties": {
          "plain": {
            "type": "object",
            "properties": {
              "representation": { "type": "string" },
              "value": { "type": "string" }
            }
          },
          "view": {
            "type": "object",
            "properties": {
              "representation": { "type": "string" },
              "value": { "type": "string" }
            }
          }
        }
      },
      "icon": {
        "type": "object",
        "properties": {
          "path": { "type": "string" },
          "apiDownloadLink": { "type": "string" }
        }
      },
      "_links": {
        "type": "object",
        "properties": {
          "webui": { "type": "string" }
        }
      }
    },
    "PageResponse": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/Page"
          }
        },
        "_links": {
          "type": "object",
          "properties": {
            "next": {
              "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
1 Like

components is one level too high in your schema, and operationId is required on each get as a top-level key. You can just name each operationId something related to the path, so /pages/{id} might have an operationId of page-by-id (you name it anything you want though)

1 Like

Could you please share the steps to set up the oAuth 2.0 authentication/authorization, scopes in confluence. Many Thanks

1 Like

I’m also interested on getting OAuth working with my Atlassian integration.

2 Likes

were you able to connect to confluence via custom GPT?

I have tried via API key basic option, format base64 email:apitoken but no luck

curious, If you were able to find the way?

2 Likes

I had to do some major trimming/filtering with jq to get a spec file that I could test. In my case, Jira Service Management

Even then I struggle to debug.