Files
Uploading a File
Slate uses presigned S3 URLs for file uploads. Your application never sends file bytes directly to the Slate API. Instead, you get a short-lived upload URL and form fields from Slate, then POST the file directly to S3 using multipart form data.1
Create a file record and get a presigned upload URL
Call Response:
POST /v1/files with metadata about the file. Slate returns a presigned S3 URL, required form fields, and an id for the new record.2
Upload the file bytes directly to S3
Use the A successful upload returns HTTP
uploadUrl and fields from the previous response to construct a multipart form POST. Include every key-value pair from fields as individual form fields, then append the actual file as the file field last. The order matters: S3 requires all policy fields to appear before the file bytes.204 No Content from S3. Slate detects the upload asynchronously and transitions the file record’s uploadStatus to uploaded.3
Confirm the file is available
Once the S3 upload completes, poll the file record to confirm it is ready to use in requests.
File Statuses
v1 vs v2 Files
Use v2 for new integrations. The v1 files API uses a single
fileType field that blends the document’s tag and its canonical type. The v2 API (GET /v2/files) separates these into tag (the document tag) and fileType (the canonical Slate document type). This makes filtering and display significantly easier. Migrate existing integrations to v2 when convenient.Redaction Summaries
When listing or retrieving files, append?redactionSummary=true to include the current redaction state for each file that has at least one redaction. The redactionSummary object reflects the most recently created redaction job: latestId, latestStatus (pending, processing, completed, or failed), latestCreatedOn, latestErrorMessage (populated only when latestStatus is failed), and count of jobs for the file. Files with no redactions omit the object entirely.
filter[redactionStatus] (in_progress, completed, failed, or none), which requires redactionSummary=true.
Archiving a File
To remove a file from active workflows, callDELETE /v1/files/{fileId}. This sets the file’s status to archived without deleting the underlying document. Archived files no longer appear in default GET /v2/files results unless you explicitly filter with filter[status]=archived.
204 No Content.
Concatenating Files
Merge multiple existing Slate PDF files into a single document usingPOST /v1/files/concat. Provide an ordered array of file IDs. Slate returns a presigned downloadUrl for the merged output. Non-PDF files are excluded from the merge and reported in the nonPdfFiles array.
Bulk Downloading Files
To retrieve many files at once, submit a bulk download job withPOST /v1/bulkDownloads, passing a files array of file UUIDs (and an optional fileName). Slate responds with 202 Accepted and a job object containing id, status, and a pollUrl. Poll GET /files/bulkDownloads/{bulkDownloadId} until status is done; the response then includes a presigned downloadUrl for the zip. Job statuses are pending, processing, done, and failed.
Requests
A Request is a document bundle tied to amatterId. You define the structure of the bundle through a triggerContext that determines which templates and exhibits Slate attaches. Then you fill template fields, generate a preview PDF, and approve the request to create a permanent file record.
Request Workflow
1
Create a request
Call
POST /v1/requests with the matterId and one or more trigger contexts. Each trigger context specifies only a templateType — Slate derives the lifecycle step and line of business from the matter’s state, so you no longer supply them. Provide a single context with triggerContext, or several at once with the triggerContexts array (the request carries the union of all matching templates). Slate returns the created request with its id and sets the initial status to pending. You can also optionally provide notes, priority, or status.2
Fill template fields
Use Field fills are merged, not replaced. Previously filled keys remain unless you overwrite them.Send only the fields you are actually setting. Slate does not store a copy of the account on the request: a field you never fill is resolved from the account’s current data every time the request is read or rendered, so the document always reflects the account as it stands. A key you send is recorded as an override and from then on wins over the account — including if its value happens to match what the account already says. Sending
PATCH /v1/requests/{requestId} to submit values for the template fields listed in requestedFields. Each fill targets a specific templateId and provides an array of { key, value } pairs."" is an override too: the field renders blank, which is how you keep account data off a document. To undo an override and let the field follow the account again, send { "key": "...", "overridden": false }.This is why you should not echo back the filledFields a GET returned: those are resolved values, and sending them all would freeze the account’s data onto the request.3
Generate a preview PDF
Before finalizing, call
POST /v1/requests/{requestId}/generate to compile the filled templates and exhibits into a preview PDF. Slate returns a temporary downloadUrl you can present to reviewers. This does not create a permanent file record.4
Approve to finalize
Once the preview has been reviewed, call
POST /v1/requests/{requestId}/approve to generate the permanent file record. Slate compiles the output into a persistent PDF, creates a new file record, attaches it to the request’s generatedFile field, and sets the request status to completed. Approval is irreversible.Approving also moves the request’s workflowStatus to prepared, which hands the document to the signature and quality control steps that follow. See Workflow status. Approving a request that is no longer pending returns a 400 with reason: "FILE_REQUEST_NOT_PENDING", so a retry or a double-click cannot disturb a workflow that has already moved on.Request Statuses
Workflow status
status only covers the request’s own lifecycle, which ends at approval. The document’s life carries on from there: it still has to be signed and reviewed before it is finished. workflowStatus tracks that whole arc, and keeps moving long after status reads completed.
A document is done once it has been both signed and reviewed. Workflows run those two steps in either order — some sign and then QC, others QC and then sign — so workflowStatus is derived from those two facts rather than from a position in a sequence. The timestamps behind it are on the request as signedOn and qcApprovedOn.
status and workflowStatus move independently once a request is approved. A request with status: "completed" and workflowStatus: "awaiting_qc" is the normal state of a document in flight, not an inconsistency. Read workflowStatus when you want to know whether a document is finished.Following a request into signatures and QC
Once a request is approved, Slate links it forward to the work it produced. These fields appear onGET /v1/requests and GET /v1/requests/{requestId} as soon as each step exists, so you can follow a document across all three APIs without searching for it.
A field is absent until that step exists. A request that has not reached signing yet has no
signatureRequestId, and one in a QC-first workflow has a qualityCheckRequestId before it has a signatureRequestId. The request below has been signed and is waiting on review, so it carries signedOn but no qcApprovedOn yet:
Listing Requests
Retrieve document requests usingGET /v1/requests. You must pass owner if using multi-owner credentials. Filter by status, workflow status, matter (filter[matterId]), creditor reference (filter[crid]), service firm (filter[firmId]), template (filter[templateId]), priority (filter[hasPriority]), and completion date (filter[completedFrom] / filter[completedTo]). Order by id, crid, createdOn, matterId, or priority. Results are paginated: the response contains a fileRequests array and a pagination object with nextCursor, previousCursor, and totalCount.
status and workflowStatus are top-level query parameters rather than filter[...] entries, and they apply independently. Use workflowStatus to build work queues around where documents actually are — everything waiting on a reviewer, or everything a rejection has sent back:
Deleting a Request
Permanently remove a request that was created in error or is no longer needed usingDELETE /v1/requests/{requestId}. This is irreversible and removes the request record, template fill state, and exhibit references. Any file generated from a prior approval of this request remains intact.
204 No Content.