# Quality Control
> Pre-close and post-close quality control — submit loans, retrieve findings, and track QC status.
## OpenAPI specs
- [Authentication](https://developers.snapdocs.com/content/qc/specs/authentication.json)
- [QC API](https://developers.snapdocs.com/content/qc/specs/qc-api.json)
(Specs are schemas, not prose — fetch the JSON directly rather than pasting it here.)
## Shared platform guides
Authentication, environments, webhooks, and testing are shared across every Snapdocs product — see [Getting Started](https://developers.snapdocs.com/platform/llms.txt).
## Guides
### Welcome to Quality Control API
# Welcome to Quality Control API
Streamline your quality control reviews by leveraging Snapdoc Quality Control (QC) API, a set of HTTP endpoints that enable developers to seamlessly integrate your LOS with Snapdocs QC products, using OpenAPI technology.
Easily integrate your Loan Origination System (LOS) to send required documents and loan data for Snapdocs QC to review, receive status updates along the way, and download QC results and individual classified documents when they are ready.
To help you better understand what Snapdocs QC APIs offer, we have put together this API documentation, which includes:
* **[Pre-Close QC](https://developers.snapdocs.com/qc/guides/pre-close/pre_close_qc):** Review origination documents before the closing package is signed.
* **[Post-Close QC](https://developers.snapdocs.com/qc/guides/post-close/post_close_qc):** Review the signed closing package after the closing.
* **[Environments & Introduction](https://developers.snapdocs.com/qc/guides/guides/environments_introduction):** Base URLs and how to authenticate.
* **[Subscription & Webhooks](https://developers.snapdocs.com/qc/guides/guides/subscription_webhooks):** Find out how to listen for events, securely retrieve the information, and present it in your system. Covers both reviews.
* **[Documents Glossary](https://developers.snapdocs.com/qc/guides/guides/documents_glossary):** A list of available documents you may send in the QC API Upload documents.
* **[Security](https://developers.snapdocs.com/qc/guides/guides/security):** Learn about how we maintain secure communication with our API.
---
### Environments & Introduction
# Environments & Introduction
## Various Environments
Use our *Demo Environment* as any customer starting your integration:
| API | URL |
| :-------------- | :------------------------------------------- |
| Token API | `https://login.demo-eks.snpd.io/oauth/token` |
| Snapdocs QC API | `https://api.cs-demo0.snpd.io/api/v1/qc/` |
| Audience | `https://api.*.snpd.io` |
Once the integration is complete, you can then switch to *Production Environment*.
| API | URL |
| :-------------- | :---------------------------------------- |
| Token API | `https://login.snapdocs.com/oauth/token/` |
| Snapdocs QC API | `https://api.snapdocs.com/api/v1/qc/` |
| Audience | `https://api.snapdocs.com` |
Use our *Integrator Environment* if you are a partner and were given the integrator keys to cx-int0:
| API | URL |
| :-------------- | :------------------------------------------- |
| Token API | `https://login.demo-eks.snpd.io/oauth/token` |
| Snapdocs QC API | `https://api.cx-int0.snpd.io/api/v1/qc/` |
| Audience | `https://api.*.snpd.io` |
## Authenticate with Snapdocs QC
Snapdocs QC uses OAuth 2.0 for authentication. Specifically, we use the OAuth 2.0 Client Credentials grant type, which means when you authenticate with Snapdocs QC, you must pass these client credentials:
* Client Id
* Client Secret
* Grant Type
* Audience
### Client Credentials
You cannot retrieve your client credentials from Snapdocs QC directly. However, your Customer Success Manager can provide them.
Your client credentials carry many privileges, so be sure to keep them secure. Because they aren’t available as a secure download, we have some recommendations for how to distribute them securely with your team:
Leverage Gmail’s [Confidential Mode](https://support.google.com/a/answer/7684332?hl=en) to share the client credentials with one-day expiry and enable an SMS passcode for the recipient. Store client credentials under password protection. Use a file protected with a 14+ character password. Securely share the file and password separately.
### Audience
The API you intend to call using a token generated by this request, example `https://api.snapdocs.com`
### Grant Type
Use value "client\_credentials" for grant type.
```json
"grant_type": "client_credentials"
```
### Example Authentication Request
This example code demonstrates the API requests to retrieve an OAuth access token and use it in the following requests to Snapdocs QC.
```python
from requests import Session
token_url = "https://login.demo-eks.snpd.io/oauth/token"
test_api_url = "https://api.cs-demo0.snpd.io/api/v1/subscriptions"
client_id = 'CLIENT_ID_HERE'
client_secret = 'CLIENT_SECRET_HERE'
audience = 'https://api.*.snpd.io'
data = {
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
"grant_type": "client_credentials"
}
s = Session()
access_token_response = s.post(token_url, data=data)
access_token_response.raise_for_status()
print(access_token_response)
tokens = access_token_response.json()
print("access token: " + tokens['access_token'])
#step B - with the returned access_token we can make as many calls as we want
api_call_headers = {'Authorization': 'Bearer ' + tokens['access_token']}
api_call_response = s.get(test_api_url, headers=api_call_headers)
api_call_response.raise_for_status()
print(api_call_response.text)
```
### Verify the Access Token
If you have questions of the access token or need to inspect it, you can copy the value to to decode it.
---
### Subscription & Webhooks
# Subscription & Webhooks
Snapdocs Connect facilitates the signing experiences for wet, full eClose, and hybrid signing activities. To build trust that Snapdocs is facilitating the closings as expected, Snapdocs Connect offers a broadcast of **quality and document events** so that connected systems can keep the loan in sync and automate downstream actions—such as sending loan data and documents to QC when requested, or reflecting QC report status in the system of record.
These events cover both Pre-Close QC and Post-Close QC. Every event carries a `report_type` identifying which review it belongs to, so a single subscription can serve both — or you can filter to the one you integrate with.
**Webhooks** let you subscribe to events that occur during quality processing. Instead of polling, CQC can send an HTTP request (or deliver events via your chosen integration) when something happens. You can configure which events you subscribe to using the API endpoints described below.
Follow the steps below to set up notifications:
1. **Designate an endpoint** in your system that will receive quality events and trigger the right work (e.g., send loan data or documents to CQC, or update your UI when report status changes).
2. **Create a subscription** for the events you care about, using the URL from the previous step.
# Manage subscriptions
Use the subscription APIs to manage which events you receive. See [Subscriptions](https://developers.snapdocs.com/qc/reference/qc-api/operations/GetSubscriptions) for full details.
* [Get all subscriptions](https://developers.snapdocs.com/qc/reference/qc-api/operations/GetSubscriptions)
* [Create a subscription](https://developers.snapdocs.com/qc/reference/qc-api/operations/CreateSubscription)
* [Delete a subscription](https://developers.snapdocs.com/qc/reference/qc-api/operations/DeleteSubscription)
## Subscription events (Quality)
Events you can subscribe to for CQC:
| Event | Description |
| :----------------------------- | :-------------------------------------------------------------------------------------- |
| `loan_data_requested` | QC is requesting loan data for a package. Send loan data via the QC API. |
| `documents_requested` | QC is requesting documents for a package. Send documents via the QC API. |
| `report_status_updated` | QC report status has been updated (e.g. `in_progress`, `passed`, `errors`, `canceled`). |
| `classified_documents_updated` | QC classified documents "Note", "Closing Disclosure", etc. are ready for download |
See [Create a subscription](https://developers.snapdocs.com/qc/reference/qc-api/operations/CreateSubscription) for the full list of subscribable quality events.
# Webhooks (Listeners)
The endpoint URL you configure for webhooks will receive requests from Snapdocs when quality events occur.
**Method:** `POST`
**Headers:**
* `Content-Type`: `application/json`
## Webhook event object
| Key | Type | Description |
| -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `schema` | String | Event schema version. Always `com.snapdocs/quality/1-0-0`. |
| `report_type` | String | Which review the event belongs to: `pre_close`, `post-close`, `funding`, or `trailing`. |
| `event_type` | String | The event being broadcast. One of: `request_loan_data`, `request_documents`, `report_status_updated`, `classified_documents_updated` |
| `package_uuid` | String | QC package (quality context) identifier. |
| `timestamp` | String | ISO 8601 timestamp when the event was generated. |
| `payload` | Object | Specific event type attributes, including [External identifiers](#external-identifiers). |
Only keys with present values are included in the payload.
## Status values
The `status` field appears only on `report_status_updated` events and reflects the current state of the QC report:
| Value | Description |
| ------------- | -------------------------------------------------------------------------- |
| `in_progress` | Quality processing is running (also used when `pending` is `true`). |
| `passed` | All QC checks passed successfully. |
| `errors` | One or more documents have issues (e.g. missing pages, missing documents). |
| `none` | All signed documents have been removed. |
| `qc_canceled` | The QC review was canceled. |
If `status` is omitted, it has not changed since the last event.
## External identifiers
`external_identifiers` is an array of objects linking this closing to your system. Each entry can include:
| Key | Type | Description |
| ----------------- | ------ | -------------------------------- |
| `external_system` | String | System name (e.g. `encompass`). |
| `external_type` | String | Type of id (e.g. `file_number`). |
| `value` | String | The identifier value. |
> 📘 `external_identifiers` may contain 0 or more records.
## Example webhook payload (loan\_data\_requested)
```json
{
"schema": "com.snapdocs/quality/1-0-0",
"report_type": "post-close",
"event_type": "loan_data_requested",
"package_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-03-09T18:00:00.000Z",
"payload": {
"external_identifiers": [
{
"external_system": "encompass",
"external_type": "file_number",
"value": "12345678"
},
{
"external_system": "snapdocs",
"external_type": "closing",
"value": "d679e2ad-278d-e547-9756-84639ba3865"
}
],
}
```
## Example webhook payload (documents\_requested)
Sent when CQC needs documents from your LOS. Same shape as `loan_data` but with `event_type: "documents_requested"`. Respond with 200 and then submit documents via the CQC API.
```json
{
"schema": "com.snapdocs/quality/1-0-0",
"report_type": "post-close",
"event_type": "documents_requested",
"package_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2026-03-09T18:01:00.000Z",
"payload": {
"external_identifiers": [
{
"external_system": "encompass",
"external_type": "file_number",
"value": "12345678"
},
{
"external_system": "snapdocs",
"external_type": "uuid",
"value": "d679e2ad-278d-e547-9756-84639ba3865"
}
],
}
```
## Example webhook payload (report\_status\_updated)
Sent when QC needs loan data from your LOS. Respond with 200 and then submit loan data via the QC API.
```json
{
"schema": "com.snapdocs/quality/1-0-0",
"report_type": "post-close",
"event_type": "report_status_updated",
"timestamp": "2026-03-09T18:05:00.000Z",
"package_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"payload": {
"external_identifiers": [
{
"external_system": "snapdocs",
"external_type": "uuid",
"value": "d679e2ad-278d-e547-9756-84639ba3865"
}
],
"collated": true,
"status": "passed"
}
}
```
***
## Handle Snapdocs requests
* **Filter by event type** — Configure your endpoint to handle only the event types your integration needs. Handling every event type can add unnecessary load.
* **Idempotency** — The same event may be delivered more than once. Implement idempotent processing (e.g. using `package_id` + `event_type` + `status`) so duplicate deliveries do not cause duplicate side effects.
* **Verify source** — Use webhook signatures (if provided) to confirm that requests originate from Snapdocs.
* **Ordering** — Events are not guaranteed to arrive in the order they occurred. Use the `timestamp` to determine when the event actually happened.
## Webhook responses
Respond with **HTTP 200** when the webhook is received successfully. Use other status codes when the request is invalid or your processing fails.
> 📘 **Best practice**
>
> Respond with **200** as soon as you have accepted the webhook, before completing background processing. This reduces the chance of Snapdocs retrying due to timeouts. If Snapdocs does not receive a 200 response, it may retry with exponential backoff over a period of hours.
**Success:**
```json
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "OK",
"code": 200,
"message": "webhook received successfully"
}
```
**Client error (e.g. bad payload):**
```json
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"status": "Bad Request",
"code": 400,
"message": "[reason for failure]"
}
```
## Retries
If your endpoint does not respond with 200, Snapdocs may retry failed deliveries multiple times over a 24-hour window, with increasing delay between attempts (exponential backoff). Implement idempotent handling so retries are safe.
## Example: handling all three event types
Below is a minimal example of how a listener might handle CQC quality events and respond with 200 before processing.
```python
import json
import logging
logger = logging.getLogger(__name__)
SUCCESS_BODY = {
"status": "OK",
"code": 200,
"message": "webhook received successfully"
}
def handle_quality_webhook(event):
"""
Handle incoming CQC quality webhook (e.g. from API Gateway or SQS).
Return (status_code, body_dict).
"""
try:
body = json.loads(event.get("body", "{}"))
except json.JSONDecodeError as e:
return 400, {
"status": "Bad Request",
"code": 400,
"message": f"Invalid JSON: {e}"
}
event_type = body.get("event_type")
closing_uuid = body.get("closing_uuid")
package_id = body.get("package_id")
logger.info("Quality event: %s for closing %s package %s", event_type, closing_uuid, package_id)
# Enqueue or process based on event_type; respond 200 first for reliability.
if event_type == "request_loan_data":
# Enqueue job to send loan data to CQC for this package/closing
enqueue_send_loan_data(package_id, closing_uuid)
elif event_type == "request_documents":
# Enqueue job to send documents to CQC for this package/closing
enqueue_send_documents(package_id, closing_uuid)
elif event_type == "report_status_updated":
# Optionally sync QC status to your system of record. report_type tells
# you which review this is ("pre_close", "post-close", …).
status = body.get("status")
sync_report_status(closing_uuid, status)
return 200, SUCCESS_BODY
def enqueue_send_loan_data(package_id, closing_uuid):
# Push to your queue; worker will call CQC API to submit loan data.
pass
def enqueue_send_documents(package_id, closing_uuid):
# Push to your queue; worker will call CQC API to submit documents.
pass
def sync_report_status(closing_uuid, status):
# Update your LOS or UI with the QC status.
pass
```
In production, return 200 after accepting the webhook and process the event asynchronously (e.g. via a queue) so that retries and timeouts are minimized
Below is how to use the endpoints end-to-end to start a QC review and retrieve the results.
1. **Event to Start QC:** Once Snapdocs is ready to begin QC, Snapdocs will send an event to begin uploading additional documents & data required for the review. This event occurs after the first signed document is uploaded to the closing.
2. **Get pre-signed upload URL:** After receiving the event to start QC, get the pre-signed upload URL from our endpoint. This is the URL you will use to upload additional documents for Snapdocs to QC in the review.
3. **Upload documents to review:** Once you have the pre-signed upload URL, get the required documents from the LOS and upload them to the pre-signed upload URL. This will give Snapdocs the documents to conduct QC according to your requirements (e.g., review the 1008 Transmittal for accuracy compared to the LOS).
4. **Upload loan data to review:** After receiving the event to start QC, get the required data fields & values from your LOS and post them to the upload data endpoint. This will give Snapdocs the data points to conduct QC according to your requirements (e.g., check the loan amount on the Note is accurate compared to the loan amount in the LOS).
5. **Event once Finish QC:** Once the review is complete, Snapdocs will send an event informing you are ready to retrieve QC results and classified documents.
6. **Get QC Results:** Call the QC results endpoint to download the QC results. QC results will be delivered as a PDF report to index into your LOS file directory.
7. **Get classified documents:** Call the classified documents endpoint to download each individual signed document. In Closings, Snapdocs returns all signed documents as a combined package. This endpoint enables you to download each classified document in that package separately (e.g., a Closing Disclosure, a Note, a Mortgage) to index into your LOS file directory.
**Subscribe to QC Status Updates:** As Snapdocs begins the review, you can receive status updates by subscribing to our status updates about the progress of the QC review (e.g., not started, in progress, QC passed or possible errors)
**Note on Documents & Data Fields:** We provide all the possible documents you can send in the Documents Glossary and all the possible data points in the Upload Data endpoint. A Snapdocs Implementation Manager will work with you to identify the required documents per your review requirements.
---
### Documents Glossary
# Documents Glossary
In the endpoint Upload documents to review, you may upload one or more of the following documents.
| Internal Name | Document Definition |
| :-------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1040 | IRS Form 1040 – U.S. Individual Income Tax Return: The standard IRS tax return form. |
| 1008\_transmittal | Uniform Underwriting and Transmittal Summary (Fannie Mae Form 1008 / Freddie Mac Form 1077): A standardized one-page summary form that provides key borrower, property, and underwriting information submitted to investors. |
| 92800\_5b | HUD Form 92800.5B – Conditional Commitment/Direct Endorsement Statement of Appraised Value: An FHA document that states the appraised value of the property and lists conditions that must be met before FHA insurance endorsement. |
| ability\_to\_repay | Ability-to-Repay Worksheet: Documentation required under the CFPB’s Ability-to-Repay rule (Regulation Z) demonstrating that the lender made a reasonable, good-faith determination of the borrower’s ability to repay the loan. |
| acknowledgement\_of\_intent\_to\_proceed | Intent to Proceed: A written confirmation from the borrower, as required by TRID, indicating their intent to move forward with the mortgage application after receiving the Loan Estimate. |
| acknowledgment\_of\_receipt\_of\_homeownership\_counseling\_notice | Homeownership Counseling Notice Acknowledgment: A document confirming the borrower received a written list of HUD-approved housing counseling agencies. |
| appraisal | Uniform Residential Appraisal Report (URAR – Fannie Mae Form 1004 / Freddie Mac Form 70): A standardized appraisal report used to estimate the market value of a residential property securing a mortgage loan. |
| appraisal\_1004d | Fannie Mae Form 1004D – Appraisal Update and/or Completion Report: A form used by appraisers to certify completion of required repairs or to update a prior appraisal’s effective date. |
| appraisal\_waiver | Appraisal Waiver (Property Inspection Waiver): A document confirming the borrower may waive an appraisal for the mortgage. |
| assignment\_of\_mortgage | Assignment of Mortgage: A legal document that transfers the mortgage lien from the original lender to another party, typically produced by a DocPrep provider. |
| automated\_underwriting\_decision | Automated Underwriting System (AUS) Findings: The risk assessment findings generated by Fannie Mae’s Desktop Underwriter (DU) or Freddie Mac’s Loan Product Advisor (LPA) evaluating borrower credit and eligibility. |
| CA\_disbursement\_ledger | TBC |
| closing\_disclosure\_approved | Closing Disclosure (Approved Version): The final Closing Disclosure approved, created, and sent with the final closing documents to be signed; typically saved as the approved version in the LOS and reviewed in post-closing to ensure the borrower signed the correct version |
| closing\_protection\_letter | Closing Protection Letter (CPL): A letter issued by a title insurer agreeing to indemnify the lender against losses caused by certain misconduct of the closing agent. |
| condo\_master\_insurance\_policy | Condominium Master Insurance Policy: The insurance policy maintained by a condo association. |
| credit\_report | Credit Report: A report detailing a borrower’s credit history, credit scores, etc., typically obtained from a consumer reporting agency. |
| electronic\_consent\_document | E-Sign Consent Disclosure: A document required under the federal E-SIGN Act that obtains the borrower’s consent to receive disclosures electronically. |
| escrow\_waiver | Escrow Waiver Agreement: A document disclosing the loan will not have an escrow account; typically produced by a DocPrep provider and signed by the borrower. |
| fha\_case\_number | FHA Case Number Assignment: A document issued by HUD with the 10-digit identifier and other details for the FHA mortgage. |
| fha\_loan\_transmittal | HUD Form 92900-LT – FHA Loan Underwriting and Transmittal Summary: A summary form submitted to HUD providing key underwriting data for FHA-insured loans. |
| flood\_certification | Standard Flood Hazard Determination Form (SFHDF): A FEMA-required form that indicates whether a property is located in a Special Flood Hazard Area. |
| flood\_insurance | Flood Insurance Policy: An insurance policy issued by flood insurance providers providing coverage flood-related property damage for properties in flood zones. |
| fraudguard | FraudGuard: A report from third-party provider that identifies and documents potential fraud risk and errors in mortgage applications |
| h06 | HO-6 Insurance Policy (Condominium Unit Owners Policy): An insurance policy that provides coverage for a condominium unit owner’s personal property and interior structures not covered by the master policy. |
| homebuyer\_education\_certification | Homebuyer Education Certification: Documentation verifying completion of a HUD-approved homeownership education course, often required for certain loan programs. |
| homeowner\_insurance | Homeowner Insurance Policy: A homeowner’s insurance policy issued by homeowner insurance providers that provides coverage against damage to the borrower’s property |
| homeownership\_counseling\_organization\_list | Written List of Homeownership Counseling Organizations: A list of HUD-approved housing counseling agencies provided to applicants within three business days of application under RESPA. |
| income\_calculation\_worksheet | Income Calculation Worksheet: A document outlining the income calculations an underwriter used to underwrite the loan. |
| income\_cpa\_letter | CPA Letter: A letter from a Certified Public Accountant verifying a self-employed borrower’s business existence and/or income status. |
| initial\_closing\_disclosure | Initial Closing Disclosure: The first version of the Closing Disclosure provided to the borrower at least three business days before consummation under TRID requirements. |
| initial\_hud\_addendum | Initial HUD Addendum to Uniform Residential Loan Application: The HUD addendum to the loan application form that was submitted with the initial loan application during the application process. |
| initial\_urla | Initial Uniform Residential Loan Application (URLA – Fannie Mae Form 1003 / Freddie Mac Form 65): The standardized mortgage loan application form that was submitted during application process. |
| initial\_va\_addendum\_to\_urla | TBC |
| loan\_estimate | Loan Estimate: A disclosure required under TRID that provides borrowers with key loan terms, estimated payments, and closing costs within three business days of application. |
| mavent\_report | Mavent Report: A document produced from automated compliance checks within the LOS to ensure loan files adhere to federal, state, and local regulations, including TILA, RESPA, and HOEPA |
| mortgage\_insurance | Mortgage Insurance Certificate: Documentation of private mortgage insurance (PMI) or FHA mortgage insurance providing coverage to the lender in the event of borrower default. |
| pmi\_disclosure | Private Mortgage Insurance Disclosure: A disclosure informing borrowers of PMI requirements, costs, and cancellation rights under the Homeowners Protection Act (HPA). |
| power\_of\_attorney | Power of Attorney: A legal document authorizing one person to act on behalf of another in financial or legal matters, including mortgage transactions. |
| preliminary\_title\_report | Preliminary Title Report (Commitment for Title Insurance): A report issued by a title company outlining ownership, liens, and conditions under which title insurance will be issued. |
| purchase\_agreement | Residential Purchase Agreement: A legally binding contract between buyer and seller outlining the terms and conditions of the property sale. |
| request\_for\_single\_family\_housing\_loan\_guarantee | USDA Form RD 3555-21 – Request for Single Family Housing Loan Guarantee: A form used by lenders to request a USDA Rural Development loan guarantee. |
| settlement\_service\_list\_of\_providers | Written List of Providers: A list of settlement service providers given to the borrower under RESPA when the lender permits shopping for certain services. |
| ucdp | Uniform Collateral Data Portal (UCDP) Submission Summary Report: A report confirming appraisal submission to Fannie Mae and Freddie Mac through UCDP and providing appraisal quality findings. |
| uniform\_collection\_dataset\_report | Uniform Closing Dataset (UCD) Findings Report: A report generated from submission of Closing Disclosure data to the GSEs validating data accuracy and compliance. |
| va\_26\_1880\_request\_for\_a\_certificate\_of\_eligibility | VA Form 26-1880 – Request for a Certificate of Eligibility: A form used by veterans to apply for proof of eligibility for a VA home loan benefit. |
| va\_form\_26\_0286\_loan\_summary | VA Form 26-0286 Loan Summary Sheet: A document used by lenders to submit critical loan data to the Department of Veterans Affairs (VA) when requesting a Loan Guaranty Certificate. |
| va\_guaranteed\_home\_loan\_cash\_out\_refinance\_comparison\_certification | VA Cash-Out Refinance Comparison Certification: A VA-required certification confirming the borrower reviewed a comparison of refinance loan options and costs. |
| va\_loan\_analysis | VA Form 26-6393 – Loan Analysis: A VA-required underwriting form documenting the borrower’s income, expenses, and residual income calculation. |
| va\_notice\_of\_value | VA Notice of Value (NOV): A document issued by the VA establishing the appraised value and conditions for a property securing a VA-guaranteed loan. |
| verification\_of\_employment | Verification of Employment (VOE): A report that verifies a borrower’s employment status for underwriting purposes; typically produced from third-party verification providers or internally |
---
### Security
# Security
Authentication is a key process when integrating with Snapdocs Connect REST API. We recommend using OAuth to authenticate against our REST API.
Authenticating via OAuth requires the following steps:
1. Create a Client
2. Generate a JWT token
3. Make authenticated requests
Create a Client
Our Customer Success member will reach out to you and provide your Client ID, Client Secret, as well as a list of scopes you have access to. These API keys carry many privileges, so be sure to keep them secure!
Generate a JWT token
To obtain an access token, simply make a POST request to the /oauth/token endpoint.
This operation requires the following authentication parameters:
* client\_id - the unique Client ID provided by Snapdocs
* client\_secret - the unique Client Secret provided by Snapdocs
* grant\_type - must be set to client\_credentials
* audience - the API you intend to call using a token generated by this request
> 📘 **Tokens expire after 2 hours.** After the call is made, the response will specify how long the bearer token is valid for. We recommend reusing the bearer token until it is expired, then make another call to generate a new token.
# Authenticate via Bearer Auth
To authenticate subsequent API requests, ensure to include a valid bearer token in the
HTTP header:
`Authorization: Bearer {bearer_token}`
---
## Pre-Close QC
### Pre-Close QC
# Pre-Close QC
Pre-Close QC reviews origination documents **before** the closing package is signed — the appraisal waiver disclosure, the title report, and similar — so errors surface while there is still time to correct them.
There is no closing yet at this point, so your system creates the QC package. That extra first call is the only structural difference from [Post-Close QC](https://developers.snapdocs.com/qc/guides/post-close/post_close_qc); everything after it is the same API.
> 📘 Pre-Close QC is enabled per company. If [Create a package](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages/post) returns `403 Forbidden`, the feature is not yet enabled for your account — contact your Snapdocs Implementation Manager.
| Functionality | Description | Endpoint |
| :------------------------------- | :-------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
| Create a package | Create the QC package and receive the `uuid` every later call needs | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages/post) |
| Get pre-signed upload URL | Get a pre-signed URL to upload documents to review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents-upload-url/get) |
| Upload documents to review | Upload origination documents required to review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents/post) |
| Upload loan data to review | Upload loan data required as a part of the review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--loan-data/post) |
| Download QC results | Download the latest QC results, with `type=pre_close` | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--reports/get) |
| Download classified documents | Download individual classified documents, with `report_type=pre_close` | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents/get) |
| \[Status endpoint title] | Get notified via Webhook of status changes in the QC review | |

## Create the package
Post-Close packages already exist in Snapdocs, because they come from a closing. Pre-Close has none, so you create it first and store the returned `uuid` against the loan in your LOS — every later call takes it.
**`POST /qc/packages`**
```json
{
"fileNumber": "12345678",
"signerName": "Smith",
"loanGuid": "d679e2ad-278d-e547-9756-84639ba3865"
}
```
The response returns the package `uuid`. Creating the package is what starts Pre-Close QC, so the loan-data and document events described below fire from that point — not from a signed-document upload as they do for Post-Close.
## Upload documents and loan data
Identical to Post-Close:
1. [Get a pre-signed upload URL](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents-upload-url/get) for each file.
2. `PUT` the file to that URL.
3. [Register the uploaded documents](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents/post) with their `internal_name`.
4. [Upload loan data](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--loan-data/post) for the fields your review compares against.
See [Documents Glossary](https://developers.snapdocs.com/qc/guides/guides/documents_glossary) for the `internal_name` values.
## Retrieve results
**Classified documents** — pass `report_type=pre_close`:
```
GET /qc/packages/{uuid}/documents?report_type=pre_close
```
> 🚧 `report_type` defaults to `funding`. A Pre-Close request that omits it returns the Post-Close set — usually empty for a Pre-Close package — rather than an error.
**The QC report** — pass `type=pre_close`:
```
GET /qc/packages/{uuid}/reports?type=pre_close
```
`type` has no default here; omitting it is an error.
## Events
Pre-Close publishes the same event types described in [Subscription & Webhooks](https://developers.snapdocs.com/qc/guides/guides/subscription_webhooks), carrying `report_type: "pre_close"`. Filter on that field if you subscribe to both reviews, so a Pre-Close status update is not mistaken for a Post-Close one.
---
## Post-Close QC
### Post-Close QC
# Post-Close QC
Post-Close QC reviews the **signed closing package** after the closing. Snapdocs creates the QC package from the closing itself, so your integration starts at the point where QC asks for loan data and documents.
Use the QC API to upload required documents and loan data for a given QC review, receive status updates, and download the latest QC results.
| Functionality | Description | Endpoint |
| :----------------------------------- | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------ |
| Get pre-signed upload URL | Get a pre-signed URL to upload documents to review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents-upload-url/get) |
| Upload documents to review | Upload non-closing documents required to review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents/post) |
| Upload loan data to review | Upload loan data required as a part of the review | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--loan-data/post) |
| Download QC results | Download the latest QC results | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--reports/get) |
| Download classified signed documents | Download individual classified signed documents (e.g., Note, Closing Disclosure, Mortgage) | [Link](https://developers.snapdocs.com/qc/reference/qc-api/paths/qc-packages-uuid--documents/get) |
| \[Status endpoint title] | Get notified via Webhook of status changes in the QC review | |
Documents and reports both default to the Post-Close set, so no `report_type` is needed on these calls. See [Pre-Close QC](https://developers.snapdocs.com/qc/guides/pre-close/pre_close_qc) for the review that runs before signing.

---