Draft Packages API
The Draft Packages API allows you to create and manage draft document packages before they are finalized.
Overview
Draft Packages are packages in a staging state that can be modified before being published to the vault. This workflow supports document preparation and review processes.
Key concepts: A Draft Package is a package being prepared but not yet finalized. Publishing is the process of finalizing a draft into a permanent package (called “completing”). File Upload is adding PDF documents to a draft package. History Items are pre-existing custody transfer records that can be attached to a draft before completion. The Status Lifecycle is Pending → Ready → Processing → Completed (or Cancelled).
Draft package lifecycle
- Pending → Ready: When the first file is added to a draft, it automatically transitions to Ready status.
- Ready → Pending: If all files are removed from a Ready draft, it transitions back to Pending.
- Ready → Processing: Calling the Complete endpoint on a Ready draft begins the finalization process.
- Processing → Completed: Once processing succeeds, the draft becomes a permanent vault package.
- Pending or Ready → Cancelled: Calling the Cancel endpoint removes the draft and enqueues cleanup of any uploaded files.
Required scopes
| Scope | Description |
|---|---|
draft-packages:read | View draft packages and files |
draft-packages:write | Create, modify, and complete drafts |
draft-packages | Full access (read + write) |
Constraints
| Constraint | Limit |
|---|---|
| Maximum file size | 100 MB per file |
| Maximum draft size | 500 MB total |
| Maximum files per draft | 50 files |
| Allowed file types | PDF only |
List Draft Packages
Retrieve a paginated list of draft packages.
GET /api/packages/drafts
Required scope: draft-packages:read.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number (1-based) |
pageSize | integer | No | 25 | Items per page (max: 100) |
status | string | No | — | Filter by status (Pending, Ready, Processing, Completed, Cancelled) |
Response (200 OK)
{
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"organizationId": "1fa85f64-5717-4562-b3fc-2c963f66afa6",
"vaultId": "2fa85f64-5717-4562-b3fc-2c963f66afa6",
"vaultFolderId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Loan Package 2024-001",
"status": "Ready",
"fields": { "field-guid-1": "LN-2024-001" },
"fileCount": 2,
"totalFileSize": 524288,
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T11:00:00Z"
}
],
"metadata": { "page": 1, "pageSize": 25, "totalCount": 1 }
}
Get Draft Package
Retrieve details for a specific draft package.
GET /api/packages/drafts/{draftId}
Required scope: draft-packages:read. Path parameter draftId (guid, required).
Response (200 OK): Returns a DraftPackageViewModel object.
Error responses: 404 — Draft package not found.
Create Draft Package
Create a new draft package.
POST /api/packages/drafts
Required scope: draft-packages:write.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Package name (max 255 characters) |
vaultFolderId | guid | No | Target folder when completed |
fields | object | No | Custom field values (fieldId → value map) |
Response (201 Created): Returns the created DraftPackageViewModel with status “Pending”.
Error responses: 400 — Validation error (invalid fields); 400 — Vault is not active.
Update Draft Package
Update a draft package's metadata.
PATCH /api/packages/drafts/{draftId}
Required scope: draft-packages:write. Path parameter draftId (guid, required).
Request body (all fields optional)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New package name (max 255 chars) |
vaultFolderId | guid | No | New target folder |
fields | object | No | Updated field values |
Response (200 OK): Returns the updated DraftPackageViewModel.
Error responses: 400 — Validation error (invalid fields); 404 — Draft package not found; 409 — Cannot update draft in terminal state (Completed, Cancelled); 422 — Draft is currently processing.
List Draft Package Files
Retrieve all files in a draft package.
GET /api/packages/drafts/{draftId}/files
Required scope: draft-packages:read. Path parameter draftId (guid, required).
Query parameters: page (integer, default 1), pageSize (integer, default 25, max 100).
Response (200 OK)
{
"data": [
{
"id": "8fa85f64-5717-4562-b3fc-2c963f66afa6",
"draftId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"fileName": "promissory_note.pdf",
"fileType": "application/pdf",
"fileSize": 245678,
"checksum": "d41d8cd98f00b204e9800998ecf8427e",
"uploadedAt": "2024-01-15T10:35:00Z"
}
],
"metadata": { "page": 1, "pageSize": 25, "totalCount": 1 }
}
Get Draft Package File
Retrieve metadata for a specific file in a draft package.
GET /api/packages/drafts/{draftId}/files/{fileId}
Required scope: draft-packages:read. Path parameters draftId and fileId (both guid, required).
Response (200 OK): Returns a DraftPackageFileViewModel object.
Add File to Draft Package
Upload a PDF file to a draft package.
POST /api/packages/drafts/{draftId}/files
Required scope: draft-packages:write. Path parameter draftId (guid, required).
Request body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | PDF file to upload |
fileName | string | No | Override the original filename |
Response (201 Created): Returns the created DraftPackageFileViewModel. Note: When the first file is added to a Pending draft, the status automatically transitions to “Ready”.
Error responses: 400 — Only PDF files are allowed; 400 — File exceeds maximum size (100 MB); 409 — File with same name already exists in draft; 409 — Draft would exceed maximum size (500 MB); 409 — Draft would exceed maximum file count (50).
Delete Draft Package File
Remove a file from a draft package.
DELETE /api/packages/drafts/{draftId}/files/{fileId}
Required scope: draft-packages:write. Path parameters draftId and fileId (both guid, required).
Response (204 No Content). Note: When all files are removed from a Ready draft, the status automatically transitions back to “Pending”.
Error responses: 404 — Draft or file not found; 409 — Cannot delete from draft in terminal state (Completed, Cancelled); 422 — Draft is currently processing.
List Draft Package History Items
Retrieve all history items for a draft package, ordered by transfer date and sort order.
GET /api/packages/drafts/{draftId}/history
Required scope: draft-packages:read. Path parameter draftId (guid, required).
Response (200 OK)
[
{
"id": "4fa85f64-5717-4562-b3fc-2c963f66afa6",
"draftId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transferDate": "2019-03-15T00:00:00Z",
"previousEntity": "Originator Bank",
"newEntity": "Warehouse Lender LLC",
"sortOrder": 1
},
{
"id": "5fa85f64-5717-4562-b3fc-2c963f66afa6",
"draftId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transferDate": "2021-07-01T00:00:00Z",
"previousEntity": "Warehouse Lender LLC",
"newEntity": "Servicer Corp",
"sortOrder": 2
}
]
Error responses: 404 — Draft package not found.
Add History Item to Draft Package
Add a historical custody transfer record to a draft package.
POST /api/packages/drafts/{draftId}/history
Required scope: draft-packages:write. Path parameter draftId (guid, required).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
transferDate | datetime | Yes | Date and time the transfer occurred (ISO 8601) |
previousEntity | string | Yes | Name of the custodian relinquishing custody (max 255 characters) |
newEntity | string | Yes | Name of the custodian receiving custody (max 255 characters) |
sortOrder | integer | No | Controls ordering for transfers sharing the same transfer date; lower values sort first |
Response (201 Created): Returns the created DraftPackageHistoryItemViewModel. A Location header is included with the URI of the created resource.
Error responses: 400 — Validation error (missing required fields); 404 — Draft package not found; 409 — Cannot modify draft in terminal state (Completed, Cancelled); 422 — Draft is currently processing.
Update Draft Package History Item
Replace a history item on a draft package.
PUT /api/packages/drafts/{draftId}/history/{historyItemId}
Required scope: draft-packages:write. Path parameters draftId and historyItemId (both guid, required).
Request body: Same fields as Add History Item (transferDate, previousEntity, newEntity required; sortOrder optional).
Response (200 OK): Returns the updated DraftPackageHistoryItemViewModel.
Error responses: 400 — Validation error (missing required fields); 404 — Draft or history item not found; 409 — Cannot modify draft in terminal state (Completed, Cancelled); 422 — Draft is currently processing.
Delete Draft Package History Item
Remove a history item from a draft package.
DELETE /api/packages/drafts/{draftId}/history/{historyItemId}
Required scope: draft-packages:write. Path parameters draftId and historyItemId (both guid, required).
Response (204 No Content).
Error responses: 404 — Draft or history item not found; 409 — Cannot modify draft in terminal state (Completed, Cancelled); 422 — Draft is currently processing.
Complete Draft Package
Finalize a draft package, converting it to a permanent vault package. Important: You must specify a vault folder ID if one is not set already.
POST /api/packages/drafts/{draftId}/complete
Required scope: draft-packages:write. Path parameter draftId (guid, required).
Request body (optional overrides)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Override package name |
vaultFolderId | guid | No | Override target folder |
fields | object | No | Override field values |
history | DraftPackageHistoryItem array | No | Historical custody transfer records to import as package history (see Chain of Title Import) |
Chain of Title Import
When onboarding loan documents that have pre-existing custody transfer history from before entering the eVault, provide the prior chain of title. History items can be managed in two ways:
- Draft history endpoints (recommended): Add, update, and delete history items on the draft before completing it using the POST/PUT/DELETE
/api/packages/drafts/{draftId}/historyendpoints. This allows incremental editing and review of the chain of title. - Inline at completion: Supply all history items via the
historyfield on the Complete request body. If provided, inline items replace any history items previously stored on the draft.
Each item becomes a HistoricalCustodyTransfer activity on the completed package, visible via GET /api/packages/{id}/events and rendered in certified prints and paper-out exports using the item's actual transferDate. Use the sortOrder field to preserve the intended ordering of transfers that share the same transferDate. Static loan attributes such as loan number and funded date should be supplied as vault field values via the fields property, not as history items.
Request example
{
"name": "Loan Package LN-2024-001",
"vaultFolderId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"fields": {
"0642B476-2933-49FC-A411-D9D761E8B8BF": "LN-2024-001",
"8017D635-6B51-46B9-A870-7E7CB31D96C3": "2019-03-15"
},
"history": [
{
"transferDate": "2019-03-15T00:00:00Z",
"previousEntity": "Originator Bank",
"newEntity": "Warehouse Lender LLC",
"sortOrder": 1
},
{
"transferDate": "2019-03-15T00:00:00Z",
"previousEntity": "Warehouse Lender LLC",
"newEntity": "Servicer Corp",
"sortOrder": 2
},
{
"transferDate": "2021-07-01T00:00:00Z",
"previousEntity": "Servicer Corp",
"newEntity": "Secondary Market Investor",
"sortOrder": 3
}
]
}
Response (200 OK)
{
"id": "9fa85f64-5717-4562-b3fc-2c963f66afa6",
"organizationId": "1fa85f64-5717-4562-b3fc-2c963f66afa6",
"vaultId": "2fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Loan Package 2024-001",
"vaultFolderId": "7fa85f64-5717-4562-b3fc-2c963f66afa6",
"packageType": "AuthoritativeCopy",
"source": "Api",
"numberOfFiles": 2,
"totalFileSize": 524288,
"fields": [
{ "fieldId": "field-guid-1", "name": "Loan Number", "value": "LN-2024-001" }
],
"importedAt": "2024-01-15T12:00:00Z",
"draft": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "Completed",
"completedAt": "2024-01-15T12:00:00Z"
}
}
Error responses: 400 — Draft must have at least one file; 400 — Draft must have a target folder; 400 — Cannot complete a cancelled draft; 404 — Draft package not found.
Cancel Draft Package
Cancel a draft package that is no longer needed.
POST /api/packages/drafts/{draftId}/cancel
Required scope: draft-packages:write. Path parameter draftId (guid, required).
Response (204 No Content). This operation is idempotent — calling it on an already cancelled draft returns success. Note: Cancelling a draft enqueues a background job to clean up the stored files.
Error responses: 400 — Cannot cancel completed or processing draft; 404 — Draft package not found.
Response models (Draft Packages API)
DraftPackageViewModel
| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier |
organizationId | guid | Organization ID |
vaultId | guid | Vault ID |
vaultFolderId | guid | Target folder ID (nullable) |
name | string | Package name |
status | string | Pending, Ready, Processing, Completed, Cancelled |
fields | object | Custom field values (fieldId → value map) |
fileCount | integer | Number of files |
totalFileSize | integer | Total size in bytes |
createdAt | datetime | Creation timestamp (ISO 8601) |
updatedAt | datetime | Last update timestamp (ISO 8601) |
DraftPackageFileViewModel
| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier |
draftId | guid | Parent draft package ID |
fileName | string | Original file name |
fileType | string | MIME type (application/pdf) |
fileSize | integer | File size in bytes |
checksum | string | MD5 hash of file content |
uploadedAt | datetime | Upload timestamp (ISO 8601) |
DraftPackageHistoryItemViewModel
Returned by the history item endpoints.
| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier |
draftId | guid | Parent draft package ID |
transferDate | datetime | Date and time the transfer occurred (ISO 8601) |
previousEntity | string | Name of the custodian relinquishing custody |
newEntity | string | Name of the custodian receiving custody |
sortOrder | integer | Controls ordering for transfers sharing the same transferDate; lower values sort first |
DraftPackageHistoryItem
Represents a single historical custody transfer submitted inline at draft completion time via the history field on the Complete endpoint.
| Field | Type | Required | Description |
|---|---|---|---|
transferDate | datetime | Yes | Date and time the transfer occurred (ISO 8601) |
previousEntity | string | Yes | Name of the custodian relinquishing custody (max 255 characters) |
newEntity | string | Yes | Name of the custodian receiving custody (max 255 characters) |
sortOrder | integer or null | No | Controls ordering for transfers sharing the same transferDate; lower values sort first |
Draft status values
| Status | Description |
|---|---|
Pending | Draft created but has no files |
Ready | Draft has files and can be completed |
Processing | Draft is being converted to a package |
Completed | Draft successfully converted to package |
Cancelled | Draft was cancelled and files are deleted |
Next: Folders API.
