#How to get families, family variants, and attributes

Use case:
App Workflow
PIM Features:
REST API endpoint(s):
family family variants attributes
If you're starting to build your App, make sure you previously followed:


Families and attributes are the basis of an Akeneo catalog structure: get them before retrieving the products from the PIM.

If you plan to get product variants and their corresponding models, we advise you to retrieve now the associated family variants.

relationship schema

Get the big picture here.

#Fetch the catalog structure: families and attributes


relationship schema

#0 - Initialization

    $pimUrl = 'https://url-of-your-pim.com';
    $appToken = 'your_app_token'; // Token provided during oAuth steps
    // If you haven't done it yet, please follow the Guzzle official documentation for installing the client 
    // https://docs.guzzlephp.org/en/stable/overview.html#installation
    // Set your client for querying Akeneo API as follows
    $client = new \GuzzleHttp\Client([
        'base_uri' => $pimUrl,
        'headers' => ['Authorization' => 'Bearer ' . $appToken],

#1 - Collect families and attribute codes

Get families and attribute codes by requesting the PIM API

    const API_URL = '/api/rest/v1/families?search={"has_products":[{"operator":"=","value":true}]}';
    // Make an authenticated call to the API
    $response = $client->get(API_URL);
    $data = json_decode($response->getBody()->getContents(), true);
    // Collect families and list of unique attribute codes from paginated API
    $families = $data['_embedded']['items'];
    $attributeCodes = array_merge(...array_column($data['_embedded']['items'], 'attributes'));
    while (array_key_exists('next', $data['_links'])) {
        $response = $client->get($data['_links']['next']['href']);
        $data = json_decode($response->getBody()->getContents(), true);
        $families = array_merge($families, $data['_embedded']['items']);
        $attributeCodes = array_merge(
            ...array_column($data['_embedded']['items'], 'attributes')
    $attributeCodes = array_unique($attributeCodes);
    // Save families and attribute codes into stores

Store family codes in a family_code_list and attribute codes in a separate list (attribute_code_list). We will deal with attribute_code_list later in this tutorial.

Warning! with the API call GET api/rest/v1/families, you will collect all the families into the database! Please ask yourself this question before continuing: Do I really need all of them? At this step, it’s the perfect occasion to save time later, during products synchronization. We strongly advise you to filter your families as much as you can before building family_code_list and attribute_code_list.
👉 One way to do this is the family codes filter

#2 - Collect family variants

This step is mandatory if you want to synchronize product variants later. If not, jump to the third step.

Get family variants by requesting the PIM API for each families

    const MAX_ITEMS = 100;
    const API_URL = '/api/rest/v1/families/%s/variants?limit=' . MAX_ITEMS;
    // Get family codes from storage
    $codes = getFamilyCodes();
    // Collect family variants from paginated API
    $variants = [];
    foreach ($codes as $code) {
        $response = $client->get(sprintf(API_URL, $code));
        $data = json_decode($response->getBody()->getContents(), true);
        $variants = array_merge($variants, $data['_embedded']['items']);
    // Save variants into storage

#3 - Collect attributes

Remember your attribute_code_list? It’s (already) time to use it to retrieve attribute information

    const MAX_ITEMS = 100;
    const API_URL = '/api/rest/v1/attributes?search={"code":[{"operator":"IN","value":%s}]}&limit=' . MAX_ITEMS;
    // Get attributes codes from storage
    $attributeCodes = getAttributesCodes();
    // Collect attributes from paginated API
    $rawAttributes = [];
    foreach (array_chunk($attributeCodes, MAX_ITEMS) as $chunk) {
        $response = $client->get(sprintf(API_URL, json_encode($chunk)));
        $data = json_decode($response->getBody()->getContents(), true);
        $rawAttributes = array_merge($rawAttributes, $data['_embedded']['items']);
    // Only keep fields needed
    $attributes = [];
    foreach ($rawAttributes as $rawAttribute) {
        $attributes[$rawAttribute['code']] = [
            'code' => $rawAttribute['code'],
            'type' => $rawAttribute['type'],
            // Add additional fields if needed
    // save attributes into storage

attribute_code_list may be significant, very big! If you get an HTTP 414 error , you probably hit these boundaries. A workaround is to split your attribute_code_list into different parts and call them independently.