Submission JSON Endpoint - Schema Reference
Note
As our product develops we will add new fields to the schema without notice.
Where possible we will not deprecate or remove existing fields. If this becomes required we will notify active users of the integration.
The intent values are an open set — your code must tolerate values it does not recognise.
These are the TypeScript definitions for the document. All times are UTC.
Root document
{
/**
* Self-describing envelope for the feed
*/
_meta: Meta;
/**
* High level details for the event
*/
event: EventDetails;
/**
* The whole submission form: its sections, questions and options.
* Present even for questions that have no answers.
*/
form: Form;
/**
* The submissions (responses) to the form
*/
responses: Response[];
/**
* The title of the Call for Papers
*/
title: string;
/**
* The UUID of the Call for Papers
*/
id: string;
}Meta
{
/**
* The schema version. Incremented on breaking changes. Currently 1.
*/
schemaVersion: number;
/**
* When this feed was generated, ISO 8601 UTC.
* Changes only when the data is (re)published, not on every request.
* eg 2026-02-04T18:03:03.662Z
*/
generatedAt: string;
/**
* A human/agent-readable description of the feed
*/
description: string;
/**
* The URL of this schema reference's parent documentation
*/
documentationUrl: string;
}EventDetails
{
/**
* The UUID of the event
*/
id: string;
/**
* The name of the event
*/
name: string;
/**
* The timezone for the event.
* Potentially null for awards only events.
* Note that all times in this document are UTC.
*/
timezone: string | null;
/**
* The dates for the event
*/
dates: EventDate[];
/**
* If the event has a portal, the public url submitters use to access
* their content. Null otherwise.
*/
portalURL: string | null;
}EventDate
The start and end times for a day of the event. These are the times in which sessions can be scheduled, not necessarily the opening hours for the event. endDate may be more than 24 hours later than startDate.
{
/**
* The start of an event day in UTC, ISO 8601
* eg 2022-02-04T18:05:00.000Z
*/
startDate: string | null;
/**
* The start of an event day in the event timezone, YYYY-MM-DD
*/
localStartYYYYMMDD: string | null;
/**
* The start of an event day in the event timezone, HH:MM
*/
localStartHHMM: string | null;
/**
* The end of an event day in UTC, ISO 8601
*/
endDate: string | null;
/**
* The end of an event day in the event timezone, YYYY-MM-DD
*/
localEndYYYYMMDD: string | null;
/**
* The end of an event day in the event timezone, HH:MM
*/
localEndHHMM: string | null;
}Form
The form describes the whole submission form. Answers in responses reference form questions and options by id.
{
/**
* The sections of the form, in form order. Each section owns its questions.
*/
sections: FormSection[];
}FormSection
{
/**
* The UUID of the section
*/
id: string;
/**
* The name of the section. Null if unnamed.
*/
name: string | null;
/**
* The position of the section within the form, for ordering
*/
position: number;
/**
* Which part of the form this section belongs to:
* - 'profile' questions about the people submitting
* - 'main' questions about the submission itself (the session/proposal)
* - 'evaluation' questions answered by evaluators
*/
group: 'main' | 'profile' | 'evaluation';
/**
* The questions in this section, in form order
*/
questions: FormQuestion[];
}FormQuestion
{
/**
* The UUID of the question
*/
id: string;
/**
* The label (text) of the question. Null if unset.
*/
label: string | null;
/**
* The question type, eg 'text', 'textarea', 'number', 'checkbox', 'radio',
* 'dimension', 'table', 'email', 'phone', 'url', 'ugc-upload', 'image'.
*/
type: string;
/**
* Which part of the form this question belongs to (see FormSection.group)
*/
group: 'main' | 'profile' | 'evaluation';
/**
* The question's model-link intent, eg 'firstName', 'title', 'score'.
* Open set — tolerate unknown values. Null if the question is not model-linked.
* See the Intent reference below.
*/
intent: string | null;
/**
* The position of the question within the form, for ordering
*/
position: number;
/**
* The UUID of the section this question belongs to.
*/
sectionId: string;
/**
* The options for choice questions (checkbox, radio, dimension). Absent for
* question types that have no options.
*/
options?: QuestionOption[];
}QuestionOption
{
/**
* The UUID of the option. Stable; pairs with the option id on answers.
*/
id: string;
/**
* The label of the option. Null if unset.
*/
label: string | null;
/**
* The option's model-link intent. Closed set.
*/
intent: 'RECOMMENDATION_YES' | 'RECOMMENDATION_NO' | 'RECOMMENDATION_MAYBE' | null;
}Two options sharing the same label are distinguishable by their id.
Response
A response is a single submission to the form.
{
/**
* The UUID of the response (submission)
*/
id: string;
/**
* The display title of the response
*/
title: string;
/**
* The current phase of the response.
*/
phase: { id: string; name: string };
/**
* The ordered history of phase transitions, earliest first.
*/
phaseHistory: PhaseHistoryEntry[];
/**
* The submitter of the response
*/
respondent: User;
/**
* The speakers on this response. A profile is a speaker (contributor);
* a response may carry several.
*/
profiles: Profile[];
/**
* When the response was created, ISO 8601 UTC. Null if unknown.
*/
createdDate: string | null;
/**
* The answers to the 'main' (session / proposal) questions
*/
sessionAnswers: Answer[];
/**
* The evaluations of this response
*/
evaluations: Evaluation[];
/**
* If the response has been linked to an agenda session, its details.
* Absent otherwise.
*/
session?: Session;
}User
{
/**
* The UUID of the user
*/
id: string;
/**
* The display name of the user
*/
name: string;
/**
* The user's email.
* Absent when the publication has contact details turned off.
*/
email?: string;
}PhaseHistoryEntry
{
/**
* The phase transitioned to.
* id is null if the phase has since been deleted; name is retained.
*/
phase: { name: string | null; id: string | null };
/**
* Who initiated the transition
*/
initiator: 'RESPONDENT' | 'TEAM';
/**
* When the transition happened, ISO 8601 UTC
*/
timestamp: string;
}Profile
A profile is a speaker (a contributor on the submission). A speaker’s details — name, email, bio and so on — are carried as model-linked answers, keyed by intent (see the Intent reference), not as flat fields.
{
/**
* The UUID of the profile
*/
id: string;
/**
* The answers to the 'profile' questions for this speaker
*/
answers: Answer[];
/**
* If this profile is linked to an agenda contributor, its UUID. Null otherwise.
*/
contributorId: string | null;
}Session
{
/**
* The UUID of the agenda session
*/
id: string;
/**
* The name of the agenda session
*/
name: string;
}Evaluation
{
/**
* The UUID of the evaluation
*/
id: string;
/**
* The state of the evaluation, eg 'PENDING', 'COMPLETED'
*/
state: string;
/**
* The per-question scores given by the evaluator. Null if none recorded.
*/
scores: EvaluationScore[] | null;
/**
* The evaluator's summary. Null if unset.
*/
summary: string | null;
/**
* When the evaluation was assigned, ISO 8601 UTC. Null if unset.
*/
assignedDate: string | null;
/**
* When the evaluation is due, ISO 8601 UTC. Null if unset.
*/
dueDate: string | null;
/**
* The evaluator
*/
evaluator: User;
/**
* The answers to the 'evaluation' questions
*/
answers: Answer[];
/**
* The phase the evaluation belongs to, if any. Absent otherwise.
*/
phase?: { id: string; name: string };
}EvaluationScore
Scores are per-question — an evaluation may carry several.
{
/**
* The UUID of the question this score is for. Resolves against the form.
*/
questionId: string;
/**
* The numeric score
*/
score: number;
}Answer
An answer is a discriminated union. The discriminant is type (the question type). Check type before reading the variant-specific fields (value, options, files). The variants are: StandardAnswer, OptionsAnswer, DimensionAnswer, ShoutoutAnswer and FileAnswer.
All answers carry these common fields:
{
/**
* The UUID of the answer
*/
id: string;
/**
* The UUID of the question. Resolves against the form.
*/
questionId: string;
/**
* The label of the question. Null if unset.
*/
question: string | null;
/**
* The question's model-link intent (see Intent reference).
* Open set. Absent if the question is not model-linked.
*/
intent?: string;
}StandardAnswer (discriminant type)
| {
type: 'number';
/**
* The numeric value. Null if empty or not a number.
*/
value: number | null;
}
| {
type: 'option' | 'text' | 'textarea' | 'url' | 'email' | 'phone';
/**
* The text value. Null if unanswered.
*
* For 'email' and 'phone', `value` is also `null` when the publication
* (or report) has contact details turned off — the answer is still
* present, but the contact detail is redacted.
*/
value: string | null;
}
| {
type: 'table';
/**
* The parsed table data. Any JSON value (object, array, string, number,
* boolean or null).
*/
value: JSONValue;
}JSONValue is any valid JSON value:
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| { [key: string]: JSONValue };Info
When the publication has contact details turned off, answers to questions of type email and phone are redacted: the answer is still present with the common fields, but its value is null.
OptionsAnswer (discriminant type)
{
type: 'checkbox' | 'radio';
options: OptionSelection[];
}OptionSelection
The common fields plus selected — whether this option is selected.
{
/**
* The UUID of the option. Resolves against the form.
*/
id: string;
/**
* The label of the option. Null if unset.
*/
label: string | null;
/**
* The option's model-link intent. Closed set.
*/
intent: 'RECOMMENDATION_YES' | 'RECOMMENDATION_NO' | 'RECOMMENDATION_MAYBE' | null;
/**
* Whether this option is selected.
*/
selected: boolean;
}DimensionAnswer (discriminant type)
A dimension answer carries a human-readable summary value and a
machine-readable options array — one entry per visible option, in display
order, carrying the option id (resolves against the form), label, model-link
intent, and that option’s value.
{
type: 'dimension';
/**
* Human-readable summary of the answer, eg 'Knowledge: 5, Relevance: 3'.
*/
value: string;
/**
* Per-option values. One entry per visible option, in display order.
*/
options: {
/**
* The UUID of the option. Resolves against the form.
*/
id: string;
/**
* The option's label. Null if unset.
*/
label: string | null;
intent: 'RECOMMENDATION_YES' | 'RECOMMENDATION_NO' | 'RECOMMENDATION_MAYBE' | null;
/**
* The value for this option. Number for numeric dimensions, string for
* text dimensions, or null when unset.
*/
value: string | number | null;
}[];
}ShoutoutAnswer (discriminant type)
{
type: 'shoutout';
/**
* The video links once processed. Null until the video is ready.
*/
value: null | { sharableLink: string; downloadLink: string };
}FileAnswer (discriminant type)
File and image answers carry a list of files. Files are off by default — see Files. When files are off, or none match the selected File Types, files is empty.
{
type: 'ugc-upload' | 'image';
files: File[];
}File
{
/**
* The UUID of the file
*/
id: string;
/**
* The name of the file
*/
fileName: string;
/**
* The File Type of the file (see below)
*/
type: FileType;
/**
* The size of the file in bytes
*/
size: number;
/**
* The mime type of the file, eg 'image/png'
*/
mimeType: string;
/**
* The URL to retrieve the file. Unique to this publication; revoked when
* the publication is deleted.
*/
url: string;
/**
* For image answers, the scaled variants of the image. Empty for files.
*/
variants: FileVariant[];
}FileType (discriminant isPredefined)
The File Type identifiers match the Agenda JSON Endpoint, so files correlate across both feeds.
| {
/**
* A custom File Type created for this event
*/
isPredefined: false;
/**
* The name of the File Type, eg 'Slides'
*/
name: string;
/**
* The UUID of the custom File Type
*/
id: string;
}
| {
/**
* A predefined File Type
*/
isPredefined: true;
/**
* The name of the predefined type, eg 'Speaker Profile Image'
*/
name: string;
/**
* The predefined type id. Additional types may be added over time.
*/
id:
| 'generic'
| 'contributorHeadshot'
| 'contributorLogo'
| 'locationLogo'
| 'locationSponsorLogo'
| 'sessionHandouts'
| 'sessionSlides'
| 'sessionSponsorLogo'
| 'trackLogo';
}FileVariant
Image files have variants — the image scaled to fit within a size. A variant has the same fields as a File plus a scale.
File & {
/**
* The size the image was scaled to fit within
* THUMB = 128x128
* SMALL = 256x256
* MEDIUM = 512x512
* LARGE = 1024x1024
* FULL = the same resolution as the originally uploaded image
*/
scale: 'THUMB' | 'SMALL' | 'MEDIUM' | 'LARGE' | 'FULL';
}Intent reference
Model-linked questions carry an intent. The well-known values are grouped below by the part of the form they belong to (the form group). The intent values for the main group are listed here under Session.
Note
This set is open. New intents may be added at any time, and event managers may build forms whose questions carry intents not listed here. Your code must tolerate unknown intent values and fall back gracefully.
Profile (group profile)
| Intent | Typical question type |
|---|---|
honorific |
text |
firstName |
text |
lastName |
text |
postNominal |
text |
position |
text |
company |
text |
bio |
textarea |
email |
|
phone |
phone |
country |
select-system |
headshot |
image |
logo |
image |
profile-image |
image |
profile-ugc-upload |
ugc-upload |
linkedIn |
url |
twitter |
url |
youtube |
url |
instagram |
url |
facebook |
url |
github |
url |
website |
url |
timeframes |
checkbox |
role |
radio |
profile-labels |
checkbox |
custom-field |
varies |
Session (group main)
| Intent | Typical question type |
|---|---|
title |
text |
description |
textarea |
tracks |
radio |
resources |
checkbox |
locations |
radio |
labels |
checkbox |
duration |
number |
image |
image |
sessionSponsorLogo |
image |
sessionSlides |
ugc-upload |
sessionHandouts |
ugc-upload |
ugc-upload |
ugc-upload |
award-title |
text |
award-image |
image |
award-ugc-upload |
ugc-upload |
Evaluation (group evaluation)
| Intent | Typical question type |
|---|---|
score |
number |
recommendation |
radio |
feedback |
textarea |
evaluation-image |
image |
evaluation-ugc-upload |
ugc-upload |
Webhook
If configured Lineup Ninja will call a webhook after a successful publish. See the developer index for the webhook payload.
Still can’t find what you’re looking for? Email support@lineupninja.com and one of the team will get back to you as soon as possible.