> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solo.one/llms.txt
> Use this file to discover all available pages before exploring further.

# JSONL Files

> Furnish batches of records as JSONL files, from the dashboard or over SFTP

A JSONL file furnishes a whole batch of records at once. There is one file
format and two ways to deliver it:

* **The dashboard** — upload a file from the SOLO dashboard. No credentials or
  file-transfer infrastructure beyond your sign-in.
* **[SFTP](/api-overview/sftp/overview)** — drop files from systems that
  already produce them on a schedule.

Both land in the same place and run through the same
[furnishing pipeline](/api-overview/furnishing/overview) as a per-record REST
furnish. A record uploaded in a file and the same record furnished over HTTPS
produce identical network data.

## File format

A JSONL file is UTF-8 text with **one JSON object per line**:

```json furnish_records.jsonl theme={null}
{"_type":"kyc_certificate","ssn":"123456789","dob":"1990-01-01","first_name":"Alice","last_name":"Anderson"}
{"_type":"kyb_certificate","ein":987654321,"jurisdiction":"DE","legal_name":"Acme Holdings LLC"}
```

* **Extension** — `.jsonl`.
* **Filename** — exactly one dot, and a name made of letters, digits,
  underscores, and hyphens: `consumers_aug.jsonl` is valid; `consumers aug.jsonl`
  (space) and `consumers.aug.jsonl` (two dots) are rejected.
* **Blank lines** are skipped and don't count as records.
* **Every line is independent.** A line that isn't valid JSON fails on its own;
  the rest of the file still ingests.
* **Dashboard uploads** are limited to 10 MB per file.

## Record types

Every record carries a `_type` field naming what kind of record it is. That
value is how the network decides which [mappings](/concepts/governance/furnishing-policies)
receive the record:

* Each **feed** in the dashboard declares a sample record. The sample's `_type`
  is the record type that feed's mappings claim.
* A record is sent to **every active mapping** in the target network that claims
  its `_type`. One record can therefore feed several mappings — for example,
  one that persists document-capture events and another that persists
  biometric-capture events from the same line.
* A record whose `_type` **no mapping claims** is counted as *unmatched* and
  skipped. Unmatched records never fail the file: they're expected when a file
  carries record kinds this network doesn't ingest.
* A mapping can also bound when it accepts records. A record whose type is
  claimed but that arrives outside every claiming mapping's window is reported
  separately from an unclaimed type, so the two causes are easy to tell apart.

The rest of each record is whatever your mapping reads. The mapping's source
schema, shown on the feed in the dashboard, lists the fields it requires.

## Choosing the network

Records are written to exactly one network per file:

* **Dashboard** — the upload dialog asks which network to furnish into. It
  selects the network automatically when you can furnish into only one.
* **SFTP** — put the file under `network_<network_id>/jsonl_furnish_data/` to
  target a network explicitly. A file directly under `jsonl_furnish_data/` goes
  to your organization's governed network.

Either way, your organization must hold the **furnisher** or **governor**
[role](/concepts/governance/network-roles) in that network.

## Uploading from the dashboard

The same upload dialog opens from three places:

* **Upload JSONL records** in the command palette.
* **Furnish** on a product's detail page.
* **Upload data** on an SFTP feed's detail page.

Pick the file, confirm the network, and submit. The upload is accepted
immediately and ingested in the background.

## Results

When ingestion finishes, the upload records what happened to every line:

| Count | Meaning |
| - | - |
| **Records** | Non-blank lines read from the file. |
| **Succeeded** | Record and mapping pairs that persisted. |
| **Filtered** | Record and mapping pairs a mapping skipped on purpose (for example, a filter excluded them). Filtered is not failed. |
| **Failed** | Lines that weren't valid JSON, plus record and mapping pairs that errored. |
| **Unmatched** | Records whose `_type` no active mapping claims. |

Errors are grouped by cause, with sample line numbers, so a thousand records
failing the same way show up as one error rather than a thousand. Review them
on the dashboard's **Uploads** page, or on a feed's recent deliveries, which
also name the unmatched record types.

<Tip>
  Re-sending a corrected file is safe. Identity records resolve to the existing
  consumer or business on their natural keys (SSN and date of birth for
  consumers; tax identifier and jurisdiction for businesses), so a re-upload
  attaches to the same profile instead of creating a duplicate.
</Tip>

## Failure modes

<AccordionGroup>
  <Accordion title="The file is rejected before upload">
    The dashboard checks the extension, the filename rules, and the size before
    sending anything. Rename the file (letters, digits, `_`, `-`, one dot,
    `.jsonl`) or split it into smaller files.
  </Accordion>

  <Accordion title="Every line fails as invalid JSON">
    The file isn't UTF-8 JSONL — often a JSON array (`[{…},{…}]`) or a
    pretty-printed object spread across several lines. Write one compact object
    per line.
  </Accordion>

  <Accordion title="Records are counted as unmatched">
    No active mapping in the target network claims their `_type`. Check the
    value against the feed's sample record, confirm the mapping is active
    rather than a draft, and confirm the file went to the network you expected.
  </Accordion>

  <Accordion title="Records fail against a mapping">
    The record doesn't carry what the mapping reads — usually a missing required
    field or a value of the wrong type. The grouped error names the field;
    compare the record with the mapping's source schema.
  </Accordion>
</AccordionGroup>

## In the dashboard

<Frame caption="Product furnish — JSONL records ready to upload">
  <img src="https://mintcdn.com/soloone/9HdwBb7FHoPnTmO1/images/dashboard/journeys/furnishing/furnishing-complete/05-product-furnish-upload-filled.png?fit=max&auto=format&n=9HdwBb7FHoPnTmO1&q=85&s=a644c791630bc349fc2ae319c5d28dd5" alt="Product furnish — JSONL records ready to upload" width="1440" height="900" data-path="images/dashboard/journeys/furnishing/furnishing-complete/05-product-furnish-upload-filled.png" />
</Frame>

<Frame caption="Product furnish — upload accepted, dialog closed">
  <img src="https://mintcdn.com/soloone/9HdwBb7FHoPnTmO1/images/dashboard/journeys/furnishing/furnishing-complete/06-product-furnish-upload-success.png?fit=max&auto=format&n=9HdwBb7FHoPnTmO1&q=85&s=a33c50d56a51b6ce19ae0d9fc2b7eb77" alt="Product furnish — upload accepted, dialog closed" width="1440" height="900" data-path="images/dashboard/journeys/furnishing/furnishing-complete/06-product-furnish-upload-success.png" />
</Frame>

<Frame caption="File uploads list (ingest status)">
  <img src="https://mintcdn.com/soloone/9HdwBb7FHoPnTmO1/images/dashboard/journeys/furnishing/furnishing-complete/09-uploads-list.png?fit=max&auto=format&n=9HdwBb7FHoPnTmO1&q=85&s=64c5f006b9eb53253c5410e518ea64dd" alt="File uploads list (ingest status)" width="1440" height="900" data-path="images/dashboard/journeys/furnishing/furnishing-complete/09-uploads-list.png" />
</Frame>

## When to use a different channel

* **One record at a time, in real time** — use the product furnish endpoints,
  e.g. `POST /v1/products/kyc_certificate_snapshot/furnish`. See the
  [furnishing overview](/api-overview/furnishing/overview).
* **Recurring drops from systems that produce files natively** — use
  [SFTP](/api-overview/sftp/getting-started). Same files, same pipeline, no
  dashboard session required.

<CardGroup cols={2}>
  <Card title="SFTP Getting Started" icon="rocket" href="/api-overview/sftp/getting-started">
    Deliver JSONL files on a schedule.
  </Card>

  <Card title="Furnishing Policies" icon="shield-check" href="/concepts/governance/furnishing-policies">
    How mappings turn records into network data.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.