Skip to navigation

Experience

An experience is a hydrated representation of content authored in Contentful — the visual structure, personalization variants, and content of a published experience, ready for a client application to render.

The XDA returns experiences in two ways:

  • By ID — a straightforward GET request returns the hydrated experience.
  • With personalization input — a POST request lets you send personalization overrides in the request body, which the API applies while hydrating the experience.

Both operations support locale selection, variant targeting, optimization profiles, and experience parameters.

Getting localized experiences

By default, a request to the experience endpoint returns the experience hydrated with content in the environment’s default locale:

GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}

To hydrate the experience with a different locale, add a locale query parameter with the locale code:

GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}?locale=en-US

Experience fields aren’t localized, so changing the locale never affects the layout or the personalization rules applied — the experience and its rules stay the same. Only the content pulled from bound entries and assets changes: if a bound entry or asset has localized fields, the API returns the value matching the requested locale, following the fallback chain configured for the environment’s locales.

Locale selection also applies when requesting a variant of an experience:

GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}?locale=en-US&variant=Experience:3foFgkr9iq8bWSZQtb2H1G:1b414538-5894-483a-9441-2cbfa65a0aab
On the production host, entries and assets must be published for the requested locale. Requesting a locale that hasn’t been published, or that doesn’t exist for the environment, returns a 404.

Passing parameters to an experience

An experience can declare parameters that its data bindings read at request time, such as the entry shown on a product page, or how many posts a list includes. Pass their values as query parameters in a GET request, or in the parameters object of a POST request body.

In a GET request, prefix every key with parameter.. The prefix keeps experience parameters apart from system query parameters, so locale=de-DE&parameter.locale=fr-FR sets the request locale and an experience parameter named locale separately. A key without the prefix returns a 422 error.

# String or Number
parameter.<id>=<value>
# ResourceLink, by entry ID
parameter.<id>=<entryId>
# ResourceLink, by field value
parameter.<id>.fields.<field>=<value>
# Record, for collections
parameter.<id>.limit=<number>
parameter.<id>.order=<fieldPath>
GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}?parameter.item=4fJx2kQ9mN&parameter.featuredPosts.limit=6

In a POST request body, key each value by its parameter ID, without the prefix:

{
"parameters": {
// String or Number
"heading": "Summer sale",
// ResourceLink, by entry ID
"author": "4fJx2kQ9mN",
// ResourceLink, by field value
"item": { "fields": { "slug": "standing-desk" } },
// Record, for collections
"featuredPosts": { "limit": 6, "order": "-fields.title" }
}
}

Collection parameters

A Record parameter controls a collection that the experience displays, such as a list of blog posts. It isn’t a free-form object: it accepts only the collection fields the experience declares for it, and any other key is rejected as an unknown parameter.

  • limit sets the number of entries to return, within the range the experience allows.
  • order sets the sort order as a single field path, such as fields.title or sys.createdAt. Prefix it with a minus sign for descending order, such as -fields.title. Lists of several fields aren’t accepted, and the experience can restrict which fields are allowed.

Fallback values

If you omit a String or Number parameter, or a collection’s limit or order, the API uses the experience’s fallback value. If the experience does not have a fallback value, it uses the one of the bound data assembly.

ResourceLink parameters have no fallback. A required parameter with no value and no fallback on the experience returns a 422 error.

Looking up an entry by field value

Instead of an entry ID, you can fill a ResourceLink parameter with a field value, such as the slug from a URL like /products/standing-desk. You no longer need a separate request to find the entry ID first.

GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}?parameter.item.fields.slug=standing-desk
POST https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}
{
"parameters": {
"item": { "fields": { "slug": "standing-desk" } }
}
}

The API finds the matching entry and returns the experience exactly as if you had passed the entry’s ID.

Content type

A lookup searches one content type. If the parameter allows only one, the API uses it. Otherwise, name the content type with parameter.<id>.content_type in a GET request, or with content_type next to fields in a POST request body.

It must be one of the content types the parameter allows.

GET https://xdn.contentful.com/spaces/{spaceId}/environments/{envId}/experiences/{expId}?parameter.item.content_type=product&parameter.item.fields.slug=standing-desk

Matching rules

  • A lookup matches one field exactly. Pass a single, non-empty value.
  • Values are compared as strings, so look up by text fields such as a slug or SKU. A value such as “007” isn’t converted to a number.
  • The field is matched against its value in the request locale only. A value the entry inherits from a fallback locale doesn’t match, even if it appears in the response. If you request the de-DE locale, pass the slug stored in de-DE.
  • Uniqueness isn’t enforced. If several entries match, the API uses one of them, with no guarantee which, and reports an error. Look up by a field whose values are unique.
  • You can’t send a lookup and an entry ID for the same parameter.

Lookup outcomes

A lookup that passes validation always returns 200. If it doesn’t find exactly one entry, the experience is still returned, and the problem is reported in its errors array, with one of these codes in originalError.code:

OutcomeCodeResult
No entry matchesENTRY_LOOKUP_NO_MATCHContent bound to the parameter is null. The bound data assembly also reports the missing parameter.
Several entries matchAMBIGUOUS_ENTRY_LOOKUPOne of the matching entries is used.
The content type has no such fieldINVALID_ENTRY_LOOKUP_FIELDThe parameter isn’t resolved.
The content type doesn’t exist in the environmentLOOKUP_TARGET_NOT_IN_SCHEMAThe parameter isn’t resolved.
{
"sys": { "id": "productPage", "type": "Experience" },
"nodes": [ ... ],
"errors": [
{
"fieldPath": "Experience.productPage.dataAssembly",
"message": "Lookup for parameter 'item' by fields.slug matched more than one entry",
"originalError": { "code": "AMBIGUOUS_ENTRY_LOOKUP", "parameter": "item" }
}
]
}

Parameter validation errors

The API validates parameters against the experience’s declarations before it resolves any content. An invalid value returns a 422 error. Each item in its details array has a code and the parameter you sent: the full query key in a GET request, such as parameter.item.fields.slug, or the parameter ID in a POST request.

CodeCause
unknown_parameterThe experience doesn’t declare the parameter or collection field, the key is missing the prefix or is malformed, or two keys conflict for the same parameter.
missing_requiredA required parameter has no value and no fallback, or a lookup needs a content type because the parameter allows several.
type_mismatchThe value has the wrong type, such as text for a Number parameter, or a lookup on a parameter that isn’t a ResourceLink.
invalid_valueThe value isn’t allowed: it’s not one of the allowed values, the order isn’t a single valid field path, the content type isn’t one the parameter allows, or the lookup is empty or names more than one field.
out_of_rangeA number is outside the allowed range.