{"openapi":"3.0.0","info":{"title":"Afineo Webservices API — listvalues","description":"Module `listvalues` of the Afineo API v3 (6 endpoints).\n\nManage dropdown lists (list values) used by select-type attributes: create lists, add options, and update existing values. These are the predefined option sets that populate dropdown, checkbox and radio attributes.\n\nFull specification: https://api.afineo.io/openapi.json","version":"3.0.0","contact":{"name":"Afineo Solutions","url":"https://www.afineo.com"},"x-logo":{"url":"./logo.png","altText":"Afineo - Powerful Data, Powerful People"}},"servers":[{"url":"https://{instance}.afineo.io","description":"Afineo instance","variables":{"instance":{"description":"Your Afineo instance name","default":"client"}}}],"tags":[{"name":"listvalues","description":"Manage dropdown lists (list values) used by select-type attributes: create lists, add options, and update existing values. These are the predefined option sets that populate dropdown, checkbox and radio attributes."}],"paths":{"/api/v3/listvalues/add-option/":{"post":{"tags":["listvalues"],"summary":"Add option to list value","description":"## Purpose\n\nAdds a new option (choice) to an existing dropdown list.\n\n## Use Cases\n\n- Extend available choices for a dropdown field\n- Add new values to existing list configurations\n- Automate list value population via API\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Add option response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"Option added successfully","description":"Status message"},"result":{"type":"object","properties":{"list_id":{"type":"integer","example":50,"description":"ID of the list value"},"option_id":{"type":"integer","example":205,"description":"ID of the newly created option"},"label":{"type":"string","example":"Nouvelle Couleur","description":"Display label for the new list option. Must be unique within the list"},"code":{"type":"string","example":"NEW_COLOR","description":"Code of the new option"}},"required":["list_id","option_id","label","code"]}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","example":2,"description":"Status code (2 = list not found, 3 = error)"},"status_message":{"type":"string","example":"List value \"50\" does not exist","description":"Error message"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"list_id":{"type":"integer","description":"List value ID. Use POST /api/v3/listvalues/list with class_id to get available list values.","example":50},"value":{"type":"string","description":"Display label for the new list option. Must be unique within the list","example":"Nouvelle Couleur"},"code":{"type":"string","description":"Optional code for the option (auto-generated if not provided)","example":"NEW_COLOR"}},"required":["list_id","value"]}}}}}},"/api/v3/listvalues/create/":{"post":{"tags":["listvalues"],"summary":"Create a new dropdown list","description":"## Purpose\n\nCreates a new dropdown list (list value) in a library, optionally with initial options (values).\n\n## Idempotent Behavior\n\nIf a list with the same label already exists in the library, returns the existing list with `created: false` and adds any new values provided.\n\n## Use Cases\n\n- Create dropdown lists for product attributes (colors, sizes, categories)\n- Pre-populate lists with initial values and translations\n- Automate list creation during platform setup\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Create list value response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"List created successfully","description":"Status message"},"result":{"type":"object","properties":{"id":{"type":"integer","example":127,"description":"List value ID"},"class_id":{"type":"integer","example":4,"description":"Library ID"},"label":{"type":"string","example":"Colors","description":"List label"},"created":{"type":"boolean","example":true,"description":"true if newly created, false if already existed"},"values_added":{"type":"integer","example":3,"description":"Number of option values added"}},"required":["id","class_id","label","created","values_added"]}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","example":2,"description":"Status code (2 = validation error)"},"status_message":{"type":"string","example":"Label cannot be empty","description":"Error message"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"class_id":{"type":"integer","description":"Library ID. Use POST /api/v3/administration/classes/list to get available libraries.","example":4},"label":{"type":"string","description":"Name of the dropdown list. Must be unique within the library for creation (idempotent if duplicate).","example":"Colors"},"values":{"type":"array","description":"Array of option objects to add to the list. Empty labels are ignored. (Array of objects - see example for structure)","example":[{"label":"Rouge","code":"RED","translations":{"2":"Red","3":"Rojo"},"type_ids":[100,102],"afs":"#123#"},{"label":"Bleu","code":"BLU"}],"items":{"type":"object","properties":{"label":{"type":"string","description":"Display label in the default language.","example":"Rouge"},"code":{"type":"string","description":"Option code. Auto-generated as \"id_<ID>\" if omitted.","example":"RED"},"translations":{"type":"object","description":"Translated labels by version_id. Keys are version IDs (as strings), values are translated labels. Use POST /api/v3/listvalues/full to see available version IDs.","additionalProperties":{"type":"string"},"example":{"2":"Red","3":"Rojo"}},"type_ids":{"type":"array","items":{"type":"integer"},"description":"Asset type IDs to restrict this option to. If omitted, option is available for all types. Use POST /api/v3/types/list to get available type IDs.","example":[100,102]},"afs":{"type":"string","description":"AFS condition using Smarty/hashtag syntax (e.g. \"#123#\", \"{if #153#}1{/if}\"). Syntax is validated before creation.","example":"#123#"}},"required":["label"]}}},"required":["class_id","label"]}}}}}},"/api/v3/listvalues/full/":{"post":{"tags":["listvalues"],"summary":"Get list values for dropdowns","description":"## Purpose\n\nReturns all dropdown options configured for a class with full details (options, linked attributes, versions).\n\n## Use Cases\n\n- Populate select fields with available choices\n- Validate user input against allowed values\n- Build dynamic forms based on list configuration\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List values list response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"","description":"Status message"},"result":{"type":"object","properties":{"results_total":{"type":"integer","example":2,"description":"Total number of list values found"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":45,"description":"List value ID"},"class_id":{"type":"integer","example":4,"description":"Class ID"},"code":{"type":"string","example":"code_list","description":"List value code"},"label":{"type":"string","example":"Colors","description":"List value label"},"linked_attributes":{"type":"object","additionalProperties":{"type":"string"},"example":{"125":"Color attribute","126":"Main color"},"description":"Map of attribute IDs to labels that use this list value"},"tags":{"type":"array","items":{"type":"string"},"example":["tag1","tag2"],"description":"Array of tags (can be empty)"},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1001,"description":"Option ID"},"value_code":{"type":"string","example":"RED","description":"Option value code"},"order":{"type":"integer","example":1,"description":"Display order"},"afs":{"type":"string","example":"#123#","description":"AFS value"},"versions":{"type":"array","items":{"type":"object"},"example":{"1":{"data_value":"No","real_value":"No"},"2":{"data_value":"No","real_value":"No"}},"description":"Associated versions"},"asset_types":{"type":"array","items":{"type":"string"},"example":["all"],"description":"Associated asset types (can be 'all' or specific type labels)"}},"required":["id","value_code","order","afs","versions","asset_types"]},"description":"Array of options"}},"required":["id","class_id","code","label","tags","linked_attributes","options"]},"description":"Array of list values"}},"required":["results_total","items"],"description":"List values with total count"}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","example":3,"description":"Status code (3 = error, 0 = class not found)"},"status_message":{"type":"string","example":"Class not found or access denied","description":"Error message"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"class_id":{"type":"integer","description":"Library ID. Use POST /api/v3/administration/classes/list to get available libraries.","example":4}},"required":["class_id"]}}}}}},"/api/v3/listvalues/get/":{"post":{"tags":["listvalues"],"summary":"Get list value details","description":"## Purpose\n\nReturns complete information for a single list value including all options, linked attributes, and version data.\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List value information response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"","description":"Status message"},"result":{"type":"object","properties":{"id":{"type":"integer","example":45,"description":"List value ID"},"class_id":{"type":"integer","example":4,"description":"Class ID"},"code":{"type":"string","example":"code_list","description":"List value code"},"label":{"type":"string","example":"Colors","description":"List value label"},"tags":{"type":"array","items":{"type":"string"},"example":["tag1","tag2"],"description":"Array of tags (can be empty)"},"linked_attributes":{"type":"object","additionalProperties":{"type":"string"},"example":{"125":"Color attribute","126":"Main color"},"description":"Map of attribute IDs to labels that use this list value"},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1001,"description":"Option ID"},"value_code":{"type":"string","example":"RED","description":"Option value code"},"order":{"type":"integer","example":1,"description":"Display order"},"afs":{"type":"string","example":"#123#","description":"AFS value"},"versions":{"type":"array","items":{"type":"object"},"example":{"1":{"data_value":"No","real_value":"No"},"2":{"data_value":"No","real_value":"No"}},"description":"Associated versions"},"asset_types":{"type":"array","items":{"type":"string"},"example":["all"],"description":"Associated asset types (can be 'all' or specific type labels)"}},"required":["id","value_code","order","afs","versions","asset_types"]},"description":"Array of options"}},"required":["id","class_id","code","label","tags","linked_attributes","options"],"description":"List value information"}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","example":2,"description":"Status code (2 = not found)"},"status_message":{"type":"string","example":"List value \"20\" does not exist","description":"Error message with list value ID"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"List value ID. Use POST /api/v3/listvalues/list with class_id to get available list values.","example":20}},"required":["id"]}}}}}},"/api/v3/listvalues/list/":{"post":{"tags":["listvalues"],"summary":"List dropdown configurations","description":"## Purpose\n\nReturns simplified list values for a class (id, code, label, tags only).\n\n## Comparison\n\nUse `listvalues/full` for complete details including options and linked attributes.\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List values list response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"","description":"Status message"},"result":{"type":"object","properties":{"results_total":{"type":"integer","example":2,"description":"Total number of list values found"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":45,"description":"List value ID"},"class_id":{"type":"integer","example":4,"description":"Class ID"},"code":{"type":"string","example":"code_list","description":"List value code"},"label":{"type":"string","example":"Colors","description":"List value label"},"tags":{"type":"array","items":{"type":"string"},"example":["tag1","tag2"],"description":"Array of tags (can be empty)"}},"required":["id","class_id","code","label","tags"]},"description":"Array of list values"}},"required":["results_total","items"],"description":"List values with total count"}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","example":3,"description":"Status code (3 = error, 0 = class not found)"},"status_message":{"type":"string","example":"Class not found or access denied","description":"Error message"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"class_id":{"type":"integer","description":"Library ID. Use POST /api/v3/administration/classes/list to get available libraries.","example":4}},"required":["class_id"]}}}}}},"/api/v3/listvalues/update/":{"post":{"tags":["listvalues"],"summary":"Update a dropdown list with full options synchronization","description":"## Purpose\n\nUpdates an existing dropdown list: its label and/or its options. When `values` is provided, the endpoint performs a **full synchronization** of the list options.\n\n## What can be updated\n\n- `label`: Display name of the list\n- `values`: Complete list of options (exhaustive synchronization)\n\n## What cannot be updated\n\n- `class_id` (immutable — the list belongs to a specific library)\n\n## Recommended workflow\n\n1. Call `POST /api/v3/listvalues/get` with the list ID to retrieve all existing options and their IDs\n2. Modify the returned options array as needed (add, remove, or edit entries)\n3. Send the modified array as the `values` parameter to this endpoint\n\nThis read-modify-write pattern ensures you don't accidentally delete existing options by sending a partial list.\n\n## Options synchronization (`values` parameter)\n\nWhen `values` is provided, it must contain the **complete and exhaustive** list of options for this dropdown. The endpoint compares the provided options with the existing ones in database and performs:\n\n### 1. Matching logic (by priority)\n- **By `id`**: if an option has an `id` field, it is matched to the existing option with that `id_asset`\n- **By `code`**: if no `id` but a `code` is provided, it is matched to the existing option with that `code_valeur`\n- **No match**: the option is treated as new and will be created\n\n### 2. ADD — Options present in `values` but not in database\n- Creates the option element (asset) in the list\n- Sets translations for each provided `version_id`\n- Creates type associations if `type_ids` is provided\n\n### 3. UPDATE — Options matched between `values` and database\nFor each matched option, only fields that actually differ are updated:\n- `label` (translations): compared per version_id, only changed versions are written\n- `code`: updated if different from current `code_valeur`\n- `afs`: updated if different from current `asset_afs` (syntax validated before update)\n- `type_ids`: diff computed with `array_diff()` — types to add and types to remove are processed separately\n\n### 4. DELETE — Options in database but NOT in `values`\n**⚠️ DESTRUCTIVE**: options present in the database but absent from the `values` array will be **permanently deleted**. This includes:\n- The option element (asset) itself (soft-delete: `deleted=1`)\n- All type associations for this option (`links_element_list_values_type` rows)\n- All references in library link tables (`links_XXX_list_values`)\n\n### 5. No `values` parameter\nIf `values` is omitted, only the `label` is updated (if provided). Existing options are left untouched.\n\n## Important\n\n- If neither `label` nor `values` is provided, the endpoint returns success with empty sync counts.\n- All option validations (translations version_ids, type_ids, AFS syntax) are performed **before any write operation**. If any validation fails, the entire update is aborted.\n\n## Common Errors\n\n| status_code | Cause | Example message |\n|-------------|-------|-----------------|\n| 2 | Invalid or non-existent id | \"List not found with id 99999\" |\n| 2 | Empty label after trim | \"Label cannot be empty\" |\n| 2 | Invalid version_id in translations | \"Invalid version_id \\\"99\\\" in values[0].translations\" |\n| 2 | Invalid type_id | \"Invalid type_id \\\"999\\\" in values[0].type_ids\" |\n| 2 | AFS syntax error | \"AFS syntax error in values[0].afs: ...\" |\n| 997 | User is not sadmin | \"Not allowed operation\" |\n","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List update response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"Success Response","properties":{"status_code":{"type":"integer","example":1,"description":"Status code (1 = success)"},"status_message":{"type":"string","example":"List updated successfully","description":"Status message"},"result":{"type":"object","properties":{"id":{"type":"integer","example":127,"description":"List ID"},"class_id":{"type":"integer","example":4,"description":"Library ID"},"label":{"type":"string","example":"Colors","description":"Current list label (after update)"},"updated_fields":{"type":"array","items":{"type":"string"},"example":["label"],"description":"List-level fields that were actually modified"},"options_added":{"type":"integer","example":1,"description":"Number of new options created"},"options_updated":{"type":"integer","example":2,"description":"Number of existing options modified"},"options_deleted":{"type":"integer","example":1,"description":"Number of options permanently removed from the list"}},"required":["id","class_id","label","updated_fields","options_added","options_updated","options_deleted"]}},"required":["status_code","status_message","result"]},{"type":"object","title":"Error Response","properties":{"status_code":{"type":"integer","enum":[2,997],"example":2,"description":"Status code (2 = validation error, 997 = insufficient permissions)"},"status_message":{"type":"string","example":"List not found","description":"Error message"},"result":{"type":"array","items":{"type":"object"},"example":[],"description":"Empty array on error"}},"required":["status_code","status_message","result"]}]}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","description":"List value ID to update. Use POST /api/v3/listvalues/list with class_id to get available lists and their IDs.","example":127},"label":{"type":"string","description":"New list label (display name). Maximum 255 characters. Empty strings are not allowed.","example":"Colors"},"values":{"type":"array","description":"Complete and exhaustive array of options for this list. This triggers a full synchronization: options not in this array will be DELETED from the database. Omit this parameter entirely to leave existing options untouched. (Array of objects - see example for structure)","example":[{"id":456,"label":"Rouge","code":"RED","translations":{"2":"Red","3":"Rojo"},"type_ids":[100,102]},{"label":"Vert","code":"GRN","translations":{"2":"Green"}}],"items":{"type":"object","properties":{"id":{"type":"integer","description":"Existing option ID (id_asset). If provided, the option is matched by ID for update. Use POST /api/v3/listvalues/get to retrieve existing option IDs.","example":456},"label":{"type":"string","description":"Display label in the default language.","example":"Rouge"},"code":{"type":"string","description":"Option code. Used as matching key if no `id` is provided. Auto-generated as \"id_<ID>\" if omitted on new options.","example":"RED"},"translations":{"type":"object","description":"Translated labels by version_id. Keys are version IDs (as strings), values are translated labels. Use POST /api/v3/listvalues/full to see available version IDs.","additionalProperties":{"type":"string"},"example":{"2":"Red","3":"Rojo"}},"type_ids":{"type":"array","items":{"type":"integer"},"description":"Asset type IDs to restrict this option to. If omitted on new options, option is available for all types. On update: if provided, types are synchronized (missing types added, extra types removed). If omitted entirely on an existing option, its current type restrictions are left unchanged.","example":[100,102]},"afs":{"type":"string","description":"AFS condition using Smarty/hashtag syntax (e.g. \"#123#\", \"{if #153#}1{/if}\"). Syntax is validated before update.","example":"#123#"}},"required":["label"]}}},"required":["id"]}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token generated with /api/v3/token/get/"}}}}