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.
Terminology
Lineup Ninja’s user interface and this feed sometimes use different names for the same thing. The feed’s field names are the contract, so this reference uses them for every type and field; the descriptions name the concepts by their product term. This table maps between the two.
| Product term | In the feed | What it is |
|---|---|---|
| Submission Flow | the whole document (title, id) |
The Call for Papers / awards / data-gathering flow this feed describes |
| Submission | responses[] |
A single entry to the form |
| Submitter | response.respondent |
The person who created the Submission |
| Speaker | response.profiles[] |
A contributor on the Submission (a Submission may have several) |
| Submission Stage | form.responsePhases[], response.phase, response.phaseHistory |
A stage of the submission lifecycle; carries per-question visibility |
| Review | response.evaluations[] |
A Reviewer’s assessment of a Submission |
| Reviewer | evaluation.evaluator |
The person who carries out a Review |
| Review Stage | form.evaluationPhases[], evaluation.phase |
A stage of the review process; owns the Review questions |
| Review question | a question with group: 'evaluation' |
A question Reviewers answer, within a Review Stage |
A Submission Stage and a Review Stage are both phases internally, which is why the field carrying one is named phase in both places — the product term depends on which it relates to: a Submission’s phase is a Submission Stage, a Review’s phase is a Review Stage.
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 — its sections and questions, and its Review Stages and Review questions. Answers on Submissions reference form questions and options by id.
{
/**
* The sections of the form, in position order. Each section owns its
* 'main' / 'profile' questions.
*/
sections: FormSection[];
/**
* The Review Stages, in position order. Each stage owns the evaluation
* questions reviewers answer in that stage. An evaluation's `scores` and
* `answers` resolve their question id against the questions nested here.
*/
evaluationPhases: EvaluationPhase[];
/**
* The Submission Stages, in position order. Each records which 'main' /
* 'profile' questions are editable / locked / hidden in that stage. A
* Submission's `phase` (and each `phaseHistory` entry) resolves here.
*/
responsePhases: ResponsePhase[];
}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 are not grouped into sections — they appear under
* their Review Stage in the top-level `evaluationPhases` array, not here.
*/
group: 'main' | 'profile';
/**
* 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:
* - 'profile' a question about the people submitting
* - 'main' a question about the submission itself
* - 'evaluation' a question answered by a reviewer (nested under a Review
* Stage in form.evaluationPhases, with a null sectionId)
*/
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. Null for evaluation
* questions, which are grouped under a Review Stage instead
* (see form.evaluationPhases).
*/
sectionId: string | null;
/**
* 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.
EvaluationPhase
A Review Stage — a stage of the review process in which Reviewers answer Review questions. Each stage owns its questions; a Review’s phase resolves to the stage here.
{
/**
* The UUID of the Review Stage
*/
id: string;
/**
* The name of the Review Stage
*/
name: string;
/**
* The position of the Review Stage, for ordering
*/
position: number;
/**
* The evaluation questions answered in this stage, in form order
*/
questions: FormQuestion[];
}ResponsePhase
A Submission Stage — a stage of the submission lifecycle. Each Submission Stage records the visibility of every main / profile question while a Submission is in that stage: a question is editable (the Submitter can change it), locked (shown but read-only) or hidden (not shown). Every such question falls into exactly one of the three lists. This visibility is only tracked on Content Portal events; on other events all three lists are empty (see questionVisibility below). (Evaluation questions are not governed by Submission Stages — their visibility follows their Review Stage.)
{
/**
* The UUID of the Submission Stage
*/
id: string;
/**
* The name of the Submission Stage
*/
name: string;
/**
* The position of the Submission Stage, for ordering
*/
position: number;
/**
* Which questions are editable / locked / hidden in this stage. Each entry
* references a question by `{ id, name }` (name being the question label),
* in form order.
*
* Only populated for Content Portal events. On other events all three lists
* are empty — per-stage question visibility is not tracked there.
*/
questionVisibility: {
editable: QuestionReference[];
locked: QuestionReference[];
hidden: QuestionReference[];
};
}QuestionReference
A lightweight pointer to a question; resolve id against the form for the full definition.
{
id: string;
/**
* The question label. Null if unset.
*/
name: string | null;
}Response
A Submission — a single entry to the form. (Feed field: responses.)
{
/**
* The UUID of the Submission
*/
id: string;
/**
* The display title of the Submission
*/
title: string;
/**
* The current Submission Stage. Its id resolves against form.responsePhases.
*/
phase: { id: string; name: string };
/**
* The ordered history of Submission Stage transitions, earliest first.
*/
phaseHistory: PhaseHistoryEntry[];
/**
* The Submitter
*/
respondent: User;
/**
* The Speakers on this Submission. A profile is a Speaker (contributor);
* a Submission may carry several.
*/
profiles: Profile[];
/**
* When the Submission was created, ISO 8601 UTC. Null if unknown.
*/
createdDate: string | null;
/**
* The answers to the 'main' (session / proposal) questions
*/
sessionAnswers: Answer[];
/**
* The Reviews of this Submission
*/
evaluations: Evaluation[];
/**
* If the Submission 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
A single transition in a Submission’s history of Submission Stages.
{
/**
* The Submission Stage transitioned to.
* id is null if the stage 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
A Review — a Reviewer’s assessment of a Submission. (Feed field: evaluations.)
{
/**
* The UUID of the Review
*/
id: string;
/**
* The state of the Review, eg 'PENDING', 'COMPLETED'
*/
state: string;
/**
* The per-question scores the Reviewer gave. Null if none recorded.
*/
scores: EvaluationScore[] | null;
/**
* The Reviewer's summary. Null if unset.
*/
summary: string | null;
/**
* When the Review was assigned, ISO 8601 UTC. Null if unset.
*/
assignedDate: string | null;
/**
* When the Review is due, ISO 8601 UTC. Null if unset.
*/
dueDate: string | null;
/**
* The Reviewer
*/
evaluator: User;
/**
* The answers to the Review questions
*/
answers: Answer[];
/**
* The Review Stage the Review belongs to. Always present;
* its id resolves against form.evaluationPhases.
*/
phase: { id: string; name: string };
}EvaluationScore
Scores are per-question — a Review 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 |
Review questions (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.