Embed the content editor
The content editor can run inside your own app, so your customers change their logo, colours and wording themselves. Each customer edits one content set of a template and sees the pages as they type. They need no Typefold account: your server makes an embed token for them, and your page shows the editor that token opens.
- A developer marks the template’s content fields and publishes it. Each of your customers gets a content set of that template.
- When a customer opens the editor in your app, your server makes an embed token for their set with an API key.
- Your page frames the editor at the token’s
url. - The customer edits the fields and clicks Save. Renders that name the set use the new values at once.
The editor shows the template’s published version. Fields that only the draft has are not shown, and their values in the set are kept.
1. Allow your site
Section titled “1. Allow your site”In Studio, open Settings → Embedding and list the origins of the pages that show the editor
under Allowed sites, one per line, such as https://app.example.com.
https://*.example.com allows every subdomain. http://localhost and http://127.0.0.1 are
allowed for development. No other site can frame the editor, and no embed token can be made
until a site is listed.
Under Style, match the editor to your app. The preview beside the settings shows the editor inside your site with the style as you change it. To check the real editor, pick a published template and a content set under Try the real editor and open it: it opens in a new tab with the saved sites and style, and what you save there changes that content set.
| Setting | What it changes |
|---|---|
| Colour mode | Light, dark, or as the viewer’s device. |
| Accent | Buttons, links and the outline of the parts that can be changed. |
| Background | The page behind the editor. |
| Font | Figtree (the default), the viewer’s system font, a serif or a monospace font. |
| Corner radius | Of buttons, inputs and panels, 0 to 24 pixels. |
Only owners and administrators can change these settings. An API key with template:read can
read them with GET /v1/workspace/embedding.
2. Make an embed token on your server
Section titled “2. Make an embed token on your server”Create an API key under Manage → API keys with the permissions template:read,
template:content and render:create, and keep it on your server. Each time a customer opens the
editor, make a token for their content set:
curl "$PDF_URL/v1/embed-tokens" \ -H "x-api-key: $API_KEY" \ -H "content-type: application/json" \ --fail-with-body \ -d '{ "templateId": "'"$TEMPLATE_ID"'", "contentSetId": "'"$CONTENT_SET_ID"'", "expiresInMinutes": 30, "label": "customer-42" }'using Typefold.Client;
var client = new TypefoldClient( new Uri(Environment.GetEnvironmentVariable("PDF_URL")!), Environment.GetEnvironmentVariable("API_KEY")!);
var embed = await client.CreateEmbedTokenAsync(new CreateEmbedTokenRequest{ TemplateId = Environment.GetEnvironmentVariable("TEMPLATE_ID")!, ContentSetId = Environment.GetEnvironmentVariable("CONTENT_SET_ID")!, ExpiresInMinutes = 30, Label = "customer-42",});
// Send embed.Url to your page.Console.WriteLine(embed.Url);import { TypefoldClient } from "@typefold/client";
const client = new TypefoldClient({ baseUrl: process.env.PDF_URL!, apiKey: process.env.API_KEY!,});
const embed = await client.createEmbedToken({ templateId: process.env.TEMPLATE_ID!, contentSetId: process.env.CONTENT_SET_ID!, expiresInMinutes: 30, label: "customer-42",});
// Send embed.url to your page.console.log(embed.url);import { TypefoldClient } from "@typefold/client";
const client = new TypefoldClient({ baseUrl: process.env.PDF_URL, apiKey: process.env.API_KEY,});
const embed = await client.createEmbedToken({ templateId: process.env.TEMPLATE_ID, contentSetId: process.env.CONTENT_SET_ID, expiresInMinutes: 30, label: "customer-42",});
// Send embed.url to your page.console.log(embed.url);import os
from typefold import CreateEmbedTokenRequest, TypefoldClient
client = TypefoldClient(os.environ["PDF_URL"], os.environ["API_KEY"])
embed = client.create_embed_token( CreateEmbedTokenRequest( template_id=os.environ["TEMPLATE_ID"], content_set_id=os.environ["CONTENT_SET_ID"], expires_in_minutes=30, label="customer-42", ))
# Send embed.url to your page.print(embed.url)| Field | What it does |
|---|---|
templateId |
Required. A published template with content fields. Spreadsheet templates are not supported. |
contentSetId |
Required. The content set the customer edits. |
actions |
What the customer may do: save and uploadImages. Both when left out; without save the editor only shows the pages. |
expiresInMinutes |
How long the token works, 5 to 1,440 minutes. 60 when left out. |
label |
Who the token is for, such as your own customer ID, kept on the audit log. |
The answer is 201 with the token’s id, expiresAt, the secret token and the url your
page opens. The secret is returned only here; Typefold keeps only its hash. Make a new token each
time the editor opens rather than storing one.
A workspace with no allowed site, or a template without content fields or not yet published,
answers 400 BAD_REQUEST. A workspace without the visual editor answers 403 FORBIDDEN.
3. Show the editor on your page
Section titled “3. Show the editor on your page”Load /embed.js from your Typefold address and pass it the token’s url:
<div id="content-editor"></div><script src="https://app.typefold.dev/embed.js"></script><script> const editor = Typefold.embed({ url: embedUrl, // embed.url from your server container: "#content-editor", height: "760px", onSaved: ({ revision }) => console.log("Saved revision", revision), onClosed: () => editor.destroy(), onError: ({ code, message }) => console.warn(code, message), });</script>On a self-hosted installation, load it from your own installation’s address instead.
| Option | What it does |
|---|---|
url |
Required. The token’s url. |
container |
Required. The element the editor goes in, or a CSS selector for it. |
height |
The frame’s height, such as "760px". 720px when left out. |
title |
The frame’s title for screen readers. Content editor when left out. |
onReady |
Called once the editor has connected to your page. |
onSaved |
Called after each save with { revision, values }: the set’s new revision and values. |
onClosed |
Called when the customer clicks Close. |
onError |
Called with { code, message } when something fails. |
Typefold.embed returns { frame, destroy }: the <iframe> element, and a function that
removes it. The editor talks only to a page on an allowed site, and /embed.js listens only to
its own frame.
onError code |
Meaning |
|---|---|
session_ended |
The token expired or was revoked. Make a new token and open the editor again. |
conflict |
The set was saved elsewhere since the editor opened. The editor offers to load the latest values. |
save_failed |
The save was refused, such as a value that does not fit its field. |
Revoke a token
Section titled “Revoke a token”A token stops working when it expires, when you revoke it, when the API key that made it is disabled or deleted, when the member who made it leaves the workspace, and when its content set is deleted. Revoke one early, such as when the customer signs out:
curl -X POST "$PDF_URL/v1/embed-tokens/$EMBED_TOKEN_ID/revoke" \ -H "x-api-key: $API_KEY" \ --fail-with-bodyusing Typefold.Client;
var client = new TypefoldClient( new Uri(Environment.GetEnvironmentVariable("PDF_URL")!), Environment.GetEnvironmentVariable("API_KEY")!);
await client.RevokeEmbedTokenAsync(Environment.GetEnvironmentVariable("EMBED_TOKEN_ID")!);import { TypefoldClient } from "@typefold/client";
const client = new TypefoldClient({ baseUrl: process.env.PDF_URL!, apiKey: process.env.API_KEY!,});
await client.revokeEmbedToken(process.env.EMBED_TOKEN_ID!);import { TypefoldClient } from "@typefold/client";
const client = new TypefoldClient({ baseUrl: process.env.PDF_URL, apiKey: process.env.API_KEY,});
await client.revokeEmbedToken(process.env.EMBED_TOKEN_ID);import os
from typefold import TypefoldClient
client = TypefoldClient(os.environ["PDF_URL"], os.environ["API_KEY"])
client.revoke_embed_token(os.environ["EMBED_TOKEN_ID"])Revoking needs template:content. The open editor shows that the session has ended.
What a token allows
Section titled “What a token allows”- One content set of one template: reading its fields and values, showing its pages, and, with the token’s actions, saving the set and uploading images for its image fields. It cannot publish, read other templates or sets, or render documents.
- Never more than the API key or member that made it may do. Narrowing the key’s permissions narrows its tokens at once.
- The secret travels in the address’s
#part, which browsers do not send to servers, and the editor removes it from the address bar once loaded. - Each token may make 120 previews a minute and upload 20 images.
Making and revoking tokens and changing the embedding settings are recorded in the
audit log as embed_token.created, embed_token.revoked
and workspace.embed_settings_updated. A customer’s saves are recorded as
template.content_set_updated, as made by the key or member that made the token.