1. Cache Invalidation

Cache Invalidation

Storyblok uses a Content Delivery Network (CDN) before the API to deliver your content as fast as possible. To have a high cache hit rate for published content, Storyblok appends a parameter called cv, which stands for "cache version." This parameter is an integer that represents a Unix timestamp.

The most up-to-date cv value of a space can be retrieved with an API call excluding the cv parameter:

https://api.storyblok.com/v2/cdn/spaces/me/?token=YOUR_TOKEN

While any API endpoint can be used, it is recommended to use /v2/cdn/spaces/me/ for performance purposes (see Retrieve Current Space for further reference).

The API response will contain a cv value that can be used in subsequent API requests to receive the latest version of the content. In order to handle cache invalidation, the cv value needs to be stored in memory. Furthermore, it needs to be updated when certain criteria are met. For example, Storyblok's webhook events may be used to invalidate the cache whenever content is published, updated, or deleted.

When using one of the official Storyblok SDKs (which are based on the storyblok-js-client), cache invalidation is handled automatically.

Related Resources

Examples

Request
curl "https://api.storyblok.com/v2/cdn/spaces/me?token=wANpEQEsMYGOwLxwXQ76Ggtt" \
  -X GET \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"
Request
// Using the Universal JavaScript Client:
// https://github.com/storyblok/storyblok-js-client
Storyblok.get('cdn/spaces/me', {})
  .then(response => {
    console.log(response)
  }).catch(error => { 
    console.log(error)
  })
Request
$client = new \Storyblok\Client('YOUR_STORYBLOK_SPACE_ACCESS_TOKEN');

$client->get('/spaces/me')->getBody();
Request
require 'storyblok'
client = Storyblok::Client.new(oauth_token: 'YOUR_OAUTH_TOKEN')

client.space()
Request
HttpResponse<String> response = Unirest.get("https://api.storyblok.com/v2/cdn/spaces/me?token=wANpEQEsMYGOwLxwXQ76Ggtt")
  .asString();
Request
var client = new RestClient("https://api.storyblok.com/v2/cdn/spaces/me?token=wANpEQEsMYGOwLxwXQ76Ggtt");
var request = new RestRequest(Method.GET);

IRestResponse response = client.Execute(request);
Request
import Foundation

let request = NSMutableURLRequest(url: NSURL(string: "https://api.storyblok.com/v2/cdn/spaces/me?token=wANpEQEsMYGOwLxwXQ76Ggtt")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.method = "GET"

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
Request
import requests

url = "https://api.storyblok.com/v2/cdn/spaces/me"

querystring = {"token":"wANpEQEsMYGOwLxwXQ76Ggtt"}

payload = ""
headers = {}

response = requests.request("GET", url, data=payload, headers=headers, params=querystring)

print(response.text)
Example Response
{
    "space": {
        "id": 123456,
        "name": "Example Space",
        "domain": "https://storyblok.com/",
        "version": 1706094649
    }
}

Use the cv attribute value as cv parameter for the subsequent requests:

Request
curl "https://api.storyblok.com/v2/cdn/stories?cv=1541863983&token=wANpEQEsMYGOwLxwXQ76Ggtt" \
  -X GET \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"
Request
// Using the Universal JavaScript Client:
// https://github.com/storyblok/storyblok-js-client
Storyblok.get('cdn/stories', {
  "cv": "1541863983"
})
  .then(response => {
    console.log(response)
  }).catch(error => { 
    console.log(error)
  })
Request
$client = new \Storyblok\Client('YOUR_STORYBLOK_SPACE_ACCESS_TOKEN');

$client->getStories([
  "cv" =>  "1541863983"
])->getBody();
Request
require 'storyblok'
client = Storyblok::Client.new(oauth_token: 'YOUR_OAUTH_TOKEN')

client.stories({:params => {
  "cv" =>  "1541863983"
}})
Request
HttpResponse<String> response = Unirest.get("https://api.storyblok.com/v2/cdn/stories?cv=1541863983&token=wANpEQEsMYGOwLxwXQ76Ggtt")
  .asString();
Request
var client = new RestClient("https://api.storyblok.com/v2/cdn/stories?cv=1541863983&token=wANpEQEsMYGOwLxwXQ76Ggtt");
var request = new RestRequest(Method.GET);

IRestResponse response = client.Execute(request);
Request
import Foundation

let request = NSMutableURLRequest(url: NSURL(string: "https://api.storyblok.com/v2/cdn/stories?cv=1541863983&token=wANpEQEsMYGOwLxwXQ76Ggtt")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.method = "GET"

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
Request
import requests

url = "https://api.storyblok.com/v2/cdn/stories"

querystring = {"cv":"1541863983","token":"wANpEQEsMYGOwLxwXQ76Ggtt"}

payload = ""
headers = {}

response = requests.request("GET", url, data=payload, headers=headers, params=querystring)

print(response.text)