Get a theme
GET /themes/{id}
Description
Retrieves a single theme by its id. A theme sets how a gift's invitation
email and landing page look and read: the colors, fonts, and logo, and the
default wording the recipient sees. The response summarizes the look as colors,
a heading font, and a logo, and links to the full theme in the &Open web app.
When to use
Use this endpoint when you hold a theme's id, for example one your user picked
from List themes, and want to refresh its details before you show
it again. To find themes in the first place, or to find the account's default
theme, use List themes.
Parameters
Path
id (string · uuid · required) is the theme to retrieve, a UUID. An id that
matches no theme in your account returns 404, and so does a theme that has
been deleted in &Open since you last listed it.
Headers
AndOpen-API-Version (string · required) is the API version this request
targets. Always send 2026-05. Requests authenticate with a bearer token; see
Authentication for how to present it and
Environments for the regional base URL to send it to.
Worked examples
The cURL version is the raw HTTP call; the JavaScript, Python, and Ruby versions
are idiomatic equivalents. Replace the path id with the theme you want.
- cURL
- JavaScript
- Python
- Ruby
curl -X GET "https://api.andopen.co/themes/7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "Authorization: Bearer <api_key>" \
-H "AndOpen-API-Version: 2026-05"
const themeId = "7c9e6679-7425-40de-944b-e07fc1f90ae7";
const response = await fetch(`https://api.andopen.co/themes/${themeId}`, {
headers: {
Authorization: "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const theme = await response.json();
console.log(theme.name, theme.appearance.background_color, theme.owner?.name);
import requests
theme_id = "7c9e6679-7425-40de-944b-e07fc1f90ae7"
response = requests.get(
f"https://api.andopen.co/themes/{theme_id}",
headers={
"Authorization": "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
)
response.raise_for_status()
theme = response.json()
owner = theme["owner"]
print(
theme["name"],
theme["appearance"]["background_color"],
owner["name"] if owner else None,
)
require "net/http"
require "json"
theme_id = "7c9e6679-7425-40de-944b-e07fc1f90ae7"
uri = URI("https://api.andopen.co/themes/#{theme_id}")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer <api_key>"
request["AndOpen-API-Version"] = "2026-05"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(request)
end
response.value # raises on a non-2xx response
theme = JSON.parse(response.body)
puts "#{theme['name']} #{theme.dig('appearance', 'background_color')} #{theme.dig('owner', 'name')}"
Response shape
A successful call returns 200 OK with the theme as a flat top-level JSON
object.
| Field | Description |
|---|---|
name (string · required) | The theme's display name, as your users see it in &Open. |
default (boolean · required) | Whether this is the account's default theme. A gift request sent without a campaign uses the default theme. |
appearance (object · required) | A summary of the landing page's look: appearance.background_color (string · required · nullable), appearance.text_color (string · required · nullable), appearance.button_background_color (string · required · nullable), appearance.button_text_color (string · required · nullable), appearance.heading_font_family (string · required · nullable), and appearance.logo_url (string · uri · required · nullable). |
owner (object · required · nullable) | The user who created the theme, embedded as an { id, name, email } summary, or null. Read their team and budget with Get a user. |
web_url (string · uri · required) | The theme editor in the &Open web app, on your organization's own domain, where the theme is previewed in full and edited. |
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Acme Classic",
"default": true,
"appearance": {
"background_color": "#FCF8F2",
"text_color": "#000000",
"button_background_color": "#000000",
"button_text_color": "#FCF8F2",
"heading_font_family": "Playfair Display, serif",
"logo_url": "https://files.andopen.co/rndd63mwgj94j2vf3v2ngnye0hkn"
},
"owner": {
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"name": "Dana Okafor",
"email": "dana@acme.example"
},
"web_url": "https://acme.andopen.co/sender/themes/42",
"created_at": "2026-04-16T10:30:00.000Z",
"updated_at": "2026-04-16T10:30:00.000Z"
}
Per-field notes
- Each
appearancevalue isnullwhen the theme doesn't set it. Fall back to your own default rather than treatingnullas a color. - Colors are CSS color values, such as
#FCF8F2or#fff, and drop straight into a style rule. heading_font_familyis usually one family name with no fallback, such asLexend Deca, and often a brand font your page hasn't loaded. Load the font and add a generic family such assans-serif, or the browser shows its default font instead.appearanceis a summary for a swatch or picker, not a full preview. To see the theme as a recipient would, openweb_url.web_urlopens only for a signed-in administrator on an account with the branding tool turned on; anyone else is redirected. Show it to admins, not to every user.ownerisnullwhen the creator isn't recorded or is no longer a user.- The theme is read-only here. This endpoint has no write counterpart in
2026-05; themes are created and edited in &Open.
Error cases
Every failure uses the shared error model: a top-level errors array of
objects carrying type, code, message, and (for field-level problems)
param. See Errors for the full type/code taxonomy and how
to handle each category; the codes below are the ones this endpoint produces.
| Status | Meaning |
|---|---|
| 400 | The request is malformed or violates a precondition. Typical triggers are a missing or unsupported `AndOpen-API-Version` header, a request body that is not valid JSON, or pagination parameters that fail server-side validation (`limit` non-numeric or non-positive, `after` referencing a record that does not exist). |
| 401 | Authentication failed: missing or invalid bearer token. |
| 403 | Authorized but not permitted to access this resource. |
| 404 | The requested resource does not exist. |
| 429 | Too many requests. Rate limit exceeded. |
| 500 | Internal server error. |
| 503 | Service unavailable. The account may be under maintenance. Check the `Retry-After` header. |
Every error carries a type, one of: validation_error, authentication_error, authorization_error, not_found_error, rate_limit_error, api_error.
A read takes no body, so there's nothing to validate. The failure you'll handle most is a missing theme:
404 not_found_error: no theme with thatidexists in your account (not_found). A theme deleted in &Open lands here.400 api_error:unsupported_api_versionwhen theAndOpen-API-Versionheader is missing or unsupported (returned before authentication).401 authentication_error: the bearer token is missing, invalid, or expired (unauthorized).403 authorization_error: the token is valid but not permitted to read themes (forbidden).429 rate_limit_error: too many requests; back off and retry (rate_limited). TheRateLimit-*response headers tell you the budget and reset time.500/503 api_error: a fault on our side; rare, and safe to retry after a short delay (honorRetry-Afteron a503).