Stack
Stack
A stack holds the content and assets of one project. Stack is the entry point to this SDK. Construct it once with your credentials, then call its factory methods to reach the rest of the library. Use this class to
- authenticate against one stack, environment, and region
- reach content types, entries, assets, global fields, and taxonomies
- retrieve published content in bulk through the Sync API
- build a transformed image URL
| Name | Type | Description |
| --- | --- | --- |
| api_key | str | API key of the stack. Required. |
| delivery_token | str | Delivery token of the stack. Required. |
| environment | str | Environment to read published content from. Required. |
| host | str | Delivery host to send requests to. Defaults to cdn.contentstack.io. |
| version | str | Delivery API version segment in the URL. Defaults to v3. |
| region | ContentstackRegion | Region that owns the stack. Defaults to ContentstackRegion.US. |
| timeout | int | Request timeout in seconds. Defaults to 30. |
| retry_strategy | Retry | urllib3 retry policy for every request. Defaults to Retry(total=5, backoff_factor=0, status_forcelist=[408, 429]). |
| live_preview | dict | Live preview configuration. Defaults to None. |
| branch | str | Branch to read content from. Defaults to None. |
| early_access | list | Early access feature names to request. Defaults to None. |
| logger | Logger | Logger the instance writes to. Defaults to the module logger. |
Stack raises PermissionError when api_key, delivery_token, or environment is None or an empty string. The three checks run before any request, so a missing credential fails at construction rather than on the first call.
The accepted region values are us, eu, au, azure-na, azure-eu, gcp-na, and gcp-eu.
Warning Pass region as a ContentstackRegion member, not as a string. Stack reads region.value, so contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>', region='eu') raises AttributeError: 'str' object has no attribute 'value'.
| Name | Type | Description |
|---|---|---|
| headers (required) | dict | |
| early_access | dict | Optional array of header strings for early access features. |
| sync_param | dict | |
| endpoint | str | |
| api_key (required) | str | |
| delivery_token (required) | str | |
| environment (required) | str | |
| host | str | |
| version | str | |
| region | Region | DB region for your stack. You can choose from seven regions namely, AWS NA, AWS EU, AWS AU, Azure NA, Azure EU, GCP NA, and GCP EU |
| timeout | int | |
| branch | str | |
| retry_strategy | Retry | |
| live_preview_dict | dict |
asset
asset returns a handle for one asset in the stack, identified by its UID.
| Name | Type | Description |
|---|---|---|
| uid (required) | str | UID of the asset to read. |
A handle for the asset with the given UID.
Validation
- asset rejects its own argument. Passing None, or any value that is not a string, raises KeyError with the message "Invalid UID. Provide a valid UID and try again." The SDK builds the asset URL from the UID and cannot do that without a string.
- The raise happens on the call itself, not on the fetch() that follows. Wrap asset in its own try when the UID comes from user input.
- An empty string passes the check, because it is a string. stack.asset('') returns a handle whose URL ends in an empty path segment, and the rejection arrives from the API rather than as a raise.
- Omitting the argument raises TypeError immediately, because uid is a positional parameter with no default.
- Any remaining errors come from the terminal call, fetch().
- fetch() raises an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection, including a UID that names no asset, returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. asset constructs an Asset and makes no request.
- The handle targets GET /assets/{uid}, and fetch() makes one HTTP request per call.
- The constructor copies the environment out of the headers into the asset query parameters, so fetch() sends environment as a query parameter as well as a header.
- The new handle carries the connection object from Stack, so it shares the credentials, host, timeout, and retry policy described under Authentication on the Stack class page.
- Chainable modifiers on the returned handle include environment, relative_urls, include_dimension, include_fallback, asset_fields, and params.
Warning Asset.environment and Asset.remove_environment write to the header dictionary that Stack owns, and every class in the SDK shares that dictionary. Changing the environment on one asset handle therefore changes it for every later request from the same Stack.
Limitations
- Does not accept a version number. Use the asset_query method, which exposes a version modifier, to read a specific asset version.
Example
Basic usage: read one asset by UID
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.asset('<ASSET_UID>').fetch()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
print('asset retrieved:', result)Keyword form: name the UID and chain a modifier
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# uid is positional, so pass it by name or by position.
result = stack.asset(uid='<ASSET_UID>').include_dimension().fetch()
except Exception as error:
print('Request failed:', error)Error handling: a non-string UID raises at the call site
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
asset_uid = None
try:
result = stack.asset(asset_uid).fetch()
except KeyError as error:
# Fires on asset() itself, before any request goes out.
print('Invalid asset UID:', error)Edge case: an empty UID reaches the API
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
asset_uid = ''
try:
# The empty string is a string, so the UID check passes and a request goes out.
result = stack.asset(asset_uid).fetch()
except Exception as error:
print('Request failed:', error)
else:
if 'error' in result:
print('code:', result.get('error_code'), 'message:', result.get('error_message'))asset_query
asset_query returns a query across every asset in the stack.
A query across the assets in the stack.
Validation
- asset_query cannot fail. It takes no arguments and constructs an AssetQuery from state that Stack already validated.
- Errors that do occur come from the find() call that follows, not from asset_query().
- find() raises an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. asset_query constructs an AssetQuery and makes no request.
- The query targets GET /assets, and find() makes one HTTP request per call.
- The constructor appends the environment to the base URL when the headers carry one, so the environment reaches the request even before you chain a modifier.
- The new query carries the connection object from Stack, so it shares the credentials, host, timeout, and retry policy described under Authentication on the Stack class page.
- Chainable modifiers that reach the request are environment, version, locale, include_dimension, include_branch, include_fallback, include_metadata, relative_url, and asset_fields.
- Each call constructs a new query. Two calls produce two independent objects, and a modifier set on one does not reach the other.
- Several methods that the returned query inherits from BaseQuery reach no request. The AssetQuery class page names them under Class-Level Notes.
Limitations
- Does not paginate. skip and limit have no effect here, so read one asset at a time with the asset method when you need a subset.
Example
Basic usage: list the assets in the stack
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.asset_query().find()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
print('assets retrieved:', result)No parameters: chain the modifiers instead
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# asset_query takes no arguments, so every option is a chained modifier.
result = stack.asset_query() \
.locale('fr-fr') \
.include_dimension() \
.include_fallback() \
.include_metadata() \
.find()
except Exception as error:
print('Request failed:', error)Edge case: a chained environment outlives the query
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# environment() writes to the header dictionary that Stack owns, so this
# switch applies to every later request from the same stack.
staging_assets = stack.asset_query().environment('staging').find()
# This query now reads staging too, not <ENVIRONMENT>.
more_assets = stack.asset_query().find()
except Exception as error:
print('Request failed:', error)content_type
content_type returns a handle for one content type, or for the list of content types in the stack.
| Name | Type | Description |
|---|---|---|
| content_type_uid | str | UID of the content type to work with. |
A handle for the named content type.
Validation
- There is no client-side validation. content_type stores the argument as given, so None, an empty string, and a non-string value all produce a ContentType.
- Omitting the argument is valid and is the default. The resulting handle supports find(), which lists the content types in the stack.
- A None UID fails on the terminal call rather than here. ContentType.entry raises PermissionError with the message "Content type UID is invalid. Provide a valid UID and try again."
- ContentType.fetch raises KeyError on a None UID, and ContentType.query raises PermissionError. Both carry ErrorMessages.CONTENT_TYPE_UID_REQUIRED.
- An empty string passes every one of those checks, because each tests the UID against None alone. stack.content_type('') therefore reaches the API with an empty path segment and comes back as a rejection rather than a raise.
- Errors that do occur come from the terminal call that follows, fetch() on the content type or find() on its query, not from content_type().
- Those calls raise an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection, including a UID that names no content type, returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. content_type constructs a ContentType and makes no request.
- The new handle carries the connection object from Stack, so it shares the credentials, host, timeout, and retry policy described under Authentication on the Stack class page.
- What the handle supports depends on the argument.
- With a UID: fetch() reads the content type schema, query() returns an entry query, entry(entry_uid) reads one entry, and variants(variant_uid) reads its variants.
- Without a UID: find() lists the content types in the stack. The other three raise on the call.
- Each call constructs a new handle. Two calls with the same UID produce two independent objects, and a modifier set on one does not reach the other.
- The SDK sends the environment query parameter on the terminal call, reading it from the headers that Stack built.
Example
Basic usage: query the entries of one content type
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.content_type('product').query().find()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
for entry in result.get('entries', []):
print(entry['uid'])All parameters: read one content type schema by UID
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# content_type_uid is the method's only parameter.
result = stack.content_type('product').fetch()
print('content type:', result['content_type']['uid'])
except Exception as error:
print('Request failed:', error)Listing: omit the UID to list every content type
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# Without a UID the handle supports find() and nothing else.
result = stack.content_type().find()
if 'error' not in result:
print('content type list:', result)
except Exception as error:
print('Request failed:', error)Error handling: a null UID raises on the terminal call
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
content_type_uid = None
try:
# content_type() itself succeeds. query() is where the null UID fails.
result = stack.content_type(content_type_uid).query().find()
except PermissionError as error:
# Fires on query(), before any request goes out.
print('Guard the UID before building a query:', error)get_api_key
get_api_key returns the API key that the Stack instance authenticates with.
The API key the instance authenticates with.
Validation
- get_api_key cannot fail. It returns the attribute that the constructor stored, and Stack already rejected a None or empty API key with PermissionError.
- Reading it with parentheses raises TypeError: 'str' object is not callable, because the parentheses call the returned string rather than the property.
- Assigning to it raises AttributeError, because the class defines no setter. Assign to stack.api_key to change the attribute, though that assignment never reaches a request. See Class-Level Properties on the Stack class page.
- get_api_key makes no request, so it produces no API error of its own. A rejected key surfaces on the terminal call that uses it.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_api_key reads one attribute and makes no request.
- Returns the string exactly as you passed it to the constructor. The SDK neither trims nor normalizes it.
- The same value reaches every request as the api_key header, which get_headers returns.
- The value is fixed for the life of the instance, because Stack copies it into the headers during construction. Construct a second Stack to authenticate against a different stack.
Example
Basic usage: confirm which stack an instance targets
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
print('api key:', stack.get_api_key)
print('endpoint:', stack.endpoint)Edge case: parentheses raise instead of reading the value
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
api_key = stack.get_api_key()
except TypeError as error:
# Fires because the parentheses call the returned string.
print('Read the property without parentheses:', error)Logging: mask the key before writing it anywhere
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
# The property returns the full key, so mask it before it reaches a log.
api_key = stack.get_api_key
print('api key ending in:', api_key[-4:])get_branch
get_branch returns the branch that the Stack instance reads content from.
The branch the instance reads content from, or None.
Validation
- get_branch cannot fail. It returns the attribute that the constructor stored, and Stack validates that attribute at no point.
- None is the default and a valid return value. A Stack constructed without branch returns None here, and the SDK sends no branch header.
- Reading it with parentheses raises TypeError. The message names 'str' object when the instance carries a branch, and 'NoneType' object when it does not.
- Assigning to it raises AttributeError, because the class defines no setter. See Class-Level Properties on the Stack class page.
- get_branch makes no request, so it produces no API error of its own. A branch name that no stack defines surfaces on the terminal call as a Delivery API rejection.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_branch reads one attribute and makes no request.
- Returns the branch string as you passed it, with no validation against the stack. An alias is also valid here, because the SDK sends whatever you pass.
- Stack adds a branch request header during construction only when branch is not None. An empty string therefore produces an empty branch header rather than no header.
- Every request from the instance carries that header, so the branch applies to content types, entries, assets, global fields, and taxonomies alike.
Limitations
- Does not switch branches. Construct a second Stack with a different branch when you need to read from two branches.
Example
Basic usage: read the branch back off the instance
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
branch='development',
)
print('branch:', stack.get_branch)Branch-aware code: react to an unset branch
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
# None is the default, and it means the SDK sends no branch header.
if stack.get_branch is None:
print('reading the default branch')
else:
print('reading branch:', stack.get_branch)Edge case: an empty branch still sends the header
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
branch='',
)
# The constructor tests branch against None alone, so the empty string
# produces an empty branch header rather than no header.
print('branch:', repr(stack.get_branch))
print('branch header present:', 'branch' in stack.get_headers)get_delivery_token
get_delivery_token returns the delivery token that the Stack instance authenticates with.
The delivery token the instance authenticates with.
Validation
- get_delivery_token cannot fail. It returns the attribute that the constructor stored, and Stack already rejected a None or empty delivery token with PermissionError.
- Reading it with parentheses raises TypeError: 'str' object is not callable, because the parentheses call the returned string rather than the property.
- Assigning to it raises AttributeError, because the class defines no setter. See Class-Level Properties on the Stack class page.
- get_delivery_token makes no request, so it produces no API error of its own. A token of the wrong type surfaces on the terminal call as a Delivery API rejection rather than as a raise.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_delivery_token reads one attribute and makes no request.
- Returns the string exactly as you passed it to the constructor, including a token of the wrong type. The SDK neither trims nor normalizes it. See the Warning under SDK-Wide Notes in the Python Delivery SDK API Reference overview.
- The SDK sends the same value as the access_token header, not as a header named delivery_token. get_headers returns the header dictionary that carries it.
Example
Basic usage: read the token back off the instance
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
token = stack.get_delivery_token
print('token ending in:', token[-4:])Header mapping: confirm the token travels as access_token
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
# The header name differs from the constructor argument name.
print(stack.get_headers['access_token'] == stack.get_delivery_token)Edge case: parentheses raise instead of reading the value
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
token = stack.get_delivery_token()
except TypeError as error:
# Fires because the parentheses call the returned string.
print('Read the property without parentheses:', error)get_early_access
get_early_access returns the early access feature names that the Stack instance requests.
The early access feature names the instance requests, or None.
Validation
- get_early_access cannot fail. It returns the attribute that the constructor stored, and Stack validates that attribute at no point.
- None is the default and a valid return value. A Stack constructed without early_access returns None here, and the SDK sends no x-header-ea header.
- Reading it with parentheses raises TypeError. The message names 'list' object when the instance carries a list, and 'NoneType' object when it does not.
- Assigning to it raises AttributeError, because the class defines no setter. See Class-Level Properties on the Stack class page.
- get_early_access makes no request, so it produces no API error of its own. A feature name your account cannot reach surfaces on the terminal call as a Delivery API rejection.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_early_access reads one attribute and makes no request.
- Returns the list object you passed, not a copy of it. Mutating the returned list mutates the constructor argument, though the header itself is already fixed.
- Stack joins the list with a comma and a space during construction, and writes the result into the x-header-ea header. That join happens once, so a later change to the list never reaches a request.
- An empty list still produces the header. Stack tests the argument against None alone, so early_access=[] sends x-header-ea with an empty value.
- Returns a bare string unchanged, so the property alone does not reveal the header that a bare string produces. Read stack.get_headers['x-header-ea'] to confirm the header, and see the Warning under Headers the SDK adds on the Stack class page.
Example
Basic usage: read the early access list back off the instance
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
early_access=['taxonomy'],
)
print('early access:', stack.get_early_access)
print('header:', stack.get_headers['x-header-ea'])Feature-aware code: react to an unset list
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
# None is the default, and it means the SDK sends no x-header-ea header.
if stack.get_early_access is None:
print('no early access features requested')Edge case: a bare string becomes a character list in the header
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
early_access='taxonomy',
)
# The property returns the string as given.
print('early access:', stack.get_early_access)
# The header shows the join, which is where the mistake becomes visible.
print('header:', stack.get_headers['x-header-ea'])get_environment
get_environment returns the environment that the Stack instance reads published content from.
The environment the instance reads published content from.
Validation
- get_environment cannot fail. It returns the attribute that the constructor stored, and Stack already rejected a None or empty environment with PermissionError.
- Reading it with parentheses raises TypeError: 'str' object is not callable, because the parentheses call the returned string rather than the property.
- Assigning to it raises AttributeError, because the class defines no setter. See Class-Level Properties on the Stack class page.
- get_environment makes no request, so it produces no API error of its own. An environment name that no stack defines surfaces on the terminal call as a Delivery API rejection.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_environment reads one attribute and makes no request.
- Returns the constructor argument, not the environment header. The two hold the same value at construction, and they can diverge later.
- Asset.environment, Asset.remove_environment, and AssetQuery.environment write to the header dictionary that Stack owns, and none of them touches this attribute. After one of those calls, get_environment still returns the constructor value while requests go to the new environment.
- Read stack.get_headers['environment'] to find out which environment the next request actually targets.
Example
Basic usage: read the environment back off the instance
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
print('environment:', stack.get_environment)Edge case: a chained environment leaves this property behind
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.asset_query().environment('staging').find()
except Exception as error:
print('Request failed:', error)
# Still the constructor value.
print('constructor environment:', stack.get_environment)
# The environment the next request targets.
print('header environment:', stack.get_headers['environment'])Edge case: parentheses raise instead of reading the value
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
environment = stack.get_environment()
except TypeError as error:
# Fires because the parentheses call the returned string.
print('Read the property without parentheses:', error)get_headers
get_headers returns the request headers that the SDK sends on every call from this Stack.
The request headers the SDK sends on every call.
Validation
- get_headers cannot fail. It returns the dictionary that Stack built during construction, and that construction already rejected a missing credential with PermissionError.
- Reading it with parentheses raises TypeError: 'dict' object is not callable, because the parentheses call the returned dictionary rather than the property.
- Assigning to it raises AttributeError, because the class defines no setter. The dictionary itself accepts mutation, and that mutation does reach the next request.
- get_headers makes no request, so it produces no API error of its own. A rejected credential surfaces on the terminal call.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_headers reads one attribute and makes no request.
- Always carries api_key, access_token, and environment. The delivery token travels as access_token, not under its constructor argument name.
- Carries branch when you passed branch, x-header-ea when you passed early_access, and preview_token when live_preview supplied one.
- Returns the live dictionary, not a copy. Every class in the SDK shares it, so a mutation here changes every later request, and a chained Asset.environment or AssetQuery.environment call changes what this property returns.
- User-Agent and X-User-Agent are absent until the first request. The connection object adds both immediately before it sends, so they appear here only after a terminal call has run once.
Warning The returned dictionary holds the API key and the delivery token in plain text. Do not print or log it whole.
Example
Basic usage: inspect the headers the SDK will send
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
branch='development',
early_access=['taxonomy'],
)
# Print the header names rather than the values, which hold the credentials.
print('headers:', sorted(stack.get_headers.keys()))
print('environment:', stack.get_headers['environment'])Edge case: the user agent headers appear only after a request
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
print('before:', 'User-Agent' in stack.get_headers)
try:
stack.asset_query().find()
except Exception as error:
print('Request failed:', error)
# The connection object adds the user agent headers as it sends.
print('after:', 'User-Agent' in stack.get_headers)Edge case: a chained environment call rewrites the shared dictionary
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
stack.asset_query().environment('staging').find()
except Exception as error:
print('Request failed:', error)
# environment() wrote into this same dictionary, so every later request
# from this stack now reads staging.
print('environment header:', stack.get_headers['environment'])get_live_preview
get_live_preview returns the live preview configuration on the Stack instance.
The live preview configuration, or None.
Validation
- get_live_preview cannot fail. It returns the attribute that the constructor stored, and Stack validates that attribute at no point.
- None is the default and a valid return value. A Stack constructed without live_preview returns None here, and live preview never engages.
- Reading it with parentheses raises TypeError. The message names 'dict' object when the instance carries a dictionary, and 'NoneType' object when it does not.
- Assigning to it raises AttributeError, because the class defines no setter. See Class-Level Properties on the Stack class page.
- get_live_preview makes no request, so it produces no API error of its own. A preview token the stack does not accept surfaces on the terminal call as a Delivery API rejection.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. get_live_preview reads one attribute and makes no request.
- Returns the dictionary object you passed, not a copy of it. Stack writes into that same object, so the property is how to read what the SDK resolved.
- The keys the SDK adds to the dictionary depend on what you set.
- host, when enable is truthy and you passed no host. Stack resolves the content management host for the region during construction.
- live_preview, content_type_uid, entry_uid, and url, after a live_preview_query call.
- Reading this property is how to detect a live preview setup that never engaged, because nothing raises when enable is missing or falsy.
- The preview_token key stays in the dictionary and also reaches the request as a preview_token header, which get_headers returns.
Example
Basic usage: read the resolved live preview configuration
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': True, 'preview_token': '<PREVIEW_TOKEN>'},
)
# The host is absent from the argument above, so the SDK resolved it.
print('live preview config:', stack.get_live_preview)
print('resolved host:', stack.get_live_preview['host'])Diagnosing an inert setup: check enable before previewing
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': False, 'preview_token': '<PREVIEW_TOKEN>'},
)
config = stack.get_live_preview
# No exception marks a falsy enable, so test it yourself.
if not config or not config.get('enable'):
print('live preview is configured but inactive')Reading the preview URL after live_preview_query
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': True, 'preview_token': '<PREVIEW_TOKEN>'},
)
stack.live_preview_query(
live_preview_query={
'live_preview': '<LIVE_PREVIEW_HASH>',
'content_type_uid': 'product',
'entry_uid': '<ENTRY_UID>',
}
)
# live_preview_query writes the url key into the same dictionary.
print('preview URL:', stack.get_live_preview['url'])global_field
global_field returns a handle for one global field, or for the list of global fields in the stack.
| Name | Type | Description |
|---|---|---|
| global_field_uid | str | UID of the global field to work with. |
A handle for the named global field.
Validation
- There is no client-side validation. global_field stores the argument as given, so None, an empty string, and a non-string value all produce a GlobalField.
- Omitting the argument is valid and is the default. The resulting handle supports find(), which lists the global fields in the stack.
- A None UID fails on the terminal call rather than here. GlobalField.fetch raises KeyError with the message "global_field_uid can not be None to fetch GlobalField".
- An empty string passes that check, because it tests the UID against None alone. stack.global_field('') therefore reaches the API with an empty path segment and comes back as a rejection rather than a raise.
- Errors that do occur come from the terminal call that follows, fetch() or find(), not from global_field().
- Those calls raise an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection, including a UID that names no global field, returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. global_field constructs a GlobalField and makes no request.
- The new handle carries the connection object from Stack, so it shares the credentials, host, timeout, and retry policy described under Authentication on the Stack class page.
- What the handle supports depends on the argument.
- With a UID: fetch() calls GET /global_fields/{global_field_uid}.
- Without a UID: find() calls GET /global_fields. fetch() raises instead.
- Both terminal calls send the environment query parameter, which the handle reads from the headers that Stack built.
- Each call constructs a new handle, so two calls with the same UID produce two independent objects.
Limitations
- Does not return the entries that use the global field. Query the content types that reference it with the content_type method instead.
Example
Basic usage: read one global field by UID
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.global_field('seo_metadata').fetch()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
print('global field retrieved:', result)Listing: omit the UID to list every global field
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# find() accepts an optional dictionary of extra query parameters.
result = stack.global_field().find({'include_branch': 'true'})
except Exception as error:
print('Request failed:', error)Error handling: a null UID raises on fetch
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
global_field_uid = None
try:
# global_field() itself succeeds. fetch() is where the null UID fails.
result = stack.global_field(global_field_uid).fetch()
except KeyError as error:
# Fires on fetch(), before any request goes out.
print('Guard the UID before calling fetch:', error)image_transform
image_transform appends Image Delivery API parameters to an image URL.
| Name | Type | Description |
|---|---|---|
| image_url (required) | str | Image URL to apply the transformations to. |
| kwargs | Any | Image Delivery API parameters, passed as keyword arguments. |
A builder for the transformed image URL.
Validation
- image_transform rejects its own first argument. Passing None or an empty string raises PermissionError with the message "image_url required for the image_transformation", because the transformation has nothing to append to.
- The raise happens on the call itself. Wrap image_transform in its own try when the URL comes from a lookup that can return nothing.
- Omitting image_url raises TypeError immediately, because it is a positional parameter with no default.
- image_transform validates none of the keyword arguments. It accepts any name and any value, and get_url() writes them into the query string as given, so an unsupported parameter name reaches the request unchanged.
- image_transform makes no request, so it produces no API error of its own. The Image Delivery API rejects an invalid parameter when a browser or client requests the URL.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. image_transform constructs an ImageTransform and makes no request. Call get_url() on the result to read the finished URL.
- get_url() joins the keyword arguments as key=value pairs with &, and appends them to the URL after a ?.
- The SDK does not encode the values. Encode any value containing a reserved character before passing it.
- get_url() mutates the stored URL rather than returning a copy of it. Calling get_url() twice on one handle appends the parameters twice and produces a malformed URL, so call it once per handle.
- Passing no keyword arguments returns the URL unchanged, with no ? appended.
Warning logger is a named parameter of ImageTransform, so stack.image_transform(url, logger=my_logger) sets the logger instead of adding a logger transformation parameter. Every other keyword argument reaches the URL.
Limitations
- Does not fetch the image. get_url() returns a string, and retrieving the bytes is your HTTP client's job.
- Does not validate the transformation against the asset. A URL that names no asset resolves only when a client requests it.
Example
Basic usage: resize an image
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
image_url = 'https://images.contentstack.io/v3/assets/<API_KEY>/<ASSET_UID>/hero.jpg'
try:
transform = stack.image_transform(image_url, width=640)
result = transform.get_url()
except Exception as error:
# Raised only for a null or empty image_url
print('Transform failed:', error)
else:
print('transformed URL:', result)All parameters: image_url plus several keyword arguments
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
image_url = 'https://images.contentstack.io/v3/assets/<API_KEY>/<ASSET_UID>/hero.jpg'
try:
# kwargs collects every transformation parameter.
result = stack.image_transform(
image_url,
width=640,
height=480,
format='webp',
quality=80,
).get_url()
print('transformed URL:', result)
except Exception as error:
print('Transform failed:', error)Error handling: an empty URL raises at the call site
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
image_url = ''
try:
result = stack.image_transform(image_url, width=640).get_url()
except PermissionError as error:
# Fires on image_transform itself, before the URL is built.
print('Provide an image URL:', error)Edge case: calling get_url twice appends twice
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
image_url = 'https://images.contentstack.io/v3/assets/<API_KEY>/<ASSET_UID>/hero.jpg'
transform = stack.image_transform(image_url, width=640)
# First call returns ...hero.jpg?width=640
first = transform.get_url()
# Second call returns ...hero.jpg?width=640?width=640
second = transform.get_url()
# Construct a new handle for each URL you need instead.
print(first)live_preview_query
live_preview_query records the live preview hash, content type, and entry that the next request previews.
| Name | Type | Description |
|---|---|---|
| kwargs | Any | Keyword arguments. Only live_preview_query has an effect. |
The same stack, for chaining.
Validation
- There is no client-side validation, and live_preview_query never raises. Three separate conditions have to hold before it changes anything, and it returns the instance unchanged when any one of them fails.
- The Stack constructor received a live_preview dictionary.
- That dictionary carries a truthy enable key.
- The call passes a live_preview_query keyword argument holding a dictionary.
- live_preview_query skips a live_preview_query value that is not a dictionary, because the check tests isinstance(query, dict). No error marks the skip.
- live_preview_query also skips every other keyword argument. live_preview_query(content_type_uid='product') changes nothing, because the method reads the nested live_preview_query key alone.
- Errors that do occur come from the terminal call that follows, find() or fetch() on the entry or query you build next, not from live_preview_query().
- Those calls raise an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection, for example a preview token the stack does not accept, returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Warning Nothing reports a live preview configuration that never took effect. A stack constructed without live_preview, or with enable set to a falsy value, accepts this call and returns normally while previewing nothing. Read stack.get_live_preview after the call to confirm the values landed.
Behavior
- Client-side only. live_preview_query updates the live preview dictionary on the instance and makes no request.
- The nested dictionary merges into the stored live_preview dictionary, so a key you omit keeps the value it already had.
- live_preview defaults to the string init when the nested dictionary omits it. The SDK writes that value into the preview URL as the live_preview query parameter.
- content_type_uid and entry_uid from the nested dictionary reach the preview URL, which takes the form https://<host>/v3/content_types/<content_type_uid>/entries/<entry_uid>?live_preview=<hash>. Without entry_uid the URL stops at the entries collection. Without content_type_uid the URL uses the literal segment default_content_type.
- release_id and preview_timestamp behave differently from the rest. The SDK writes each one into the request headers when the nested dictionary carries it, and removes the header when it does not. Every call therefore resets both.
- The method returns the Stack itself, so chain the next factory call directly onto it.
- The host comes from the live_preview dictionary that Stack resolved during construction. See Live preview on the Stack class page.
Example
Basic usage: preview one entry
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': True, 'preview_token': '<PREVIEW_TOKEN>'},
)
try:
result = stack.live_preview_query(
live_preview_query={
'live_preview': '<LIVE_PREVIEW_HASH>',
'content_type_uid': 'product',
'entry_uid': '<ENTRY_UID>',
}
).content_type('product').entry('<ENTRY_UID>').fetch()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
print('previewing:', result)All parameters: every key the nested dictionary accepts
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': True, 'preview_token': '<PREVIEW_TOKEN>'},
)
try:
# kwargs is the method's only parameter, and live_preview_query is the one
# key it reads. release_id and preview_timestamp become request headers.
stack.live_preview_query(
live_preview_query={
'live_preview': '<LIVE_PREVIEW_HASH>',
'content_type_uid': 'product',
'entry_uid': '<ENTRY_UID>',
'release_id': '<RELEASE_UID>',
'preview_timestamp': '2024-06-01T00:00:00.000Z',
}
)
print('preview URL:', stack.get_live_preview.get('url'))
except Exception as error:
print('Request failed:', error)Edge case: the call is inert without enable
import contentstack
# No live_preview dictionary, so live preview never engages.
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
# This returns the same stack and records nothing. No exception marks it.
stack.live_preview_query(
live_preview_query={'live_preview': '<LIVE_PREVIEW_HASH>'}
)
# get_live_preview is still None, which is how to detect the inert call.
print('live preview config:', stack.get_live_preview)Edge case: an omitted header key clears the previous one
import contentstack
stack = contentstack.Stack(
'<API_KEY>',
'<DELIVERY_TOKEN>',
'<ENVIRONMENT>',
live_preview={'enable': True, 'preview_token': '<PREVIEW_TOKEN>'},
)
# Sets the release_id header.
stack.live_preview_query(
live_preview_query={'live_preview': '<HASH>', 'release_id': '<RELEASE_UID>'}
)
# Omitting release_id removes the header rather than keeping it.
stack.live_preview_query(
live_preview_query={'live_preview': '<HASH>', 'content_type_uid': 'product'}
)
print('release_id header present:', 'release_id' in stack.get_headers)pagination
pagination continues a sync and retrieves the next page of items.
| Name | Type | Description |
|---|---|---|
| pagination_token (required) | str | Pagination token from the previous sync response. |
The next page of sync items.
Validation
- There is no client-side validation. pagination stores the token as given and sends it, so an expired or malformed token reaches the API unchanged.
- Omitting the argument raises TypeError immediately, because pagination_token is a positional parameter with no default.
- A non-string argument makes no error and no new request parameters. pagination replaces the shared sync parameters only when isinstance(pagination_token, str) holds.
- A None or numeric token therefore leaves the previous parameters in place, and the call repeats the earlier sync request. See Sync state on the instance on the Stack class page.
- An empty string passes the check, because it is a string. pagination('') sends pagination_token= and the API rejects it.
- pagination raises an exception only for network failures (timeout, DNS error, dropped connection). The exception type is RequestError.
- An API-level rejection, including an invalid token, returns as a normal result with an errors key. It does not raise an exception.
- The sync endpoint holds one list of messages per rejected field under that key, so an invalid token surfaces at result['errors']['pagination_token'][0].
- Check the result for an errors key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Calls GET /stacks/sync with the pagination token, and makes one HTTP request per call.
- Replaces the shared sync parameters rather than adding to them, so the content type, locale, and event type filters from the sync_init call do not repeat. The token itself carries the filters forward.
- The SDK adds the environment parameter from the headers that Stack built, on top of the replaced dictionary.
- Returns the raw parsed API response as a dictionary, carrying items and total_count.
Limitations
- Does not loop. One call returns one page, so call pagination in your own loop until the response stops carrying a pagination token.
Example
Basic usage: retrieve the next page of a sync
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.pagination('<PAGINATION_TOKEN>')
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'errors' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['errors'])
else:
print('items:', len(result.get('items', [])), 'of', result.get('total_count'))All parameters: continue a sync that sync_init started
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
first_page = stack.sync_init(content_type_uid='product')
print('first page items:', len(first_page.get('items', [])))
# pagination_token is the method's only parameter. Read the token out of the
# sync response above and pass it here.
next_page = stack.pagination('<PAGINATION_TOKEN>')
print('next page items:', len(next_page.get('items', [])))
except Exception as error:
print('Request failed:', error)Error handling: an invalid token returns rather than raises
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.pagination('not_a_real_token')
except Exception as error:
print('Request failed:', error)
else:
# A rejected token arrives as an ordinary return value, not an exception.
if 'errors' in result:
print('token rejected:', result['errors'].get('pagination_token'))Edge case: a non-string token repeats the previous request
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
token = None
try:
first_page = stack.sync_init(content_type_uid='product')
# The isinstance check fails, so the sync parameters stay as sync_init left
# them and this call repeats the first page. Guard the token instead.
same_page_again = stack.pagination(token)
except Exception as error:
print('Request failed:', error)sync_init
sync_init starts a sync and retrieves the first page of published entries and assets.
| Name | Type | Description |
|---|---|---|
| content_type_uid | str | Restricts the sync to one content type. |
| start_from | str | ISO 8601 date to sync published content from. |
| locale | str | Locale code to restrict the sync to. |
| publish_type | str | Comma-separated publish event types to include. |
The first page of published entries and assets.
Validation
- There is no client-side validation. Every argument is optional, and sync_init() with no arguments syncs all published entries and assets.
- A non-string argument disappears without an error. sync_init tests each argument with isinstance(value, str) and skips the parameter when the test fails, so sync_init(content_type_uid=123) sends no content type filter and syncs the whole stack instead.
- An empty string passes both checks, because it is a string and it is not None. sync_init(locale='') therefore sends locale= as an empty query parameter and the API rejects it.
- sync_init raises an exception only for network failures (timeout, DNS error, dropped connection). The exception type is RequestError.
- An API-level rejection, for example an unparseable start_from date, returns as a normal result with an errors key. It does not raise an exception.
- The sync endpoint holds one list of messages per rejected field under that key, rather than the single error key the other endpoints use.
- Check the result for an errors key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Calls GET /stacks/sync with init=true, and makes one HTTP request per call.
- The SDK adds the environment parameter from the headers that Stack built, so the sync covers one environment.
- publish_type reaches the API as the type query parameter. The other three arguments keep their own names.
- Returns the raw parsed API response as a dictionary, carrying items and total_count.
- sync_init adds to the sync parameter dictionary that Stack holds without clearing it first. A second sync_init call on the same instance therefore still carries the arguments from the first. See Sync state on the instance on the Stack class page.
Limitations
- Does not retrieve every page. Pass the pagination token from the response to the pagination method until the response carries a sync token instead.
- Does not resume from a previous sync. Use the sync_token method for that.
Example
Basic usage: sync everything published in the environment
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.sync_init()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'errors' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['errors'])
else:
print('items:', len(result.get('items', [])), 'of', result.get('total_count'))All parameters: narrow the sync by content type, date, locale, and event type
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.sync_init(
content_type_uid='product',
start_from='2024-01-01T00:00:00.000Z',
locale='en-us',
publish_type='entry_published',
)
print('items:', len(result.get('items', [])))
except Exception as error:
print('Request failed:', error)Multiple event types: pass them as one comma-separated string
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# publish_type takes one string, not a list.
result = stack.sync_init(
publish_type='entry_published,entry_unpublished,asset_published'
)
except Exception as error:
print('Request failed:', error)Edge case: a non-string argument syncs the whole stack
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
content_type_uid = 12345
try:
# The isinstance check fails, so the filter never reaches the request and
# this call syncs every content type. Cast the value before passing it.
result = stack.sync_init(content_type_uid=content_type_uid)
print('items:', len(result.get('items', [])))
except Exception as error:
print('Request failed:', error)sync_token
sync_token resumes a sync and retrieves the content that changed since the previous one.
| Name | Type | Description |
|---|---|---|
| sync_token (required) | str | Sync token from the previous completed sync. |
The content that changed since the last sync.
Validation
- There is no client-side validation. sync_token stores the token as given and sends it, so an expired or malformed token reaches the API unchanged.
- Omitting the argument raises TypeError immediately, because sync_token is a positional parameter with no default.
- A non-string argument makes no error and no new request parameters. sync_token replaces the shared sync parameters only when isinstance(sync_token, str) holds.
- A None or numeric token therefore leaves the previous parameters in place, and the call repeats the earlier sync request. See Sync state on the instance on the Stack class page.
- An empty string passes the check, because it is a string. sync_token('') sends sync_token= and the API rejects it.
- sync_token raises an exception only for network failures (timeout, DNS error, dropped connection). The exception type is RequestError.
- An API-level rejection, including an invalid token, returns as a normal result with an errors key. It does not raise an exception.
- The sync endpoint holds one list of messages per rejected field under that key, so an invalid token surfaces at result['errors']['sync_token'][0].
- Check the result for an errors key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Calls GET /stacks/sync with the sync token, and makes one HTTP request per call.
- Returns the content added after the previous sync, plus the details of the content that changed or that someone deleted.
- Replaces the shared sync parameters rather than adding to them, so the filters from the sync_init call do not repeat. The token itself carries them forward.
- The SDK adds the environment parameter from the headers that Stack built, on top of the replaced dictionary.
- Returns the raw parsed API response as a dictionary, carrying items and total_count.
Limitations
- Does not start a sync. Call the sync_init method first, and store the sync token it eventually returns.
- Does not loop. A large change set arrives in pages, so pass the pagination token to the pagination method until the response stops carrying one.
Example
Basic usage: retrieve everything that changed since the last sync
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.sync_token('<SYNC_TOKEN>')
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'errors' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['errors'])
else:
print('changed items:', len(result.get('items', [])), 'of', result.get('total_count'))Error handling: an invalid token returns rather than raises
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.sync_token('not_a_real_token')
except Exception as error:
print('Request failed:', error)
else:
# A rejected token arrives as an ordinary return value, not an exception.
if 'errors' in result:
print('token rejected:', result['errors'].get('sync_token'))Edge case: a non-string token repeats the previous request
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
stored_token = None
try:
first_page = stack.sync_init(locale='en-us')
# The isinstance check fails, so the sync parameters stay as sync_init left
# them and this call repeats that request. Guard the token instead.
changed = stack.sync_token(stored_token)
except Exception as error:
print('Request failed:', error)taxonomy
taxonomy returns a handle for one published taxonomy, or a query across the taxonomies in the stack.
| Name | Type | Description |
|---|---|---|
| taxonomy_uid | str | UID of the taxonomy to read. |
A single taxonomy, or a query across taxonomies.
Validation
- There is no client-side validation of the argument. taxonomy tests it for truthiness and branches, so it never raises.
- Omitting the argument is valid and is the default. It selects the TaxonomyQuery branch.
- An empty string selects that same branch rather than raising. See the Warning on the Taxonomy class page.
- Which object you get decides which methods exist. Calling fetch() on a TaxonomyQuery, or limit() on a Taxonomy, raises AttributeError.
- Errors that do occur come from the terminal call that follows, find() on a TaxonomyQuery or fetch() on a Taxonomy, not from taxonomy().
- Those calls raise an exception only for network failures (timeout, DNS error, dropped connection).
- An API-level rejection, including a UID that names no taxonomy, returns as a normal result with an error key. It does not raise an exception.
- Check the result for an error key even inside a try block.
Additional Resource Refer to Delivery API Errors for the full error code list.
Behavior
- Client-side only. taxonomy constructs an object and makes no request.
- The argument selects one of two classes.
- A truthy taxonomy_uid returns a Taxonomy, which reads that one taxonomy through fetch() and reaches its terms through term().
- A missing or falsy taxonomy_uid returns a TaxonomyQuery, which lists taxonomies through find() and filters entries by term when you chain a filter first.
- The new object carries the connection object from Stack, so it shares the credentials, host, timeout, and retry policy described under Authentication on the Stack class page.
- Each call constructs a new object. Chaining a modifier onto one handle leaves any other handle untouched.
- The full set of methods on both branches lives on the Taxonomy class page in this reference.
Example
Basic usage: list the published taxonomies
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
result = stack.taxonomy().find()
except Exception as error:
# Raised only for network failures (timeout, DNS error, dropped connection)
print('Request failed:', error)
else:
if 'error' in result:
# The Delivery API rejected the request and returned the error body
print('Delivery API error:', result['error'])
else:
for taxonomy in result.get('taxonomies', []):
print(taxonomy['uid'], taxonomy['name'])All parameters: pass taxonomy_uid to read one taxonomy
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# taxonomy_uid is the method's only parameter, and it selects the Taxonomy branch.
result = stack.taxonomy('regions').fetch()
print('taxonomy name:', result.get('name'))
except Exception as error:
print('Request failed:', error)Filtering: return entries tagged with a term
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
try:
# Chaining a filter onto the no-UID branch returns entries instead of taxonomies.
result = stack.taxonomy().in_('taxonomies.regions', ['europe']).find()
except Exception as error:
print('Request failed:', error)Edge case: an empty UID returns the wrong branch
import contentstack
stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')
taxonomy_uid = ''
try:
result = stack.taxonomy(taxonomy_uid).fetch()
except AttributeError as error:
# Fires because the empty string returned a TaxonomyQuery, which has no fetch.
print('Guard the UID before calling fetch:', error)