ContentstackClient
ContentstackClient
ContentstackClient is the entry point of the .NET Delivery SDK. It holds the stack credentials, the environment, and the request settings, and every other object in the SDK starts from it. Use this class to
- connect to one stack and one environment
- reach content types, entries, assets, global fields, and taxonomies
- retrieve published content in bulk through the Sync API
- set request headers and live preview values that later requests carry
| Name | Type | Description |
|---|---|---|
| SerializerOptions | JsonSerializerOptions | Options the SDK uses to bind responses to your model classes. |
Asset
Asset returns an object for the asset that a UID names.
| Name | Type | Description |
|---|---|---|
| Uid (required) | string | UID of the asset to read. |
Returns: Asset. A new asset object.
Validation
- There is no client-side validation. Asset accepts a null or empty UID and stores it as given.
- A null or empty UID fails when Fetch sends the request, with an AssetException.
- Errors that do occur come from the Fetch call that follows, not from Asset.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. Asset builds the object and makes no request.
- The asset object uses the client's credentials, environment, branch, and headers.
- Call Fetch on the result to read the asset. See the Asset class page for the methods you can chain.
- To read many assets, use the AssetLibrary method instead.
Example
Basic usage: fetch one asset by UID
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
Asset asset = await client.Asset("<ASSET_UID>").Fetch();
Console.WriteLine($"{asset.FileName}: {asset.Url}");
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}AssetLibrary
AssetLibrary returns a query across every asset in the stack.
Returns: AssetLibrary. A new asset library object.
Validation
- There is no client-side validation, because AssetLibrary takes no argument.
- Errors that do occur come from the FetchAll or Count call that follows, not from AssetLibrary.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. AssetLibrary builds the query object and makes no request.
- Each call returns a new object, so filters you chain on one asset library object do not reach another.
- Chain filters such as Limit or Tags, then call FetchAll to read the matching assets. See the AssetLibrary class page for the full set.
- To read one asset by its UID, use the Asset method instead.
Example
Basic usage: list the first ten assets
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
ContentstackCollection<Asset> assets = await client.AssetLibrary().Limit(10).FetchAll();
foreach (Asset asset in assets)
{
Console.WriteLine($"{asset.Uid}: {asset.FileName}");
}
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}ContentType
ContentType returns an object for one content type, from which you reach its schema, its entries, and its queries.
| Name | Type | Description |
|---|---|---|
| contentTypeName (required) | string | UID of the content type to work with. |
Returns: ContentType. A new content type object.
Validation
- There is no client-side validation. ContentType accepts a null or empty UID and stores it as given.
- A null or empty UID fails on the terminal call (Fetch or Find) that follows, with a ContentstackException subclass.
- Errors that do occur come from that terminal call, not from ContentType.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. ContentType builds the object and makes no request.
- Pass the content type UID, not its display title. The SDK places the value of contentTypeName in the request URL.
- When the UID is not empty, ContentType records it on the client. LivePreviewQueryAsync uses that UID when its dictionary has no content_type_uid key.
- Chain Entry("<ENTRY_UID>") to read one entry, Query() to search entries, or Fetch() to read the content type schema. See the ContentType class page.
- To list every content type in the stack, use the GetContentTypes method instead.
Example
Basic usage: fetch one entry of a content type
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}Query entries: find the first five entries of a content type
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
ContentstackCollection<Entry> entries = await client.ContentType("<CONTENT_TYPE_UID>").Query().Limit(5).Find<Entry>();
foreach (Entry entry in entries)
{
Console.WriteLine(entry.Title);
}
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}GetAccessToken
GetAccessToken returns the delivery token that the client sends in the access_token header.
Returns: string. The delivery token the client sends.
Validation
- Throws KeyNotFoundException if the client holds no access_token header, because GetAccessToken reads that header directly. This happens when you create the client without a delivery token, or after RemoveHeader("access_token").
Behavior
- Client-side only. GetAccessToken reads the header the constructor wrote and makes no request.
- The constructor writes DeliveryToken into the access_token header. When the deprecated AccessToken option also holds a value, the constructor writes that value instead.
- A later SetHeader("access_token", ...) call changes the value that GetAccessToken returns.
Example
Basic usage: read the delivery token back
using System;
using Contentstack.Core;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
string token = client.GetAccessToken();
Console.WriteLine($"Token length: {token.Length}");Edge case: the header is missing
using System;
using System.Collections.Generic;
using Contentstack.Core;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
client.RemoveHeader("access_token");
try
{
string token = client.GetAccessToken();
}
catch (KeyNotFoundException)
{
// Thrown when the client holds no access_token header
Console.WriteLine("The client has no delivery token.");
}GetApplicationKey
GetApplicationKey returns the stack API key that you passed to the constructor.
Returns: string. The API key the client holds.
Validation
- There is no client-side validation. GetApplicationKey returns null when you created the client without an API key.
Behavior
- Client-side only. GetApplicationKey reads the value the constructor stored and makes no request.
- GetApplicationKey returns the constructor value even after SetHeader("api_key", ...) changes the header that requests carry.
Example
Basic usage: read the API key back
using System;
using Contentstack.Core;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
string apiKey = client.GetApplicationKey();
Console.WriteLine($"API key: {apiKey}");GetContentTypes
GetContentTypes retrieves every content type in the stack, with its schema.
| Name | Type | Description |
|---|---|---|
| param | Dictionary<string, object> | Extra query parameters for the request. |
Returns: Task<IList>. The content types in the stack.
Validation
- There is no client-side validation of the keys or values in param.
- Throws ArgumentException if param holds an environment key, because the SDK adds environment from the client first and the request parameters cannot hold the same key twice. The exception occurs before the SDK sends anything.
- Throws ContentstackException if the API rejects the request. GetContentTypes throws the base class, not ContentTypeException.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Sends one GET /content_types request with the client's environment, and adds each param entry as a query parameter. See Get all content types.
- The API reference documents include_branch and include_global_field_schema for this request. include_global_field_schema returns the schema of each global field inside the content type schema.
- The SDK writes each value with its default string form, so the bool value true reaches the API as True. Pass flags as the string "true".
- Returns the content_types array only. Each item is a Dictionary<string, object>, and nested objects and arrays arrive as further dictionaries and List<object> values.
- GetContentTypes drops every other key in the response. A count that include_count adds does not reach you.
- To read one content type, use the ContentType method and call Fetch on the result.
Example
Basic usage: list content type UIDs and titles
using System;
using System.Collections;
using System.Collections.Generic;
using Contentstack.Core;
using Contentstack.Core.Internals;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
IList contentTypes = await client.GetContentTypes();
foreach (Dictionary<string, object> contentType in contentTypes)
{
Console.WriteLine($"{contentType["uid"]}: {contentType["title"]}");
}
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}All parameters: include global field schemas and branch details
using System;
using System.Collections;
using System.Collections.Generic;
using Contentstack.Core;
using Contentstack.Core.Internals;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
// Pass flag values as strings. A bool reaches the API as "True".
Dictionary<string, object> param = new Dictionary<string, object>()
{
{ "include_global_field_schema", "true" },
{ "include_branch", "true" }
};
try
{
IList contentTypes = await client.GetContentTypes(param);
foreach (Dictionary<string, object> contentType in contentTypes)
{
List<object> schema = (List<object>)contentType["schema"];
Console.WriteLine($"{contentType["uid"]}: {schema.Count} fields");
}
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}GetEnvironment
GetEnvironment returns the environment that the client reads published content from.
Returns: string. The environment the client reads content from.
Validation
- There is no client-side validation. GetEnvironment returns null when you created the client without an environment.
Behavior
- Client-side only. GetEnvironment reads the value the constructor stored and makes no request.
- The SDK sends this value as the environment query parameter. SyncToken and SyncPaginationToken leave it out. The All Query Parameters reference lists environment for every Content Delivery API request except those two sync requests.
Example
Basic usage: read the environment back
using System;
using Contentstack.Core;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
string environment = client.GetEnvironment();
Console.WriteLine($"Environment: {environment}");GetLivePreviewConfig
GetLivePreviewConfig returns the live preview settings object that the client uses for its requests.
Returns: LivePreviewConfig. The live preview settings the client uses.
Validation
- There is no client-side validation, because GetLivePreviewConfig takes no argument. It never returns null.
Behavior
- Client-side only. GetLivePreviewConfig makes no request.
- Returns the same object the client holds, not a copy. A change to a property of the returned object, such as PreviewToken, applies to the next request.
- When you created the client without ContentstackOptions.LivePreview, the object has Enable set to false.
- When live preview is on and you left Host unset, the constructor filled Host in. Read it here to see which host the client uses.
- See the LivePreviewConfig class page for each property.
Example
Basic usage: check the live preview host
using System;
using Contentstack.Core;
using Contentstack.Core.Configuration;
ContentstackClient client = new ContentstackClient(new ContentstackOptions()
{
ApiKey = "<API_KEY>",
DeliveryToken = "<DELIVERY_TOKEN>",
Environment = "<ENVIRONMENT>",
LivePreview = new LivePreviewConfig()
{
Enable = true,
PreviewToken = "<PREVIEW_TOKEN>"
}
});
LivePreviewConfig config = client.GetLivePreviewConfig();
Console.WriteLine($"Live preview enabled: {config.Enable}, host: {config.Host}");GetVersion
GetVersion returns the API version path segment that the client puts in every request URL.
Returns: string. The API version segment the client uses.
Validation
- There is no client-side validation, because GetVersion takes no argument.
Behavior
- Client-side only. GetVersion reads the client configuration and makes no request.
- Returns v3 unless you passed a version to the constructor or set ContentstackOptions.Version.
- GetVersion returns the API version, not the SDK package version.
Example
Basic usage: read the API version
using System;
using Contentstack.Core;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
string version = client.GetVersion();
Console.WriteLine($"API version: {version}");GlobalField
GlobalField returns an object for the global field that a UID names.
| Name | Type | Description |
|---|---|---|
| globalFieldName (required) | string | UID of the global field to read. |
Returns: GlobalField. A new global field object.
Validation
- Throws GlobalFieldException at once if globalFieldName is an empty string, because the global field object rejects an empty UID.
- A null UID passes this check and fails when Fetch sends the request.
- Errors from the API come from the Fetch call that follows, not from GlobalField.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. GlobalField builds the object and makes no request.
- Pass the global field UID, not its display title. The SDK places the value in the request URL.
- Call Fetch on the result to read the global field schema. See the Global Fields class page.
- To read every global field, use the GlobalFieldQuery method instead.
Example
Basic usage: fetch one global field schema
using System;
using System.Text.Json.Nodes;
using Contentstack.Core;
using Contentstack.Core.Internals;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
JsonObject globalField = await client.GlobalField("<GLOBAL_FIELD_UID>").Fetch();
Console.WriteLine(globalField["title"]);
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}GlobalFieldQuery
GlobalFieldQuery returns a query across every global field in the stack.
Returns: GlobalFieldQuery. A new global field query.
Validation
- There is no client-side validation, because GlobalFieldQuery takes no argument.
- Errors that do occur come from the Find call that follows, not from GlobalFieldQuery.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. GlobalFieldQuery builds the query object and makes no request.
- Call Find on the result to read the global fields. See the Global Field Query class page.
- To read one global field by its UID, use the GlobalField method instead.
Example
Basic usage: list every global field
using System;
using System.Text.Json.Nodes;
using Contentstack.Core;
using Contentstack.Core.Internals;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
JsonObject response = await client.GlobalFieldQuery().Find();
JsonArray globalFields = response["global_fields"]?.AsArray();
Console.WriteLine($"Global fields: {globalFields?.Count ?? 0}");
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}LivePreviewQueryAsync
LivePreviewQueryAsync stores the live preview values from a preview request on the client. The next entry fetch or query for that content type then returns the draft content.
| Name | Type | Description |
|---|---|---|
| query (required) | Dictionary<string, string> | Live preview values from the preview URL. |
Returns: Task. A task that completes when the client holds the preview values.
Validation
- Throws NullReferenceException if query is null, because LivePreviewQueryAsync reads the dictionary keys without a null check.
- There is no check on the values. An empty or wrong hash reaches the API on the next Fetch or Find.
- LivePreviewQueryAsync ignores keys it does not recognize.
- Errors that do occur come from the Entry.Fetch or Query.Find call that follows.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. LivePreviewQueryAsync writes into the client's LivePreviewConfig and makes no request. The returned task has already completed.
- LivePreviewQueryAsync reads the five keys below from query:
- live_preview: the preview hash. When the key is missing, the client clears the hash.
- content_type_uid: the content type to preview. When the key is missing, the client uses the UID from the last ContentType call.
- entry_uid: the entry to preview. When the key is missing, the client uses the UID from the last SetEntryUid call.
- release_id: sent as the release_id header. When the key is missing, the client clears it.
- preview_timestamp: sent as the preview_timestamp header. When the key is missing, the client clears it.
- The values take effect only when LivePreviewConfig.Enable is true.
- When the client holds a hash, Entry.Fetch and Query.Find on the matching content type send the request to LivePreviewConfig.Host with the hash. They send the preview token (or the management token as authorization) in place of the delivery token.
- Requests for every other content type, and every request while the client holds no hash, go to the delivery host as usual.
- The values live on the client. Two preview requests that share one client overwrite each other's values, so create a client for each incoming preview request.
Example
Basic usage: preview the entry that the preview URL names
using System;
using System.Collections.Generic;
using Contentstack.Core;
using Contentstack.Core.Configuration;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient(new ContentstackOptions()
{
ApiKey = "<API_KEY>",
DeliveryToken = "<DELIVERY_TOKEN>",
Environment = "<ENVIRONMENT>",
LivePreview = new LivePreviewConfig()
{
Enable = true,
PreviewToken = "<PREVIEW_TOKEN>"
}
});
// In a web app, read the hash from the preview request's query string.
string livePreviewHash = Environment.GetEnvironmentVariable("LIVE_PREVIEW_HASH") ?? "";
await client.LivePreviewQueryAsync(new Dictionary<string, string>()
{
{ "live_preview", livePreviewHash },
{ "content_type_uid", "<CONTENT_TYPE_UID>" },
{ "entry_uid", "<ENTRY_UID>" }
});
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}Preview a release at a point in time
using System;
using System.Collections.Generic;
using Contentstack.Core;
using Contentstack.Core.Configuration;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient(new ContentstackOptions()
{
ApiKey = "<API_KEY>",
DeliveryToken = "<DELIVERY_TOKEN>",
Environment = "<ENVIRONMENT>",
LivePreview = new LivePreviewConfig()
{
Enable = true,
PreviewToken = "<PREVIEW_TOKEN>"
}
});
// In a web app, read each value from the preview request's query string.
Dictionary<string, string> previewQuery = new Dictionary<string, string>()
{
{ "live_preview", Environment.GetEnvironmentVariable("LIVE_PREVIEW_HASH") ?? "" },
{ "content_type_uid", "<CONTENT_TYPE_UID>" },
{ "entry_uid", "<ENTRY_UID>" },
{ "release_id", Environment.GetEnvironmentVariable("LIVE_PREVIEW_RELEASE_ID") ?? "" },
{ "preview_timestamp", Environment.GetEnvironmentVariable("LIVE_PREVIEW_TIMESTAMP") ?? "" }
};
await client.LivePreviewQueryAsync(previewQuery);
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}RemoveHeader
RemoveHeader removes a header from the requests that objects created from this client send.
| Name | Type | Description |
|---|---|---|
| key (required) | string | Name of the header to remove. |
Returns: void. This method returns nothing.
Validation
- Throws ArgumentNullException if key is null, because the SDK stores headers in a dictionary that rejects a null key.
- A name the client does not hold is not an error. RemoveHeader does nothing in that case.
- Header names match exactly, including case. RemoveHeader("Branch") does not remove a header you set as branch.
Behavior
- Client-side only. RemoveHeader changes the client's header dictionary and makes no request.
- The constructor writes api_key and access_token into the same dictionary. Removing either one removes it from later requests, and the API then rejects those requests.
- After RemoveHeader("access_token"), the GetAccessToken method throws KeyNotFoundException.
- Use the SetHeader method to add the header back.
Example
Basic usage: stop sending a custom header
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
client.SetHeader("x-request-source", "catalog-sync");
// Later requests no longer carry x-request-source.
client.RemoveHeader("x-request-source");
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}SetEntryUid
SetEntryUid stores an entry UID on the client for live preview.
| Name | Type | Description |
|---|---|---|
| entryUid (required) | string | UID of the entry to preview. |
Returns: void. This method returns nothing.
Validation
- There is no client-side validation that raises an error. SetEntryUid ignores a null or empty value and keeps the UID it held before.
Behavior
- Client-side only. SetEntryUid stores the UID and makes no request.
- LivePreviewQueryAsync copies the stored UID into the live preview settings when its dictionary has no entry_uid key.
- ContentType.Entry("<ENTRY_UID>") calls SetEntryUid for you, so the stored UID is usually the last entry you created an object for.
- No request reads the stored entry UID. Live preview applies to the entry you fetch, so the stored UID does not change which entry a request returns.
Example
Basic usage: store the entry UID before a preview request
using System;
using System.Collections.Generic;
using Contentstack.Core;
using Contentstack.Core.Configuration;
ContentstackClient client = new ContentstackClient(new ContentstackOptions()
{
ApiKey = "<API_KEY>",
DeliveryToken = "<DELIVERY_TOKEN>",
Environment = "<ENVIRONMENT>",
LivePreview = new LivePreviewConfig()
{
Enable = true,
PreviewToken = "<PREVIEW_TOKEN>"
}
});
client.SetEntryUid("<ENTRY_UID>");
// The dictionary has no entry_uid key, so the client uses the stored UID.
await client.LivePreviewQueryAsync(new Dictionary<string, string>()
{
{ "live_preview", Environment.GetEnvironmentVariable("LIVE_PREVIEW_HASH") ?? "" },
{ "content_type_uid", "<CONTENT_TYPE_UID>" }
});
Console.WriteLine("Preview values stored.");SetHeader
SetHeader adds a header to the requests that objects created from this client send, or replaces the value of a header the client already holds.
| Name | Type | Description |
|---|---|---|
| key (required) | string | Name of the header to send. |
| value (required) | string | Value to send for that header. |
Returns: void. This method returns nothing.
Validation
- There is no client-side validation that raises an error. When key or value is null, SetHeader ignores the call and keeps the previous value.
- A name or value that .NET rejects as an HTTP header does not raise an error either. The SDK drops that header when it builds each request.
Behavior
- Client-side only. SetHeader changes the client's header dictionary and makes no request.
- Setting a name the client already holds replaces its value. Header names match exactly, including case.
- The constructor writes api_key and access_token into the same dictionary, so SetHeader("access_token", ...) replaces the delivery token on later requests.
- The header reaches requests from the objects you create after the call. Set client headers before you create content type, asset, or taxonomy objects.
- Use the RemoveHeader method to stop sending a header.
Example
Basic usage: send a custom header with every request
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
client.SetHeader("x-request-source", "catalog-sync");
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}Read from a branch for this client only
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
// The Content Delivery API reads the branch from the branch header.
client.SetHeader("branch", "<BRANCH>");
try
{
Entry entry = await client.ContentType("<CONTENT_TYPE_UID>").Entry("<ENTRY_UID>").Fetch<Entry>();
Console.WriteLine(entry.Title);
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}SyncPaginationToken
SyncPaginationToken retrieves the next page of a sync, using the pagination token from the previous page.
| Name | Type | Description |
|---|---|---|
| paginationToken (required) | string | Pagination token from the previous sync response. |
Returns: Task<SyncStack>. The next page of sync items.
Validation
- There is no client-side validation. A null token sends a request without pagination_token, and the API rejects it because the request needs that parameter.
- Throws ContentstackException if the API rejects the request. SyncPaginationToken throws the base class, not a subclass.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Sends one Sync using pagination token request, GET /stacks/sync with pagination_token. The request carries no environment.
- The API returns up to 100 items per page.
- The response carries a PaginationToken while more pages remain, and a SyncToken on the last page. Store the sync token for the SyncToken method.
- SyncRecursive calls SyncPaginationToken for you. Call it yourself after the SyncToken method, or to read a large sync one page at a time.
Example
Basic usage: read the next page
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack page = await client.SyncPaginationToken("<PAGINATION_TOKEN>");
if (page.PaginationToken != null)
{
Console.WriteLine($"More pages remain. Next token: {page.PaginationToken}");
}
else
{
Console.WriteLine($"Last page. Save this sync token: {page.SyncToken}");
}
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}SyncRecursive
SyncRecursive starts a sync of the published content in the environment and reads every page of the result before it returns.
| Name | Type | Description |
|---|---|---|
| Locale | string | Locale code to restrict the sync to. |
| SyncType | SyncType | Event types to include in the sync. |
| ContentTypeUid | string | Content type to restrict the sync to. |
| StartFrom | DateTime? | Earliest publish date to include, in UTC. |
Returns: Task<SyncStack>. Every item the sync returns, across all pages.
Validation
- There is no client-side validation. Every argument is optional, and SyncRecursive() with no arguments syncs every published entry and asset in the environment.
- SyncRecursive writes StartFrom as given and appends Z, without converting it to UTC. Pass a UTC value, such as DateTime.UtcNow.AddDays(-7). A local time reaches the API offset by your time zone.
- SyncType.Default sets no event type, so the SDK sends an empty type parameter. Use SyncType.All to include every event type.
- Throws ContentstackException if the API rejects any request in the sequence. SyncRecursive throws the base class, not a subclass, and returns none of the pages it already read.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Sends the Initial Sync request, GET /stacks/sync with init=true and the client's environment.
- The arguments map to the locale, type, content_type_uid, and start_from query parameters. The SDK leaves out each one you do not pass, apart from type.
- SyncType is a flags enum. Combine values with |, and the SDK sends them as a comma-separated type list. SyncType.All, alone or combined, sends all seven event types. See the SyncType class page.
- While the response carries a pagination token, SyncRecursive calls the SyncPaginationToken method and appends the new items. Each page is one request, and the API returns up to 100 items per page, as Sync using pagination token describes.
- The returned SyncStack holds every item, a SyncToken for the next sync, and a null PaginationToken.
- Each item in Items is a System.Text.Json.JsonElement that holds one item of the API response as the API returns it. Read its fields with TryGetProperty.
- Store SyncToken and pass it to the SyncToken method later to receive only the changes.
Limitations
- Does not return the first page alone. A large stack produces many requests before SyncRecursive returns. Narrow the sync with ContentTypeUid, Locale, SyncType, or StartFrom.
- Does not resume an earlier sync. Use the SyncToken method for that.
Example
Basic usage: sync everything published in the environment
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack result = await client.SyncRecursive();
Console.WriteLine($"Items: {result.TotalCount}. Save this sync token: {result.SyncToken}");
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}All parameters: sync published entries and assets of one content type and locale from last week
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack result = await client.SyncRecursive(
Locale: "<LOCALE>",
SyncType: SyncType.EntryPublished | SyncType.AssetPublished,
ContentTypeUid: "<CONTENT_TYPE_UID>",
// StartFrom must be UTC. The SDK does not convert a local time.
StartFrom: DateTime.UtcNow.AddDays(-7));
Console.WriteLine($"Items: {result.TotalCount}");
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}Read the items: each one is a JsonElement
using System;
using System.Text.Json;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack result = await client.SyncRecursive(SyncType: SyncType.EntryPublished);
foreach (JsonElement item in result.Items)
{
// Each item describes one publish, unpublish, or delete event.
if (item.TryGetProperty("type", out JsonElement eventType))
{
Console.WriteLine(eventType.GetString());
}
}
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}SyncToken
SyncToken retrieves the publish, unpublish, and delete events since an earlier sync, using the sync token that sync returned.
| Name | Type | Description |
|---|---|---|
| SyncToken (required) | string | Sync token from the previous completed sync. |
Returns: Task<SyncStack>. The content that changed since the last sync.
Validation
- There is no client-side validation. A null token sends a request without sync_token, and the API rejects it because the request needs that parameter.
- Throws ContentstackException if the API rejects the request, for example for an expired or unknown token. SyncToken throws the base class, not a subclass.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Sends one Subsequent Sync request, GET /stacks/sync with sync_token. The request carries no environment.
- SyncToken reads one page only. When the changes exceed 100 items, the response carries a PaginationToken in place of a SyncToken.
- Pass that pagination token to the SyncPaginationToken method until a response carries a SyncToken. Store that token for the next sync.
- See the SyncStack class page for the fields of the result.
Example
Basic usage: read the changes since the last sync
using System;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack result = await client.SyncToken("<SYNC_TOKEN>");
Console.WriteLine($"Changed items on this page: {result.TotalCount}");
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}Read every page of the changes
using System;
using System.Collections.Generic;
using System.Linq;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
SyncStack page = await client.SyncToken("<SYNC_TOKEN>");
List<dynamic> changes = page.Items.ToList();
// A pagination token means more pages remain.
while (page.PaginationToken != null)
{
page = await client.SyncPaginationToken(page.PaginationToken);
changes.AddRange(page.Items);
}
Console.WriteLine($"Changed items: {changes.Count}. Next sync token: {page.SyncToken}");
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}Taxonomies
Taxonomies returns a taxonomy object that covers every taxonomy in the stack, or one taxonomy when you pass its UID.
| Name | Type | Description |
|---|---|---|
| uid (required) | string | UID of the published taxonomy to read. |
Returns: Taxonomy. A new taxonomy object.
Overloads
- Taxonomies(): This overload takes no parameters.
- Taxonomies(string uid)
Validation
- Taxonomies(uid) throws TaxonomyException at once if uid is null or empty, because the scoped object builds its request URL from the UID.
- The two overloads enable different methods, and calling a method from the other set throws TaxonomyException before any request:
- Fetch, Term, and Terms need a UID. Calling them on Taxonomies() throws.
- Listing taxonomies with Find needs no UID. Calling Find on Taxonomies(uid) throws.
- Errors from the API come from the Fetch or Find call that follows, not from Taxonomies.
Additional Resource Refer to Content Delivery API Errors for the full error code list.
Behavior
- Client-side only. Taxonomies builds the object and makes no request.
- Taxonomies() reaches every taxonomy. Call Find alone to list the published taxonomies, or chain a filter such as Above or Below before Find to return the entries tagged with matching terms.
- Taxonomies("<TAXONOMY_UID>") reaches one taxonomy. Call Fetch to read it, Terms to query its terms, or Term("<TERM_UID>") to reach one term.
- Taxonomy inherits from Query. See the Taxonomy class page for the methods on each object.
Example
Basic usage: list the published taxonomies
using System;
using System.Text.Json.Nodes;
using Contentstack.Core;
using Contentstack.Core.Internals;
using Contentstack.Core.Models;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
ContentstackCollection<JsonObject> taxonomies = await client.Taxonomies().Find<JsonObject>();
foreach (JsonObject taxonomy in taxonomies)
{
Console.WriteLine($"{taxonomy["uid"]}: {taxonomy["name"]}");
}
}
catch (ContentstackException e)
{
// Thrown when the API rejects the request
Console.WriteLine($"Request failed: {(int)e.StatusCode} {e.ErrorCode} {e.Message}");
}One taxonomy: fetch it by UID
using System;
using System.Text.Json.Nodes;
using Contentstack.Core;
using Contentstack.Core.Internals;
ContentstackClient client = new ContentstackClient("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
try
{
JsonObject taxonomy = await client.Taxonomies("<TAXONOMY_UID>").Fetch<JsonObject>();
Console.WriteLine(taxonomy["name"]);
}
catch (ContentstackException e)
{
Console.WriteLine(e.Message);
}