Developer Documentation for Submission JSON Endpoint

Intro

The Submission JSON Endpoint makes all of an event’s Call for Papers (CFP) submission data available at a single endpoint. The data is returned in one document describing the whole submission form and every response to it.

In a hurry? Jump to Finding common data for the route to the submitter, the speakers and the session title.

To create an endpoint a new ‘JSON’ publication needs to be configured by an event manager, this will generate a unique URL for the event.

The document is self-describing. The top-level _meta object carries a schemaVersion (currently 1) and a documentationUrl pointing back to this page. See the Schema Reference for the full typed definitions.

Requesting the data

Warning

The endpoint is not for consumption directly by an end-user app, or other similar software. You must ingest the data into your system and use it from there.

To request the submission data perform a GET to the URL you have been provided by the event manager. This URL is unique for each publication. The endpoint may require credentials using HTTP Basic Auth depending on the settings in the configuration.

The endpoint always returns a 302 redirect to a temporary URL for the location of the data. The destination of this redirect changes for each request and will expire. You should always begin your request from the initial URL starting with http://api.lineup.ninja, and your client must follow redirects.

Refreshing the data

The event manager will make changes to their content over the course of time. To receive the changes you can either poll every 5 minutes, or integrate the webhook to receive an instant notification that new submission data is ready.

The endpoint serves the data as it was at the most recent publication, so the _meta.generatedAt timestamp changes only when the event manager (re)publishes, not on every request.

If you are polling the data be sure to schedule the removal of the polling after the event has completed.

When content is removed from an event, eg a submission is withdrawn, you will not receive an explicit notification. Instead, because the document contains the full set of data for the event, you should treat the absence of a previously existing object as a request to delete that object.

Files

The event manager can choose to include links to files uploaded against submissions — for example headshots, company logos, session slides, handouts and other uploads.

Files are off by default. To include them the event manager enables files in the publication configuration. They can choose to include all files, or only files of selected File Types.

File selection is by File Type, using the same type identifiers as the Agenda JSON Endpoint, so a file’s type correlates across both feeds. Each file in the feed carries its File Type (see type in the Schema Reference).

The included links are unique to each publication for the event. If the event manager deletes the publication the links will cease to operate.

Interpreting answers

The document has two halves that work together:

  • The form describes the whole submission form — its sections, questions and options — even questions that nobody has answered. Use it to render or map the form.
  • Each response carries the answers, referencing the form’s questions and options by id.

A response has a respondent — the person who submitted it — and one or more profiles. A profile is a speaker (a contributor on the submission); a single response can carry several profiles, for example a panel with multiple speakers. The respondent is often, but not always, also one of the speakers. A speaker’s details (name, email, bio, …) are not flat fields — they live in that profile’s answers, keyed by the question’s intent.

An answer is a discriminated union keyed by its type (the question type, eg text, number, table, checkbox, ugc-upload). Check the type before reading the variant-specific fields (value, options, files). Each answer’s value is typed to match its question type — a number answer’s value is a number, a table answer’s value is parsed JSON — rather than always a string. See the Schema Reference for every variant.

A submission’s state is its current phase (response.phase), which is always present — every submission is placed into a phase when it is created. Each response also carries an ordered phaseHistory of the transitions it has been through.

Interpreting intents

Many questions are model-linked — the event manager has tied them to a known field such as the submitter’s first name, the session title, or an evaluator’s score. Where a question is model-linked, the form question and the matching answer carry an intent string (eg firstName, title, score).

The intent set is open: new intents may be added over time, so your code must tolerate values it does not recognise. A question with no model link carries no intent. The Schema Reference lists the well-known intent values grouped by profile, session and evaluation.

Options on recommendation questions additionally carry a closed intent of RECOMMENDATION_YES, RECOMMENDATION_NO, RECOMMENDATION_MAYBE or null.

Finding common data

The most frequently needed values and where to read them. Remember a profile is a speaker, and a speaker’s details live in that profile’s answers keyed by the question’s intent — so a small helper to pull a value out by intent is handy:

const answerFor = (answers, intent) =>
    answers.find((a) => a.intent === intent)?.value ?? null;
What you want Where to find it
The submitter’s name response.respondent.name
The submitter’s email response.respondent.email (omitted when contact details are off)
A speaker’s name per profile in response.profiles, join firstName + lastNameanswerFor(profile.answers, 'firstName'), answerFor(profile.answers, 'lastName')
A speaker’s email per profile in response.profilesanswerFor(profile.answers, 'email') (null when contact details are off)
The session title response.title — the authoritative title (it may be composed from more than just the title question)

See Interpreting intents for the full list of intent values, and the Schema Reference for every field.

Contact details

By default the feed includes contact details (email and phone). The event manager can turn these off in the configuration of both the JSON publication and the one-off JSON report.

Redaction is driven by the question type, not by an intent: when contact details are off, the structured email fields on respondent / evaluator are omitted and every answer to a question of type email or phone has its value set to null (the answer is still present, so the question is still discoverable). Driving redaction off the question type closes the gap where an email value would otherwise survive in the answers array after the structured email field was dropped.

Webhook

If configured Lineup Ninja will call a webhook after a successful publish of the submission data. The webhook is called as a POST with this body:

{
    /**
     * The UUID of the event
     */
    eventId: string;
    /**
     * The name of the event
     */
    eventName: string;
    /**
     * The timestamp for the publication. You can use this to deduplicate calls to the webhook
     * It is in epoch time with milliseconds (A javascript timestamp)
     */
    publicationTimestamp: number;
    /**
     * The UUID for the integration. The customer may wish to configure multiple integrations per event,
     * for example to different staging and production events. This ID can uniquely identify them
     */
    integrationId: string;
    /**
     * Deprecated alias for integrationId. Prefer integrationId.
     */
    endpointId: string;
}

The webhook tells you that new data is ready; it does not contain the submission data itself. Fetch the endpoint to retrieve it.

To create the webhook ask the event manager to edit the configuration to set the value of ‘Webhook URL’ to your desired URL.


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