Uploading & ingesting data
There are two ways to get records into an artifact source: upload a CSV file, such as a session export from your practice-management system, or send records through a connected AI tool.
Loading is built to be trivial. When records arrive, the app detects the columns automatically and infers each new column’s type (text, number, date, true/false, and so on). You don’t define a schema by hand. The point is to get data in, connect it to your people, and visualize it for supervision with as little setup as possible.
Core concepts
Section titled “Core concepts”A source has one column that matters for loading: the Reference ID, the identifier each record carries from its origin system, such as an appointment or session ID. Its field name in a record sent by an AI tool is ref_id. Everything else is flexible.
- Reference ID: the stable, unique key for a record within the source. It powers deduplication (below), so the same record updates in place instead of piling up duplicates on re-upload. In a CSV, name this column either
Reference IDorref_id; both work the same. - Every other column is optional and can be any type. You don’t pre-declare them; columns are created and typed from the data as it arrives. There’s no required timestamp, owner, or status column. Include whatever your data has.
- From JSON, a column can route to a nested field. Top-level fields become columns on their own. For a nested one, set the column’s JSON Path on the Columns tab (for example
$.provider.email). See records of any shape.
Deduplication
Section titled “Deduplication”Records are matched on the Reference ID within a source: re-sending a record with a Reference ID already seen updates the existing row instead of creating a duplicate. That’s what makes repeated loads, and re-uploading a corrected export, safe to run as often as you like. A record sent by an AI tool always needs a Reference ID. In a CSV without one, rows are matched by their position in the file, so uploading a different file replaces the earlier rows at the same positions instead of adding to them. Include a Reference ID whenever re-uploads should update the right rows.
CSV upload
Section titled “CSV upload”Choose Upload CSV on the source’s page. It needs Can edit on the source, takes files up to 10 MB and 50,000 rows, and isn’t offered on a derived source or a question set’s results table. The header row is read, any new columns are added to the source automatically, and each one’s type is inferred, so you can start from a spreadsheet or an export without defining the schema by hand. Include a Reference ID (or ref_id) column so the file is safe to re-upload.
A simple session export might look like this:
| Reference ID | Provider Email | Session Date | Service | Status | Billable Hours |
|---|---|---|---|---|---|
| APPT-20931 | maya.chen@example.com | 2026-05-02 | Direct therapy | completed | 3.5 |
| APPT-20932 | david.okafor@example.com | 2026-05-02 | Supervision | completed | 1 |
| APPT-20933 | maya.chen@example.com | 2026-05-03 | Direct therapy | cancelled |
Here Reference ID becomes the matching key, Session Date is detected as a date, Billable Hours as a number, and the rest as text. Blank cells are simply left empty.
Ingesting through an AI tool
Section titled “Ingesting through an AI tool”A connected AI tool can send records into a source, up to 500 records per call, for example records it has pulled out of a session export you gave it. Each record carries its own ref_id, so sending the same records again keeps rows up to date rather than duplicating them. Supply ref_id directly as a field on each record (the Reference ID header is a convenience for CSV uploads), and key the rest of the record by each column’s stable reference.
With data loaded, query it to power reports and metrics.