Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.jointoevent.io/llms.txt

Use this file to discover all available pages before exploring further.

The Event Architect API lets you build the parse → review → apply workflow programmatically. All four endpoints are scoped to a meeting (event) and require a bearer token obtained through the standard JTE Panel login flow.

Base URL and authentication

Base route: /api/event-architect/meetings/{meetingId}/session
Every request must include an Authorization header with a valid bearer token.
Authorization: Bearer <token>
Tokens are obtained through the standard JTE Panel authentication flow described in Login & Access.

Session behavior

A session is the server-side state that holds the most recently parsed plan for a user and event combination.
  • Scope: keyed on (userId, meetingId). One user can have independent sessions across multiple events.
  • Tab sharing: the same user opening the same event in multiple tabs shares a single session and a single current plan.
  • Sliding TTL: the session expires after 120 minutes of inactivity. Any read or write operation resets the timer and updates lastActivityAt and expiresAt.
  • Auto-creation: sending a prompt via POST /messages creates a session automatically if none exists.

GET /session

Retrieves the current in-memory session for the authenticated user and the specified meeting.
GET /api/event-architect/meetings/{meetingId}/session
Use this endpoint when the user loads the AI Assistant page to restore any previously parsed plan.

Path parameters

meetingId
string
required
The GUID of the meeting (event) whose session you want to retrieve.

Response

Returns 200 OK with an EventArchitectSessionResponse object when a session exists, or 404 Not Found when no session exists or the session has expired.
meetingId
string
required
The GUID of the meeting this session belongs to.
currentPlan
object
The most recently parsed EventArchitectPlan, or null if none has been parsed yet.
originalUserRequest
string
The raw prompt string that produced currentPlan, if available. Used to restore the prompt text field on page load.
createdAt
string
required
ISO 8601 datetime when the session was first created.
lastActivityAt
string
required
ISO 8601 datetime of the most recent read or write operation.
expiresAt
string
required
ISO 8601 datetime when the session will expire if no further activity occurs.

Code example

const response = await fetch(
  `/api/event-architect/meetings/${meetingId}/session`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
)

if (response.status === 404) {
  // No session — start with empty state
  return null
}

if (!response.ok) {
  throw new Error(`Unexpected error: ${response.status}`)
}

const session = await response.json()
// session.currentPlan contains the last parsed plan
return session

POST /session/messages

Parses a natural-language prompt and stores the resulting plan in the session. Creates the session automatically if none exists.
POST /api/event-architect/meetings/{meetingId}/session/messages
The server builds the current event state from the database — you do not send the current configuration. Send only the user’s prompt text.

Path parameters

meetingId
string
required
The GUID of the meeting to parse a plan for.

Request body

prompt
string
required
The natural-language instruction describing the changes to make. Maximum length is determined by the AI model’s context window; keep prompts under 25,000 characters for best results.

Response

Returns 200 OK with an EventArchitectParseResponse object.
plan
object
required
The newly parsed EventArchitectPlan. Same shape as described under GET /session.
session
object
required
The updated EventArchitectSessionResponse reflecting the new plan and refreshed TTL timestamps.

Code example

const response = await fetch(
  `/api/event-architect/meetings/${meetingId}/session/messages`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ prompt: userPrompt }),
  }
)

if (!response.ok) {
  const err = await response.json().catch(() => ({}))
  throw new Error(err.message ?? `Error ${response.status}`)
}

const { plan, session } = await response.json()

Request and response example

POST /api/event-architect/meetings/9f9e2cc9-390a-4dd0-a56a-c5f5ffddf6ff/session/messages
Authorization: Bearer <token>
Content-Type: application/json

{
  "prompt": "Set capacity to 500, add Early Bird ticket for 99 PLN, and add form fields company and job title."
}
{
  "plan": {
    "redoFromScratch": false,
    "capacity": { "hasLimit": true, "limit": 500 },
    "tickets": [{ "name": "Early Bird", "price": 99, "isFree": false }],
    "form": {
      "fields": [
        { "label": "Company", "fieldType": "Text", "options": [], "dependencies": [] },
        { "label": "Job title", "fieldType": "Text", "options": [], "dependencies": [] }
      ]
    },
    "landingPage": null,
    "webhook": null,
    "mailing": null
  },
  "session": {
    "meetingId": "9f9e2cc9-390a-4dd0-a56a-c5f5ffddf6ff",
    "currentPlan": { "...": "same as plan above" },
    "createdAt": "2026-03-01T12:00:00Z",
    "lastActivityAt": "2026-03-01T12:00:00Z",
    "expiresAt": "2026-03-01T14:00:00Z"
  }
}

POST /session/apply

Applies the currently stored plan to the event data in the database. The plan must have been created by a prior call to POST /session/messages.
POST /api/event-architect/meetings/{meetingId}/session/apply
This endpoint has no request body.
Applying a plan with redoFromScratch: true replaces the existing event configuration. Tickets that have already been purchased are preserved, but all other settings are overwritten.

Path parameters

meetingId
string
required
The GUID of the meeting whose stored plan should be applied.

Response

Returns 200 OK with an EventArchitectApplyResult object.
redoFromScratch
boolean
required
Whether the plan was applied in replace mode (true) or merge mode (false).
capacityMessage
string
required
Human-readable summary of the capacity changes applied.
ticketsCreated
number
required
Number of new tickets created.
ticketsUpdated
number
required
Number of existing tickets updated.
ticketsDeleted
number
required
Number of tickets removed.
ticketsPreservedUsed
number
required
Number of tickets that could not be deleted because they have been purchased.
webhookApplied
boolean
required
Whether a webhook configuration was written.
webhookEventCount
number
required
Number of webhook event subscriptions configured.
landingPageMessage
string
required
Human-readable summary of the landing page changes applied, or a skip message if the plan had no landing page section.
persistedFormFieldsCount
number
Number of registration form fields saved. Present when the plan included form changes.

Code example

const response = await fetch(
  `/api/event-architect/meetings/${meetingId}/session/apply`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
)

if (!response.ok) {
  const err = await response.json().catch(() => ({}))
  throw new Error(err.message ?? `Error ${response.status}`)
}

const result = await response.json()
// result.ticketsCreated, result.capacityMessage, etc.

Response example

{
  "redoFromScratch": false,
  "capacityMessage": "Capacity step finished. Limit set to 500.",
  "ticketsCreated": 1,
  "ticketsUpdated": 0,
  "ticketsDeleted": 0,
  "ticketsPreservedUsed": 0,
  "webhookApplied": false,
  "webhookEventCount": 0,
  "landingPageMessage": "Landing page step skipped.",
  "persistedFormFieldsCount": 7
}

DELETE /session

Clears the in-memory session for the authenticated user and the specified meeting.
DELETE /api/event-architect/meetings/{meetingId}/session
Call this endpoint when the user explicitly resets their draft or after a successful apply to prevent accidental re-application of a stale plan.

Path parameters

meetingId
string
required
The GUID of the meeting whose session should be deleted.

Response

Returns 200 OK with an empty body on success. Returns 404 Not Found if no session existed.

Code example

const response = await fetch(
  `/api/event-architect/meetings/${meetingId}/session`,
  {
    method: 'DELETE',
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  }
)

if (!response.ok && response.status !== 404) {
  throw new Error(`Error ${response.status}`)
}
// Session cleared — reset local UI state

Error codes

StatusCondition
400 Bad Requestprompt field missing on POST /messages; or no parsed plan in session on POST /apply
401 UnauthorizedMissing Authorization header
403 ForbiddenToken is present but invalid or the user does not have access to the meeting
404 Not FoundMeeting does not exist (parse or apply); or no session exists (GET /session or DELETE /session)
500 Internal Server ErrorUnexpected backend failure
When the response body contains a message field, display it in the UI to give the user actionable context:
const err = await response.json().catch(() => ({}))
const message = err?.message ?? `Unexpected error (${response.status})`

TypeScript models

The key TypeScript interfaces for the Event Architect API are:
export interface EventArchitectParseRequest {
  prompt: string
}

export interface EventArchitectParseResponse {
  plan: EventArchitectPlan
  session: EventArchitectSessionResponse
}

export interface EventArchitectSessionResponse {
  meetingId: string          // GUID
  currentPlan?: EventArchitectPlan | null
  originalUserRequest?: string | null
  createdAt: string          // ISO 8601
  lastActivityAt: string     // ISO 8601
  expiresAt: string          // ISO 8601
}

export interface EventArchitectApplyResult {
  redoFromScratch: boolean
  capacityMessage: string
  ticketsCreated: number
  ticketsUpdated: number
  ticketsDeleted: number
  ticketsPreservedUsed: number
  webhookApplied: boolean
  webhookEventCount: number
  landingPageMessage: string
  persistedFormFieldsCount?: number | null
}
The frontend does not send currentStateJson. The server builds current event state from the database. Send only { "prompt": "..." } in the request body.