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.

Payment always stays with the person.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

  1. 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: true in the API). It also needs access to the clients or events you will register people for, under Allowed clients or Allowed events: each allowedClients entry is a { tenantCode, clientCode } object and each allowedEvents entry 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.
  2. 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.
  3. Your MCP client must let your code set HTTP headers on each request: the API token in Authorization on every call and, once the person is verified, their session token in X-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/participant

Send 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...

A missing, revoked or expired token gets 401 Unauthorized, and a token whose API account does not have canActAsParticipantAgent gets 403 Forbidden.

The endpoint is also listed in Jade’s MCP discovery document, as the entry named participant, with its transport (streamable-http), what it needs to sign in and every tool it serves:

GET /api/.well-known/mcp.json

Signing 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

Call 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
}

Send the token in the 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.

A wrong code returns 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

Call 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

Send everything you know about the person. The more fields you fill in now, the fewer the person has to fill in when they open the link. Leave out 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"
}

Field keys use the @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 (and matchStatus, the same value): new for a new registration, existing_incomplete when the person had already started one, which the link continues, or existing_complete when they are already registered.
  • url — the link the person opens to finish, payment included. For existing_complete it 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 for existing_complete.
  • flowSlug — the flow used (not for existing_complete) — and, for a new registration only, participantId.
  • When a field fails validation the response is instead status: validation_failed with an errors list, 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

Use 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.

The same goes for the recommendation tools — 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

Jade serves 23 tools on this endpoint, grouped below for reading. Unlike the organizer endpoint there is no way to pick groups: every connection gets them all. Every tool except 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_registration returns.
  • 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_otp emails a sign-in code to the address it is given.
  • agent_submit_registration creates 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_registration changes the person’s saved answers.
  • import_group_members registers someone else as a member of the person’s group, with a hotel reservation when @housing.* fields are sent.
  • book_exhibitor_appointment books 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_appointment cancels 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_email sends one of the person’s emails to them again. Called without an emailId, it only lists the ones it can resend.
  • generate_participant_profile writes a short AI-generated description of the person and saves it on their record, replacing any earlier one.

None of them takes payment: the person pays in their browser, at the link 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

A Jade administrator can revoke the API token, untick Allow an AI assistant to register people, or remove the account’s access to a tenant, client or event, under Developers → API Accounts. Each change applies from the next request: the token and the account’s access are checked again on every call, so sessions already issued stop working too.

Sessions also end on their own after one hour.

Rate limits

Sign-in codes are limited to 3 per email address per hour and 200 per API account per day, so an assistant cannot work through an address book. Past either limit, 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.

Related