Sometimes a person needs to write one thing for your site — a guest blog post, a bio, an announcement — but you don't want to create them a StaticOwl account, burn a seat, or hand over admin access. A guest write link is a secret, branded, single-purpose editor URL. You mint it, send it to them, they write in a clean editor (no login), and it stays a draft until you review and publish.
The link is scoped to exactly one page, one content type, and a fixed list of fields — a guest can never touch anything else.
How it works
- You mint a link for a content type (e.g.
post). StaticOwl creates an empty draft and binds a secret token to it — scoped to that one page and an allow-list of editable fields (default:title+body). - You send the link to your guest. It looks like
https://app.staticowl.com/api/public/guest/<token>/editor. - They write. The editor is branded with your site name, logo, and colors. It has a title field and a rich-text body (bold/italic/heading/list/link) plus any other allowed fields. It autosaves as they type. No account, no seat.
- You publish. The draft shows up in your site like any other content. You review it and publish it on your schedule. Nothing the guest wrote goes live on its own.
The token can carry an expiry (ttlDays), and you can revoke it at any time.
Minting a link
Guest-link management is an admin operation on the site.
API
curl -X POST https://app.staticowl.com/api/guest-links \
-H "Authorization: Bearer $STATICOWL_API_KEY" \
-H "X-Site-Id: site:mysite" \
-H "Content-Type: application/json" \
-d '{
"contentType": "post",
"title": "Guest post — draft",
"allowedFields": ["title", "body"],
"ttlDays": 14,
"note": "Jordan's guest article"
}'
Response (the raw token is shown once — keep the editUrl):
{
"editUrl": "https://app.staticowl.com/api/public/guest/Gbly…/editor",
"token": "Gbly…",
"pageId": "post:guest-post-draft",
"record": { "...": "the created draft" }
}
| Field | Required | Meaning |
|---|---|---|
contentType |
yes | The type the draft is created as (must exist on the site). |
title |
no | Starting title for the draft (default "Untitled draft"). |
slug |
no | Key/slug for the draft; derived from the title if omitted. |
allowedFields |
no | Fields the guest may edit. Default ["title","body"]. Intersected with the type's real fields. |
ttlDays |
no | Expiry in days. Omit for no expiry. |
note |
no | A private label to help you remember who the link is for. |
Only fields that actually exist on the content type end up editable — a typo in
allowedFields is dropped, not an error (as long as at least one valid field
remains).
MCP (AI agents)
guest_link_create— mint a link (same arguments as above)guest_links_list— list the site's active guest linksguest_link_revoke— revoke a link by id
These need an admin key on the site.
Managing links
# List active guest links for the site
curl https://app.staticowl.com/api/guest-links \
-H "Authorization: Bearer $STATICOWL_API_KEY" -H "X-Site-Id: site:mysite"
# Revoke one (the link stops working immediately)
curl -X DELETE https://app.staticowl.com/api/guest-links/<id> \
-H "Authorization: Bearer $STATICOWL_API_KEY" -H "X-Site-Id: site:mysite"
A revoked or expired link shows the guest a friendly "this link is no longer active" page rather than an error.
What the guest sees
The editor page (…/guest/<token>/editor) is self-contained and branded from
your site's theme:
- Your site name and logo in the header, your primary/accent colors on buttons and focus states.
- A large title input and a rich-text body with a small toolbar (bold, italic, H2, bullet list, link). Any other allowed field appears as a labeled text input.
- An autosave indicator ("Editing…" → "Saved ✓"). Changes are saved on a short debounce and on leaving the page.
- A footer note making it clear the draft is private until you publish it.
The page is marked noindex, so it won't show up in search engines.
Security model
Guest links are deliberately narrow:
- Scoped to one page. The token binds a single
pageId. A guest save can only ever update that page. - Field allow-list. Only the fields in
allowedFieldsare writable — anything else in a save request is dropped before it reaches storage. - Sanitized rich text. The
bodyHTML is sanitized (script/style/iframe/ form/embed tags, inlineon*handlers, andjavascript:URLs are stripped) on save. You still review before publishing — this is defense in depth. - Draft-only. Guests can't publish, build, change types, upload arbitrary files, or see the rest of your site. Publishing is always an owner action.
- Expirable + revocable. Set
ttlDays, or revoke the moment you're done.
Gotchas & tips
- Treat the link like a password. Anyone who has it can edit that one draft until it expires or you revoke it. Send it over a private channel.
- The raw token is shown once at mint time (in
token/editUrl). If you lose it, revoke and mint a new one. - One link, one page. For a second guest post, mint a second link. This keeps each contributor isolated to their own draft.
- Publishing is on you. The draft won't appear on the live site until you publish it — mint the link early, review whenever it's ready.
- Pre-seeded placeholders. The draft starts with non-empty placeholder values for required fields so it validates; the guest just overwrites them.
See also
- Content modeling & field types — define the content type your guest link targets.
- Publishing & environments — how a draft becomes live.
- Zero to deployed — the 5-minute quickstart.