Documents
A shared file library with favorites, labels, search, and AI extraction that reads PDFs and fills a form for you.
The document explorer is a flat, searchable library for uploaded files. A file can be standalone or attached to a record, such as a job, purchase order, or RFQ. Attached files appear on both the record and in the explorer. The library supports personal pins and labels, name and description search, and AI extraction that reads supported PDFs and prefills forms.
Open the explorer from Documents in the sidebar. It defaults to the All Documents view (useDocumentsSubmodules.tsx:15-45).
The explorer
The table lists accessible files with pinned files first (documents.service.ts:86-88). Each row shows the name, linked source document, personal labels, size, type, extension, and created and updated metadata (DocumentsTable.tsx:174-405).
Five views scope the list, switched by the tab rail down the left (useDocumentsSubmodules.tsx:15-45):
createdBy = you).Type is derived, not chosen. When a file is uploaded, Carbon reads its name and classifies it into one of ten buckets: Archive, Document, Presentation, PDF, Spreadsheet, Text, Image, Video, Audio, or Other (20230423023136_documents.sql:1-12). The extension column is computed by the database from the filename itself (the text after the last dot), so it always matches the real file (20230423023136_documents.sql:20).
Trash is a soft delete, not a purge
"Move to Trash" only flips the file's active flag to false — the row and the stored file both stay put, and "Restore from Trash" flips it back (documents.service.ts:124-152). To actually remove a file, use Permanently Delete from the row menu; that one cannot be undone (DocumentsTable.tsx:461-471).
Uploading
Upload accepts any file. The browser uploads it to private storage at {companyId}/{random}.{ext}, then creates a document row with its path, name, and size (DocumentCreateForm.tsx:22-69). Uploads, downloads, edits, favorites, and label changes create activity transactions that drive the Recent view (useDocument.ts:44-57, 20230423023136_documents.sql:117-146).
Who can see a file
Visibility depends on group membership and permissions. A user can view a document only when they belong to one of its readGroups and have documents view permission. Editing or deleting also requires membership in a writeGroups entry and the corresponding permission (20230423023136_documents.sql:40-66, useDocument.ts:22-42). Private storage applies the same read-group rule, so unauthorized links do not resolve (20230423023136_documents.sql:68-119).
Groups are Carbon's company groups
Read and write groups are drawn from your membership, the same groups used elsewhere for scoping. Set them when you edit a document's properties; a file with no matching read group for a user is simply invisible to that user.
Pins and labels
Two personal organizers sit on top of the shared library, and both are per-user — what you pin or label is yours alone, not the whole company's.
- Pins (shown as a pushpin, called "Favorite" in the row menu) float a file to the top of your list and power the Pinned view. Toggling one writes or removes a
documentFavoriterow keyed to you (useDocument.ts:113-130,documents.service.ts:199-219). - Labels are free-text tags you attach to a file. Type into the label popover on a row to reuse an existing label or create a new one on the fly; click a label to filter the list down to it (
DocumentsTable.tsx:239-296,useDocument.ts:142-164). Labels are stored per user, so your "Q3-audit" label doesn't clutter a colleague's view (20230423023136_documents.sql:186-215).
Search
Search performs a case-insensitive substring match on name and description, not file contents (documents.service.ts:72-76). Combine search with filters for source document, label, type, extension, or creator and with the view tabs. Download CSV exports the current result set with a signed download link for each row (search.tsx, DocumentsTable.tsx:393-405).
How documents attach to records
A document can point back at the record it belongs to. The row's Source Document column shows that link and jumps straight to the parent record (DocumentsTable.tsx:207-237). The set of record types a document can attach to is fixed (documents.models.ts:9-23):
The attachment is stored as a sourceDocument (the type) plus a sourceDocumentId (the record's id) on the file (documents.service.ts:154-183). Because the file also lives in the shared explorer, you can find it either by opening the record or by searching the library. See the sales orders, purchase orders, and jobs references for where each record surfaces its files, and suppliers & customers for the party-level Documents tab.
AI extraction
In supported workflows, Carbon can extract fields from a PDF and prefill a form. Two document types are supported (document-extraction.ts:9-13, documents.models.ts:126):
- a Request for Quote PDF, on the sales side, and
- a Purchase Invoice PDF, on the purchasing side.
What it does, step by step
When you drop a PDF into one of those flows, Carbon creates a documentExtraction row (starting at status pending) and enqueues a background job (documents.service.ts:248-296, 20260609001724_add-document-extraction.sql:4-30). The job then (extract-document.ts:26-232):
- flips the row to
processing; - downloads the PDF from private storage and extracts its text with a PDF parser (this is text extraction, not image OCR — a scanned image-only PDF yields no text);
- loads the company's candidate records so the model can resolve names to real ids itself — suppliers and payment terms for an invoice, customers for an RFQ (
extract-document.ts:84-140); - sends the text plus those candidate lists to the AI model, which returns every field as a
{ value, confidence }pair (schemas.ts:1-88); - filters by confidence: any field scoring below the threshold (default
0.85) is dropped tonull, so a low-confidence guess never lands in your form (extract-document.ts:184-224,packages/env/src/index.ts:173-178); and - normalizes dates to
YYYY-MM-DDand saves both the raw output and the filtered result on the row, statuscompleted(extract-document.ts:184-232).
The form then reads the filtered values and pre-fills itself, matching extracted contacts and addresses against the customer's or supplier's existing records where it can (documents.models.ts:168-255).
It resolves ids for you, it doesn't invent them
The model is handed the actual list of your suppliers, payment terms, or customers and told to return the id of the single best match or null — never to make one up (extract-document.ts:141-152). So supplierId / customerId / paymentTermId come back either as a real record you already have or as blank, and the form's own matching fills the rest.
What it pulls out
For a Purchase Invoice, extraction targets the supplier (name, contact, address, and a resolved supplierId), the invoice header (number, invoice and due dates, payment terms and a resolved paymentTermId, referenced PO number, currency), the money (subtotal, tax, shipping, total), and the line items (part number, description, quantity, unit price, line total) (schemas.ts:20-54).
For a Request for Quote, it targets the customer (name, a resolved customerId, plus separate purchasing and engineering contacts and the customer address), the RFQ header (number, RFQ date, due date, requested delivery date), and the line items (part number, description, quantity) (schemas.ts:63-86).
Extraction is a draft, not a commit
A documentExtraction row is only a staging area — it never creates an invoice or an RFQ by itself. The extracted values pre-fill the normal form, and the real record is created through the usual permission-gated route action when you save (20260609001724_add-document-extraction.sql:37-39). If the background job can't be enqueued or the parse fails, the row is marked failed with the error, and you just fill the form manually (documents.service.ts:272-295, extract-document.ts:225-231).
Extraction quality depends on the PDF being text-based and on the AI keys being configured for your deployment; without them the flows still work, you simply type the fields yourself.
Not the document template customizer
This page is about the file library. The separate document template feature — the drag-and-drop customizer for the PDFs Carbon generates (quotes, order confirmations, invoices) — is a different subsystem and isn't covered here.