Retrieve a previously completed PDF analysis by its unique check ID.
GET https://api.htpbe.tech/v1/result/{id}
This endpoint requires API key authentication via the Authorization header.
Authorization: Bearer YOUR_API_KEYImportant: You can only retrieve analysis results that belong to your API client. Attempting to access another client's results will return a 404 error, even if the check ID exists. This ensures complete data privacy and isolation between API clients.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Check ID returned from POST /api/v1/analyze. UUID v4 for all requests — live and test keys both return UUID v4 IDs. |
Live key format: UUID v4 — xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx
Test key format: Deterministic UUID v4 — fixed all-zeros pattern, e.g. 00000000-0000-4000-8000-000000000001
Valid Examples:
506a6b1b-1360-48a2-b389-abb346f85d04(live key request)00000000-0000-4000-8000-000000000001(test key request —clean.pdf)
Invalid Examples:
abc123(too short, not a UUID)- `` (empty string)
Where to Get: The id field returned by POST /api/v1/analyze.
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer token with your API key (Bearer htpbe_live_... or Bearer htpbe_test_...). The Bearer prefix is recommended but optional — sending the raw key directly is also accepted, but only if the key starts with htpbe_ (e.g., Authorization: htpbe_live_sk_...). |
curl https://api.htpbe.tech/v1/result/506a6b1b-1360-48a2-b389-abb346f85d04 \
-H "Authorization: Bearer htpbe_live_sk_1234567890abcdef"// Node.js / TypeScript
const checkId = '506a6b1b-1360-48a2-b389-abb346f85d04';
const response = await fetch(`https://api.htpbe.tech/v1/result/${checkId}`, {
headers: {
Authorization: `Bearer ${process.env.HTPBE_API_KEY}`,
},
});
const result = await response.json();# Python
import requests
import os
check_id = '506a6b1b-1360-48a2-b389-abb346f85d04'
response = requests.get(
f'https://api.htpbe.tech/v1/result/{check_id}',
headers={
'Authorization': f"Bearer {os.getenv('HTPBE_API_KEY')}"
}
)
result = response.json()Returns a ResultResponse object containing all stored analysis data for the check.
Note: /api/v1/analyze returns only { "id": "..." }. This endpoint is where all analysis data lives: metadata, structure, signatures, findings, and verdict details.
{
// Core Identification
id: string;
filename: string;
check_date: number | null;
file_size: number;
// Algorithm version tracking
algorithm_version: string;
current_algorithm_version: string;
outdated_warning?: string;
// Primary Verdict
status: "intact" | "modified" | "inconclusive";
status_reason?: "consumer_software_origin" | "online_editor_origin" | "scanned_document" | "unverifiable_metadata" | "filled_form_origin" | "fill_sign_origin";
// PDF Metadata (Unix timestamps)
creation_date: number | null;
modification_date: number | null;
creator: string | null;
producer: string | null;
// Critical Modification Detection
modification_confidence: string | null;
// Metadata Analysis
date_sequence_valid: boolean;
metadata_completeness_score: number;
// PDF Structure
xref_count: number;
has_incremental_updates: boolean;
update_chain_length: number;
pdf_version: string | null;
// Digital Signatures
has_digital_signature: boolean;
signature_count: number;
signature_removed: boolean;
modifications_after_signature: boolean;
// Content Analysis
page_count: number;
object_count: number;
has_javascript: boolean;
has_embedded_files: boolean;
// Modification Evidence
modification_markers: string[];
// Responsible-use guardrail (always present)
usage_caution: {
safe_for_automated_adverse_decision: false;
recommended_action: "route_to_human_review" | "request_from_issuer" | "no_action";
message: string;
};
}- Type:
string(UUID v4) - Always Present: Yes
- Description: Unique identifier for this check
- Format:
xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx - Example:
"506a6b1b-1360-48a2-b389-abb346f85d04"
- Type:
string - Always Present: Yes
- Description: The stored filename for this check. If
original_filenamewas provided in thePOST /analyzerequest body, that value is used. Otherwise it is extracted from the last segment of theurlpath. - Examples:
"contract.pdf"(provided asoriginal_filenamein the analyze request, or extracted fromhttps://example.com/docs/contract.pdf)"invoice-2024-01.pdf""document.pdf"(default set at analysis time when no filename is determinable from the URL)""(empty string for legacy records created before filename tracking)
- Type:
number | null(Unix timestamp in seconds) - Can Be Null: Yes —
nullfor test key results (synthetic responses have no real analysis timestamp) and for legacy records created before timestamp tracking was introduced - Description: Timestamp when the analysis was performed
- Format: Seconds since Unix epoch (January 1, 1970 00:00:00 UTC)
- Example:
1736542583= January 10, 2025, 18:23:03 UTC - Convert to Date:
- JavaScript:
check_date ? new Date(check_date * 1000) : null - Python:
datetime.fromtimestamp(check_date) if check_date else None
- JavaScript:
- Type:
number(integer, bytes) - Always Present: Yes
- Range:
1to10485760(10 MB) - Description: File size in bytes
- Example:
245632= ~240 KB - Convert to MB:
file_size / 1024 / 1024
Note: Version numbers reflect the algorithm in use at the time of analysis. The current version may differ.
- Type:
string - Always Present: Yes
- Description: Version of the detection algorithm used when this check was performed. Defaults to
"1.0.0"for records created before algorithm versioning was introduced. - Format: Semantic versioning (e.g.,
"2.2.1") - Usage: Compare against the current version to determine if re-analysis is recommended
- Example:
"2.2.1"
- Type:
string - Always Present: Yes
- Description: The current algorithm version running on the server
- Format: Semantic versioning (e.g.,
"2.2.1") - Usage: Compare
algorithm_versionagainstcurrent_algorithm_versionto determine if the check is outdated. Ifalgorithm_version !== current_algorithm_version, the check was performed with an older algorithm and re-analysis is recommended. - Example:
"2.2.1"
- Type:
string(optional) - Present When:
algorithm_versionis older thancurrent_algorithm_version(semver comparison — a future version would not trigger this warning even if the values differ) - Absent When:
algorithm_versionis current - Description: Human-readable explanation of what changed in the newer algorithm version and why re-analysis is recommended
- Example:
"Our detection software has been updated since this file was analyzed. The results shown below may no longer be accurate. We recommend re-analyzing this file for more accurate results."
- Type:
"intact" | "modified" | "inconclusive" - Always Present: Yes
- Description: PRIMARY VERDICT. Priority:
modified > inconclusive > intact"modified"— forensic evidence of post-creation modification detected; takes priority over origin type — a modified Word or Excel document is stillmodified"inconclusive"— consumer software, online editor, scanned, unverifiable (re-rendered or image-only), filled-form, or Fill & Sign origin with no modification detected; integrity check does not apply to documents anyone can create, reprocess, fill in, or scan from scratch. The specific cause is instatus_reason"intact"— no structural evidence of modification, and the document did not originate from consumer software, an online editor, or a scan
- Note:
status_reasononly appears whenstatus === "inconclusive"
- Type:
"consumer_software_origin" | "online_editor_origin" | "scanned_document" | "unverifiable_metadata" | "filled_form_origin" | "fill_sign_origin"| absent - Always Present: No — only present when
status === "inconclusive" - Description: Explains why the result is inconclusive.
- Values:
"consumer_software_origin"— the PDF was created by consumer software (Microsoft Word, LibreOffice, Google Docs, etc.) or a freely available HTML-to-PDF renderer. These tools let anyone create a document from scratch, so there is no meaningful "original" to compare against. For a file that claims institutional origin (a payslip, an invoice, a bank statement), this origin is itself a strong signal to route for review — a real payroll or banking system does not distribute documents this way. If the document will support a financial or compliance decision, verify its content directly with the issuing organisation."online_editor_origin"— the PDF was processed through an online editing service (iLovePDF, Smallpdf, PDF24, etc.). These services strip original metadata, making provenance verification impossible."scanned_document"— the PDF is a pure raster scan (no fonts, no text layer, at least one image per page). Anyone can print and scan a document, so its content cannot be verified through metadata analysis."unverifiable_metadata"— the PDF was rebuilt by a render engine (e.g. a browser print backend) that flattens away the structural history an integrity check depends on. The original provenance can no longer be established."filled_form_origin"— the PDF is an interactive form (AcroForm) with at least one filled field. A form can be filled or re-filled any number of times, so a structural check cannot certify what it currently shows."fill_sign_origin"— the PDF carries an Adobe Fill & Sign overlay, which lets anyone add text and marks over a page. A structural check cannot separate an original fill from a later edit.
- Usage: Always check
status_reasonwhenstatus === "inconclusive"— it tells you why the result is inconclusive, not just that it is.
Handle every branch — an inconclusive verdict is not a failure and not a pass. It means the integrity check does not apply, so route the document by why rather than treating it as clean:
function handleResult(result) {
switch (result.status) {
case 'modified':
// Forensic evidence of post-creation modification — route to human review.
return 'review';
case 'intact':
// No structural evidence of modification.
return 'accept';
case 'inconclusive':
// Integrity check does not apply. Branch on status_reason to decide handling.
switch (result.status_reason) {
case 'scanned_document':
// Pure raster scan — no text layer, provenance unverifiable.
case 'online_editor_origin':
// Processed through an online editor — original metadata stripped.
case 'unverifiable_metadata':
// Re-rendered or image-only — structural history flattened away.
case 'filled_form_origin':
// Interactive form with filled fields — content can be re-filled at any time.
case 'fill_sign_origin':
// Adobe Fill & Sign overlay — an original fill can't be told from a later edit.
case 'consumer_software_origin':
// Created in consumer software or a free HTML-to-PDF renderer.
// On a document that CLAIMS institutional origin (payslip, invoice, bank
// statement), this is itself a red flag — verify the content directly with
// the issuing organisation before relying on it.
return 'verify-with-issuer';
default:
return 'verify-with-issuer';
}
}
}All timestamps are Unix integers (seconds since epoch). Convert with: new Date(timestamp * 1000) in JavaScript, datetime.fromtimestamp(ts) in Python.
- Type:
number | null(Unix timestamp in seconds) - Can Be Null: Yes
- Description: PDF creation timestamp from embedded metadata
- Null When: PDF does not contain creation date
- Example:
1704110400= January 2, 2024 00:00:00 UTC - Convert: JavaScript:
new Date(creation_date * 1000).toISOString()
- Type:
number | null(Unix timestamp in seconds) - Can Be Null: Yes
- Description: Last modification timestamp from embedded metadata
- Null When: PDF does not contain modification date
- Critical: If different from
creation_date, indicates modification - Example:
1707840000= February 13, 2024 12:00:00 UTC
- Type:
string | null - Can Be Null: Yes
- Description: Application that created the original document
- Example:
"Microsoft Word for Microsoft 365" - Common Values:
"Microsoft Word for Microsoft 365","Adobe InDesign CC","LibreOffice Writer","Google Docs"
- Type:
string | null - Can Be Null: Yes
- Description: Software that generated the final PDF
- Example:
"Adobe PDF Library 15.0" - Common Values:
"Adobe PDF Library 15.0","PDFKit","Microsoft: Print To PDF","iText 7.0.0"
- Type:
string | null(enum) - Can Be Null: Yes
- Description: How certain the algorithm is about the modification verdict. Use it to decide how to route the case for review — never as a trigger for an automatic adverse decision against a person (see
usage_caution). - Possible Values:
"certain"— conclusive structural or cryptographic evidence; the finding cannot be a false positive (date mismatch, post-signature modification, signature removal). Treat the document as modified and route it to human review or request a fresh copy directly from the issuer — do not auto-reject the person on this alone."high"— strong forensic evidence; flag for manual review — highly reliable but rare false positives are possible in unusual legitimate workflows (e.g. linearization, batch processing pipelines)"none"— no modification detected; the document can proceed, subject to your own downstream checks
- Relationship to
status:certainandhighalways correspond tostatus: "modified".nonecorresponds tostatus: "intact"or"inconclusive"depending on origin. - Null When: Legacy records before this field was added
- Type:
boolean - Always Present: Yes
- Description: Whether creation and modification dates are in chronologically valid sequence
- Valid Sequence:
creation_date≤modification_date - Possible Values:
true- Dates are valid (creation before or equal to modification)false- Suspicious - Modification date is before creation date (impossible in normal workflow)
- Red Flag:
falsestrongly suggests date tampering
- Type:
number(integer) - Always Present: Yes
- Range:
0to100 - Description: How complete the PDF metadata is (percentage of fields present)
- Calculation: Based on presence of:
- Creation date
- Modification date
- Creator
- Producer
- Title, Subject, Author (standard metadata)
- Interpretation:
90-100- Excellent metadata, most fields present70-89- Good metadata coverage50-69- Moderate metadata30-49- Limited metadata0-29- Very sparse metadata (may hinder analysis)
- Impact: Higher scores enable more confident modification detection
- Type:
number(integer) - Always Present: Yes
- Description: Number of cross-reference (xref) tables in the PDF
- Interpretation:
1= original document,2+= document has been modified and saved multiple times
- Type:
boolean - Always Present: Yes
- Description: Whether PDF has incremental update sections (been saved multiple times after initial creation)
- Values:
true= PDF has been edited and saved incrementally,false= PDF was generated in one operation
- Type:
number(integer) - Always Present: Yes
- Description: Number of update sections in PDF structure (how many times the PDF was saved)
- Interpretation:
1= original,2-5= light editing,6-10= moderate editing,11+= heavy editing
- Type:
string | null - Can Be Null: Yes
- Description: PDF specification version
- Examples:
"1.7","1.4","2.0",null - Common Versions:
"1.7"(most common, Acrobat 8.x+),"1.4"(Acrobat 5.x),"2.0"(modern ISO standard)
- Type:
boolean - Always Present: Yes
- Description: Whether PDF currently contains digital signatures
- Values:
true= digitally signed,false= not signed - Note: Signature validity is NOT checked (only presence)
- Type:
number(integer) - Always Present: Yes
- Description: Number of digital signature fields in the PDF
- Range:
0and higher
- Type:
boolean - Always Present: Yes
- Description: Whether a digital signature was removed from the document
- Critical: If
true, this is strong evidence of tampering
- Type:
boolean - Always Present: Yes
- Description: Whether PDF was modified after being digitally signed
- Critical: If
true, the digital signature is likely invalidated
- Type:
number(integer) - Always Present: Yes
- Range:
1and higher - Description: Total number of pages in the PDF document
- Example:
12= 12-page document - Usage: Useful for estimating document size and complexity
- Type:
number(integer) - Always Present: Yes
- Range:
0and higher - Description: Number of PDF objects in the internal structure
- What It Means:
- PDF objects include: pages, fonts, images, annotations, forms, etc.
- Higher object count generally means more complex document
- Useful for detecting unusual structural complexity
- Typical Ranges:
50-200- Simple text document200-500- Document with images500-1000- Complex document with forms/annotations1000+- Very complex document or potential obfuscation
- Type:
boolean - Always Present: Yes
- Description: Whether PDF contains embedded JavaScript code
- Values:
true= JavaScript present (potential security risk),false= no JavaScript detected - Security Note: JavaScript in PDFs can be used for malicious purposes
- Type:
boolean - Always Present: Yes
- Description: Whether PDF has embedded file attachments
- Values:
true= has attachments (potential security risk),false= no attachments - Security Note: Attachments can hide malware
- Type:
string[](array of strings) - Always Present: Yes
- Description: All modification signals detected, ordered strongest-first. The first element (
modification_markers[0]) is the strongest marker — the single most important forensic indicator that drove the verdict. Usually contains one entry; may have two or three when multiple independent signals fired simultaneously (e.g. dates disagree AND an editing tool detected). Empty whenstatusis"intact"or"inconclusive". - Format: Each entry is a stable machine-readable id (e.g.
HTPBE_SIGNATURE_REMOVED,HTPBE_DATES_DISAGREE). The full id → outcome-label dictionary is published on htpbe.tech/how — branch on the id in your integration, render the user-facing label from the dictionary. - Empty When: No modification detected (
status: "intact"orstatus: "inconclusive") - Example Values:
"HTPBE_DATES_DISAGREE""HTPBE_MULTIPLE_REVISION_LAYERS""HTPBE_SIGNATURE_REMOVED""HTPBE_POST_SIGNATURE_EDIT""HTPBE_EDITING_TOOL_FINGERPRINT""HTPBE_IDENTITY_BLANKED""HTPBE_FONT_VS_TOOL_MISMATCH""HTPBE_DESIGN_TEMPLATE_ASSEMBLY""HTPBE_TEXT_OVERLAY_ON_SCAN""HTPBE_PAGES_FROM_MULTIPLE_SOURCES"
- Type:
object - Always Present: Yes
- Description: In-contract responsible-use guardrail. A structural verdict describes the file, not the person who sent it, so it must never be the sole basis for an automatic adverse decision (rejecting or denying an applicant, claimant, or customer). This field ships the guardrail in the payload itself, not only in the docs — branch on
recommended_actionto route the case instead of auto-rejecting. - Fields:
safe_for_automated_adverse_decision—boolean, alwaysfalse. A machine-checkable assertion that this verdict alone must not drive an automatic adverse decision against a person.recommended_action—"route_to_human_review"(forstatus: "modified"),"request_from_issuer"(forstatus: "inconclusive"— the check could not confirm integrity, which is not proof of fraud), or"no_action"(forstatus: "intact").message— human-readable guidance matchingrecommended_action.
- Example:
{
"safe_for_automated_adverse_decision": false,
"recommended_action": "route_to_human_review",
"message": "Structural evidence of post-creation modification was found. Route this document to a human reviewer before any decision — do not use this verdict as the sole basis for an automatic adverse decision against a person."
}{
"id": "506a6b1b-1360-48a2-b389-abb346f85d04",
"filename": "contract.pdf",
"check_date": 1736542583,
"file_size": 245632,
"algorithm_version": "2.2.1",
"current_algorithm_version": "2.2.1",
"status": "modified",
"creation_date": 1704110400,
"modification_date": 1707840000,
"creator": "Adobe Acrobat Pro DC",
"producer": "Adobe PDF Library 15.0",
"modification_confidence": "certain",
"date_sequence_valid": true,
"metadata_completeness_score": 90,
"xref_count": 2,
"has_incremental_updates": true,
"update_chain_length": 3,
"pdf_version": "1.7",
"has_digital_signature": false,
"signature_count": 0,
"signature_removed": true,
"modifications_after_signature": false,
"page_count": 12,
"object_count": 487,
"has_javascript": false,
"has_embedded_files": false,
"modification_markers": ["HTPBE_SIGNATURE_REMOVED", "HTPBE_DATES_DISAGREE"],
"usage_caution": {
"safe_for_automated_adverse_decision": false,
"recommended_action": "route_to_human_review",
"message": "Structural evidence of post-creation modification was found. Route this document to a human reviewer before any decision — do not use this verdict as the sole basis for an automatic adverse decision against a person."
}
}{
"id": "00000000-0000-4000-8000-000000000011",
"filename": "inconclusive.pdf",
"check_date": null,
"file_size": 204800,
"algorithm_version": "2.2.1",
"current_algorithm_version": "2.2.1",
"status": "inconclusive",
"status_reason": "consumer_software_origin",
"creation_date": 1709283600,
"modification_date": 1709283600,
"creator": "Microsoft Excel 2019",
"producer": "Microsoft: Print To PDF",
"modification_confidence": "none",
"date_sequence_valid": true,
"metadata_completeness_score": 65,
"xref_count": 1,
"has_incremental_updates": false,
"update_chain_length": 1,
"pdf_version": "1.7",
"has_digital_signature": false,
"signature_count": 0,
"signature_removed": false,
"modifications_after_signature": false,
"page_count": 1,
"object_count": 82,
"has_javascript": false,
"has_embedded_files": false,
"modification_markers": [],
"usage_caution": {
"safe_for_automated_adverse_decision": false,
"recommended_action": "request_from_issuer",
"message": "The check could not confirm this document’s integrity, which is not proof of fraud. Confirm the content directly with the issuing organisation or route it to human review — do not treat inconclusive as an automatic rejection."
}
}{
"id": "00000000-0000-4000-8000-000000000014",
"filename": "inconclusive-online-editor.pdf",
"check_date": null,
"file_size": 312000,
"algorithm_version": "2.2.1",
"current_algorithm_version": "2.2.1",
"status": "inconclusive",
"status_reason": "online_editor_origin",
"creation_date": null,
"modification_date": null,
"creator": null,
"producer": "iLovePDF",
"modification_confidence": "none",
"date_sequence_valid": true,
"metadata_completeness_score": 15,
"xref_count": 1,
"has_incremental_updates": false,
"update_chain_length": 1,
"pdf_version": "1.7",
"has_digital_signature": false,
"signature_count": 0,
"signature_removed": false,
"modifications_after_signature": false,
"page_count": 2,
"object_count": 110,
"has_javascript": false,
"has_embedded_files": false,
"modification_markers": [],
"usage_caution": {
"safe_for_automated_adverse_decision": false,
"recommended_action": "request_from_issuer",
"message": "The check could not confirm this document’s integrity, which is not proof of fraud. Confirm the content directly with the issuing organisation or route it to human review — do not treat inconclusive as an automatic rejection."
}
}{
"id": "00000000-0000-4000-8000-000000000015",
"filename": "scanned-document.pdf",
"check_date": null,
"file_size": 890000,
"algorithm_version": "2.2.1",
"current_algorithm_version": "2.2.1",
"status": "inconclusive",
"status_reason": "scanned_document",
"creation_date": null,
"modification_date": null,
"creator": null,
"producer": null,
"modification_confidence": "none",
"date_sequence_valid": true,
"metadata_completeness_score": 0,
"xref_count": 1,
"has_incremental_updates": false,
"update_chain_length": 1,
"pdf_version": "1.4",
"has_digital_signature": false,
"signature_count": 0,
"signature_removed": false,
"modifications_after_signature": false,
"page_count": 3,
"object_count": 45,
"has_javascript": false,
"has_embedded_files": false,
"modification_markers": [],
"usage_caution": {
"safe_for_automated_adverse_decision": false,
"recommended_action": "request_from_issuer",
"message": "The check could not confirm this document’s integrity, which is not proof of fraud. Confirm the content directly with the issuing organisation or route it to human review — do not treat inconclusive as an automatic rejection."
}
}All errors follow this format:
{
"error": "Human-readable error message",
"code": "machine_readable_error_code",
"details": "Optional additional context (present for some errors)"
}Returned when the check ID format is invalid.
{
"error": "Invalid check ID format",
"code": "invalid_request"
}Causes:
idis empty stringidis not a valid UUID v4 (e.g.abc123,12345678-1234-1234-1234-12345678)idcontains invalid characters
Solution: Ensure you're using the full UUID v4 returned by POST /api/v1/analyze or from the id field in GET /api/v1/checks. Format: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx (32 hex digits with 4 hyphens).
Authentication errors (same as analyze endpoint).
See: analyze.md for details.
No active subscription found for this API key.
See: analyze.md for details.
Access forbidden due to account status (deactivated key).
See: analyze.md for details.
Check not found or access denied.
{
"error": "Check not found or access denied",
"code": "not_found"
}Causes:
- Check ID doesn't exist in the database
- Check ID belongs to another API client (data isolation)
- Check ID is malformed but passed basic validation
Security Note: For privacy, we intentionally don't distinguish between "doesn't exist" and "belongs to another client". This prevents enumeration attacks.
Solution:
- Verify the check ID is correct
- Ensure you're using the API key that created the check
- If you need to share results between API clients, contact support for guidance
Server error during retrieval.
{
"error": "Failed to fetch result",
"code": "internal_error"
}Cause: Unexpected database or server error.
Solution:
- Retry the request
- If persists, contact support with the check ID
Store check IDs and retrieve full results later for compliance:
// Store check ID after analysis
await db.documents.create({
id: uploadId,
htpbe_check_id: analysisResponse.id,
verified_at: new Date(),
});
// Later, retrieve full details for audit
const auditData = await fetch(`https://api.htpbe.tech/v1/result/${doc.htpbe_check_id}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});Use the additional fields for comprehensive reports:
const result = await getResult(checkId);
const report = {
summary:
result.status === 'modified'
? 'Modified'
: result.status === 'inconclusive'
? 'Unverifiable'
: 'Original',
// Use fields not available in analyze endpoint
details: {
pages: result.page_count,
objects: result.object_count,
metadataQuality: result.metadata_completeness_score,
analysisDate: new Date(result.check_date * 1000),
},
criticalMarkers: result.modification_markers,
};Related Endpoints:
- POST /api/v1/analyze - Analyze a PDF
- GET /api/v1/checks - List all checks with filtering for custom analytics