curl --request POST \
--url https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore', 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.usertour.io/v2/projects/{projectId}/themes/{id}/restore",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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.usertour.io/v2/projects/{projectId}/themes/{id}/restore"
req, _ := http.NewRequest("POST", 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.post("https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "theme",
"name": "<string>",
"isDefault": true,
"isSystem": true,
"updatedAt": "2023-11-07T05:31:56Z",
"createdAt": "2023-11-07T05:31:56Z",
"variationCount": 0,
"settings": {},
"resolvedSettings": {},
"variations": [
{
"id": "<string>",
"name": "<string>",
"conditions": [
{
"type": "group",
"match": "all",
"conditions": "<array>"
}
],
"settings": {}
}
]
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}Restore a deleted theme
Bring a soft-deleted theme back as it was (find it via GET /themes?deleted=true). It returns as a non-default theme. Refused (E1046) while its variation conditions use deleted attributes or segments — restore those first. Idempotent on a theme that is not deleted.
curl --request POST \
--url https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore', 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.usertour.io/v2/projects/{projectId}/themes/{id}/restore",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
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.usertour.io/v2/projects/{projectId}/themes/{id}/restore"
req, _ := http.NewRequest("POST", 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.post("https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usertour.io/v2/projects/{projectId}/themes/{id}/restore")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "theme",
"name": "<string>",
"isDefault": true,
"isSystem": true,
"updatedAt": "2023-11-07T05:31:56Z",
"createdAt": "2023-11-07T05:31:56Z",
"variationCount": 0,
"settings": {},
"resolvedSettings": {},
"variations": [
{
"id": "<string>",
"name": "<string>",
"conditions": [
{
"type": "group",
"match": "all",
"conditions": "<array>"
}
],
"settings": {}
}
]
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"issues": [
{
"rule": "<string>",
"message": "<string>",
"path": "<string>"
}
],
"doc_url": "<string>"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Response
Restored theme
theme Built-in theme: read-only — it cannot be updated or deleted (duplicating it into your own theme is the way to start from it). It CAN be made the project default.
How many conditional variations this theme carries (always present, no expand needed). Check it BEFORE pointing content at another theme: variations do NOT travel with the content, so moving from a theme with variations to one with 0 silently drops the conditional styling (e.g. dark mode) for every user those conditions targeted — nothing errors. Read the variations themselves with expand: ["variations"].
-9007199254740991 <= x <= 9007199254740991Stored style INTENT — the same shape as the create/update settings body (that write schema is the field dictionary); Auto-capable colors read back as the literal "Auto".
Show child attributes
Show child attributes
Read-only render resolution of settings (the shared derivation the SDK runs). Two transformations: every "Auto" is replaced by the concrete derived color, and font.fontFamily is rewritten to the real font stack ("System font" → the system stack, "Custom font" → the customFontFamily value, named fonts gain a sans-serif fallback). Same field set as settings (stored settings are grounded complete at write) — differences between the two are exactly these derivations, so diff against the settings you wrote, not this, to find your edits. Request with expand: ["resolvedSettings"]. Not writable — author intent in settings.
Show child attributes
Show child attributes
Show child attributes
Show child attributes