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

  1. Pending → Ready: When the first file is added to a draft, it automatically transitions to Ready status.
  2. Ready → Pending: If all files are removed from a Ready draft, it transitions back to Pending.
  3. Ready → Processing: Calling the Complete endpoint on a Ready draft begins the finalization process.
  4. Processing → Completed: Once processing succeeds, the draft becomes a permanent vault package.
  5. Pending or Ready → Cancelled: Calling the Cancel endpoint removes the draft and enqueues cleanup of any uploaded files.

Required scopes

ScopeDescription
draft-packages:readView draft packages and files
draft-packages:writeCreate, modify, and complete drafts
draft-packagesFull access (read + write)

Constraints

ConstraintLimit
Maximum file size100 MB per file
Maximum draft size500 MB total
Maximum files per draft50 files
Allowed file typesPDF only

List Draft Packages

Retrieve a paginated list of draft packages.

GET /api/packages/drafts

Required scope: draft-packages:read.

Query parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number (1-based)
pageSizeintegerNo25Items per page (max: 100)
statusstringNoFilter 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

FieldTypeRequiredDescription
namestringYesPackage name (max 255 characters)
vaultFolderIdguidNoTarget folder when completed
fieldsobjectNoCustom 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)

FieldTypeRequiredDescription
namestringNoNew package name (max 255 chars)
vaultFolderIdguidNoNew target folder
fieldsobjectNoUpdated 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)

FieldTypeRequiredDescription
filefileYesPDF file to upload
fileNamestringNoOverride 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

FieldTypeRequiredDescription
transferDatedatetimeYesDate and time the transfer occurred (ISO 8601)
previousEntitystringYesName of the custodian relinquishing custody (max 255 characters)
newEntitystringYesName of the custodian receiving custody (max 255 characters)
sortOrderintegerNoControls 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)

FieldTypeRequiredDescription
namestringNoOverride package name
vaultFolderIdguidNoOverride target folder
fieldsobjectNoOverride field values
historyDraftPackageHistoryItem arrayNoHistorical 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:

  1. 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}/history endpoints. This allows incremental editing and review of the chain of title.
  2. Inline at completion: Supply all history items via the history field 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

FieldTypeDescription
idguidUnique identifier
organizationIdguidOrganization ID
vaultIdguidVault ID
vaultFolderIdguidTarget folder ID (nullable)
namestringPackage name
statusstringPending, Ready, Processing, Completed, Cancelled
fieldsobjectCustom field values (fieldId → value map)
fileCountintegerNumber of files
totalFileSizeintegerTotal size in bytes
createdAtdatetimeCreation timestamp (ISO 8601)
updatedAtdatetimeLast update timestamp (ISO 8601)

DraftPackageFileViewModel

FieldTypeDescription
idguidUnique identifier
draftIdguidParent draft package ID
fileNamestringOriginal file name
fileTypestringMIME type (application/pdf)
fileSizeintegerFile size in bytes
checksumstringMD5 hash of file content
uploadedAtdatetimeUpload timestamp (ISO 8601)

DraftPackageHistoryItemViewModel

Returned by the history item endpoints.

FieldTypeDescription
idguidUnique identifier
draftIdguidParent draft package ID
transferDatedatetimeDate and time the transfer occurred (ISO 8601)
previousEntitystringName of the custodian relinquishing custody
newEntitystringName of the custodian receiving custody
sortOrderintegerControls 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.

FieldTypeRequiredDescription
transferDatedatetimeYesDate and time the transfer occurred (ISO 8601)
previousEntitystringYesName of the custodian relinquishing custody (max 255 characters)
newEntitystringYesName of the custodian receiving custody (max 255 characters)
sortOrderinteger or nullNoControls ordering for transfers sharing the same transferDate; lower values sort first

Draft status values

StatusDescription
PendingDraft created but has no files
ReadyDraft has files and can be completed
ProcessingDraft is being converted to a package
CompletedDraft successfully converted to package
CancelledDraft was cancelled and files are deleted

Next: Folders API.