CSV schema

The formal specification of the upload format, for writing an export or checking a file.

If you are preparing data for the first time, start with Prepare your data, which explains what to put in these columns and why it matters. This page assumes you already know that and need the exact rules.

File format

PropertyRequirement
FormatCSV
EncodingUTF-8
Byte order markTolerated
DelimiterComma
Line endingsLF or CRLF
Header rowRequired
Column orderAny

Quoting and escaping

Standard CSV quoting, as in RFC 4180:
  • A field containing a comma must be wrapped in double quotes.
  • A double quote inside a quoted field is escaped by doubling it.
  • A line break inside a field is allowed, provided the field is quoted.


session_id,timestamp,side,utterance,channel
a1,2024-06-01T09:00:00.000,USER,"I said ""cancel it"", not ""change it""",TEXT
a1,2024-06-01T09:00:05.120,BOT,"Understood.
Which card should I cancel?",TEXT

Columns

Five columns are required. Names are matched exactly as written here.

ColumnTypeRequiredConstraints
session_idstringYesdentifies the conversation. Must be unique across every file you ever upload, not only within one file. Format is yours to choose.
utterancestringYesThe full text of one message, including any markup for buttons or components. No practical length limit. A row with an empty value is dropped — see Rows that are dropped.
timestampstringYesISO 8601, millisecond precision. See Timestamps.
channelenumYesVOICE, TEXT or BUTTON. Case-insensitive.
sideenumYesUSER or BOT. Case-insensitive.

Enumerated values

ColumnAccepted values
channelVOICE — spokenTEXT — typedBUTTON — clicked
sideUSER — the personBOT — the assistant

Case does not matter: TEXT, Text and text are all accepted. The documentation uses upper case throughout for legibility.

Timestamps

Pattern: YYYY-MM-DDTHH:MM:SS.sss followed by an optional time zone.

FormExampleInterpreted as
No zone2024-06-01T09:00:00.123UTC
Z2024-06-01T09:00:00.123ZUTC
Offset2024-06-01T09:00:00.123+02:00That offset

Use millisecond precision. Inquio orders utterances within a conversation by timestamp, so at second-level precision a user message and an assistant message that share a second may be ordered wrongly — which changes what the conversation appears to say.

Row order in the file does not matter. Inquio sorts by timestamp itself, so an export that emits conversations out of order is fine.

Optional columns

ColumnTypeDescriptionExample
custom_metastringAny parameter or flag belonging to that utterance — a thumbs up or down, a client ID, an outcome marker. Read and displayed alongside the conversation.success

Any other column you include is ignored. Extra columns never cause a failure, so there is no need to strip your export down.

Note that custom_meta is per row, not per conversation. Each utterance carries its own value, so you can mark the single answer a user rated badly rather than labelling the whole exchange.

What makes a file fail

There are two different outcomes, and the difference matters: one stops the upload, the other is silent.

Errors that reject the file

Nothing is analyzed and the upload reports Validation failed, listing what was wrong. See When processing fails.

  • The header is missing one or more required columns.
  • The file is not valid CSV — for example an unterminated quoted field.
  • The file is not readable as UTF-8.
  • Every session_id in the file is already present in Inquio.

Rows that are dropped

These do not stop the upload. The row is discarded, the rest of the file is processed, and nothing tells you it happened.

  • An empty utterance.

That last point is worth designing around. If your export produces empty utterances — for a button click with no label, a system event, an attachment with no text — those messages disappear from the conversation without a trace, and the analysis reads a conversation with holes in it. Filter them out deliberately, or give them text, rather than letting them be dropped silently.

What Inquio does with the file

In order:
  1. Validate. Format and header are checked. A failure here stops everything.
  2. Drop invalid rows. Rows that cannot be used are discarded.
  3. Remove duplicates. Any session_id already in Inquio is skipped, and not charged.
  4. Truncate. If what remains exceeds your plan's limits, the oldest data that fits is kept and the rest discarded, with a note on the report card.
  5. Analyze.

Limits per plan are in Plans and limits.

Complete example

One conversation, all five columns:

session_id,timestamp,side,utterance,channel
cc145dc461eefd1ff1,2024-06-01T08:12:03.000,BOT,"Hello, I am your virtual banking assistant. How can I help you?<buttons><button title=""Account statements""></button><button title=""Card problems""></button></buttons>",TEXT
cc145dc461eefd1ff1,2024-06-01T08:12:19.447,USER,Account statements,BUTTON
cc145dc461eefd1ff1,2024-06-01T08:12:20.101,BOT,"Statements for the last 12 months are in the Documents section of your online banking. Which account do you need?",TEXT
cc145dc461eefd1ff1,2024-06-01T08:12:41.882,USER,"The savings one, ending 4471",TEXT
cc145dc461eefd1ff1,2024-06-01T08:12:42.503,BOT,"Your savings account statements are ready to download. Anything else?",TEXT
cc145dc461eefd1ff1,2024-06-01T08:12:58.219,USER,"No, thanks.",TEXT

Note the assistant's first row: the button markup is included, the channel is TEXT even though buttons are offered, and the user's reply carries the button's visible label with channel set to BUTTON.

A ready-made file is also available from Template on the upload screen.

Related