Browse API docs

Website

These endpoints read and change what the website area of the dashboard edits: pages made of blocks, blog posts, the menu and the old website’s addresses. Pages and posts start as drafts; nothing is public until you publish it.

Reading requires a token with Read or Read + Write permission; everything else requires Read + Write. The website belongs to the account, so personal co-organizer tokens can’t use these endpoints. See Authentication.

Pages and posts are addressed by their slug, the last part of their address (/ueber-uns, /blog/silvester). The home page is a page of blocks too, addressed as home.

Pages

GET /admin/website/pages

curl \
  -H "Authorization: Bearer your-token-here" \
  -H "Accept: application/json" \
  https://app.usetix.io/admin/website/pages

Response

{
  "pages": [
    {
      "id": 12,
      "slug": "ueber-uns",
      "home": false,
      "title": "Über uns",
      "intro": "Seit 2019 in Gießen.",
      "description": null,
      "status": "published",
      "published_at": "2026-10-27T09:12:00Z",
      "url": "https://club-shop.usetix.io/ueber-uns",
      "cover_image_url": "https://app.usetix.io/rails/active_storage/blobs/…/cover.jpg",
      "blocks": [
        {
          "id": 31,
          "kind": "faq",
          "position": 1,
          "shown": true,
          "heading": "Fragen",
          "items": [ { "question": "Gibt es eine Garderobe?", "answer": "Ja, für 2 €." } ],
          "body": null,
          "section_id": null,
          "image_url": null,
          "gallery_image_urls": []
        }
      ],
      "created_at": "2026-10-27T09:00:00Z",
      "updated_at": "2026-10-27T09:12:00Z"
    }
  ]
}

The list starts with the home page (home: true, slug home), then the other pages in the order they were made. id is what a menu entry for the page takes (menu_item[page_id]). status is draft or published; url is set once the page is published, and the home page is always online at your shop’s address. Every block also carries caption, width, image_side, button_label, button_url, source, limit, event_ids, video_url, embed_url, code, text, author and venue_id (null where its kind doesn’t use them). shown says whether the block has what it shows: a picture block without a picture stays off the page.

GET /admin/website/pages/:slug

Returns one page in the same shape; GET /admin/website/pages/home returns the home page.

POST /admin/website/pages

Creates a draft page. Send page[title] and optionally page[slug], page[intro] and page[description] (for search engines). Without a slug, the address comes from the title (Über uns becomes ueber-uns). Addresses the shop uses itself, such as blog or events, are taken.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"page": {"title": "Über uns", "intro": "Seit 2019 in Gießen."}}' \
  https://app.usetix.io/admin/website/pages

Returns 201 Created with the page and a Location header.

Instead of a title, send template to start from a template filled with your shop’s details: about (your about text, cover, gallery and next events), directions (the venues of your next events), contact, faq (your questions) or blank.

PATCH /admin/website/pages/:slug

Changes title, slug, intro or description.

DELETE /admin/website/pages/:slug

Deletes the page with its blocks. Returns 204 No Content.

POST /admin/website/pages/:slug/publication and DELETE

POST puts the page online and into the menu; send in_menu=0 to leave it out of the menu. DELETE takes it offline. Both return the page.

The home page is always online and can’t be changed, deleted or taken offline here (404); its blocks change like any page’s. Its tagline and the about text are your shop’s settings: see Shop settings.

Blocks

A page is made of blocks, shown in order. The kinds and the fields each uses:

Kind What it shows Fields
text A heading and text heading, body (HTML)
about Your shop’s about text, as your event pages show it heading
media A picture beside text heading, body, image_side (start, end), button_label, button_url
image One picture caption, width (wide, full)
gallery Pictures to browse: the block’s own, or your shop’s gallery with source: "shop" heading, source
events Your next events, or chosen ones heading, source (upcoming, selected), limit (1–12), event_ids
past_events The way to your past events, once there are some heading
faq Questions and answers: the block’s own, or your shop’s questions with source: "shop" heading, items (question, answer), source
location A venue with map and directions heading, venue_id, body
contact A contact form; messages go to your support address heading, body
newsletter A newsletter sign-up with double opt-in (with email marketing) heading, body
posts Your newest blog posts heading, limit
banner One call to action on your accent color heading, text, button_label, button_url
quote A quote text, author
video A YouTube video heading, video_url
embed Another site’s player, map or form, loaded once a visitor allows it heading, embed_url (an https:// address or the embed code with one), caption
code Your own HTML, CSS and JavaScript with Liquid, run in a sandboxed frame; its links open in your shop when clicked heading, caption (what it shows), code
section A section Usetix’s AI designer wrote; read only here section_id

A block with source: "shop" and the about block show what your shop keeps itself, which your event pages show too: the about text is a shop setting, the gallery and the questions are edited in the dashboard. A custom block comes from asking the AI for a section and names it in section_id; read the section with GET /admin/account_settings/look/sections/:id. It can be moved and removed like any block. section_id is null for every other kind.

Pictures and galleries are uploaded in the dashboard. Buttons lead to a path of your shop (/ueber-uns), a full https:// address, mailto: or tel:.

POST /admin/website/pages/:slug/blocks

Adds a block at the end of the page. A new block starts with your shop’s details where it has them (your next events, the venue of your next event, your questions), so {"block": {"kind": "events"}} is enough.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"block": {"kind": "faq", "heading": "Fragen", "items": [{"question": "Gibt es eine Garderobe?", "answer": "Ja, für 2 €."}]}}' \
  https://app.usetix.io/admin/website/pages/ueber-uns/blocks

Returns 201 Created with the block.

PATCH /admin/website/pages/:slug/blocks/:id

Changes a block’s fields.

PUT /admin/website/pages/:slug/blocks/:id/position

Moves the block to position (1 is the top). Returns 204 No Content.

DELETE /admin/website/pages/:slug/blocks/:id

Removes the block. Returns 204 No Content.

Blog posts

GET /admin/website/posts

{
  "posts": [
    {
      "slug": "silvester",
      "title": "Silvester",
      "excerpt": "Was für eine Nacht.",
      "status": "scheduled",
      "published_at": "2026-12-31T18:00:00Z",
      "url": "https://club-shop.usetix.io/blog/silvester",
      "cover_image_url": null,
      "event_ids": [ 42 ],
      "event_slugs": [ "silvester-2026" ],
      "created_at": "2026-10-27T09:00:00Z",
      "updated_at": "2026-10-27T09:00:00Z"
    }
  ]
}

status is draft, scheduled (online from published_at) or published. event_ids and event_slugs name the events the post is about. GET /admin/website/posts/:slug returns one post with its body as HTML.

POST /admin/website/posts and PATCH /admin/website/posts/:slug

Send post[title], and optionally post[slug], post[excerpt], post[body] (HTML) and post[event_ids]: the events the post is about, whose tickets show under it while they’re on sale.

POST /admin/website/posts/:slug/publication and DELETE

POST publishes the post now, or on published_at (ISO 8601) if that is ahead. DELETE takes it off the blog.

DELETE /admin/website/posts/:slug

Deletes the post. Returns 204 No Content.

GET /admin/website/menu

{
  "customized": false,
  "items": [
    { "id": "events", "kind": "events", "name": "Events", "label": null, "url": null, "page_slug": null, "position": null },
    { "id": "page-12", "kind": "page", "name": "Über uns", "label": null, "url": null, "page_slug": "ueber-uns", "position": null }
  ]
}

Until you change it (customized is false), the menu follows your shop: its events, its published pages, and the blog once a post is online. The first change keeps that order; from then on each entry has a number as its id.

POST /admin/website/menu

Adds an entry: menu_item[kind] is events, page (with menu_item[page_id], the page’s id), blog, vouchers, past_events or link (with menu_item[label] and menu_item[url]).

PATCH /admin/website/menu/:id, PUT /admin/website/menu/:id/position, DELETE /admin/website/menu/:id

Renames an entry (menu_item[label], and url for a link), moves it to position, or removes it.

Redirects

When your domain points to Usetix, addresses of your old website lead on to their new pages, permanently (301), so links and search rankings keep working.

GET /admin/website/redirects

{
  "redirects": [
    { "id": 4, "path": "/about.html", "target": "/ueber-uns", "hits_count": 12, "last_hit_at": "2026-10-26T21:14:03Z" }
  ]
}

POST /admin/website/redirects, PATCH /admin/website/redirects/:id, DELETE /admin/website/redirects/:id

Send redirect[path] (the old address, with its query if it had one, like /index.php?id=12) and redirect[target] (a path of your shop or a full https:// address).

AI

With Usetix’s AI on for your account, ask it to write a page or a post, a section for one page, or to move your old website over. It works in the background: a minute for a page, post or section, a few minutes for a website. Every page and post it makes starts as a draft.

POST /admin/website/requests

design_request[kind] What it does Fields
page Writes a page from your words, made of blocks prompt
post Writes a blog post prompt, and optionally event_id (then prompt is optional)
section Writes a section for one page and adds it as a section block at the end of the page; it shows once it passed Usetix’s accessibility check prompt, page_slug (home for the home page)
website Moves your old website over: pages, posts and a redirect from every old address website_url

Another kind returns 422 Unprocessable Entity with errors.kind. Any request gets 422 too when AI is off for your account or its daily limit is reached.

curl -X POST \
  -H "Authorization: Bearer your-token-here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"design_request": {"kind": "website", "website_url": "https://club.example"}}' \
  https://app.usetix.io/admin/website/requests

Returns 201 Created and a Location header.

GET /admin/website/requests/:id

{
  "id": 7,
  "kind": "website",
  "state": "done",
  "error_message": null,
  "pages": [ { "slug": "ueber-uns", "title": "Über uns" } ],
  "posts": [ { "slug": "silvester", "title": "Silvester" } ],
  "redirects_count": 14,
  "section_ids": [],
  "created_at": "2026-10-27T09:00:00Z"
}

state is pending, working, done or failed; error_message says why it failed. A finished section request lists its section in section_ids.