Workflows
A workflow is the central unit in Alk. It defines what documents you process, what data you extract, and how results are organized. Every API call in this reference is scoped to a workflow_id.
What a workflow contains
| Concept | Role |
|---|---|
| Columns | Extraction fields — each has a name, type (text, number, date, singleSelect, multiSelect, url, table), and a natural-language prompt that tells Alk what to pull from documents. |
| Documents | Files uploaded into the workflow (PDFs, images, and other supported types). |
| Collections | Optional folders that group related documents (for example, one loan package or one deal). |
| Stages | Optional pipeline states for organizing work inside the workflow. |
| Extractions | Structured values produced when Alk runs columns against your documents. |
At a high level:
Code
Workflow lifecycle
- Configure — columns and prompts are defined for the workflow (typically in the Alk dashboard; your account team provisions the workflow ID).
- Ingest — upload documents via direct multipart upload or the signed URL flow.
- Extract — run bulk or per-document extraction so Alk populates column values.
- Retrieve — list extractions, read workflow status (
extraction_status,is_extracting), and integrate results into your product.
Workflow status fields you will see in API responses include:
status— workflow state (for exampledraft)extraction_status— overall extraction progress (not_started,pending,complete,has_failures)is_extracting— whether an extraction job is currently running
Setting up a workflow
Most teams receive a workflow ID from Alk after onboarding. You can also create your workflows yourself. That ID is all you need to call the API.
If you are configuring a new use case with your account team, align on:
- Column schema — field names, types, and prompts for each data point you need.
- Collection strategy — whether documents should be flat in the workflow or grouped (and default collection names, if any).
- Extraction triggers — manual via API after upload, batch on a schedule, or event-driven from your backend.
- Environments — separate test and live workflows or keys as needed.
Verify setup via API
Confirm the workflow is ready before building upload logic:
Code
A successful response includes columns, and optionally documents and stages, so you can validate IDs used in later calls.
List columns separately
When you only need schema metadata:
Code
Use returned column id values when filtering extractions or passing column_ids to bulk extract.
Working with documents and collections
Documents are the files Alk processes. Upload them with:
POST /api/v1/workflows/{workflow_id}/documents— multipart upload from your serverPOST .../documents/upload-urlthenPOST .../documents/confirm— signed URL flow for larger or client-origin files
Collections group documents. When uploading, you can:
- Pass
collection_idto add files to an existing collection - Pass
collection_nameto create a new collection and add files in one step
Collections are useful when extraction should consider multiple files together or when your product UI mirrors folder-style organization.
Bulk upload with per-person validation data
POST .../documents/bulk (multipart) and POST .../documents/confirm/bulk (JSON, signed URL flow) upload files for many people or groups in one call, each with its own validation_data. Limits and response shape match between the two; confirm/bulk groups by items[].file_ids instead of on-disk files.
Reference
| Field | Where | Type | Required | Notes |
|---|---|---|---|---|
files | /documents/bulk request | file[] | Yes | Every file must be referenced by exactly one manifest item |
manifest | /documents/bulk request | string (JSON array) | Yes | One item per person or group |
items | /documents/confirm/bulk request | array | Yes | One item per person or group |
extract_when_ready | Either request | boolean | No, default false | Auto-starts extraction once the batch is ready; see below |
files | manifest item | filenames or indexes | Yes | Uploaded filename, or zero-based index into files[]. Use an index when filenames repeat or a file has none |
file_ids | confirm item | string[] | Yes | IDs from .../documents/upload-url |
collection_id | item | string | No | Add to an existing collection. Mutually exclusive with collection_name |
collection_name | item | string | No | Create a new collection |
validation_data | item | object | No | Max 50 keys, 4096 bytes. Replaces stored data wholesale, never merges |
file_names | manifest item | string[] | No | Display names parallel to files. Multipart only |
Limits: 100 files and 100 items per request (confirm/bulk: 100 file_ids total across items); 100 MB per file; validation_data capped at 50 keys / 4096 bytes per item, same as POST .../documents and POST .../documents/confirm.
Item shape
An item becomes a standalone document or a collection, and a request can mix both:
| Item shape | Result | validation_data stored on |
|---|---|---|
| One file, no collection field | Standalone document | The document |
One file with collection_name/collection_id | Joins that collection | The collection |
Several files with collection_name/collection_id | Collection holding them | The collection |
| Several files, no collection field | Rejected (400) | - |
Behavior
- Validation is per item. Each item validates against its own
validation_data, somatchedis reported per item, not once for the batch. - Bad manifests reject the whole call. Any rule above is violated: nothing uploads.
400on/documents/bulk;422onconfirm/bulk, since that body is JSON rather than a parsed string. - Partial success is per item. Failures that only surface while uploading (a
collection_idthat does not exist, a storage error) return HTTP 200 withuploaded_count(documents created across all items),failed_count(items that failed), and one result per item in the order sent. Checkerroron each item: a failed item has nodocuments, and any files it already uploaded are rolled back; the rest of the batch is unaffected.documentswithin a successful item follows the order its files were listed. - Late additions keep existing reference data. Omit
validation_datawhen appending to a collection to leave its stored data untouched. file_idsare single-use. Afile_idmay appear in only one confirm item.- Confirmed documents have
label: null. They take their name from the stored file rather than a display name. - Extraction does not start on its own. Poll
GET .../documentsuntil documents reachconverted, then callPOST .../extract, or setextract_when_readyto skip the poll (below).
extract_when_ready
Set extract_when_ready: true on the upload or confirm request to start extraction automatically once the batch is ready, instead of polling conversion status yourself.
- A document counts as ready once it has converted or failed conversion, so one bad file cannot stall the batch.
- Documents from multiple uploads that become ready together coalesce into a single extraction run.
- If the account has insufficient credits, nothing starts, and the reason is recorded on the affected documents'
error_message.
Examples
One document per person, no collections:
Code
Grouping files into a collection (an item with more than one file must name a collection):
Code
A mixed batch: two new collections, a late report appended to an existing collection, and two standalone documents. manifest is always a string form field holding a JSON array; it is shown expanded here for readability:
Code
Send it with every file it references:
Code
Response
One entry per manifest item, in the order sent. The example below is abridged to the first item (one of its two documents) and the last item, which failed; the counts cover the whole eight-file batch above. Each document carries its id, which is what you pass to .../documents/{document_id}/extract and use to match documents when polling GET .../documents:
Code
Appending a late file to an existing collection, without touching its stored validation_data:
Code
The signed URL equivalent: generate URLs with .../documents/upload-url, upload the bytes, then call POST .../documents/confirm/bulk with the same per-item grouping, using items[].file_ids in place of files on disk.
Running extraction
After documents are in the workflow:
Code
Filter by document_ids, collection_id, or column_ids when you do not need a full workflow re-run.
- Only converted documents are covered. Calling
/extractwhile some documents in the workflow are still converting extracts only the ones that have already converted; the rest are skipped, not queued. Setextract_when_readyon the upload call to avoid polling for this yourself. - Extraction resumes, it does not restart. Calling
/extractagain is safe: it picks up only cells that have not been settled, so it never redoes completed work and never overwrites a value a person has edited or verified. A long run continues itself across multiple internal executions rather than stopping partway.
See Integration Journey for the full upload-to-results path.
Next steps
- Integration Journey — end-to-end rollout from credentials to production
- Best Practices — security and operational guidance
- API Reference — all workflow, document, upload, and extraction endpoints