Draw Requests Guide

Complete guide to requesting loan draws, handling final draws with completion certificates, and managing the disbursement process

Draw Requests Guide

This guide covers everything you need to know about requesting loan draws through the Thrive Public API, including regular draws and final draws with completion certificates.

Overview

Draw requests allow you to access approved loan funds in stages throughout your project. The Thrive API supports:

  • Regular Draws - Standard fund disbursements during project execution
  • Final Draws - The last disbursement requiring project completion documentation
  • Early Project Completion Draws - If you need to complete a project before all scheduled draws.
📘

API Endpoint Reference

This guide covers the business workflows for draw requests. For complete technical documentation of the endpoint, see our API Reference.

Draw Request Process

1. Prerequisites

Before requesting a draw, ensure:

  • ✅ Loan application is in "Approved" status
  • ✅ No pending draw requests exist for the loan
  • ✅ Available loan balance covers the requested amount
  • ✅ Required authentication headers are configured

2. Authentication

This endpoint requires authentication via headers:

HeaderRequiredDescription
x-thrive-client-idYesClient ID for authentication
x-thrive-client-secretYesClient secret for authentication
x-thrive-merchant-uidNoMerchant identifier (only needed for group accounts)

3. Path Parameters

ParameterTypeRequiredDescription
loanApplicationUidstring (UUID)YesUnique identifier of the loan application

4. Request Body

This endpoint uses multipart/form-data format and handles both regular draw requests and final draw requests with project completion documentation.

Regular Draw Request

For a standard draw request, submit with an empty body or specify optional parameters:

FieldTypeRequiredDescription
updatedDisbursementAmountstringNoRevised disbursement amount for this draw (up to 2 decimal places). Enter a specific amount less than the calculated draw amount to reduce the disbursement. This field cannot be used together with projectCompletedEarly.

Final Draw Request

For the final draw, you must provide project completion documentation:

FieldTypeRequiredDescription
filesarray of filesConditional*Project completion certificate files (PDFs, images, etc.)
metadatastring (JSON)Conditional*JSON string containing completion certificate metadata
updatedLoanAmountstringNoRevised total loan amount (up to 2 decimal places). This value cannot exceed the original loan amount. Use this field to reduce the loan amount if the project is completed under budget.

*Either files or metadata must be provided for final draws.


Early Project Completion

If you need to complete a project before all scheduled draws:

FieldTypeRequiredDescription
projectCompletedEarlybooleanYesSet to true to mark project as completed early
updatedLoanAmountstringNoRevised total loan amount (up to 2 decimal places). This value cannot exceed the original loan amount. Use this field to reduce the loan if the project is completed under budget.
filesarray of filesConditional*Completion certificate files
metadatastring (JSON)Conditional*Completion certificate metadata

*Either files or metadata (or both) must be provided when completing early.

5. Understanding Draw Requests

The system automatically determines whether this is a final draw based on the loan's disbursement schedule. You don't need to explicitly specify the draw type—the system detects this and enforces the appropriate requirements.


Regular Draw

Submit the request with no body for the full calculated draw amount, or include updatedDisbursementAmount to request a specific amount less than what's calculated for the current stage.

When to use: For standard, scheduled disbursements during project progress.

Example scenarios:

  • Requesting the next scheduled draw at the full calculated amount
  • Requesting less than the calculated amount if the current stage cost less than expected

Final Draw

The system automatically detects when this is the final draw based on the disbursement schedule and requires completion certificate documentation (files and/or metadata).

When to use: For the last scheduled draw when the project is complete.

Requirements:

  • Completion documentation is mandatory (files and/or metadata)
  • If the project was completed under budget, include updatedLoanAmount to reduce the total loan amount to reflect actual costs

Early Completion

Mark projectCompletedEarly: true and provide completion documentation to finalize a project before all scheduled draws have been requested.

When to use: When a project is completed ahead of schedule or requires fewer disbursements than originally planned.

Requirements:

  • Cannot be used on the first draw of multi-disbursement loans
  • Must include completion certificate documentation (files or metadata)
  • If the project was completed under budget, include updatedLoanAmount to reduce the total loan amount

Important: When completing a project (early or final), use updatedLoanAmount to adjust the total loan amount. Do not use updatedDisbursementAmount.

6. Making Draw Requests

Regular Draw Request

For a standard draw request:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "

For a standard draw with reduced draw amount:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "updatedDisbursementAmount=8000.99"

Final Draw Request

For the final draw with completion certificate files:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "files=@completion_certificate.pdf" \
  -F "files=@project_photos.jpg" \

For final draw using JSON metadata:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F 'metadata={"projectName": "Solar Panel System", "completionDate": "2024-01-15", "certificationNumber": "CERT-123", "inspector": "John Smith"}'

For final draw with reduced loan amount:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "updatedLoanAmount=15000" \
  -F "files=@completion_certificate.pdf" \

Early Project Completion Draw Request

For early project completion draw with completion certificate files:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "projectCompletedEarly=true" \
  -F "files=@completion_certificate.pdf" \

For early project completion draw using JSON metadata:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "projectCompletedEarly=true" \
  -F 'metadata={"projectName": "Solar Panel System", "completionDate": "2024-01-15", "certificationNumber": "CERT-123", "inspector": "John Smith"}'

For early project completion draw using reduced loan amount:

curl -X POST https://api.partnerwiththrive.com/public/v2/loan/{loanApplicationUid}/request-draw \
  -H "x-thrive-client-id: your_client_id" \
  -H "x-thrive-client-secret: your_client_secret" \
  -H "x-thrive-merchant-uid: your_merchant_uid" \
  -F "projectCompletedEarly=true" \
  -F "updatedLoanAmount=15000.25" \
  -F "files=@completion_certificate.pdf" \

Final Draw Requirements

When is a Final Draw Required?

The system automatically determines if a draw request is the final draw based on the loan's remaining disbursement balance. When making the final draw:

  • Completion documentation is mandatory (files and/or metadata)
  • Project must be completed and ready for inspection
  • All previous draws must be successfully disbursed

Completion Certificate Options

You can provide completion documentation in three ways:

1. File Upload Only

  • Upload PDF certificates, photos, inspection reports
  • Supported file types: PDF, JPG, PNG, DOCX
  • Maximum file size: 10MB per file

2. Metadata Only

  • Provide completion details as JSON string
  • Include project details, dates, certification numbers
  • Useful for digital-only completion processes

3. Files + Metadata (Recommended)

  • Combine files with structured metadata
  • Provides complete documentation trail
  • Best for compliance and record-keeping

Metadata Schema

When providing metadata, use this JSON structure:

{
  "projectName": "Solar Panel Installation",
  "completionDate": "2024-01-15",
  "certificationNumber": "CERT-123456",
  "inspector": "John Smith",
  "inspectorLicense": "LIC-789",
  "projectDescription": "20kW residential solar system installation",
  "systemDetails": {
    "capacity": "20kW",
    "panelCount": 60,
    "inverterType": "String inverters"
  },
  "complianceNotes": "Installation meets all local building codes"
}

Response Handling

Successful Draw Response

{
  "timestamp": "2025-09-10T20:17:42.562Z",
  "statusCode": 200,
  "result": {
    "data": {
      "merchantDisbursementId": 699,
      "merchantUid": "e2432827-aec8-49d7-be4e-14ec91e6813d",
      "loanApplicationUid": "c4ff1199-a135-4739-b110-91f7c1bf9d2f",
      "grossDisbursedAmount": "12000",
      "netDisbursedAmount": "11160",
      "disbursementNumber": 1,
      "amountFunded": "11160"
    },
    "error": null
  }
}

Key Response Fields:

FieldTypeDescription
timestampstring (date-time)The exact time when the response was generated
statusCodenumberHTTP status code
result.data.merchantDisbursementIdnumberInternal disbursement ID
result.data.merchantUidstring (UUID)Merchant's unique identifier
result.data.loanApplicationUidstring (UUID)Loan application unique identifier
result.data.grossDisbursedAmountstringTotal disbursement amount before fees
result.data.netDisbursedAmountstringNet amount after deducting fees
result.data.disbursementNumbernumberSequential disbursement number for this loan
result.data.amountFundedstringExact amount funded (same as netDisbursedAmount)
result.errorobject or nullError object if request failed, null on success

Common Scenarios & Solutions

Scenario 1: Multiple Regular Draws

Use Case: Solar installation with multiple milestone payments

// Draw 1: Materials purchase
const draw1 = await requestDraw(loanUid); // No files needed

// Draw 2: Installation milestone
const draw2 = await requestDraw(loanUid); // No files needed

// Final Draw: Project completion
const finalDraw = await requestDraw(loanUid, {
  files: ['completion_cert.pdf', 'final_inspection.jpg'],
  metadata: {
    projectName: 'Solar Installation',
    completionDate: '2024-01-15',
    certificationNumber: 'CERT-123'
  }
});

Scenario 2: Single Large Project Draw

Use Case: Pool installation with one large disbursement

// Final draw for complete project
const draw = await requestDraw(loanUid, {
  files: ['building_permit.pdf', 'completed_pool.jpg'],
  metadata: {
    projectName: 'In-ground Pool Installation',
    completionDate: '2024-01-15',
    permitNumber: 'PERMIT-456',
    inspector: 'Jane Doe'
  }
});

Scenario 3: Digital-Only Completion

Use Case: Service-based project without physical documentation

// Final draw with metadata only
const draw = await requestDraw(loanUid, {
  metadata: {
    projectName: 'HVAC System Service',
    completionDate: '2024-01-15',
    serviceType: 'Complete system tune-up',
    technicianName: 'Mike Johnson',
    certificationNumber: 'HVAC-789'
  }
});

Error Handling

Common Error Patterns

Missing Completion Documentation

{
  "statusCode": 400,
  "result": {
    "error": {
      "message": "File or metadata is required for completion certificate upload."
    }
  }
}

Solution: Add either files or metadata to your final draw request.

Documentation for Non-Final Draw

{
  "statusCode": 400,
  "result": {
    "error": {
      "message": "Project completion documentation was provided, but this is not the final draw for loan abc-123. Only submit documentation for the final draw."
    }
  }
}

Solution: Remove files and metadata from regular draw requests.

Application Not Approved

{
  "statusCode": 400,
  "result": {
    "error": {
      "message": "The application must be in the Approved status before requesting a Draw with accompanying Completion Certificate."
    }
  }
}

Solution: Wait for loan approval before requesting draws.

Pending Draw Exists

{
  "statusCode": 500,
  "result": {
    "error": {
      "message": "Error in requestPublicDrawV2: There is a currently pending draw for this loan."
    }
  }
}

Solution: Wait for the current draw to complete before requesting another.

Error Handling Best Practices

async function requestDrawWithRetry(loanUid, options = {}) {
  try {
    const response = await fetch(`/public/v2/loan/${loanUid}/request-draw`, {
      method: 'POST',
      headers: {
        'x-thrive-client-id': process.env.THRIVE_CLIENT_ID,
        'x-thrive-client-secret': process.env.THRIVE_CLIENT_SECRET,
        'x-thrive-merchant-uid': process.env.THRIVE_MERCHANT_UID
      },
      body: createFormData(options)
    });

    const result = await response.json();

    if (!response.ok) {
      throw new DrawRequestError(result.result.error.message, result.statusCode);
    }

    return result.result.data;

  } catch (error) {
    // Handle specific error cases
    if (error.message.includes('pending draw')) {
      console.log('Waiting for pending draw to complete...');
      await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30s
      return requestDrawWithRetry(loanUid, options); // Retry once
    }

    throw error;
  }
}

File Upload Guidelines

Supported File Types

  • Documents: PDF, DOC, DOCX
  • Images: JPG, JPEG, PNG, WEBP
  • Spreadsheets: XLS, XLSX

File Size Limits

  • Maximum per file: 10MB
  • Maximum total: 50MB per request
  • Recommended: Compress images and PDFs before upload

File Naming Best Practices

  • Use descriptive names: completion_certificate.pdf
  • Avoid special characters: Use underscores instead of spaces
  • Include dates: inspection_report_2024-01-15.pdf

Testing & Development

Sandbox Environment

Test draw requests in the sandbox environment:

# Sandbox base URL
https://dev.partnerwiththrive.com/public/v2/loan/{loanUid}/request-draw

Test Data Considerations

  • Use test loan applications in "Approved" status
  • Test both regular and final draw scenarios
  • Verify error handling with invalid requests

Integration Examples

Node.js with FormData

import FormData from 'form-data';
import fs from 'fs';

async function submitFinalDraw(loanUid, files, metadata) {
  const form = new FormData();

  // Add files
  files.forEach(filePath => {
    form.append('files', fs.createReadStream(filePath));
  });

  // Add metadata
  if (metadata) {
    form.append('metadata', JSON.stringify(metadata));
  }

  const response = await fetch(`/public/v2/loan/${loanUid}/request-draw`, {
    method: 'POST',
    headers: {
      'x-thrive-client-id': process.env.THRIVE_CLIENT_ID,
      'x-thrive-client-secret': process.env.THRIVE_CLIENT_SECRET,
      'x-thrive-merchant-uid': process.env.THRIVE_MERCHANT_UID,
      ...form.getHeaders()
    },
    body: form
  });

  return response.json();
}

Python with Requests

import requests
import json

def submit_draw_request(loan_uid, files=None, metadata=None):
    url = f"/public/v2/loan/{loan_uid}/request-draw"
    headers = {
        'x-thrive-client-id': os.environ['THRIVE_CLIENT_ID'],
        'x-thrive-client-secret': os.environ['THRIVE_CLIENT_SECRET'],
        'x-thrive-merchant-uid': os.environ['THRIVE_MERCHANT_UID']
    }

    form_data = {}
    files_data = []

    # Add files
    if files:
        for file_path in files:
            files_data.append(('files', open(file_path, 'rb')))

    # Add metadata
    if metadata:
        form_data['metadata'] = json.dumps(metadata)

    response = requests.post(url, headers=headers, data=form_data, files=files_data)
    return response.json()

Next Steps


Need Help? Contact your Thrive integration manager for assistance with draw request implementation.