External Register POST setup
Pre-register or deduplicate a participant from an external system via a browser-compatible HTTP POST.
register-error page. Endpoint
POST /api/public/tenant/{tenantCode}/client/{clientCode}/event/{eventCode}/participant/external-register Replace {tenantCode}, {clientCode} and {eventCode} with your values. The Developers → External Register POST tab's Example builder prints the exact URL — ready to copy — for any flow.
Fields
Submit as application/x-www-form-urlencoded (HTML form) or application/json. Field keys use the @entity.property token format.
@participant.email— required@participant.firstName— required@participant.lastName— requiredflowSlug— optional; defaults to the event's default flow@custom.*— optional event-specific custom fields (unrecognized keys are dropped)externalIds— optional array of{ source, value }pairs (max 20) that reconcile a returning person against their id in an upstream system (CRM/AMS/feed). Send it as a JSON array, or from a form usingexternalIds[0][source]/externalIds[0][value]bracket fields (see the External IDs example below).timestamp+signature— required in secure mode (see below)
Browser example (basic mode — pure HTML)
In basic mode no signature is needed. An auto-submitting hidden form is all that's required — no server involvement.
<form method="POST"
action="/api/public/tenant/{tenantCode}/client/{clientCode}/event/{eventCode}/participant/external-register">
<input type="hidden" name="@participant.email" value="alex@example.com">
<input type="hidden" name="@participant.firstName" value="Alex">
<input type="hidden" name="@participant.lastName" value="Rivera">
</form>
<script>document.forms[0].submit()</script>External IDs (reconcile a returning person)
externalIds carries the upstream identifiers (CRM/AMS/feed) used to match a person you've seen before. From an HTML form, add each id as an externalIds[<n>][source] / externalIds[<n>][value] pair (the application/x-www-form-urlencoded parser expands the bracket indices back into an array); from JSON, pass a plain array under externalIds. Up to 20 pairs. Both forms below carry the same data.
<form method="POST"
action="/api/public/tenant/{tenantCode}/client/{clientCode}/event/{eventCode}/participant/external-register">
<input type="hidden" name="@participant.email" value="alex@example.com">
<input type="hidden" name="@participant.firstName" value="Alex">
<input type="hidden" name="@participant.lastName" value="Rivera">
<input type="hidden" name="externalIds[0][source]" value="salesforce">
<input type="hidden" name="externalIds[0][value]" value="0031N00abc">
</form>
<script>document.forms[0].submit()</script>Server example (secure mode — Node.js)
Secure mode is opt-in per event and configured in the event's Developers → External Register POST tab. When enabled every post must carry a timestamp (Unix epoch seconds, UTC) and a signature — base64url HMAC-SHA256 of "<eventCode>:<email>:<timestamp>" using the event's signing secret, within a ±5-minute window. The secret never leaves your server. The server lowercases and trims the email before verifying, so normalize it the same way ( email.trim().toLowerCase()) before signing.
import { createHmac } from 'crypto';
const secret = process.env.MCI_XR_SECRET; // Developers → External Register POST tab
const email = 'alex@example.com'.trim().toLowerCase();
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = createHmac('sha256', secret)
.update(`acme-2026:${email}:${timestamp}`)
.digest('base64url');
// render hidden fields: @participant.*, timestamp, signature; then auto-submitBasic vs secure mode
Use basic mode when the POST originates from a trusted internal page or when the event is low-risk — no signature is required and a pure-browser form is sufficient. Use secure mode when you need to prove the request was generated by your server (the holder of the per-event signing secret) within the last ±5 minutes: a server-side process computes and injects the HMAC before the form is delivered to the browser, so the secret is never exposed to end users. Note that the signature covers only <eventCode>:<email>:<timestamp> — it authenticates the source and timing, not the submitted fields; @participant.* and @custom.* values are treated as user-supplied data regardless.