NLDocSearch (NLDS) is a platform that ingests mortgage documents, validates and indexes them asynchronously, and provides controlled document access for client-facing workflows.
Read the Getting Started guide first. It explains all constructs (company, product, case, external IDs, and upload flow) with annotated examples before you start calling APIs.
All endpoints require an OAuth2 Bearer token obtained via the AuthX machine client credentials flow.
Token endpoint:
POST /authx/oauth2/token
grant_type=client_credentials
client_id=<your-client-id>
client_secret=<your-client-secret>
scope=nldocsearch.api
Tokens expire after 30 minutes. Re-request before expiry. Cache locally — do not store in source code or version control.
Discover the product catalog for your company. Products are admin-managed and define the document context for cases. Integration clients read products; they do not create or modify them.
Returns active products for the company using a paginated response envelope. Default sort: productCode,asc.
| companyId required | integer <int64> Company tenant identifier |
| page | integer >= 0 Default: 0 Zero-based page number. Must be zero or greater. |
| size | integer [ 1 .. 100 ] Default: 50 Requested page size. Must be greater than zero and at most 100. |
| sort | string Default: "productCode,asc" Examples:
Spring Pageable sort parameter. Format: |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": {
- "content": [
- {
- "productCode": "MORTGAGE",
- "displayName": "Residential Mortgage",
- "status": "ACTIVE",
- "createdAt": "2024-06-01T00:00:00Z",
- "lastModifiedAt": "2024-06-01T00:00:00Z"
}, - {
- "productCode": "HELOC",
- "displayName": "Home Equity Line of Credit",
- "status": "ACTIVE",
- "createdAt": "2024-06-01T00:00:00Z",
- "lastModifiedAt": "2024-06-01T00:00:00Z"
}
], - "page": 0,
- "size": 50,
- "totalElements": 2,
- "totalPages": 1,
- "first": true,
- "last": true
}
}| companyId required | integer <int64> Company tenant identifier |
| productCode required | string Product identifier code |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": {
- "productCode": "MORTGAGE",
- "displayName": "Residential Mortgage",
- "status": "ACTIVE",
- "createdAt": "2024-06-01T00:00:00Z",
- "lastModifiedAt": "2024-06-01T00:00:00Z"
}
}Create and inspect loan application cases.
Each case is scoped to a product and aggregates all uploaded documents.
Use externalCaseId to make case creation idempotent with your upstream system.
Returns cases matching the optional filters using a paginated response envelope. Default sort: lastModifiedAt,desc.
| companyId required | integer <int64> Company tenant identifier |
| productCode | string Optional product filter |
| q | string Optional search term for case display name, externalCaseId, or casePublicId |
| page | integer >= 0 Default: 0 Zero-based page number. Must be zero or greater. |
| size | integer [ 1 .. 100 ] Default: 50 Requested page size. Must be greater than zero and at most 100. |
| sort | string Default: "lastModifiedAt,desc" Examples:
Spring Pageable sort parameter. Format: |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": {
- "content": [
- {
- "casePublicId": "8d5a3e7c-9f21-4a2c-b8e1-d7c6f5a4e3b2",
- "productCode": "MORTGAGE",
- "externalCaseId": "LOS-998877",
- "displayName": "Johnson Residential Mortgage - 2024",
- "status": "ACTIVE",
- "createdAt": "2024-12-15T14:32:00Z",
- "lastModifiedAt": "2024-12-15T14:32:00Z",
- "documentSummary": {
- "total": 0,
- "uploadPending": 0,
- "uploaded": 0,
- "validationPending": 0,
- "validationPassed": 0,
- "validationFailed": 0,
- "ingestionQueued": 0,
- "indexed": 0,
- "ingestionFailed": 0
}
}
], - "page": 0,
- "size": 50,
- "totalElements": 1,
- "totalPages": 1,
- "first": true,
- "last": true
}
}| companyId required | integer <int64> Company tenant identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
Case creation request
| productCode required | string |
| externalCaseId | string or null |
| displayName | string or null |
object or null |
{- "productCode": "MORTGAGE",
- "externalCaseId": "LOS-998877",
- "displayName": "Johnson Residential Mortgage - 2024",
- "metadata": {
- "borrowerName": "Mike Johnson",
- "loanPurpose": "purchase"
}
}{- "meta": {
- "code": 0,
- "message": "string",
- "type": "string"
}, - "data": {
- "casePublicId": "6e32fc0a-3656-4840-a65e-87b981967f16",
- "productCode": "string",
- "externalCaseId": "string",
- "displayName": "string",
- "status": "DRAFT",
- "documentSummary": {
- "total": 0,
- "uploadPending": 0,
- "uploaded": 0,
- "validationPending": 0,
- "validationPassed": 0,
- "validationFailed": 0,
- "ingestionQueued": 0,
- "indexed": 0,
- "ingestionFailed": 0
}, - "createdAt": "2019-08-24T14:15:22Z",
- "lastModifiedAt": "2019-08-24T14:15:22Z"
}
}| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": {
- "casePublicId": "8d5a3e7c-9f21-4a2c-b8e1-d7c6f5a4e3b2",
- "productCode": "MORTGAGE",
- "displayName": "Residential Mortgage",
- "externalCaseId": "LOS-998877",
- "status": "ACTIVE",
- "createdAt": "2024-12-15T14:32:00Z",
- "lastModifiedAt": "2024-12-15T15:00:00Z",
- "documentSummary": {
- "total": 45,
- "uploadPending": 0,
- "uploaded": 8,
- "validationPending": 5,
- "validationPassed": 40,
- "validationFailed": 0,
- "ingestionQueued": 3,
- "indexed": 40,
- "ingestionFailed": 0
}
}
}Register documents, receive SAS upload URLs, and signal completion. Documents are uploaded directly to Azure Blob Storage — the API never proxies file bytes. Validation runs automatically after upload completion.
Returns documents belonging to the specified case using a paginated response envelope. Default sort: createdAt,asc.
| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| page | integer >= 0 Default: 0 Zero-based page number. Must be zero or greater. |
| size | integer [ 1 .. 100 ] Default: 50 Requested page size. Must be greater than zero and at most 100. |
| sort | string Default: "createdAt,asc" Examples:
Spring Pageable sort parameter. Format: |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": {
- "content": [
- {
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "casePublicId": "ab3cb669-3df7-4c8a-beaa-a7ccafd76e90",
- "originalFilename": "Closing_Disclosure_signed.pdf",
- "contentType": "application/pdf",
- "contentSize": 1024576,
- "uploadStatus": "UPLOADED",
- "validationStatus": "PASSED",
- "ingestionStatus": "INDEXED",
- "diagnostics": [ ],
- "createdAt": "2026-05-28T10:00:00Z",
- "lastModifiedAt": "2026-05-28T10:00:00Z"
}
], - "page": 0,
- "size": 50,
- "totalElements": 1,
- "totalPages": 1,
- "first": true,
- "last": true
}
}Register 1-50 PDF documents for a case and receive short-lived SAS URLs for direct-to-blob upload. Full success returns an array of successful document responses. Partial and all-failed batches return a batch response object.
| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
Document registration request
required | Array of objects (DocumentRegistrationItem) [ 1 .. 50 ] items |
{- "documents": [
- {
- "originalFilename": "Closing_Disclosure_signed.pdf",
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "externalDocumentId": "DOC-CD-2024-001",
- "contentLength": 1024576,
- "pageCount": 48,
- "declaredContentType": "application/pdf",
- "sourceSystemPath": "closing-package/CD_signed_final.pdf"
}
]
}{- "meta": {
- "code": 201,
- "type": "success",
- "message": "Documents registered successfully"
}, - "data": [
- {
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "originalFilename": "Closing_Disclosure_signed.pdf",
- "externalDocumentId": "DOC-CD-2024-001",
- "sourceSystemPath": "closing-package/CD_signed_final.pdf",
- "uploadStatus": "UPLOAD_PENDING",
- "validationStatus": "PENDING",
- "ingestionStatus": "PENDING",
- "createdAt": "2026-05-28T10:00:00Z",
- "lastModifiedAt": "2026-05-28T10:00:00Z",
- "uploadMethod": "PUT",
- "sasExpiresAt": "2026-05-28T10:15:00Z",
- "existingDocument": false
}
]
}Call this endpoint after the Azure Blob PUT to sasUploadUrl succeeds. This endpoint does not accept a request body.
| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| documentPublicId required | string <uuid> Document public identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 202,
- "type": "success",
- "message": "Upload completion accepted"
}, - "data": {
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "uploadStatus": "UPLOADED",
- "validationStatus": "ENQUEUED",
- "ingestionStatus": "PENDING",
- "detectedType": null,
- "contentSize": 1024576,
- "contentHash": null,
- "diagnostics": [ ],
- "processedAt": "2026-05-28T10:00:00Z"
}
}| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| documentPublicId required | string <uuid> Document public identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
{- "meta": {
- "code": 200,
- "message": "Document status retrieved",
- "type": "success"
}, - "data": {
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "casePublicId": "8d5a3e7c-9f21-4a2c-b8e1-d7c6f5a4e3b2",
- "originalFilename": "Closing_Disclosure_signed.pdf",
- "contentType": "application/pdf",
- "contentSize": 1024576,
- "uploadStatus": "UPLOADED",
- "validationStatus": "PASSED",
- "ingestionStatus": "QUEUED",
- "diagnostics": [ ],
- "createdAt": "2026-05-28T10:00:00Z",
- "lastModifiedAt": "2026-05-28T10:00:00Z"
}
}Check whether documents are already registered before uploading.
Use documentPublicId or externalDocumentId to look up existing
registration status and avoid duplicate uploads.
Look up documents within a case by externalDocumentIds, documentPublicIds, or both.
At least one non-empty identifier list is required. Use GET /api/v1/{companyId}/cases/{casePublicId}/documents
to list all documents in a case.
| companyId required | integer <int64> Company tenant identifier |
| casePublicId required | string <uuid> Case public identifier |
| X-Request-ID | string <uuid> Optional client-provided request correlation ID |
Case document lookup request
| externalDocumentIds required | Array of strings [ 1 .. 200 ] items [ items [ 1 .. 256 ] characters ^[a-zA-Z0-9._\-:/]*$ ] |
| documentPublicIds | Array of strings <uuid> [ 1 .. 200 ] items unique [ items <uuid > ] |
{- "externalDocumentIds": [
- "DOC-001",
- "DOC-002"
]
}{- "meta": {
- "code": 200,
- "message": "success",
- "type": "success"
}, - "data": [
- {
- "externalDocumentId": "DOC-001",
- "found": true,
- "documentPublicId": "660e8400-e29b-41d4-a716-446655440001",
- "casePublicId": "ab3cb669-3df7-4c8a-beaa-a7ccafd76e90",
- "originalFilename": "Closing_Disclosure_signed.pdf",
- "contentSize": 1024576,
- "contentHash": "sha256:9f1c2a4b...",
- "uploadStatus": "UPLOADED",
- "validationStatus": "PASSED",
- "ingestionStatus": "INDEXED",
- "lastModifiedAt": "2026-05-28T10:00:00Z"
}, - {
- "externalDocumentId": "DOC-002",
- "found": false,
- "documentPublicId": null,
- "casePublicId": null,
- "originalFilename": null,
- "contentSize": null,
- "contentHash": null,
- "uploadStatus": null,
- "validationStatus": null,
- "ingestionStatus": null,
- "lastModifiedAt": null
}
]
}