Documentation Index
Fetch the complete documentation index at: https://docs.lendpathway.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Two patterns: webhook (Pathway calls you when done) or polling (you check status yourself). Both start with the same submit call.
1. Submit documents
POST /submit-book accepts multipart form data. Pass one or more PDFs. Pathway auto-classifies each file as bank statement, credit report, tax form, or loan application.
import requests
API_BASE = "https://api.lendpathway.com/api"
TOKEN = "pat_your_token_here"
headers = {"Authorization": f"Bearer {TOKEN}"}
files = [
("files", ("jan_statement.pdf", open("jan.pdf", "rb"), "application/pdf")),
("files", ("feb_statement.pdf", open("feb.pdf", "rb"), "application/pdf")),
("files", ("credit_report.pdf", open("credit.pdf", "rb"), "application/pdf")),
]
r = requests.post(
f"{API_BASE}/submit-book",
headers=headers,
files=files,
data={"book_name": "Smith Auto Body Q3 2025"}
)
book_id = r.json()["book_id"]
print(f"Book created: {book_id}")
# Parsing starts immediately in the background
Multiple files in one call is fine. Pathway processes them together as a single deal and cross-references across document types when computing analytics.
2a. Wait with a webhook
Add webhook_url to your submission. Pathway sends a POST to that URL when parsing finishes.
r = requests.post(
f"{API_BASE}/submit-book",
headers=headers,
files=files,
data={
"book_name": "Smith Auto Body Q3 2025",
"webhook_url": "https://your-server.com/pathway-webhook"
}
)
Webhook payload sent to your URL on completion:
{
"book_id": "99cc93e6-1f3f-42b1-9fe4-ba5a95be9c78",
"status": "completed",
"book_url": "https://app.lendpathway.com/books/99cc93e6-1f3f-42b1-9fe4-ba5a95be9c78"
}
status is one of completed, failed, cancelled.
Example receiver (FastAPI):
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class WebhookPayload(BaseModel):
book_id: str
status: str
book_url: str
@app.post("/pathway-webhook")
async def handle_webhook(payload: WebhookPayload):
if payload.status == "completed":
analytics = await fetch_book_analytics(payload.book_id)
elif payload.status == "failed":
print(f"Parse failed for book {payload.book_id}")
return {"ok": True}
2b. Wait with polling
Poll GET /books/:id every few seconds until parse_status is terminal.
import time
def wait_for_parse(book_id, poll_interval=5, timeout=600):
start = time.time()
while True:
r = requests.get(f"{API_BASE}/books/{book_id}", headers=headers)
book = r.json()
status = book["parse_status"]
message = book.get("parse_status_message", "")
print(f" [{status}] {message}")
if status == "completed":
return book
if status in ("failed", "cancelled"):
raise Exception(f"Parse ended with status: {status}")
if time.time() - start > timeout:
raise TimeoutError("Parse timed out")
time.sleep(poll_interval)
book = wait_for_parse(book_id)
print(f"Done: {book['parse_status_message']}")
# Done: Processed 3 bank_statements
parse_status_message tells you what Pathway parsed, e.g. Processed 3 bank_statements or Processed 1 credit_report, 2 bank_statements. Good for confirming file classification.
3. Fetch results
Once parse_status is completed, call /analytics for bank statement data.
r = requests.get(f"{API_BASE}/books/{book_id}/analytics", headers=headers)
analytics = r.json()
print(f"Deposits: ${analytics['total_deposits']:,.2f}")
print(f"True revenue: ${analytics['true_revenue']:,.2f}")
print(f"Avg daily balance: ${analytics['average_daily_balance']:,.2f}")
print(f"Days negative: {analytics['days_negative_balance']}")
print(f"DTI: {analytics.get('debt_to_income_ratio', 'N/A')}%")
print(f"Positions found: {len(analytics['positions'])}")
For credit report data, read from book_meta:
r = requests.get(f"{API_BASE}/books/{book_id}", headers=headers)
book = r.json()
cr = book["book_meta"]["parser_v2_credit_report"]
entity = cr["primary_entity"]
print(f"Subject: {entity['full_name']}")
for bureau_data in cr["credit_report_body"]:
bureau = bureau_data["credit_bureau"]["display_name"]
fico = bureau_data.get("fico_score", {})
print(f"{bureau}: FICO {fico.get('score')}")
print(f" Accounts: {len(bureau_data['underwritten_accounts'])}")
For tax forms, use /tax-analytics:
r = requests.get(f"{API_BASE}/books/{book_id}/tax-analytics", headers=headers)
tax = r.json()
for year in tax["years"]:
print(f"{year['tax_year']}: qualifying income = ${year['total_qualifying_income']:,.2f}")
4. Full flow in one script
import requests, time
API_BASE = "https://api.lendpathway.com/api"
TOKEN = "pat_your_token_here"
headers = {"Authorization": f"Bearer {TOKEN}"}
# 1. Submit
with open("statement.pdf", "rb") as f:
r = requests.post(
f"{API_BASE}/submit-book",
headers=headers,
files={"files": ("statement.pdf", f, "application/pdf")},
data={"book_name": "Test book"}
)
book_id = r.json()["book_id"]
print(f"Submitted: {book_id}")
# 2. Poll
while True:
status = requests.get(f"{API_BASE}/books/{book_id}", headers=headers).json()["parse_status"]
if status == "completed":
break
if status in ("failed", "cancelled"):
raise Exception(f"Parse failed: {status}")
time.sleep(5)
# 3. Get analytics
analytics = requests.get(f"{API_BASE}/books/{book_id}/analytics", headers=headers).json()
print(f"True revenue: ${analytics['true_revenue']:,.2f}")
print(f"Positions: {len(analytics['positions'])}")