curl --request GET \
--url https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-previewimport requests
url = "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": {
"slug": "<string>",
"page_type": "<string>",
"title_i18n": {},
"meta_title_i18n": {},
"meta_description_i18n": {},
"version_no": 123,
"blocks": [
{}
]
},
"meta": {
"page": 123,
"page_size": 123,
"total": 123,
"total_pages": 123
},
"error": "<string>",
"error_code": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Public Draft Preview
Storefront LIVE-PREVIEW read (F2): return a page’s DRAFT block-tree — the unpublished, in-progress version — gated ONLY by a signed preview token.
No auth header: the token IS the credential. Two INDEPENDENT authorities guard it, so forgetting one still can’t leak another tenant’s draft:
- the signed token — bad signature / expiry / wrong type → 403; its
tenant_idmust equal the host-resolved tenant (anti-replay across stores) and itsslugmust equal the path; - Postgres RLS — the tenant GUC is set from the resolved tenant, so
_load_pagephysically cannot see another tenant’s page row.
Serves the OPEN draft when present, else falls back to the PUBLISHED version
(right after a publish the draft is promoted to published, leaving no open
draft — the composer iframe must still show the page); 404 only when neither
exists. Response is marked no-store so it never lands in a shared/CDN
cache. Publishes nothing, mutates nothing.
curl --request GET \
--url https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-previewimport requests
url = "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vellaro.io/api/v1/cms/pages/{slug}/draft-preview")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": {
"slug": "<string>",
"page_type": "<string>",
"title_i18n": {},
"meta_title_i18n": {},
"meta_description_i18n": {},
"version_no": 123,
"blocks": [
{}
]
},
"meta": {
"page": 123,
"page_size": 123,
"total": 123,
"total_pages": 123
},
"error": "<string>",
"error_code": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Parametri del percorso
Parametri della query
Risposta
Successful Response
Public (storefront) view — the published block-tree + SEO metadata.
Reused verbatim by the draft-preview endpoint (F2): same envelope, but the
blocks/version_no come from the DRAFT version instead of the
published one, so the composer iframe renders exactly what publishing would.
Show child attributes
Show child attributes
Show child attributes
Show child attributes