Headless Collaborator Applications
Letting people apply to become collaborators from a form on your headless frontend. Either ride your forms plugin's existing integration, or use Siren's signed JWT flow directly.
Requires Siren Essentials
Last updated: April 30, 2026
A collaborator application form is the one place on a headless site where you might want a public form to write directly into Siren. Visitor fills out name and email, the frontend submits, a collaborator record gets created (or matched if the email is on file). Set up a Program Registration Form covers the WordPress-rendered version. This page reframes it for headless. Two paths, and which fits depends on whether you’re already running a forms plugin.
The shortcut: use a forms-plugin integration
Several forms plugins ship with Siren integrations that handle collaborator signup internally. Check the integration feature matrix for the current list. If your form lives in one of them, prefer this path:
- Build the form in the forms plugin, configured with the collaborator-signup integration.
- From your headless frontend, POST responses to the forms plugin’s REST endpoint. Each plugin documents its own submission API.
- The plugin processes the submission, fires Siren’s signup events, and the collaborator is created.
Your frontend never touches Siren directly. The forms plugin is the seam.
The DIY path: Siren’s signed JWT flow
The submission endpoint that creates collaborators is public by design. Anyone on the internet can POST to it. So what stops a stranger from signing themselves up to your highest-paying program with statusOnSignup: active and walking away with a referral code?
A signed JWT. Your trusted server-side code mints a token naming which programs the applicant can join. The public submit endpoint refuses any request without one. The JWT is the trust boundary: signed with a server-only secret, scoped to the programs you chose, attached to every submission as proof the form was legitimate.
Replay risk to design around. The JWT does not currently set an expiry (
exp) or single-use (jti) claim. A leaked token can be replayed until the signing secret rotates. Mint a fresh JWT per render, never cache one across visitors, and read the next section before deciding where the token lives.
How the round trip works
Visitor lands on the form page. Your frontend route runs server-side because the JWT has to be minted per render.
Server runtime POSTs to /collaborators/create-signup-form-jwt with admin auth. Body names programIds, statusOnSignup, and approveExisting. Siren returns a signed token.
Direct path: the JWT is rendered into the form HTML. Proxied path: the JWT stays on your backend.
Direct path: browser POSTs straight to /collaborators/submit-request. Proxied path: browser POSTs to your backend, which forwards server-to-server with a fresh JWT.
Submit endpoint validates the JWT signature against Siren's signing secret, reads the program list and status from the token, then creates or matches the collaborator by email.
The mint endpoint is Create Signup Form JWT. It requires admin auth using a WordPress application password from a server-side runtime. Three fields control what the token can do:
programIds: which programs the collaborator gets bound to.statusOnSignup:pending(review required before engagements fire) oractive(auto-approve and start crediting immediately). See collaborator status types for the full lifecycle.approveExisting: if the email is on file, leave it alone or auto-approve it into the new program. The WordPress-rendered registration form describes how this looks operationally.
The submit endpoint is Submit Collaborator Request. Public, gated entirely by the JWT. A missing or signature-invalid JWT returns 400 before field validation runs.
Where the token lives: direct vs proxied
The JWT only does its job if it stays in trusted hands. Two ways to wire the form. The right one depends on your statusOnSignup:
statusOnSignup | Direct submission | Proxied submission |
|---|---|---|
pending | OK (worst case: review-queue spam) | OK |
active | Avoid (leaked token = auto-approve) | OK |
Direct submission embeds the token in the rendered HTML and the browser POSTs straight to Siren. Least code. The token is visible in page source, replayable until the signing secret rotates. Fine for pending: a replay just queues another applicant for review. Throughput problem, not a fraud problem.
Proxied submission sends the form to your own backend. Your backend validates input, mints a fresh JWT, and forwards server-to-server. The token never reaches the client. One extra hop, meaningfully better isolation. Required for active, where every leaked token is an auto-approved signup waiting to happen.
In either pattern, mint per render and don’t cache. “Per render” only protects you when the page is rendered per-request. On a statically generated frontend (Astro SSG, Next.js export), the form is built once and shipped to every visitor with the same token baked in. That’s “one token forever,” the worst case. If the form lives on a static page, use proxied submission so the token is minted at submit time, not build time.