Skip to main content

Connect API (REST)

Introduction

The Octopus Connect API lets you programmatically read your community's content — posts, comments, replies, user profiles, and engagement metrics. It is read-only and intended for server-side use.

API Versioning

The Connect API is versioned. Include the version in the request path: https://connect.octopuscommunity.com/v<VERSION_NUMBER>

The following table lists the available versions:

Version numberStatus
1available

For more details on changes between versions, see the Changelog.

Authentication

The Octopus Connect API uses a Connect API secret key to authenticate requests. Pass the Connect API secret key (provided by the Octopus team) in the standard Authorization header using the Bearer scheme:

curl -H "Authorization: Bearer <YOUR_CONNECT_API_KEY>" <URL>

Connect API secret keys are prefixed with connect-secret-.

warning

The Connect API secret key is distinct from the SDK API key — calls to the REST API with an SDK API key will fail.

Treat it like a password: anyone with it can read your community's content. For this reason, call the Connect API from your server-side code only — never from a browser, mobile app, or other client where the key would be exposed.

API requests

To make a REST API request, send an HTTP GET to the API service URL with the resource URI (including the version number) in the path, and the Connect API secret key in the request headers.

The URL to the API service is:

https://connect.octopuscommunity.com

All API endpoints are GET requests that accept query parameters, for example:

curl --location 'https://connect.octopuscommunity.com/v1/users/profile?octopusId=<TARGETED_ID>' \
--header 'Authorization: Bearer <YOUR_CONNECT_API_KEY>'

All API requests must be made over HTTPS. Calls made over plain HTTP will fail.

API responses

HTTP status codes

Successful requests

Status codeDescription
200 OKThe request succeeded

Failed requests

Status codeDescriptionPossible causes and solutions
400 Bad RequestThe request is malformed or violates the schema.Verify your parameters meet the documented requirements.
401 UnauthorizedThe Connect API secret key is not provided.Ensure the Authorization header is set with a Bearer token. See Authentication section.
403 ForbiddenThe Connect API secret key is not valid.Check that you are using the right Connect API secret key.
404 Not FoundThe specified resource does not exist.The URI is incorrect, or the resource is no longer available.
429 Too Many RequestsToo many requests — rate limit reached.You have reached your rate limit. Wait until the rate limit resets. See Rate limiting section.
500 Internal Server ErrorSomething unexpected happened on our servers.Retry later; if the issue persists, contact the Octopus team.

Endpoints

These endpoints let you retrieve the content of your community.

Get a list of feed items

Your community content is organized into feeds, each grouping messages in a different way for display. This endpoint returns pages of feed items for:

  • Posts in a specified topic, sorted by creation date
  • Comments on a specified post, sorted by creation date
  • Replies to a specified comment, sorted by creation date
  • Posts by a specified user, sorted by creation date
  • All posts, sorted by creation date

For the first four feeds, the following parameters are available:

  • The ID of the parent message (topic, post, or comment)
  • The pageSize defines the number of items per page. It must be between 1 and 20 and defaults to 5.
  • The sort order, which can be Asc or Desc. Asc returns items from oldest to newest, while Desc returns items from newest to oldest. The default is Desc.
  • The pageCursor is an opaque cursor returned in the previous response. Pass it to get the next page of feed items; leave it blank for your first request. Because the cursor encodes the sort order, any order parameter passed alongside it is ignored.

To retrieve all posts, you can use these parameters:

  • originTime: if you want to start at a specific timestamp. Expected format: a Unix timestamp in milliseconds.
  • order: can be Asc or Desc. Asc returns items from oldest to newest, while Desc returns items from newest to oldest. The default is Desc.
  • direction: can be Before or After. If you provide an originTime, After retrieves all posts more recent than this timestamp, and Before returns all posts created before this timestamp. The default is Before.
  • The pageSize defines the number of posts per page. It must be between 1 and 20 and defaults to 5.
  • The pageCursor is an opaque cursor returned in the previous response. Pass it to get the next page of posts; leave it blank for your first request. Because the cursor encodes the sort order and direction, any order or direction parameters passed alongside it are ignored.
note

Feed items are returned as if they were requested by an anonymous user, so banned messages are not included in the response. A banned or shadow-banned message can still be fetched by its Octopus ID through the messages endpoints.

Get details of a message item

With a message ID, you can retrieve the following details about the targeted content:

  • Body of the message: text, image URL or video URL, poll options, call-to-action button.
  • Metrics: view count, reactions, poll results
  • The five latest answers — only available when the message is a post or comment — if retrieveLatestComments or retrieveLatestReplies is set to true
  • A cursor to retrieve the next page of replies, when more replies exist and were requested.
tip

By using the query parameter clientObjectId instead of postId, you can retrieve a bridge post by the client object ID you assigned to it (the same ID passed to the SDK when the bridge post was created).

note

All message text is returned in its original language. Use the get translations endpoint to fetch all existing translations.

Get details about a profile

With either an octopusId or a loginId as a query parameter, you can get:

  • Octopus ID of the user
  • Nickname
  • Avatar URL
  • Biography
  • Total number of messages the user has written (all types)
  • Account age in days
  • Gamification level (if gamification is enabled for your community)
  • Five most recent posts (when retrieveLatestPosts=true)

Other useful endpoints

Get all topics

This endpoint is useful if you want to list all topics in your community and get their IDs, for example to set up bridge posts.

Get all translations of a message

This endpoint returns all translations generated for the text parts of a message. Translations are grouped by language code and provided for the following fields:

  • text
  • poll options
  • call-to-action button
  • catchPhrase (for bridge posts)

Tooling

Postman Collection

To help you get started quickly, we provide a Postman collection that includes all available API endpoints with example requests and responses.

How to use the Postman Collection:

  1. Click the "Download Collection" button above (if it opens in the browser, right-click and select "Save As...").
  2. Open Postman and click "Import" in the top left
  3. Select the downloaded JSON file or drag & drop it
  4. Once imported, set your Connect API secret key:
    • Go to the collection variables tab
    • Set the API_KEY variable to your actual Connect API secret key (provided by the Octopus team)
  5. You're ready to make requests!

The collection includes:

  • Users: Get public user profiles
  • Feeds: Retrieve feeds of posts, comments, and replies
  • Messages: Get detailed information about topics, posts, comments, and replies
tip

The Postman collection is automatically configured with the correct base URL and authentication headers. Just add your Connect API secret key and start testing!

API reference (ReDoc)

You can also browse the v1 ReDoc API reference for full details on every available endpoint.

Example use cases

Display engagement counters on an article linked to a bridge post

Code sample
import org.json.JSONArray;
import org.json.JSONObject;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class OctopusApiClient {

private static final String API_KEY = "YOUR_CONNECT_API_KEY";
private static final String BASE_URL = "https://connect.octopuscommunity.com/v1/messages/post";

// Reaction unicode → Map your own reactions here
private static final Map<String, String> REACTION_LABELS = new HashMap<>();

static {
REACTION_LABELS.put("❤\uFE0F", "❤️");
REACTION_LABELS.put("\uD83D\uDE02", "😂");
REACTION_LABELS.put("\uD83D\uDE2E", "😮");
REACTION_LABELS.put("\uD83D\uDC4F", "👏");
REACTION_LABELS.put("\uD83D\uDE22", "😢");
REACTION_LABELS.put("\uD83D\uDE21", "😡");
}

public static void main(String[] args) throws Exception {
String clientObjectId = "YOUR_CLIENT_OBJECT_ID";

String url = String.format(
"%s?clientObjectId=%s&retrieveLatestComments=false",
BASE_URL, URLEncoder.encode(clientObjectId, StandardCharsets.UTF_8)
);

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + API_KEY)
.GET()
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() != 200) {
System.err.println("Request failed: HTTP " + response.statusCode());
System.err.println(response.body());
return;
}

parseAndPrintMetrics(response.body());
}

private static void parseAndPrintMetrics(String json) {
JSONObject root = new JSONObject(json);
JSONObject post = root.getJSONObject("post");

// metrics can be null per the schema
if (post.isNull("metrics")) {
System.out.println("No metrics available for this post.");
return;
}

JSONObject metrics = post.getJSONObject("metrics");

int childrenCount = metrics.optInt("childrenCount", 0);
int viewCount = metrics.optInt("viewCount", 0);

System.out.println("===== Post Metrics =====");
System.out.println("💬 Comments : " + childrenCount);
System.out.println("👁 Views : " + viewCount);

// --- Reactions ---
JSONArray reactions = metrics.optJSONArray("reactions");
System.out.println("\n----- Reactions -----");

if (reactions == null || reactions.isEmpty()) {
System.out.println("No reactions yet.");
} else {
for (int i = 0; i < reactions.length(); i++) {
JSONObject reaction = reactions.getJSONObject(i);
String unicode = reaction.getString("unicode");
int count = reaction.getInt("count");
String label = REACTION_LABELS.getOrDefault(unicode, unicode);
System.out.printf(" %s x%d%n", label, count);
}
}

System.out.println("========================");
}
}

Display posts of a specific topic

Code sample
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import org.json.JSONArray;
import org.json.JSONObject;

public class OctopusFeedClient {

private static final String API_KEY = "YOUR_CONNECT_API_KEY";
private static final String BASE_URL = "https://connect.octopuscommunity.com/v1/feeds/posts";

public static void main(String[] args) throws Exception {
String topicId = "YOUR_TOPIC_ID";
String pageSize = "20";
String order = "Desc";

String url = String.format("%s?topicId=%s&pageSize=%s&order=%s",
BASE_URL, URLEncoder.encode(topicId, StandardCharsets.UTF_8), pageSize, order);

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + API_KEY)
.GET()
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() != 200) {
System.err.println("Request failed: HTTP " + response.statusCode());
return;
}

JSONArray posts = new JSONObject(response.body()).getJSONArray("posts");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.getJSONObject(i);
String text = post.getJSONObject("content").optString("text", "(no text)");
String author = post.isNull("createdBy") ? "Unknown"
: post.getJSONObject("createdBy").optString("name", "Unknown");
System.out.println("--- Post " + (i + 1) + " ---");
System.out.println("Author : " + author);
System.out.println("Text : " + text);
}
}
}

Display a user's latest post

Code sample
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import org.json.JSONArray;
import org.json.JSONObject;

public class OctopusUserProfileClient {

private static final String API_KEY = "YOUR_CONNECT_API_KEY";
private static final String BASE_URL = "https://connect.octopuscommunity.com/v1/users/profile";

public static void main(String[] args) throws Exception {
String loginId = "YOUR_LOGIN_ID";

String url = String.format("%s?loginId=%s&retrieveLatestPosts=true", BASE_URL, URLEncoder.encode(loginId, StandardCharsets.UTF_8));

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + API_KEY)
.GET()
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() != 200) {
System.err.println("Request failed: HTTP " + response.statusCode());
return;
}

JSONObject root = new JSONObject(response.body());
String nickname = root.getJSONObject("profile").optString("nickname", "Unknown");
JSONArray posts = root.getJSONArray("firstPostsPage");
String text = posts.isEmpty() ? "(no posts)"
: posts.getJSONObject(0).getJSONObject("content").optString("text", "(no text)");

System.out.println("Nickname : " + nickname);
System.out.println("Latest post: " + text);
}
}

Rate limiting

Each Connect API secret key has a maximum number of calls that can be made in one minute. Each call consumes one credit unit, regardless of the response status.

When the rate limit has not been reached, the response includes these headers:

  • RateLimit-Limit: the maximum number of credit units allowed per minute for your key
  • RateLimit-Remaining: the number of credit units left
  • RateLimit-Reset: the number of seconds until your credit units are refilled
note

If your key is configured as unlimited, these headers are not returned.

If you exceed the limit and receive a 429 Too Many Requests response, the headers include:

  • Retry-After: the number of seconds until your credit units are refilled

Changelog

April 22, 2026

Initial release