Skip to main content

Installation

PM> Install-Package ButterCMS

Initialization

Initialize the SDK with your Read API token from the ButterCMS Settings.
using ButterCMS;

// Basic initialization
var butterClient = new ButterCMSClient("your_api_token");

// With custom timeout (default is 10 seconds)
var butterClient = new ButterCMSClient("your_api_token", TimeSpan.FromSeconds(30));

// With preview mode enabled
var butterClient = new ButterCMSClient(
    apiToken: "your_api_token",
    timeout: null,  // Use default
    maxRetryAttempts: 3,
    httpClient: null,
    previewMode: true
);

Configuration options

OptionTypeDefaultDescription
apiTokenstring-Your ButterCMS Read API token (required)
timeoutTimeSpan10 secondsRequest timeout
maxRetryAttemptsint3Number of retry attempts on failure
httpClientHttpClient-Custom HttpClient instance
previewModeboolfalseEnable preview mode for draft content

API methods

All methods are available in both synchronous and asynchronous versions. The async versions are recommended for better performance.

Pages

Retrieve and search pages created in the ButterCMS dashboard. Define a strongly-typed model for your page fields:
// Models/LandingPage.cs
public class LandingPage
{
    public string Headline { get; set; }
    public string Subheadline { get; set; }
    public string HeroImage { get; set; }
    public string Body { get; set; }
}
using ButterCMS;
using ButterCMS.Models;

// Fetch a single page (async)
var page = await butterClient.RetrievePageAsync<LandingPage>(
    pageType: "landing_page",
    pageSlug: "home-page",
    parameterDictionary: new Dictionary<string, string>
    {
        { "locale", "en" },
        { "preview", "1" }
    }
);
Console.WriteLine(page.Data.Fields.Headline);

// Fetch paginated pages (async)
var pages = await butterClient.ListPagesAsync<LandingPage>(
    pageType: "landing_page",
    parameterDictionary: new Dictionary<string, string>
    {
        { "page", "1" },
        { "page_size", "10" },
        { "locale", "en" }
    }
);

foreach (var p in pages.Data)
{
    Console.WriteLine(p.Slug);
}

// Search pages
var results = await butterClient.SearchPagesAsync<LandingPage>(
    query: "search term",
    pageType: "landing_page"
);

Collections

Fetch content from Collections (structured data tables). Define a model for your collection:
// Models/FaqCollection.cs
public class FaqCollection
{
    public List<FaqItem> Faq { get; set; }
}

public class FaqItem
{
    public string Question { get; set; }
    public string Answer { get; set; }
}
// Fetch collection content
var content = await butterClient.RetrieveContentFieldsAsync<FaqCollection>(
    keys: new[] { "faq" },
    parameterDictionary: new Dictionary<string, string>
    {
        { "locale", "en" }
    }
);

foreach (var item in content.Data.Faq)
{
    Console.WriteLine(item.Question);
    Console.WriteLine(item.Answer);
}

Blog Posts

Access the built-in Blog Engine for posts, categories, tags, and authors.
// List blog posts (async)
var postsResponse = await butterClient.ListPostsAsync(
    page: 1,
    pageSize: 10,
    excludeBody: true
);

foreach (var post in postsResponse.Data)
{
    Console.WriteLine(post.Title);
    Console.WriteLine(post.Slug);
}

// Access pagination
Console.WriteLine($"Total: {postsResponse.Meta.Count}");
Console.WriteLine($"Next page: {postsResponse.Meta.NextPage}");

// Filter by author and category
var filteredPosts = await butterClient.ListPostsAsync(
    page: 1,
    pageSize: 10,
    excludeBody: true,
    authorSlug: "jennifer-smith",
    categorySlug: "news"
);

// Fetch a single post (async)
var post = await butterClient.RetrievePostAsync("my-post-slug");
Console.WriteLine(post.Data.Title);
Console.WriteLine(post.Data.Body);

// Search posts
var searchResults = await butterClient.SearchPostsAsync(
    query: "search term",
    page: 1,
    pageSize: 10
);

Authors

// List all authors (async)
var authorsResponse = await butterClient.ListAuthorsAsync(
    includeRecentPosts: true
);

foreach (var author in authorsResponse)
{
    Console.WriteLine($"{author.FirstName} {author.LastName}");
}

// Retrieve a single author
var author = await butterClient.RetrieveAuthorAsync(
    authorSlug: "jennifer-smith",
    includeRecentPosts: true
);
Console.WriteLine(author.Bio);

Categories

// List all categories (async)
var categoriesResponse = await butterClient.ListCategoriesAsync(
    includeRecentPosts: true
);

foreach (var category in categoriesResponse)
{
    Console.WriteLine(category.Name);
    Console.WriteLine(category.Slug);
}

// Retrieve a single category
var category = await butterClient.RetrieveCategoryAsync("news");

Tags

// List all tags (async)
var tagsResponse = await butterClient.ListTagsAsync();

foreach (var tag in tagsResponse)
{
    Console.WriteLine(tag.Name);
    Console.WriteLine(tag.Slug);
}

// Retrieve a single tag
var tag = await butterClient.RetrieveTagAsync("featured");

Feeds

Retrieve RSS, Atom, and Sitemap feeds as XML documents.
// Get RSS feed
XmlDocument rssFeed = await butterClient.GetRSSFeedAsync();

// Get Atom feed
XmlDocument atomFeed = await butterClient.GetAtomFeedAsync();

// Get Sitemap
XmlDocument sitemap = await butterClient.GetSitemapAsync();

Query parameters reference

ParameterMethod ParameterDescription
pagepagePage number for pagination
page_sizepageSizeNumber of items per page
exclude_bodyexcludeBodyExclude post body for faster response
author_slugauthorSlugFilter posts by author
category_slugcategorySlugFilter posts by category
tag_slugtagSlugFilter posts by tag
includeincludeRecentPostsInclude recent_posts with authors/categories/tags
localelocale (in dictionary)Locale code for localized content
previewpreviewMode (constructor)Enable draft content access
levelslevels (in dictionary)Depth of nested references (1–3)

Synchronous vs asynchronous

All methods have both sync and async versions:
Async MethodSync Method
ListPostsAsync()ListPosts()
RetrievePostAsync()RetrievePost()
ListPagesAsync<T>()ListPages<T>()
RetrievePageAsync<T>()RetrievePage<T>()
ListAuthorsAsync()ListAuthors()
ListCategoriesAsync()ListCategories()
GetRSSFeedAsync()GetRSSFeed()
Recommendation: Always use async methods in web applications for better scalability.

Complete example

using ButterCMS;
using ButterCMS.Models;

class Program
{
    static async Task Main(string[] args)
    {
        var apiToken = Environment.GetEnvironmentVariable("BUTTERCMS_API_TOKEN");
        var client = new ButterCMSClient(apiToken);

        try
        {
            // Fetch the home page
            var homePage = await client.RetrievePageAsync<dynamic>(
                "landing_page",
                "home",
                new Dictionary<string, string> { { "locale", "en" } }
            );
            Console.WriteLine($"Page headline: {homePage.Data.Fields["headline"]}");

            // Fetch navigation collection
            var collections = await client.RetrieveContentFieldsAsync<dynamic>(
                new[] { "main_navigation" },
                new Dictionary<string, string>()
            );
            Console.WriteLine($"Navigation loaded");

            // Fetch recent blog posts
            var postsResponse = await client.ListPostsAsync(
                page: 1,
                pageSize: 3,
                excludeBody: true
            );
            Console.WriteLine($"Recent posts: {postsResponse.Data.Count()}");

            foreach (var post in postsResponse.Data)
            {
                Console.WriteLine($"  - {post.Title}");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error fetching content: {e.Message}");
        }
    }
}

Resources

GitHub Repository

View source code, report issues, and contribute

NuGet Package

Package details and version history