Skip to navigation

API Feedback

Tell Etals what is wrong with an exported value, or that a value is missing, and have it regenerated.
View as Markdown

The Feedback API is the optional return leg of the round trip. When a reviewer or an automated check in your system finds a problem with a value Etals sent you, you post the feedback back. Etals stores it and, unless you say otherwise, creates a new task that writes the value again with your feedback as extra instructions.

You can point at a value in two ways:

  • By value_id, the ID that came with the value in the API export payload.
  • By context: content type, item identifier, property and localization. This also works for a value that does not exist yet, so you can report missing content.

Endpoint

POST https://{your-workspace}.etals.app/api/v1/feedback/content-job-values
Authorization: Bearer {api-token}
Content-Type: application/json
Accept: application/json

The token needs the Create ability. No extra user permission is needed. See Authorization.

Request body

The body uses the same shape as the export payload, with feedback in place of value.

{
"attributable_type": { "system_code": "products" },
"items": [
{
"identifiers": { "identifier": "NV-1001" },
"properties": [
{
"system_code": "description",
"values": [
{
"value_id": 457,
"feedback": "Mention that the jacket weighs 410 g. Customers ask about the weight."
}
]
},
{
"system_code": "meta_title",
"values": [
{
"language": "de",
"market": "de",
"feedback": "The German meta title is missing. Write one, max 60 characters."
},
{
"language": "en",
"market": "uk",
"feedback": "Use British English and drop the brand name.",
"create_content_job": false
}
]
}
]
}
]
}
FieldRequiredMeaning
attributable_type.system_codeWhen any value has no value_idSystem code of the content type, for example products.
itemsYesAt least one item.
items[].identifiers.identifierWhen a value has no value_idThe item’s identifier, for example NV-1001.
items[].propertiesYesAt least one property per item.
items[].properties[].system_codeWhen a value has no value_idSystem code of the property.
items[].properties[].valuesYesAt least one value per property.
values[].value_idNoThe value_id from the export. When present, the context fields are ignored.
values[].language, brand, market, front, countryNoSystem codes that pick the localization when there is no value_id. See How a value is found.
values[].feedbackYesYour feedback as plain text, max 10,000 characters.
values[].create_content_jobNotrue (default) creates a task that regenerates the value. false only stores the feedback.

How a value is found

With a value_id, Etals looks up that produced value. If the ID does not exist, the request fails.

Without a value_id, Etals resolves the target step by step:

  1. The content type, by attributable_type.system_code.
  2. The item, by identifier.
  3. The property, by its system_code within that content type.
  4. The localization, from the context fields.

For the context fields:

  • A field you send with a code ("language": "de") must match exactly.
  • A field you send as null means “this localization has no value for that dimension”, and must match exactly.
  • A field you leave out is first treated as null. If no localization matches that way, Etals ignores the field and accepts the match only if exactly one localization fits.
  • If more than one localization still fits, the request fails and asks for more context, for example front.

If the localization exists but has no value yet, the feedback is still accepted and the new task writes the missing value.

Responses

Created

201 Created. Feedback is stored for every value in the request.

{
"success": true,
"message": "Feedback stored successfully",
"data": {
"feedbackIds": [311, 312, 313],
"createdContentJobIds": [1408, 1409],
"skipped": [],
"failed": []
}
}
FieldMeaning
data.feedbackIdsIDs of the stored feedback records, in request order.
data.createdContentJobIdsIDs of the tasks that were created. Empty when no value asked for regeneration.
data.skippedValues whose task could not be created yet because Etals found no suitable pipeline for the property. Each entry has reason (pipeline_not_configured or pipeline_selection_failed), attributeId, attributableId, valueId and recordId.
data.failedValues whose task creation failed. Each entry has feedbackId, reason, attributeId, attributableId, valueId and recordId.

Skipped and failed feedback is kept. Etals tries to create the task again every 5 minutes, so it goes through once a pipeline has been set up for the property.

Some values could not be resolved

422 Unprocessable Entity. Nothing is stored and no task is created, even for the values that were fine.

{
"success": false,
"message": "Some feedback items could not be resolved",
"errors": {
"1": "No attribute item matches the provided context for property \"meta_title\""
}
}

errors is keyed by the position of the value in the request, counting all values across all items and properties, starting at 0. Possible messages:

MessageCause
Value with value_id {id} does not existUnknown value_id.
attributable_type.system_code is required when value_id is not providedNo content type given.
Unknown attributable type "{code}"No content type with that system code.
An identifier is required when value_id is not providedNo item identifier given.
No record found for identifier "{identifier}"No item with that identifier.
A property system_code is required when value_id is not providedNo property given.
Unknown property "{code}" for attributable type "{type}"The content type has no property with that system code.
Unknown {dimension} "{code}"A language, brand, market, website or country code that does not exist.
No attribute item matches the provided context for property "{code}"The property has no localization matching your context.
Multiple attribute items match the provided context for property "{code}". Provide more context dimensions (for example front) to select oneYour context fits more than one localization.

Invalid body

422 Unprocessable Entity in the standard validation format, for example when feedback is missing:

{
"message": "Feedback text is required for each value",
"errors": {
"items.0.properties.0.values.0.feedback": ["Feedback text is required for each value"]
}
}

Server error

500 with {"success": false, "message": "Failed to store feedback: {reason}"}.

The regeneration task

When create_content_job is true, the new task:

  • Writes a new value instead of reusing the current one, with your feedback added to its instructions.
  • Is named [Feedback] ... and is marked as a feedback task.
  • Runs without an approval step.
  • Picks its pipeline from the property: the pipeline set on the property if there is one, otherwise the only pipeline attached to it, otherwise the best match among the attached pipelines. If none fits, the feedback is skipped (see above).

What else it does depends on how you pointed at the value:

By value_idBy context
Tasks createdOne per original task and content type. All feedback on values from the same task goes into one new task.One per item. All feedback on that item goes into one task, each line labelled with its property and context.
Task name[Feedback] {original task name}[Feedback] {content type name}
SettingsKeeps the original task’s comment, instructions and tags.Starts empty apart from your feedback.
ExportExports to your endpoint only if the original task did.Always exports when it finishes.

The regenerated value arrives at your receiver as a normal API export, with a new value_id.

Example flow

  1. Etals exports the English description of NV-1001 to your endpoint with value_id 457.
  2. Your reviewer notes that the weight is missing.
  3. Your system posts the feedback with value_id: 457.
  4. Etals answers 201 and creates a feedback task.
  5. When the task finishes, the new description reaches your endpoint with a new value_id.