Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Discover the platform

Several common concepts and conventions apply throughout the Optimizely Community (formerly Social) API. An understanding of these strategies is helpful in discovering the tools available to you.

Services

The primary interaction point with the Optimizely Community API is through service classes, each implementing an interface following the naming convention I{Feature-Name}Service. Examples include:

  • ICommentService
  • IRatingService
  • IGroupService

For Optimizely Content Management System (CMS) sites with the feature's site integration package installed, you can get an instance of a service from the inversion of control (IoC) container.

Example

var commentService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<ICommentService>();

For non-Optimizely CMS sites, you can get an instance of a service from the default factory classes provided within the package.

Example

var factory = new EPiServer.Social.Moderation.Factories.DefaultWorkflowServiceFactory();
var workflowService = factory.Create();

Data models

Data models consumed and returned by the Community API's services are found under the "core" namespace for each platform feature, following the convention EPiServer.Social.{Feature-Name}.Core. For example:

  • EPiServer.Social.Comments.Core
  • EPiServer.Social.Ratings.Core

Exceptions

Exceptions thrown by the Community API's services are located in the Core namespace (EPiServer.Social.{Feature-Name}.Core) for feature-specific exceptions, and in EPiServer.Social.Common for shared platform exceptions.

Platform exceptions

The Optimizely Community API features share several exception types to communicate general platform error situations.

SocialAuthenticationException

A SocialAuthenticationException is thrown when a request is deemed unauthentic.

This error most commonly occurs when:

  • The application's configuration is missing one or more of its authentication settings.
  • The application's configuration contains inaccurate authentication settings.
  • The application's server time is inaccurate.

For information regarding configuration and authentication, see "Get connected" in Install Optimizely Community.

MaximumDataSizeExceededException

A MaximumDataSizeExceededException is thrown when a request exceeds the platform's size restriction of 10 kilobytes for social content.

This restriction applies to any given social entity, including native properties, optional extension data, and any overhead.

For example, consider a simple comment containing an author, body, and parent reference. Consider that you also composed this comment with custom extension data. The content associated with each of those native comment properties and the extension data contribute to the total size of the request.

The platform does not explicitly restrict the amount of content associated with any individual property of a social content model. This lets you prioritize content size for native content models versus custom extension data.

📘

Note

Applications should enforce content limits to minimize this exception.

RateLimitExceededException

A RateLimitExceededException is thrown when an application issues too many requests over a short period. All requests are tallied and compared against the rate limit. When an application exceeds the rate limit, the Optimizely Community API stops processing requests until a certain time has elapsed (a "request interval").

The exception provides additional information to help regulate the application's request rate. That information includes:

  • RequestInterval – The length of time in which requests are tallied.
  • RequestsIssued – The number of requests already issued in the request interval.
  • RequestLimit – The maximum number of requests allowed in a given request interval.
  • RetryAfter – The time remaining until the application may resume issuing requests.

If your application regularly encounters this exception, consider:

  • Optimize your code to minimize unnecessary API calls.
  • Cache frequently accessed data.
  • Actively regulate the application's request rate to ensure the application never encounters the issue.
  • Implement logic to pause and retry requests after reaching the limit.

SocialCommunicationException

A SocialCommunicationException is thrown when a request encounters a fundamental communication issue.

This error most commonly occurs when:

  • The application cannot connect or communicate with Optimizely Community API cloud services.
  • A request from the application exceeds the configured timeout.

SocialException

A SocialException is thrown when a request encounters an unexpected error scenario. The exception contains a message, status code, error code, and additional reasoning to describe the error.

This error most commonly occurs when:

  • The application's configuration is missing or malformed.
  • The platform encountered an unexpected service error.

Feature exceptions

Individual services may also throw exceptions unique to the feature they support. Details can be found in the documentation for each API.

Reference and IDs

The Optimizely Community API identifies data by Id and Reference, with important semantic distinctions. See also: Work with Optimizely Community API References.

Ids

Id classes are specific to a feature's entities ({Feature-Name}Id convention), with internally-generated values used to distinguish individual entities. Examples include:

  • CommentId
  • GroupId
  • WorkflowId

They are accepted by services for retrieving specific data instances.

Reference

The Reference class identifies users or resources outside the platform, establishing relationships between social content and external entities.

The developer defines the value within a reference class. It contains the information necessary to identify or classify the resource or user to which social content is related.

The platform provides a Reference class that is used to identify any target entity in your application. For example, a resource, like Optimizely CMS content, or a product or a user, like an Optimizely CMS user.

Best practices for defining references

Ensure your reference scheme is:

  • Capable of uniquely identifying entities.
  • Interpretable by your application.
  • Robust for future enhancements.

Consider factors like: Platform, Provider, Classification, Categorization, and Facets. A URI or similar namespace scheme is recommended.

Example for ecommerce content:

resource://optimizely/commerce/{product-identifier}/{variant-identifier}/{facet-identifier}

Criteria

The Optimizely Community API services allow retrieval of custom result sets using criteria. A Criteria<TFilter> class encapsulates specifications for retrieving a collection of results.

Filter

The TFilter type parameter identifies the class encapsulating filter specifications. The Filter property accepts an instance of this class to refine a result set.

PageInfo

The PageInfo property accepts an instance of a class defining pagination specifications:

  • Page size: Maximum number of results (default 10 if not specified, must be >= 0).
  • Page offset: Zero-based index to start retrieving results (must be >= 0).
  • CalculateTotalCount: Specifies if a total result count should be calculated. If true, the TotalCount property on ResultPage will be populated; otherwise, it defaults to -1.

Best practices for paginating results

Large page sizes or deep offsets can negatively impact performance. Balance request size, volume, and user experience. Retrieving TotalCount when not needed adversely affects return time.

OrderBy

The OrderBy property accepts a collection of SortInfo rules describing how to sort the result set.

SortInfo identifies the field and direction for sorting.

A subset of fields on data models is available for sorting, exposed statically on classes named {Feature-Name}SortFields (e.g., CommentSortFields, RatingSortFields).

Sorting rules are processed in order, with subsequent rules acting as fallbacks for matching values.

Best practices for sorting results

Specify fallback sorting rules if consistency in result ordering is important, especially when navigating multiple pages. Sorting of string values is based on Unicode value; standardize data in code and store as duplicate property on extension data if alternative ordering is required.

Result sets

Services with bulk retrieval capabilities deliver results in a paginated fashion, represented by a ResultPage<T> class.

Results

The T type parameter identifies the model for the returned data (e.g., Comment, Rating). The Results property gets the collection of individual result items.

TotalCount

The TotalCount property provides the total count of items from the query. It is calculated only if CalculateTotalCount in PageInfo is set to true. If CalculateTotalCount is false, TotalCount is -1.

Info

The Info property refers to the paging specifications used when the request was issued.

HasMore

The HasMore property is a boolean indicating if more items exist beyond the current page. This helps determine if an additional query with an incremented PageOffset would return more results.

Composites

The Optimizely Community API supports data extensibility by allowing native entities to be composed with custom data models, known as Composites.

What is a composite?

A Composite represents a pairing of a native platform entity and its associated extension data. Extension data is a .NET class defined within your application to capture additional details.

Define extension data

Extension data is a .NET class for additional details. Considerations:

  • Queryability: Design for filtering and sorting by primitive value types within extension data.
  • Maintainability: Anticipate future enhancements and changes.
  • Performance: Keep extension data light.

Constraints for extension data classes:

  • Public, parameter-less constructor.
  • No nested data in a polymorphic manner (e.g., child as the Object type).
  • No self-references or referential loops.
  • Class name, assembly names, and namespaces must remain stable.
  • Minimize size to avoid exceeding platform size restrictions.

Additional caveats:

  • DateTime values are stored and returned as UTC.
  • DateTime precision is up to the millisecond.
  • Decimal type is not supported; stored as double and subject to rounding errors.

Composite criteria

Services supporting Composites provide methods for retrieving them, accepting CompositeCriteria<TFilter, TExtension>. This class extends Criteria, incorporating its capabilities while adding enhancements.

ExtensionFilter

The TExtension type parameter implicitly filters for composites with extension data of this type. The ExtensionFilter property accepts a Boolean expression (represented as a tree structure) to filter by values in your extension data.

IncludeSubclasses

A boolean indicating whether to include items where TExtension appears anywhere in the type hierarchy of their associated extension data (true by default), or only explicit TExtension types (false).

Filter composites

Filter Expressions are Boolean expressions (tree structures) used to filter Composites by values in their extension data. The FilterExpressionBuilder<TExtension> class provides methods and operator overloads for constructing these expressions.

Boolean operators can compare fields of String, Boolean, Int, Long, Double, DateTime.

Example of Filter Expression construction:

var luckyNumberOf7 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.LuckyNumber).EqualTo(7);
var bornBefore1990 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThan(new DateTime(1990, 1, 1));
var combinedExpression = FilterExpressionBuilder<MyCommentExtension>.And(luckyNumberOf7, bornBefore1990);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
    ExtensionFilter = combinedExpression
};

Best practices for defining filter expressions

  • Minimize complexity and depth for optimal performance.
  • Changes to extension data classes may result in malformed expressions.
  • Malformed expressions can lead to unexpected or empty results.

Filter expressions

The examples for each filter expression below assume the following comment extension:

public class MyCommentExtension {
  public int LuckyNumber {
    get;
    set;
  }
  public List<string> FavoriteTeams {
    get;
    set;
  }
  public DateTime Birthday {
    get;
    set;
  }
}
Any expression

Use the Any expression to filter both single-value and multi-value extension fields by a list of values. As an example of using the Any expression with a single-value extension field, assume that you want to read all comments for which the single-value LuckyNumber extension field matches any of three drawn lucky numbers. The following code shows how this is done with the Any expression:

var drawnLuckyNumbers = new List<long>{3, 7, 9};
var commentsWithDrawnLuckyNumbers = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Any(drawnLuckyNumbers);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithDrawnLuckyNumbers
};

As an example of using the Any expression with a multi-value extension field, assume that you want to read all comments for which the multi-value favoriteTeams extension field contains either "New England Patriots" or "Boston Red Sox". The following code shows how this is done with the Any expression.

var mostFavoriteTeams = new List<string>{"New England Patriots", "Boston Red Sox"};
var commentsWithMostFavoriteTeams = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.FavoriteTeams).Any(mostFavoriteTeams);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMostFavoriteTeams
};
Contains expression

The Contains expression can be used to filter both single-value and multi-value extension fields by a single value. As an example of using the Contains expression with a single-value extension field, assume that you want to read all comments for which the single-value LuckyNumber extension field matches drawn lucky number 7. The following code shows how this is done with the Contains expression:

var luckyNumber = 7;
var commentsWithLuckNumber = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Contains(luckyNumber);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithLuckNumber
};

As an example of using the Contains expression with a multi-value extension field, assume that you want to read all comments for which the multi-value favoriteTeams extension field contains "Boston Celtics". The following code shows how this is done with the Contains expression.

var favoriteTeam = "Boston Celtics";
var commentsWithFavoriteTeam = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.FavoriteTeams).Contains(favoriteTeam);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithFavoriteTeam
};
EqualTo expression

The EqualTo expression is used to filter documents by an extension field whose value equals a given value. The EqualTo expression in the following example will match any comments with a Birthday on new year 2000.

var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).EqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMatchingBirthday
};
LessThanOrEqualTo expression

The LessThanOrEqualTo expression filters documents by an extension field whose value is less than or equal to a given value. The LessThanOrEqualTo expression in the following example will match any comments with a Birthday on or before new year 2000.

var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMatchingBirthday
};
GreaterThanOrEqualTo expression

The GreaterThanOrEqualTo expression filters documents by an extension field whose value is greater than or equal to a given value. The GreaterThanOrEqualTo expression in the following example will match any comments with a Birthday on or after new year 2000.

var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMatchingBirthday
};
LessThan expression

The LessThan expression in the following example matches any comments with a Birthday before 2000.

var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThan(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMatchingBirthday
};
GreaterThan expression

The GreaterThan expression filters documents by an extension field whose value exceeds a given value. The GreaterThan expression in the following example will match any comments with a Birthday after new year 2000.

var newYear2000 = new DateTime(2000, 1, 1);
var commentsWithMatchingBirthday = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThan(newYear2000);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithMatchingBirthday
};
And expression

The And expression filters documents by one or more sub-expressions where a document is matched by all the sub-expressions. The And expression in the following example will match any comments with a Birthday in the year 2000.

var startYear2000 = new DateTime(2000, 1, 1);
var endYear2000 = new DateTime(2000, 12, 31);
var commentsMatchingBirthday1 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(startYear2000);
var commentsMatchingBirthday2 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(endYear2000);
var commentsWithBirthdayInYear2000 = FilterExpressionBuilder<MyCommentExtension>.And(commentsMatchingBirthday1, commentsMatchingBirthday2);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = commentsWithBirthdayInYear2000
};
Or expression

The Or expression is used to filter documents by one or more sub-expressions where any of the sub-expressions matches a document. The Or expression in the following example will match any comments with a Birthday in year 2000 Or LuckyNumber 7.

var startYear2000 = new DateTime(2000, 1, 1);
var endYear2000 = new DateTime(2000, 12, 31);
var commentsMatchingBirthday1 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).GreaterThanOrEqualTo(startYear2000);
var commentsMatchingBirthday2 = FilterExpressionBuilder<MyCommentExtension>.Field(d => d.Birthday).LessThanOrEqualTo(endYear2000);
var commentsWithBirthdayInYear2000 = FilterExpressionBuilder<MyCommentExtension>.And(commentsMatchingBirthday1, commentsMatchingBirthday2);
var luckyNumber = 7;
var commentsWithLuckyNumber = FilterExpressionBuilder<MyCommentExtension>.Field(ext => ext.LuckyNumber).Contains(luckyNumber);
var theWinner = FilterExpressionBuilder<MyCommentExtension>.Or(commentsWithBirthdayInYear2000, commentsWithLuckyNumber);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  ExtensionFilter = theWinner
};

Sort composites

Fields within extension data can also be used for sorting composite result sets. Sorting rules are defined using the OrderBy property of CompositeCriteria, accepting a collection of SortInfo instances.

SortInfo identifies the field and direction for sorting.

Consider an example where an application composes a comment with extension data with the following definition:

public class MyCommentExtension {
  public int LuckyNumber {
    get;
    set;
  }
  public string FavoriteTeam {
    get;
    set;
  }
  public DateTime Birthday {
    get;
    set;
  }
}

The snippet below demonstrates the construction of an instance of SortInfo, targeting the LuckyNumber field of such an extension:

var sortField = new SortField(FilterExpressionBuilder<MyCommentExtension>.Field(d => d.LuckyNumber));
var sortingRule = new SortInfo(sortField, true);
var criteria = new CompositeCriteria<Comment, MyCommentExtension>
{
  OrderBy = new List<SortInfo> { sortingRule }
};

In this example, an instance of SortField is constructed. It accepts a FieldExpression representing the LuckyNumber field of your extension data. Next, an instance of SortInfo is constructed to refer to this SortField, and assigned to the criteria as a sorting rule.

Sorting rules targeting extension data fields can be combined with those targeting standard platform entities.

Asynchronous methods

Optimizely Community API services provide asynchronous method overloads (ending with Async suffix and returning a .NET Task object) for non-blocking operations. This improves application responsiveness and performance by allowing parallel execution of tasks. Developers can use C#'s async and await keywords.

For more details, refer to Microsoft's documentation for Task-based Asynchronous Programming and Asynchronous Programming with async and await.