Get lookbook details by slug
Retrieve a single published lookbook by its URL slug, including its images and the products featured in each. Read-only; accepts both publishable (tybrite_pk_*) and secret (tybrite_sk_*) API keys. Returns 404 if no published lookbook matches the slug.
curl --request GET \
--url https://api.tybritelabs.com/v1/lookbooks/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.tybritelabs.com/v1/lookbooks/{slug}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.tybritelabs.com/v1/lookbooks/{slug}', 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.tybritelabs.com/v1/lookbooks/{slug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.tybritelabs.com/v1/lookbooks/{slug}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.tybritelabs.com/v1/lookbooks/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/lookbooks/{slug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "2a78a917-656f-4826-9968-86a2de64cfb9",
"title": "Workspace Essentials",
"slug": "workspace-essentials",
"description": "A shoppable edit of desk upgrades for a calmer, more productive day.",
"featured_image": "https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
"video": null,
"collection_id": null,
"published_at": "2026-06-19T11:00:52.880415+00:00",
"images": [
{
"url": "https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
"hotspots": []
},
{
"url": "https://images.unsplash.com/photo-1513506003901-1e6a229e2d15?w=1200&q=80",
"hotspots": []
}
]
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}{
"error": {
"code": "server_error",
"message": "An unexpected error occurred"
}
}Authorizations
API Key Authentication
Use your API key in the Authorization header:
Authorization: Bearer tybrite_sk_live_YOUR_KEY
Key Types:
Secret Keys (Server-Side Only):
- Format:
tybrite_sk_live_*(production) ortybrite_sk_test_*(sandbox) - Full read/write access to all endpoints
- ⚠️ NEVER expose in client-side code or public repositories
- Required for: every write a shopper does not make for themselves, authentication, payment verification, AI recommendations
Publishable Keys (Client-Safe):
- Format:
tybrite_pk_live_*(production) ortybrite_pk_test_*(sandbox) - Catalogue reads, plus the actions a shopper takes for themselves
- ✅ Safe for client-side JavaScript, mobile apps, and public code
- Allowed for: browsing products, search, CMS content, pricing queries, cart and wishlist, reviews, storefront events, and the Agent API's quotes, cart drafts and checkout intents
Endpoint-Specific Requirements:
- Authentication endpoints (
/v1/auth/*): Secret key required - Payment verification (
POST /v1/payments/verify): Secret key required - AI Recommendations (
POST /v1/recommendations): Secret key required - Semantic Search (
POST /v1/search): Both key types allowed (read-only operation) - Shopper actions (cart, wishlist, reviews, storefront events, Agent API quotes, cart drafts and checkout intents): Both key types allowed
- All other write operations: Secret key required
- All read operations: Both key types allowed
Using a publishable key for restricted operations returns 403 Forbidden.
Headers
Header form of visitor_id. Takes precedence over the query parameter when both are sent.
Header form of session_id. Takes precedence over the query parameter when both are sent.
Path Parameters
Query Parameters
Comma-separated list of fields to include in the response.
Allowed Fields:
id,title,slug,description,featured_image,videocollection_id,published_at,created_at,images
Identifies the shopper viewing the lookbook, so the view is attributed to them in your content analytics. Send the same value you use for other storefront analytics calls. When omitted, the view is attributed to a coarse fallback derived from the request, so repeat views by one shopper may not group together.
The x-visitor-id header carries the same value and takes precedence.
Groups this view into a browsing session. When omitted, a session is derived from the visitor identity.
The x-session-id header carries the same value and takes precedence.
Response
Success
Optional URL of a short video for this banner (MP4, H.264 with AAC audio). Null when none is set. featured_image stays the poster and the fallback, so a storefront that shows only images keeps working unchanged.
Publication status. Only published lookbooks are returned by the public API. Returned by the list; the single-lookbook response omits it.
published, draft The product collection this lookbook is backed by, or null if it is standalone.
When the lookbook was first created.
When the lookbook was last edited, in any way and by anyone. Use it to show a "last updated"
date; it is always set, and on a lookbook that has never been revised it matches
created_at.
Ordered gallery images. Each image may carry shoppable hotspots.
Show child attributes
Show child attributes
curl --request GET \
--url https://api.tybritelabs.com/v1/lookbooks/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.tybritelabs.com/v1/lookbooks/{slug}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.tybritelabs.com/v1/lookbooks/{slug}', 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.tybritelabs.com/v1/lookbooks/{slug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.tybritelabs.com/v1/lookbooks/{slug}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.tybritelabs.com/v1/lookbooks/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/lookbooks/{slug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "2a78a917-656f-4826-9968-86a2de64cfb9",
"title": "Workspace Essentials",
"slug": "workspace-essentials",
"description": "A shoppable edit of desk upgrades for a calmer, more productive day.",
"featured_image": "https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
"video": null,
"collection_id": null,
"published_at": "2026-06-19T11:00:52.880415+00:00",
"images": [
{
"url": "https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
"hotspots": []
},
{
"url": "https://images.unsplash.com/photo-1513506003901-1e6a229e2d15?w=1200&q=80",
"hotspots": []
}
]
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"details": "The 'email' field is required"
}
}{
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header"
}
}{
"error": {
"code": "not_found",
"message": "Resource not found"
}
}{
"error": {
"code": "rate_limited",
"message": "Too many requests for this API key. Please slow down and try again shortly.",
"remaining": 0,
"reset": 1706198400
}
}{
"error": {
"code": "server_error",
"message": "An unexpected error occurred"
}
}
