Home Guides API reference What's New Developer Discussion

Getting started with Community API v2

This guide will get you started with Community API v2. The Community API is a RESTful API. You will use it in FreeMarker code via the rest and restadmin context objects and in GET, POST, PUT, and DELETE operations over HTTPS.

Note: POST, PUT, and DELETE actions over HTTPS are supported on a subset of API v2 collections, but not all. Use Community API v1 if the collection you are working with does not support the POST, PUT, or DELETE operation you need. Your code can contain v1 and v2 calls together.

This guide includes:

Before you begin

Terminology

This guide and API v2 use the following terms:

  • Collection Objects - a group of similar objects, such as Messages, Kudos, or Images. Retrieve collections using LiQL queries. See the Collection Object index for a full list of API v2 collections and links to the respective reference documentation.
  • Note: Objects that do not form collections, such as Solutions_Data and Revisions, cannot be queried directly in the SELECT statement. These objects are often returned as sub-objects of LiQL Collection Objects. You can only access these objects via a query to the parent object. For example SELECT registration_data FROM users WHERE id = '31'
  • Conversation style - the board-type associated with a thread or individual message. Conversation style is synonymous with the terms interaction style and discussion style used by API v1. Conversation styles include Forum, Blog, Contest, Idea, Q&A, Group, and TKB.
  • LiQL (Lithium Query Language) - a query language used to retrieve field-level data from an object

About LiQL

LiQL is a query language that queries against the search index and enables you to access Community data. Community API v2 exposes many object fields. Using LiQL, you can make your request lean because LiQL enables you to define exactly which fields to return. LiQL is used with READ actions over HTTP and in FreeMarker code.

You can test queries in the API Browser tab in Studio. We'll show you how later in the API v2 quick start section.

Let's look at a couple of example queries.

This query returns the subject, ID of forum posts that have an average rating value of 4 or higher.

SELECT id FROM messages WHERE ratings.avg(value)>=4 AND conversation.style='forum'

This query returns the subject, ID, and conversation data for forum topics with accepted solutions.

SELECT subject, id, conversation FROM messages WHERE conversation.style= 'forum' AND depth=0 AND conversation.solved='true'

API v2 access and Community permissions

Community API v2 is accessible to signed-in and anonymous users. This is different from API v1, which requires any user making a REST call to have the Make REST API calls with read access and Make REST API calls with modify access permissions granted.

With API v2, these two permissions are not required. Instead, a user's permissions granted within the community dictate the actions he or she can take via the API. Anonymous users, for example, can read public data only; they do not have permission to post messages or access private boards or categories. Therefor, anonymous users cannot perform REST calls that post messages or access private boards or categories. On private communities where anonymous access is disabled, anonymous users cannot access the API at all.

Tip: Because you will likely be using API v1 and v2 together in your code, we recommend continuing to grant Make REST API calls with read access and Make REST API calls with modify access for any users who need to access the Community API.

Enabling CORS support

To make Community API REST calls in FreeMarker endpoints or from external domains over HTTPS, you must call Lithium Support to enable cross-origin resource sharing (CORS).

Working with HTAccess

You cannot pass HTAccess credentials in your Community API calls. However, Lithium Support can white list an IP address or range of IPs addresses so that they are exempt from requiring HTAccess credentials when testing on a stage environment. If you have IPs to white list, contact Lithium Support and review the HTAccess FAQ.

Quick start: The API Browser

Let's walk through a few example LiQL queries and look at the responses. To do this, we'll use a tool in Studio called the API Browser. This tool lets you test LiQL queries without making a formal HTTPS request or writing any FreeMarker code.

The API Browser uses your Studio login for authentication and policy checks, so the roles and permissions assigned to your user account will affect the query results. Consider creating test accounts for different user test cases, such as a test administrator, moderator, and basic user with your base Community permissions.

To use the API Browser:

  • You need to be granted the Use REST API browser permission
  • You need a community that includes boards, messages, and users

Open the API Browser by logging into the community and navigating to Studio > API Browser.

Note: If you do not see the API Browser tab, file a ticket with Lithium Support.

First, we'll run a very basic query:

SELECT * FROM messages
Import: For performance reasons, we recommend against using * in a SELECT statement in your code. Instead, we recommend making your queries as specific as possible, especially for collections, like the Messages collection, that contain many fields. For the purposes of this tutorial and when using the APi Browser, however, using * is safe and can be quite useful to understand the data structure.

Let's take a look at the results for that query. If you have boards and messages in your environment, you should see a response that looks similar to the one in the image below.

API Browser tab

Next, let's query the number of unanswered posts (topic messages with no replies):

SELECT count(*) FROM messages WHERE replies.count(*)=0 and depth=0
Tip: In this example, we used a WHERE clause to limit the message object returned in the result set to topic messages (signified by 'depth=0' in the query). The WHERE clause can also be used to perform keyword and combinatorial searches. For more information about the WHERE clause, see the WHERE clause section of Using LiQL.

If you have unanswered posts, you'll see a response similar to this. These results show that there are 19 topics without any replies:

    {
        "status" : "success",
        "message" : "",
        "http_code" : 200,
        "data" : {
              "count" : 19
              },
        "metadata" : { }
    }
    

Finally, we'll query the id, subject, and view_href fields of unsolved forum posts ordered by the last post time

SELECT id, subject, view_href FROM messages WHERE conversation.style = 'forum' AND depth = 0 ORDER BY conversation.last_post_time DESC
Tip: Notice the ORDER BY statement in that last query. We recommend using an ORDER BY clause when querying collections where fields in the ORDER BY clause are supported. This is because results from LiQL queries without ORDER BY are ordered in a inconsistent, arbitrary order. This means that every REST call will be ordered differently. To learn more, see the Best practices section of Using LiQL.

If you have posts with the conversation style of forum, you will see a response similar to this:

{
"status":"success",
"message":"",
"http_code":200,
"data": {
"type" : "messages",
"list_item_type" : "message",
"size" : 22,
"items": [ {
"type":"message",
"id":"62",
"view_href":"/t5/Forum-with-PreModeration-and/Youtube/m-p/62#M7",
"subject":"Youtube"
}, {
"type":"message",
"id":"58",
"view_href":"/t5/Forum-with-PreModeration-and/pdf/m-p/58#M5",
"subject":"pdf"
}, {
...
} ]
},
"metadata":{}
}

Continue to experiment with LiQL queries using the API reference documentation. See our Collection index for a list of API v2 collections and their definitions.

When you're finished, continue on to learn how to use LiQL queries in your code.

Making v2 calls in FreeMarker

You access the Community API in FreeMarker using these context objects:

  • rest - for POST, PUT, DELETE, and GET actions
  • restadmin - for POST, PUT, DELETE, and GET actions
  • liql - for GET actions
  • liqladmin - for GET actions
Note: Prior to Community release 19.1, you could only make GET calls to the Community API with FreeMarker.

GET calls with FreeMarker

You have two options when making a GET call with FreeMarker: Use the rest and restadmin context objects or use the liql and liqladmin context objects.

We added liql and liqladmin in Community release 19.1. These are convenience methods that enable you to make a LiQL call with a single argument. The alternative is the use rest and restadmin, which requires passing the API version and the /search endpoint with a LiQL query as the value of a query parameter.
Note: No authentication parameters are required with your FreeMarker call. The liqlliqladmin, rest, and restadmin context objects handle authentication for you on the back end.

Using rest and restadmin

rest and restadmin take the following parameters:

  • rest_version (the Community API version used). The value is always 2.0.
  • the /search endpoint appended with a URL-encoded LiQL query

Here are examples of the basic format:

rest("rest_version","/search?q=" + "liql_query"?url)
restadmin("rest_version","/search?q=" + "liql_query"?url)

A call would look something like this:

rest("2.0","/search?q=" + "SELECT * FROM messages ORDER BY post_time DESC LIMIT 5"?url)
Note: You do use the rest_version parameter when making API v1 calls using rest or restadmin.

This example component displays the subject of five most recent message subjects posted:

<#assign x= rest("2.0","/search?q=" + "SELECT subject FROM messages ORDER BY post_time DESC LIMIT 5"?url) />
    <#list x.data.items as message >
    <p>${message.subject}</p>
    </#list>

Using liql and liqladmin

liql and liqladmin take the following parameters:

  • version (Optional) The Community API version. Defaults to "2.0". At this time, 2.0 is the only version. The value is always 2.0.
  • query (Required) Specifies the LiQL query.
  • characterSet (Optional) Specifies the character set to use when encoding the LiQL query. Defaults to "UTF-8". We recommend using the default.

A call would look something like this:

liql("SELECT id, subject, body FROM messages ORDER BY post_time DESC LIMIT 5")
liqladmin("SELECT id, subject, body FROM messages ORDER BY post_time DESC LIMIT 5")

This example component displays the subject of five most recent message subjects posted:

<#assign x= liql("SELECT subject FROM messages ORDER BY post_time DESC LIMIT 5") />
    <#list x.data.items as message >
    <p>${message.subject}</p>
    </#list>

POST/PUT/DELETE calls with FreeMarker

When making POST, PUT, and DELETE call so the Community REST API v1 and v2 with FreeMarker, the rest and restadmin context objects take these parameters.
Note: No authentication parameters are required with your FreeMarker call. The rest and restadmin context objects handle authentication for you on the back end.
Parameter Description Example
version (Required only when calling the Community API v2) The API version Get the message with the ID of 34 with a call to API v2. Note that because there is no method parameter passed, the method defaults to GET.

<#assign resp = rest("2.0", "/messages/34") />
path (Required) The REST call path Get the message with the ID of 34 with a call to API v2. Note that because there is no method parameter passed, the method defaults to GET.

<#assign resp = rest("2.0", "/messages/34") />
method (Optional) The HTTP method for the REST call. Defaults to GET if not set Delete the message with the ID of 34 using API v2.

<#assign resp = rest("2.0", "/messages/34", "DELETE") />
requestBody (Optional) The REST V2 request body, as a FreeMarker hash Edit the subject of message ID 34.

<<#assign resp = rest("2.0", "/messages/34", "PUT", {
  "type": "message",
  "id": "34",
  "subject": "updated subject" }) />

Example POST (create)

<#-- Build the requestBody parameter and assign it to a variable-->
<#assign messagePostBody = {
    "type": "message",
    "subject": "How do I post a REST API message?"
} />
<#-- Make your REST call with the rest or restadmin object -->
<#assign resp = rest("2.0", "/messages", "POST", messagePostBody) />
...

Example PUT (edit)

<#-- Build the requestBody parameter and assign it to a variable-->
<#assign messagePostBody = {
    "type": "message",
    "id": "34",
    "subject": "How do I post a REST API message?"
} />

<#-- Make your REST call with the rest or restadmin object -->
<#assign resp = rest("2.0", "/messages/34", "PUT", messagePostBody) />
...

Example DELETE

<#-- Make your REST call with the rest or restadmin object -->
<#assign resp = rest("2.0", "/messages/34", "DELETE") />
...

A few FreeMarker tips

These tips will help simplify your FreeMarke code.

Assign the API version to a variable. We recommend storing the API version in a FreeMarker variable and using that variable when you make a rest call. This will make future upgrades to a newer version of the Community API easier as you will only have to change the version number in one place.

For example:
<#assign apiVersion = "2.0"/>

Assign the LiQL query to a variable. Using a variable rather than using a string concatenation within the REST call can reduce typos leading to FreeMarker errors. You can also print out the variable if needed and enables you to URL escape the entire variable as needed.

For example:
<#assign labelsQuery = "SELECT * FROM labels WHERE message.id = '"+ articleId + "'"/>

Using these conventions, you could make a REST call that looks something like this:

<#assign labels = rest(apiVersion, "/search?q=" + labelsQuery?url + "&restapi.response_style=view").data.items![] />

Error handling in FreeMarker with API v2

In Community API v1, you wrap your REST calls in a FreeMarker attempt/recover block. With API v2, this isn't necessary because the Community REST API V2 framework catches all RuntimeExceptions in Java and returns an error response. As a best practice, create a macro that just checks the response to see if there is an error and routes to one of two macros based on that check.

You can see an example in Creating higher-order functions using FreeMarker templates.

Making v2 calls over HTTPS

GET actions over HTTPS are supported for all API v2 collections. A subset of API v2 collections also support POST, PUT, and DELETE actions. The Community API v2 collection documentation details whether the collection supports POST, PUT, and DELETE actions and provides example calls.

The v2 API URL

The API URL structure for Community API v2 calls is:

https://[COMMUNITY DOMAIN]/api/[VERSION]/[RESOURCE]

where:

  • COMMUNITY DOMAIN is the host URL of the community
  • VERSION is the version of the Community API: always 2.0
  • RESOURCE is the API v2 resource to work with

Example

https://khoros.community.com/api/2.0/messages
Note: LiQL queries, which are made with a call to the /search endpoint, must be URL-encoded when called over HTTPS. Encode the '=' sign in the query using '%3D'.
https://khoros.community.com/api/2.0/search?q=SELECT+*+FROM+messages+WHERE+replies.count(*)%3D0

Header Parameters with OAuth authorization

Review the OAuth 2.0 authorization grant flow to learn about OAuth.

Include the following in the header.

Header Value
client-id The client ID. The client ID is generated and listed in Community Admin > System > API Apps. See API Keys for instructions to generate the ID.
Authroization Bearer token where token is the OAuth token obtained on behalf of the user
Content-type (Used with PUT and POST actions only) application/json or multipart/form-data

Header Parameters with Session Key authorization

Obtain a session key using the instructions in API session key authentication.

Include the following in the header.

Header Value
Li-Api-Session-Key The session key obtained from the API v1 method.
Content-type (Used with PUT and POST actions only) application/json or multipart/form-data

Supported query parameters

api.pretty_print=true (optional) Provides read-friendly formatting
api.for_ui_search=true (optional) (Added 15.2) Signifies that the call is being used to back a search in the Community UI. When true, the related search events are captured in the LSI search reports. This parameter is supported only for LiQL calls that use MATCHES when filtering on a Message collection.

HTTP examples

Example POST call with OAuth

    curl -X POST \
    https://[COMMUNITY DOMAIN]/api/2.0//messages \
    -H 'content-type: application/json' \
    -H 'Authorization: Bearer [TOKEN]' \
    -H 'client-id: [CLIENT ID]' \
    -d '{
            "data":{
                "type":"message",
                "subject":"This is the message subject",
                "body":"This is a message post.",
                "board":{
                    "id":"myForum"
                }
            }
        }'
    

Example GET call with OAuth

    curl -X GET \
    'https://[COMMUNITY DOMAIN]/api/2.0//messages/770/labels/electronics' \
    -H 'Authorization: Bearer [TOKEN]' \
    -H 'client-id: [CLIENT ID]'
    

Example GET call with session key authentication

    curl -X GET \
    'https://[COMMUNITY DOMAIN]/api/2.0/messages/770/labels/electronics' \
    -H 'li-api-session-key: [SESSION KEY]'
    

Example PUT call with session key authentication

    curl -X POST \
    https://[COMMUNITY DOMAIN]/api/2.0/messages \
    -H 'content-type: application/json' \
    -H 'li-api-session-key: [SESSION KEY]' \
    -d '{
            "data":{
                "type":"message",
                "subject":"This is the message subject",
                "body":"This is a message post.",
                "board":{
                    "id":"myForum"
                }
            }
        }'
        

Next steps

Be sure to read our additional documentation about:

The Community API v2 reference documentation provides details for v2 objects, including field definitions, examples, and CRUD support.