Asset

View as Markdown

Asset

Assets are the media files uploaded to a stack, such as images, videos, and documents. Use this class to

  • read one published asset by its UID
  • add the image dimensions or the relative URL to the response
  • request extra asset field groups such as user_defined_fields

| Name | Type | Description |

| --- | --- | --- |

| uid | str | UID of the asset. |

stack.asset('<ASSET_UID>') returns an Asset. The UID is a positional parameter with no default, so stack.asset() raises TypeError. To list assets rather than read one, call stack.asset_query(), which returns an AssetQuery.

Warning stack.asset('') returns an Asset rather than raising. The constructor compares the stripped UID against the integer 0, and a string never equals an integer, so an empty UID passes the check. fetch then requests /v3/assets/ with no UID in the path. Test the UID yourself before you call stack.asset.

NameTypeDescription
uid str

Readonly property to check value of asset’s uid

asset_fields

asset_fields adds named asset field groups to the response.

NameTypeDescription
field_names (required)str

Asset field group to include, passed as separate arguments.

Default: Not applicable

The same asset, for chaining.

Validation

  • There is no client-side validation. asset_fields converts every argument with str() and stores the result, so an unknown field name reaches the API unchanged.
  • Calling asset_fields() with no arguments is valid and changes nothing. The method returns the instance without writing a key.
  • Errors that do occur come from the fetch() call that follows, not from asset_fields().
    • fetch() raises an exception only for network failures (timeout, DNS error, dropped connection).
    • An API-level rejection (for example, a field name the endpoint does not recognize) 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_fields appends the names to a list under the asset_fields[] key and makes no request.
  • The SDK documents four values: user_defined_fields, embedded_metadata, ai_generated_metadata, and visual_markups.
  • Repeated calls accumulate rather than replace. asset_fields('user_defined_fields').asset_fields('visual_markups') stores both names in one list.
  • A list or a tuple works as a single argument. asset_fields flattens one level, so asset_fields(['user_defined_fields', 'visual_markups']) stores the same two names that two separate arguments store.
  • fetch serializes the stored list with urllib.parse.urlencode, which writes the Python list representation as one value rather than repeating the asset_fields[] key. A two-name list therefore sends asset_fields%5B%5D=%5B%27user_defined_fields%27%2C+%27visual_markups%27%5D.
  • No method removes a name once added. Build a fresh stack.asset('<ASSET_UID>') instance, or overwrite the key through the params method.

Example

Basic usage: request one asset field group

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').asset_fields('user_defined_fields').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('user defined fields:', result['asset'].get('user_defined_fields'))

All parameters: every documented field group in one call

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').asset_fields(
        'user_defined_fields',
        'embedded_metadata',
        'ai_generated_metadata',
        'visual_markups'
    ).fetch()
    print('asset keys:', sorted(result.get('asset', {}).keys()))
except Exception as error:
    print('Request failed:', error)

Edge case: repeated calls add to the list rather than replacing it

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    asset = stack.asset('<ASSET_UID>') \
        .asset_fields('user_defined_fields') \
        .asset_fields('visual_markups')

    # Both names are now in the same list.
    print(asset.asset_params['asset_fields[]'])

    result = asset.fetch()
except Exception as error:
    print('Request failed:', error)

Edge case: a list argument flattens instead of nesting

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

wanted = ['user_defined_fields', 'visual_markups']

try:
    # Passing the list directly stores the same two names as
    # asset_fields(*wanted) does, because the method flattens one level.
    result = stack.asset('<ASSET_UID>').asset_fields(wanted).fetch()
    print('title:', result.get('asset', {}).get('title'))
except Exception as error:
    print('Request failed:', error)

environment

environment sets the environment the request reads the asset from.

NameTypeDescription
environment (required)str

Environment name to read the asset from.

Default: Not applicable

The same asset, for chaining.

Validation

  • There is no client-side validation. environment accepts an empty string or a non-string value and stores it as given.
  • Passing None leaves the header untouched. The guard skips the assignment, and environment returns the instance unchanged, so the header keeps the value the Stack gave it.
  • Omitting the argument raises TypeError immediately, because environment is a positional parameter with no default.
  • Errors that do occur come from the fetch() call that follows, not from environment().
    • fetch() raises an exception only for network failures (timeout, DNS error, dropped connection).
    • An API-level rejection (for example, an environment name that no environment matches) 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. environment writes the name into the request headers and makes no request. fetch sends the header on that call.
  • The write lands in the Stack headers dictionary, which every class in the SDK shares. Every later request from that Stack carries the new name until you change it again.
  • environment does not update the environment query parameter the constructor copied. fetch therefore sends the new name in the header and the original name in the query string. See the environment note on the Asset class page.
  • Calling environment twice replaces the first value, because both calls write the same header key.
  • Use the remove_environment method to drop the header instead of overwriting it.

Example

Basic usage: read the asset from a named environment

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').environment('production').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('title:', result['asset']['title'])

Edge case: the query string keeps the original environment

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    asset = stack.asset('<ASSET_UID>').environment('production')

    # The header now says production. The query parameter still says <ENVIRONMENT>.
    print('header:', asset.http_instance.headers['environment'])
    print('query parameter:', asset.asset_params['environment'])

    # Overwrite the query parameter as well when both have to agree.
    result = asset.params('environment', 'production').fetch()
except Exception as error:
    print('Request failed:', error)

Edge case: a null value changes nothing

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

selected = None

try:
    # environment(None) is a no-op, so the request still uses <ENVIRONMENT>.
    result = stack.asset('<ASSET_UID>').environment(selected).fetch()
    print('served from:', stack.headers['environment'])
except Exception as error:
    print('Request failed:', error)

fetch

fetch retrieves the latest published version of one asset.

The requested asset inside the response envelope.

Validation

  • fetch validates nothing itself. The UID check happens earlier, in stack.asset.
  • stack.asset(None) never reaches this method. stack.asset raises KeyError with the message "Invalid UID. Provide a valid UID and try again." because the SDK cannot build the asset URL without an identifier. A UID that is not a str raises the same KeyError.
  • stack.asset('') does reach this method, and the request goes out with no UID in the path. See the Warning on the Asset class page.
  • fetch raises an exception only for network failures (timeout, DNS error, dropped connection). The exception type is RequestError.
    • 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

  • Calls GET /v3/assets/{uid} and makes one HTTP request per call.
  • Returns the parsed response body unchanged. The asset sits under the asset key, so read result['asset'] rather than result. See Response shape on the Asset class page.
  • Sends every parameter the instance holds. That covers the environment copy the constructor made, plus whatever the relative_urls, include_dimension, include_fallback, asset_fields, and params methods recorded.
  • Reads the request headers at call time, so an environment or remove_environment call made after the first fetch changes the second one.
  • Calling fetch twice on one instance repeats the same request. The SDK caches nothing.

Limitations

  • Does not list assets. Call stack.asset_query() and use its find method instead.
  • Does not read a specific version of the asset. Asset records no version, and version belongs to AssetQuery.

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:
        asset = result['asset']
        print(asset['uid'], asset['title'])

All modifiers: every flag this class records

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>') \
        .relative_urls() \
        .include_dimension() \
        .include_fallback() \
        .asset_fields('user_defined_fields') \
        .params('include_branch', 'true') \
        .fetch()
    print('url:', result.get('asset', {}).get('url'))
except Exception as error:
    print('Request failed:', error)

Error handling: an unknown UID does not raise

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('no_such_asset').fetch()
except Exception as error:
    print('Request failed:', error)
else:
    # A missing asset arrives as an ordinary return value, not an exception.
    if 'error' in result:
        print('code:', result.get('error_code'), 'message:', result.get('error_message'))

Edge case: guard an empty UID before the call

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

asset_uid = ''

# stack.asset('') builds a URL with no UID instead of raising, so test it here.
if not asset_uid:
    print('no asset UID, skipping the fetch')
else:
    try:
        result = stack.asset(asset_uid).fetch()
        print(result.get('asset', {}).get('title'))
    except Exception as error:
        print('Request failed:', error)

include_dimension

include_dimension adds the height and width of an image to the response.

The same asset, for chaining.

Validation

  • There is nothing to validate. include_dimension takes no arguments and cannot fail.
  • Errors that do occur come from the fetch() call that follows, not from include_dimension().
    • fetch() 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. Writes include_dimension=true as a string and makes no request. fetch sends the flag on that call.
  • The dimensions arrive under result['asset']['dimension'] as a dictionary with height and width keys.
  • The SDK documents support for the JPG, GIF, PNG, WebP, BMP, TIFF, SVG, and PSD image types. A file of any other type carries no dimensions to return.
  • Read the dimension key defensively. fetch returns a plain dictionary, and the key is absent whenever the API returns no dimensions.
  • Calling include_dimension twice changes nothing, because both calls write the same key and the same value.

Example

Basic usage: read the height and width of an image

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').include_dimension().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:
        dimension = result['asset']['dimension']
        print(dimension['width'], 'x', dimension['height'])

Edge case: a non-image asset returns no dimension key

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').include_dimension().fetch()

    # The key is missing for a file type that carries no dimensions,
    # so reading result['asset']['dimension'] directly raises KeyError.
    dimension = result.get('asset', {}).get('dimension')
    if dimension is None:
        print('no dimensions for this asset')
    else:
        print(dimension['width'], 'x', dimension['height'])
except Exception as error:
    print('Request failed:', error)

include_fallback

include_fallback returns the published content of the fallback locale when the asset has no localization in the requested one.

The same asset, for chaining.

Validation

  • There is nothing to validate. include_fallback takes no arguments and cannot fail.
  • Errors that do occur come from the fetch() call that follows, not from include_fallback().
    • fetch() 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. Writes include_fallback=true as a string and makes no request. fetch sends the flag on that call.
  • The flag alone changes nothing when the request names no locale. Asset exposes no locale method, so send the locale through the params method.
  • The API resolves the fallback, not the SDK. include_fallback sends the flag and reads nothing back.
  • Calling include_fallback twice changes nothing, because both calls write the same key and the same value.

Example

Basic usage: accept fallback content for a missing localization

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').include_fallback().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('title:', result['asset']['title'])

Pair the flag with a locale, which this class has no method for

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

requested = 'fr-fr'

try:
    # The flag matters only when the request asks for a specific locale.
    result = stack.asset('<ASSET_UID>') \
        .params('locale', requested) \
        .include_fallback() \
        .fetch()

    served = result.get('asset', {}).get('locale')
    if served and served != requested:
        print(f'no {requested} version, served {served} instead')
except Exception as error:
    print('Request failed:', error)

params

params adds an arbitrary query parameter to the asset request.

NameTypeDescription
key (required)str

Query parameter name to send.

Default: Not applicable
value (required)Any

Value for that query parameter.

Default: Not applicable

The same asset, for chaining.

Validation

  • Passing None as either argument raises KeyError with the message "Invalid parameters. Provide valid parameters and try again." A null key or value would produce a malformed query string.
  • Passing a key that is not a str raises the same KeyError. params(2, 'value') fails, because the SDK needs a string name to build the query string.
  • The raise happens on the call itself, not on the terminal fetch() call. Wrap params in its own try when the key or the value comes from user input.
  • An empty string passes both checks, so params('', '') stores a parameter with no name.
  • Omitting either argument raises TypeError immediately, because both are positional parameters with no default.
  • Any remaining errors come from the fetch() call that follows.
    • fetch() raises an exception only for network failures (timeout, DNS error, dropped connection).
    • An API-level rejection (for example, a query parameter the endpoint 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.

Behavior

  • Client-side only. params records the pair in the asset query parameters and makes no request.
  • The key shares one namespace with the dedicated flags. params('include_dimension', 'false') and include_dimension() write the same key, so the later call wins.
  • The environment copy the constructor made lives in the same dictionary, so params('environment', 'staging') replaces it. See the environment note on the Asset class page.
  • Use params to send a Delivery API query parameter this class exposes no method for.
  • The SDK encodes the parameters before sending them, so a value containing a space or an ampersand needs no encoding from you.

Example

Basic usage: send a query parameter this class has no method for

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').params('include_branch', 'true').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('branch:', result['asset'].get('_branch'))

Error handling: a null key raises at the call site

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

user_supplied_key = None

try:
    result = stack.asset('<ASSET_UID>').params(user_supplied_key, 'true').fetch()
except KeyError as error:
    # Fires on params itself, before any request goes out.
    print('Invalid query parameter:', error)

Error handling: an integer key raises the same way

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').params(2, 'value').fetch()
except KeyError as error:
    # params rejects a key that is not a str.
    print('Query parameter names must be strings:', error)

Edge case: a dedicated flag and params collide

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    # Both write the 'include_dimension' key, so the later call wins
    # and this sends include_dimension=false.
    result = stack.asset('<ASSET_UID>') \
        .include_dimension() \
        .params('include_dimension', 'false') \
        .fetch()
except Exception as error:
    print('Request failed:', error)

relative_urls

relative_urls requests the relative URL of the asset instead of the absolute one.

The same asset, for chaining.

Validation

  • There is nothing to validate. relative_urls takes no arguments and cannot fail.
  • Errors that do occur come from the fetch() call that follows, not from relative_urls().
    • fetch() 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. Writes relative_urls=true as a string and makes no request. fetch sends the flag on that call.
  • Calling relative_urls twice changes nothing, because both calls write the same key and the same value.
  • The API decides the form of the URL in the response. relative_urls sends the flag and does not rewrite the value the SDK receives.
  • The name is plural on Asset and singular on AssetQuery, where the same flag is relative_url. Both write the relative_urls query parameter.

Example

Basic usage: request the relative URL

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').relative_urls().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('url:', result['asset']['url'])

Edge case: overwrite the flag through params

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    # No method clears the flag, so write the key again to send 'false'.
    result = stack.asset('<ASSET_UID>') \
        .relative_urls() \
        .params('relative_urls', 'false') \
        .fetch()
    print('url:', result.get('asset', {}).get('url'))
except Exception as error:
    print('Request failed:', error)

remove_environment

remove_environment deletes the environment entry from the request headers.

The same asset, for chaining.

Validation

  • There is nothing to validate. remove_environment takes no arguments and cannot fail.
  • Calling it twice is safe. remove_environment checks for the key first, so a second call returns the instance unchanged.
  • Errors that do occur come from the fetch() call that follows, not from remove_environment().
    • fetch() 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. remove_environment removes the environment key from the request headers and makes no request.
  • The removal does not reach the query string. The constructor already copied the environment into the asset query parameters, so fetch still sends environment=<the value the Stack was built with>. See the environment note on the Asset class page.
  • Use the params method to overwrite the query-string copy, because params and the constructor write the same environment key.
  • The removal applies to the whole Stack. Every later request from that Stack goes out without the environment header until you set it again.
  • Use the environment method to restore the header.

Example

Basic usage: send the request without the environment header

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    result = stack.asset('<ASSET_UID>').remove_environment().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('title:', result['asset']['title'])

Edge case: the query parameter survives the removal

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    asset = stack.asset('<ASSET_UID>').remove_environment()

    # The header is gone. The query parameter is not.
    print('environment header present:', 'environment' in asset.http_instance.headers)
    print('query parameter:', asset.asset_params['environment'])
except Exception as error:
    print('Request failed:', error)

Edge case: restore the header for the next request

import contentstack

stack = contentstack.Stack('<API_KEY>', '<DELIVERY_TOKEN>', '<ENVIRONMENT>')

try:
    asset = stack.asset('<ASSET_UID>')
    first = asset.remove_environment().fetch()

    # Every class sharing this Stack now sends no environment header,
    # so put it back before the next request.
    second = asset.environment('<ENVIRONMENT>').fetch()
    print('second call title:', second.get('asset', {}).get('title'))
except Exception as error:
    print('Request failed:', error)