Connect an AI assistant (participants)
Build an AI assistant that registers people for Jade events on their behalf. The person proves their email with a one-time code, the assistant fills in the registration, and the person finishes — and pays — in their browser.
This guide walks through the whole flow: getting an API account, connecting to the endpoint, verifying the person’s email with a one-time code, and submitting a registration that the person completes, paying if needed, at the link Jade returns.
agent_submit_registration saves what the assistant knows about the person and returns a link. When the next step is checkout, the assistant gets that link and never any payment details: the person opens it to pay.Before you start
You need an API account from a Jade administrator, set up under Developers → API Accounts with Allow an AI assistant to register people ticked ( canActAsParticipantAgent: truein the API). It also needs access to the clients or events you will register people for, under Allowed clients or Allowed events: eachallowedClientsentry is a{ tenantCode, clientCode }object and eachallowedEventsentry a{ tenantCode, clientCode, eventCode }object. If the account is also limited to some tenants under Allowed tenants, each event’s tenant must be one of them. Copy the token when it is issued; it is shown once.- You need the tenant, client and event code of each event: the sign-in tools take all three. They are the codes in the account’s allowed clients and events; ask your Jade administrator if you do not have them.
Your MCP client must let your code set HTTP headers on each request: the API token in Authorizationon every call and, once the person is verified, their session token inX-Participant-Session. An assistant you only configure — a custom connector in Claude or ChatGPT, for example — cannot send a different session for each person, so this endpoint is for an assistant you build or host yourself.
The server address
Every request goes to the same address:
/api/mcp/participantSend the API token on every request, the two sign-in calls included, and after sign-in the person’s session token as well:
POST /api/mcp/participant
Authorization: Bearer jdo_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-Participant-Session: eyJ...session-token...canActAsParticipantAgent gets 403 Forbidden.
participant, with its transport (streamable-http), what it needs to sign in and every tool it serves:
GET /api/.well-known/mcp.jsonSigning in
The assistant proves it acts for the person with a one-time code sent to their email. The two sign-in tools are the only ones that work before a session exists.
1. Request a code
agent_request_otp with the person’s email and the event’s tenantCode, clientCode and eventCode. Jade emails a 6-digit code to that address, and the person reads it back to the assistant. The email opens with your API account’s name, so give the account a name the person will recognise.
// MCP tool call
{
"name": "agent_request_otp",
"arguments": {
"tenantCode": "acme-group",
"clientCode": "acme",
"eventCode": "acme-2026",
"email": "alex@example.com"
}
}
// Response
{
"sent": true,
"expiresInSeconds": 900
}The code expires after 15 minutes. How many codes can be sent is limited; see Rate limits below.
2. Verify the code and keep the session
// MCP tool call
{
"name": "agent_verify_otp",
"arguments": {
"tenantCode": "acme-group",
"clientCode": "acme",
"eventCode": "acme-2026",
"email": "alex@example.com",
"code": "421907"
}
}If the code matches, Jade returns a session token:
{
"verified": true,
"session": {
"token": "eyJ...session-token...",
"expiresAt": "2026-05-21T13:14:00.000Z"
},
"participantExists": false
}X-Participant-Session header on every later call. The session is for that one (tenantCode, clientCode, eventCode, email), works only with your API account, and lasts one hour; after that, request a new code. participantExists says whether the event already had a registration for that email.
verified: false with the reason wrong_code and attemptsRemaining; the third wrong attempt burns the code. While a newer code is still valid, an earlier one counts as a wrong code. The reason expired_or_missing means no unused code matches: it is more than 15 minutes old, has already been used to sign in, was burned by wrong attempts, or was sent for a different event, email or API account. Request a new one.
Using it
With the session token, find the right registration flow, submit what you know about the person, and hand them the link.
1. Find the flows
agent_list_flows to see the event’s registration flows (attendee, exhibitor, speaker and so on) with the fields each one asks for. Use it to choose the flow for the person and to see what you still need to ask them.
// MCP tool call (with X-Participant-Session)
{
"name": "agent_list_flows",
"arguments": {}
}
// Response (abridged)
{
"flows": [
{
"slug": "primary-attendee",
"name": "Attendee Registration",
"visibleForTags": null,
"descriptor": {
"descriptor": {
"eventCode": "acme-2026",
"flowSlug": "primary-attendee",
"fields": [
{
"binding": "@participant.firstName",
"flatKey": "firstName",
"entityPath": "participant.firstName",
"label": "First Name",
"type": "text",
"source": "standard",
"required": true
},
{
"binding": "@custom.tShirtSize",
"flatKey": "tShirtSize",
"entityPath": "customFieldResponses.tShirtSize",
"label": "T-Shirt Size",
"type": "choice",
"source": "custom",
"required": false,
"customFieldCode": "tShirtSize",
"choices": [
{ "code": "M", "name": "Medium" },
{ "code": "L", "name": "Large" }
]
}
]
},
"customFields": [ /* the event's own questions: key, name, responseType, choices */ ],
"timezone": "America/New_York",
"eventStartOn": "2026-10-12"
}
},
{
"slug": "exhibitor",
"name": "Exhibitor Registration",
// Shown only to people with the exhibitor tag
"visibleForTags": { "type": "all", "required": ["exhibitor"] },
// Same shape as above; null if the flow could not be described
"descriptor": { /* ... */ }
}
]
}2. Submit the registration
flowSlug and the event’s first visible flow is used.
// MCP tool call (with X-Participant-Session)
{
"name": "agent_submit_registration",
"arguments": {
"flowSlug": "primary-attendee",
"data": {
"@participant.firstName": "Alex",
"@participant.lastName": "Rivera",
"@custom.tShirtSize": "L",
"@custom.dietaryNotes": "vegetarian"
}
}
}
// Response (new registration)
{
"status": "new",
"matchStatus": "new",
"url": "/tenant/acme-group/client/acme/event/acme-2026/register/primary-attendee?token=eyJ...registration-token...",
"jwt": "eyJ...registration-token...",
"participantId": "507f1f77bcf86cd799439011",
"flowSlug": "primary-attendee"
}@entity.property token format: @participant.* for built-in fields and @custom.* for the event’s own questions. The session’s verified email is always saved as @participant.email, so a session cannot register a different address.
3. Hand off to the person
The response carries:
status(andmatchStatus, the same value):newfor a new registration,existing_incompletewhen the person had already started one, which the link continues, orexisting_completewhen they are already registered.url— the link the person opens to finish, payment included. Forexisting_completeit is instead the sign-in page for changing a registration, with their email filled in.jwt— the registration token already in the link, valid for 24 hours; submit again for a fresh link. It is not returned forexisting_complete.flowSlug— the flow used (not forexisting_complete) — and, for a new registration only,participantId.When a field fails validation the response is instead status: validation_failedwith anerrorslist, and nothing is saved. Fix the fields and submit again.
Give the person the link. It opens their registration without another sign-in, so send it to them alone; the rest of the flow, payment included, happens in their browser.
4. After they finish
get_my_registration, check_balance_due and describe_my_flow to confirm the registration or fetch its details. They act on the person’s own registration, so they need a session issued once it exists: if agent_verify_otp returned participantExists: false, they answer “No verified participant identity for this run.” Request and verify a new code after agent_submit_registration, and use the new session.
recommend_products, recommend_hotel, recommend_companies and recommend_participants — and generate_participant_profile. They work from the registered person’s details, so with a session issued before the registration existed they answer “No participant identity available”.
Tools
agent_request_otp and agent_verify_otp needs the session token, and most of the rest act on the person’s own registration, so they need a session issued after it exists (see After they finish).
| Group | What it covers | Tools |
|---|---|---|
| Sign-in | Email the person a one-time code and exchange it for their session. The only tools that work before a session exists. | agent_request_otpagent_verify_otp |
| Registration | List the flows, submit a registration, then read and update the person’s own registration, their balance due and their confirmation email. | agent_list_flowsagent_submit_registrationdescribe_my_flowget_my_registrationupdate_my_registrationcheck_balance_dueresend_my_confirmation_emaillist_data_fields |
| Housing | The event’s hotels, and a hotel recommendation for the person. | get_hotel_listrecommend_hotel |
| Groups | Register the members of the person’s group from a template. | get_group_import_templateimport_group_members |
| Exhibitors & appointments | The booth map, exhibitor availability, and booking or cancelling the person’s appointments. | get_booth_maplist_exhibitor_availabilitybook_exhibitor_appointmentlist_my_appointmentscancel_my_appointment |
| Recommendations | Products, exhibiting companies and other participants suited to the person, from their profile, once the session knows the registered person. | recommend_productsrecommend_companiesrecommend_participantsgenerate_participant_profile |
What is not available, and why
The endpoint acts for one verified person at one event, so it serves only what that person may do for themselves. Left out:
- Working through the form with the person: the cart, the product list, policy agreements, moving between form pages and form progress. Jade’s own in-registration assistant has these because it sits beside the form the person has open; here the person does those steps in their browser, at the link.
Payment. The assistant never sees payment details; the person pays at the link agent_submit_registrationreturns.- Organizer tools — event setup, other people’s registrations, reports and exports. They need an organizer’s own Jade login, through the organizer endpoint.
- Tenant-wide tools — queries across events, creating events and account administration.
- Jade’s support-inbox tools, and the tools an exhibiting company’s administrators use for their company.
Actions that cannot be undone
The assistant acts as the person, and some tools send email or change what Jade holds about them. Once one has run, the assistant cannot take it back:
agent_request_otpemails a sign-in code to the address it is given.agent_submit_registrationcreates a registration for the person from the data it is sent. When the event already has one with the same name and email, it saves nothing and links to that one instead.update_my_registrationchanges the person’s saved answers.import_group_membersregisters someone else as a member of the person’s group, with a hotel reservation when@housing.*fields are sent.book_exhibitor_appointmentbooks the appointment and shares the person’s details with the exhibitor as a lead. Jade emails the person a confirmation and tells the exhibitor’s contact.cancel_my_appointmentcancels the appointment and emails the other side — the other participant, or the exhibitor’s contact. A cancelled booth slot is free for anyone to book.resend_my_confirmation_emailsends one of the person’s emails to them again. Called without anemailId, it only lists the ones it can resend.generate_participant_profilewrites a short AI-generated description of the person and saves it on their record, replacing any earlier one.
agent_submit_registration returns. Before each one, the assistant should tell the person what it is about to do — the address a code goes to, the answers it will save, the member it will add, the appointment it will book or cancel, the email it will resend — and go ahead only once they agree.
Revoking access
Sessions also end on their own after one hour.
Rate limits
agent_request_otp returns a tool error — “OTP rate limit exceeded for this email — try again in an hour” or “Daily OTP quota exceeded for this API account” — rather than an HTTP 429. Jade sets no per-minute request limit on this endpoint; the API account’s rateLimitPerMinute applies to the REST API only.
Troubleshooting
- 401 “Missing Authorization header” or “Invalid or revoked API token”
- Send Authorization: Bearer and the token on every request, the two sign-in calls included. A revoked or expired token, or one whose API account has been deactivated, fails at once; ask your Jade administrator for a new one.
- 403 “API account is not enabled for the participant MCP endpoint”
- The account does not have Allow an AI assistant to register people ticked. Ask your Jade administrator to tick it under Developers → API Accounts.
- “API account is not authorized for …”
- The tenant, client and event codes are not covered by the account’s allowed tenants, clients or events. Check the codes, or ask your Jade administrator to add the event.
- “Event … does not belong to client …”
- The event is under a different client. Check the client code you passed with it.
- agent_verify_otp returns verified: false
- With wrong_code, attemptsRemaining says how many tries are left; while a newer code is still valid, an earlier one counts as wrong. With expired_or_missing, no unused code matches: it is more than 15 minutes old, has already been used to sign in, was burned by 3 wrong attempts, or was sent for a different event, email or API account. Request a new one.
- “Missing X-Participant-Session header — call agent_verify_otp first”
- Every tool except the two sign-in tools needs the session token from agent_verify_otp, sent in the X-Participant-Session header.
- “Invalid or expired participant session”
- A session lasts one hour and works only with the API account that verified it. Request and verify a new code.
- “This API account is no longer authorized for this event.”
- The account’s access to that event was removed after the session was issued; every call checks it again. Ask your Jade administrator.
- “No verified participant identity for this run.” or “No participant identity available” just after you registered someone
- The session was issued before the person’s registration existed (participantExists: false). Request and verify a new code, then use the new session.
- agent_submit_registration returns status: validation_failed
- errors lists what to fix, and nothing was saved. Check the fields against the flow’s descriptor from agent_list_flows, then submit again.
- “OTP rate limit exceeded for this email …” or “Daily OTP quota exceeded for this API account”
- A limit on sign-in codes was reached (see Rate limits). Wait: the per-email limit counts the codes sent to that address in the last hour, and the per-account limit the codes the account sent in the last 24 hours.