Compose and publish a social post

Write once, send to five channels, and get a tracked short link per platform for free.

Owned by Venue Manager · 11 steps · about 15 minutes

Why this exists

The publishing model is one post, many channels. You write a single body, choose which of the five platforms it goes to, and the platform materialises a separate delivery target per channel with its own state. That is why a post can end up partial: Instagram and Discord sent, X failed on length, and the post itself honestly reports partial rather than pretending it went out.

The reason the per-platform split matters more than it looks is the tracked link. Each target gets its own short link, stable across retries, carrying the platform as its source. That is the entire basis of the attribution report — without a link per platform there is no way to say which channel actually sold tickets, only that some did.

Placeholders are the other half of composing. Curly-brace tokens like event name, doors time, tier name, price and percentage sold are substituted at publish time, not at write time, so a scheduled post says what is true when it goes out rather than what was true when you typed it. Event placeholders require the post to be attached to an event — using one on a general club post is refused at save.

Length is enforced twice, at save and again at publish, because a channel's limit can bite a scheduled post that was fine when written. A target that violates it at publish time is marked failed with a body-too-long error rather than being silently truncated — the platform will not put half your sentence in public.

Before you start

  • A venue manager or admin session.
  • At least one enabled channel. The seed enables all five with the handle @neonclub.
  • For event placeholders: an event to attach the post to, such as demo-event-0001.

Practise with

PersonaEmailPasswordNote
venue_managermanager@club.test manager123shift lead: implies door_staff, plus intake, sales, guest list, marketing
adminadmin@club.test admin123the only account that can touch money, identity and contracts
host_promoterpromoter@demo.club promoter123scoped host on demo-event-0001; owns the seeded Promoter X comp bucket

Steps 1–8 — Venue Manager

their manual →
  1. 1
    Open the marketing dashboard and check the channel row first: which platforms are enabled, and what has been sent recently.
    /admin/marketing marketing
    Expected result Five channels with their handles and post counts, plus recent and scheduled posts.
    Watch out for A disabled channel is refused at save time with channel_disabled. Check before you write, not after.
  2. 2
    Open the compose page. Pick the event if this is about a specific night — that is what enables event placeholders — or leave it as a general club post.
    Expected result The compose form with an event dropdown, a body box, placeholder buttons, platform checkboxes, link target, media ref and a schedule field.
    Watch out for Attaching the event is what unlocks the placeholders. Using an event placeholder on a general post is refused with placeholder_needs_event.
  3. 3
    Write the body and use the placeholder buttons rather than typing tokens by hand. Tick the platforms. Set the link target — a path such as an event page, or a full URL.
    Expected result A body with placeholders and a target set of platforms.
    Watch out for An unrecognised token is refused with unknown_placeholder. Use the buttons; a typo in a placeholder name is not a typo you will spot by rereading.
  4. 4
    Save it. Save draft parks it, Schedule sets it to publish at the time you entered, and Publish now sends immediately.
    /api/marketing/posts POST marketing
    Expected result A post in draft, scheduled or publishing.
    Watch out for A schedule time in the past is refused with scheduled_in_past — the schedule field wants UTC in ISO form. Length limits are checked here too, against the longest platform you ticked.
  5. 5
    Open the post detail and read the Targets table: one row per platform with its state, its attempts and its external link once sent.
    /admin/marketing/posts/{post_id} marketing
    Expected result Targets as pending, sent, failed or skipped, plus a Tracked links panel with a short link per platform.
    Watch out for Skipped means the channel was disabled after you scheduled. Skipped targets are excluded from the status maths — but a post whose targets are ALL skipped ends up failed.
  6. 6
    If the post came back partial or failed, press Retry failed. This re-sends only the failed and skipped targets and never re-sends one that already went.
    /api/marketing/posts/{post_id}/retry POST marketing
    Expected result The failed targets attempted again; the sent ones untouched.
    Watch out for Retry is only available on partial or failed posts — anything else is 409 post_not_retryable. The short links are stable across retries, so your attribution does not fragment.
  7. 7
    To stop a scheduled post that is no longer true, cancel it rather than editing it into something unrelated.
    /api/marketing/posts/{post_id}/cancel POST marketing
    Expected result Status cancelled.
    Watch out for You cannot delete it — deletion is admin-only, and only for drafts, cancelled and failed posts. Cancelling is the manager-grade stop button.
  8. 8
    Edit a post that has not gone out yet — drafts and scheduled posts only.
    /api/marketing/posts/{post_id} PATCH marketing
    Expected result The updated body, platforms or schedule.
    Watch out for 409 post_not_editable means it is publishing or published. Public is public; the fix is a new post, not a rewrite of history.

Steps 9 — Host / Promoter

their manual →

Can read the posts for their own event, and will ask you why theirs has not gone out.

  1. 9
    As a promoter, open the marketing tab for your own event to see what has gone out for your night.
    /admin/marketing/events/{event_id} marketing
    Expected result Posts and rules for that event.
    Watch out for You must be looking at your own event. Hosts have no view across the venue's marketing, only their own night's.

Steps 10–11 — Admin

their manual →

Owns channel settings and post deletion, and can force a publish outside the schedule.

  1. 10
    As an admin, enable or disable a channel and set its handle when the venue's accounts change.
    /api/marketing/channels/{platform} PATCH marketing
    Expected result The channel updated; the dashboard's channel row reflects it immediately.
    Watch out for Disabling a channel does not cancel posts already scheduled to it — those targets turn into skipped at publish time. Check the schedule before you disable.
  2. 11
    Force-publish a draft or scheduled post when you are rehearsing the flow, ignoring its schedule.
    /debug/marketing/posts/{post_id}/force-publish POST marketing
    Expected result The post publishes through the real pipeline.
    Watch out for This goes through the genuine publish routine and records genuine outbound traffic. Do it on a demo post, not on the real weekend announcement.