Skip to main content
[StoryblokStoryID:245122182]

Live article: https://www.storyblok.com/faq/link-object-history


  • FAQ
  • Link object history

Since the start of Storyblok we've increased the features over the last 4 years in a non breaking behavior where the beginning of that type was an object where the linktype (since the plan was to have different types - external, internal, asset, ...) be determined by the linktype attribute.

After receiving feature request to do auto-resolving on our side to remove that step we added that feature flag resolve_links about 1,5 years ago and 1 year ago we added additional options to also remove to necessity of the Links API: https://www.storyblok.com/cl/url-resolving by allow url and story as parameter.

"link": {
    "id": "e4733f3c-6f9e-400b-a4b4-ab30753c2ed4", // internal UUID to the linked Story
    "url": "", // empty because no external URL was set in the UI
    "linktype": "story", // tells you to use the UUID + Links API or the cached_url
    "fieldtype": "multilink"
}

Since than the property cached_url was added which will be set during publishing, which already allows to not need the Links API.

"link": {
    "id": "e4733f3c-6f9e-400b-a4b4-ab30753c2ed4", // internal UUID to the linked Story
    "url": "", // empty because no external URL was set in the UI
    "linktype": "story", // tells you to use the UUID + Links API or the cached_url
    "fieldtype": "multilink", 
    "cached_url": "home" // cached full_slug of the linked Story
}
"link": {
    "id": "", // internal UUID to the linked Story but empty since not used 
    "url": "this-is-my-external-url", // String entered in the UI
    "linktype": "url", // tells you to use the url since linktype is url
    "fieldtype": "multilink", 
    "cached_url": "this-is-my-external-url" // latest cached_url
}

Since the cached_url was only updated during publishing of the entry that contains the link but not when the referenced story was changed we've introduced a feature flag resolve_links to auto-update the cached_url property and added the story property inside the Links object. The links object now allows you to access the linked Story and all its content.

"link": {
    "id": "dfbeffc6-3523-4325-805b-ba8850d07b6a", // internal UUID to the linked Story but empty since not used 
    "url": "", // String entered in the UI
    "linktype": "story", // tells you if the url or story should be used.
    "fieldtype": "multilink",
    "cached_url": "new-name", // latest cached url
    "story": {
        "name": "New name",
        "created_at": "2020-06-17T13:46:05.057Z",
        "published_at": null,
        "alternates": [
        
        ],
        "id": 13629228,
        "uuid": "dfbeffc6-3523-4325-805b-ba8850d07b6a",
        "content": {
        "_uid": "aa19cab9-0e24-4dcc-af8f-7cf667795e34",
        "component": "Post"
        },
        "slug": "new-name",
        "full_slug": "new-name",
        "default_full_slug": null,
        "sort_by_date": null,
        "position": -10,
        "tag_list": [
        
        ],
        "is_startpage": false,
        "parent_id": 0,
        "meta_data": null,
        "group_id": "830b87b9-447c-4c11-ae46-5a436bde1836",
        "first_published_at": null,
        "release_id": null,
        "lang": "default",
        "path": null,
        "translated_slugs": [
        
        ]
    }
}

Feature resolve_links=url and resolve_links=story was added

To reduce payload for those that only need links and not the full entry we've later on (1,5 years ago) published a variation of that feature using resolve_links=story (same behavior as the old resolve_links=1) and resolve_links=url to only receive a subset of fields:

"link": {
    "id": "dfbeffc6-3523-4325-805b-ba8850d07b6a", // internal UUID to the linked Story but empty since not used 
    "url": "", // String entered in the UI
    "linktype": "story", // tells you if the url or story should be used.
    "fieldtype": "multilink",
    "cached_url": "new-name", // latest cached url
    "story": {
        "name": "New name",
        "id": 13629228,
        "uuid": "dfbeffc6-3523-4325-805b-ba8850d07b6a",
        "slug": "new-name",
        "full_slug": "new-name",
        "url": "new-name" // <-- URL that can be used for links and will always stay up2date
    }
}
new StoryblokClient({
    accessToken: YOUR_PREVIEW_TOKEN,
    cache: {
      clear: "auto",
      type: "memory",
    },
  })
    .get(`cdn/stories/`, {
      version: "draft",
      resolve_links: "link", // can also be 'url' or 'story'
    })
    .then((res) => {
      console.log(res);
    })
    .catch((error) => {
      console.log(error);
    });
{
  "links": [
    {
      "id": 112813635,
      "uuid": "e75b6fdd-d961-4fe0-9f53-d265d8fe3b13",
      "slug": "about",
      "path": null,
      "parent_id": 0,
      "name": "About",
      "is_folder": false,
      "published": false,
      "is_startpage": false,
      "position": -10,
      "real_path": "/about"
    }
  ]
}

resolve_links=story

{
  "links": [
    {
      "name": "About",
      "created_at": "2022-03-03T14:39:15.492Z",
      "published_at": null,
      "id": 112813635,
      "uuid": "e75b6fdd-d961-4fe0-9f53-d265d8fe3b13",
      "content": {
      "_uid": "4ace00f1-85b2-4e03-b601-9f7a6641cfe8",
      "component": "page",
      "_editable": "<!--#storyblok#{\"name\": \"page\", \"space\": \"149145\", \"uid\": \"4ace00f1-85b2-4e03-b601-9f7a6641cfe8\", \"id\": \"112813635\"}-->"
      },
      "slug": "about",
      "full_slug": "about",
      "sort_by_date": null,
      "position": -10,
      "tag_list": [],
      "is_startpage": false,
      "parent_id": 0,
      "meta_data": null,
      "group_id": "c7058377-0f8e-47ab-a2d7-eeaa4a8bc858",
      "first_published_at": null,
      "release_id": null,
      "lang": "default",
      "path": null,
      "alternates": [],
      "default_full_slug": "about",
      "translated_slugs": []
    }
  ]
}
"links": [
  {
    "name": "About",
    "id": 112813635,
    "uuid": "e75b6fdd-d961-4fe0-9f53-d265d8fe3b13",
    "slug": "about",
    "url": "about",
    "full_slug": "about"
  }
]