Document Management System
Overview
The SynthesQ document management system provides a unified, enterprise-grade solution for storing, organizing, and managing documents across all business modules. Built on a polymorphic architecture, the system enables any entity (customers, leads, products, invoices, employees, etc.) to have associated documents while maintaining consistent behavior and security controls.
Key Capabilities:
- Polymorphic document storage for any entity type
- 16 entity types across 5 modules (CRM, Operations, Sales, Finance, HRM)
- Public and private storage options with secure access control
- Document versioning and archival
- File integrity verification with SHA-256 hashing
- Rich metadata and tagging system
- Document type categorization (23 document types)
- Expiration date tracking
- Download tracking and audit trail
- Soft delete with archive functionality
System Architecture
Polymorphic Document Model
Documents use Laravel's polymorphic relationships to attach to any entity:
Polymorphic Fields:
documentable_type- The fully qualified class name of the parent entitydocumentable_id- The ID of the parent entity
This allows a single shared_documents table to serve all modules while maintaining data isolation and tenant security.
Supported Entities
The document system supports 16 different entity types:
CRM Module (5 entities):
- Customers
- Leads
- Opportunities
- Contacts
- Activities
Operations Module (3 entities):
- Products
- Suppliers
- Purchase Orders
Sales Module (3 entities):
- Orders
- Invoices
- Payments
Finance Module (2 entities):
- Journal Entries
- Chart of Accounts
HRM Module (3 entities):
- Employees
- Leave Requests
- Performance Reviews
Document Types
The system supports 23 predefined document types, each with specific use cases:
| Type | Category | Description | Typical Use |
|---|---|---|---|
contract | Legal & Compliance | Legal contracts and agreements | Customer contracts, supplier agreements |
invoice | Financial | Invoice documents | Sales invoices, purchase invoices |
receipt | Financial | Payment receipts | Payment confirmations, purchase receipts |
quote | Sales | Price quotations | Sales quotes, supplier quotes |
proposal | Sales | Business proposals | Sales proposals, vendor proposals |
presentation | Business | Presentation files | Sales presentations, product demos |
specification | Technical | Technical specifications | Product specs, project requirements |
manual | Technical | User manuals and guides | Product manuals, operation guides |
report | Business | Business reports | Financial reports, performance reports |
certificate | Credentials | Certificates and certifications | Quality certificates, compliance certs |
license | Credentials | License documents | Software licenses, business licenses |
form | Administrative | Forms and templates | Application forms, registration forms |
policy | Legal & Compliance | Policy documents | Company policies, procedures |
procedure | Legal & Compliance | Procedural documents | Operating procedures, workflows |
marketing | Marketing | Marketing materials | Brochures, flyers, marketing content |
legal | Legal & Compliance | Legal documents | Legal notices, compliance documents |
financial | Financial | Financial documents | Financial statements, tax documents |
technical | Technical | Technical documentation | Technical drawings, diagrams |
image | Media | Image files | Photos, screenshots, diagrams |
video | Media | Video files | Product videos, training videos |
audio | Media | Audio files | Voice recordings, podcasts |
archive | General | Archive files | ZIP files, compressed archives |
other | General | Other document types | Miscellaneous documents |
Document Type Properties
Each document type has associated properties:
Sensitivity Flags:
contract,legal,financial,certificate,licenseare marked as sensitive by default- Sensitive documents require additional access controls
Approval Requirements:
contract,policy,procedure,legal,financialrequire approval workflows- These documents typically need management review before publication
Storage Architecture
Storage Disks
Documents can be stored on different storage disks based on visibility requirements:
Public Storage (public disk):
- Files are publicly accessible via URL
- Used for: Product images, marketing materials, public documents
- Path:
storage/app/public/documents/{entity_type}/{entity_id}/ - Accessible via:
https://api.crm.test/storage/documents/...
Private Storage (local disk):
- Files require authentication to access
- Used for: Contracts, financial documents, employee records, sensitive data
- Path:
storage/app/private/documents/{entity_type}/{entity_id}/ - Accessible via: Download endpoint with authentication
Storage Organization
Documents are organized in entity-specific directories:
storage/
└── documents/
├── customers/
│ └── 100001/
│ ├── contract_abc123.pdf
│ ├── invoice_def456.pdf
│ └── profile_ghi789.jpg
├── products/
│ └── 50001/
│ ├── thumbnail_jkl012.jpg
│ ├── manual_mno345.pdf
│ └── spec_pqr678.pdf
└── employees/
└── 30001/
├── contract_stu901.pdf
├── id_document_vwx234.pdf
└── certification_yza567.pdfFile Requirements and Limits
File Size Limits
File size limits vary by entity type based on business requirements:
| Entity Type | Maximum Size | Reasoning |
|---|---|---|
| Customer Documents | 50 MB | Large contracts, KYC documents |
| Customer Profile Images | 5 MB | Image-specific optimization |
| Lead Documents | 20 MB | Proposals, specifications |
| Product Documents | 10 MB | Images and product manuals |
| Supplier Documents | 50 MB | Large contracts, certifications |
| Employee Documents | 50 MB | Personnel files, certifications |
| Invoice Documents | 10 MB | PDF invoices and receipts |
| Order Documents | 20 MB | Shipping documents, customs forms |
Supported File Types
The system supports a wide range of file formats:
Images:
- JPEG (.jpg, .jpeg)
- PNG (.png)
- GIF (.gif)
- WebP (.webp)
Documents:
- PDF (.pdf)
- Microsoft Word (.doc, .docx)
- Microsoft Excel (.xls, .xlsx)
- Microsoft PowerPoint (.ppt, .pptx)
Archives:
- ZIP (.zip)
- RAR (.rar)
- 7-Zip (.7z)
Media:
- Videos (entity-specific)
- Audio files (entity-specific)
Text:
- Plain text (.txt)
- CSV (.csv)
- JSON (.json)
- XML (.xml)
Document Tags
Tags provide a flexible categorization system beyond document types. Tags are entity-specific and reflect business workflows:
Tag Strategy
Purpose:
- Fine-grained categorization within document types
- Workflow-specific organization
- Search and filtering
- Business process alignment
Best Practices:
- Use lowercase tags with underscores (e.g.,
proof_of_payment) - Keep tags consistent within entity type
- Limit tags to 3-5 per document for manageability
- Use tags that reflect business processes
API Operations
Common Endpoints
All entities follow a consistent endpoint pattern:
List Documents:
GET /api/v1/{module}/{entity}/{entityId}/documentsUpload Document:
POST /api/v1/{module}/{entity}/{entityId}/documentsGet Document Details:
GET /api/v1/{module}/{entity}/{entityId}/documents/{documentId}Download Document:
GET /api/v1/{module}/{entity}/{entityId}/documents/{documentId}/downloadDelete Document:
DELETE /api/v1/{module}/{entity}/{entityId}/documents/{documentId}List Documents
Retrieve all documents attached to an entity with optional filtering.
Authentication: Required (Bearer token)
Query Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
type | string | Filter by document type | invoice |
tags | string | Comma-separated list of tags | contract,kyc |
include_archived | boolean | Include archived documents | false |
per_page | integer | Results per page (1-100) | 25 |
page | integer | Page number | 1 |
Example Request:
curl -X GET "https://api.crm.test/api/v1/crm/customers/100001/documents?type=contract&tags=kyc&per_page=10" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"Success Response (200 OK):
{
"data": [
{
"id": 5001,
"type": {
"value": "contract",
"label": "Contract"
},
"status": {
"value": "published",
"label": "Published"
},
"name": "Customer Service Agreement",
"description": "Annual service contract 2025",
"file_size": 524288,
"formatted_file_size": "512.00 KB",
"mime_type": "application/pdf",
"file_extension": "pdf",
"is_public": false,
"is_sensitive": true,
"is_archived": false,
"tags": ["contract", "kyc", "agreement"],
"download_url": "https://api.crm.test/api/v1/crm/customers/100001/documents/5001/download",
"expires_at": "2026-12-31T23:59:59.000000Z",
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
],
"meta": {
"total": 15,
"per_page": 10,
"current_page": 1,
"last_page": 2
}
}Upload Document
Upload a new document and attach it to an entity.
Authentication: Required (Bearer token)
Content-Type: multipart/form-data
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | The document file to upload |
type | string | Yes | Document type (see Document Types) |
tags | array | Optional | Array of tags for categorization |
name | string | Optional | Custom name (max 255 characters) |
description | string | Optional | Document description (max 1000 characters) |
is_public | boolean | Optional | Public visibility (default: false) |
is_sensitive | boolean | Optional | Sensitive flag (default: false) |
expires_at | string | Optional | Expiration date (ISO 8601 format) |
Example Request (cURL):
curl -X POST https://api.crm.test/api/v1/crm/customers/100001/documents \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json" \
-F "file=@/path/to/contract.pdf" \
-F "type=contract" \
-F "tags[]=contract" \
-F "tags[]=kyc" \
-F "tags[]=agreement" \
-F "name=Customer Service Agreement 2025" \
-F "description=Annual service contract for premium support" \
-F "is_public=false" \
-F "is_sensitive=true" \
-F "expires_at=2026-12-31T23:59:59Z"Example Request (JavaScript):
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('type', 'contract');
formData.append('tags[]', 'contract');
formData.append('tags[]', 'kyc');
formData.append('name', 'Customer Service Agreement 2025');
formData.append('description', 'Annual service contract for premium support');
formData.append('is_public', 'false');
formData.append('is_sensitive', 'true');
formData.append('expires_at', '2026-12-31T23:59:59Z');
const response = await fetch('https://api.crm.test/api/v1/crm/customers/100001/documents', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Accept': 'application/json'
},
body: formData
});
const data = await response.json();Example Request (PHP):
$ch = curl_init();
$file = new CURLFile('/path/to/contract.pdf', 'application/pdf', 'contract.pdf');
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.crm.test/api/v1/crm/customers/100001/documents',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_ACCESS_TOKEN',
'Accept: application/json'
],
CURLOPT_POSTFIELDS => [
'file' => $file,
'type' => 'contract',
'tags' => ['contract', 'kyc', 'agreement'],
'name' => 'Customer Service Agreement 2025',
'description' => 'Annual service contract for premium support',
'is_public' => false,
'is_sensitive' => true,
'expires_at' => '2026-12-31T23:59:59Z'
]
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);Success Response (201 Created):
{
"message": "Document uploaded successfully",
"data": {
"id": 5001,
"type": {
"value": "contract",
"label": "Contract"
},
"status": {
"value": "published",
"label": "Published"
},
"name": "Customer Service Agreement 2025",
"description": "Annual service contract for premium support",
"file_size": 524288,
"formatted_file_size": "512.00 KB",
"mime_type": "application/pdf",
"file_extension": "pdf",
"is_public": false,
"is_sensitive": true,
"is_archived": false,
"tags": ["contract", "kyc", "agreement"],
"download_url": "https://api.crm.test/api/v1/crm/customers/100001/documents/5001/download",
"expires_at": "2026-12-31T23:59:59.000000Z",
"created_at": "2025-12-22T14:30:00.000000Z",
"updated_at": "2025-12-22T14:30:00.000000Z"
}
}Download Document
Download the actual file content of a document.
Authentication: Required (Bearer token)
Example Request:
curl -X GET https://api.crm.test/api/v1/crm/customers/100001/documents/5001/download \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json" \
--output contract.pdfSuccess Response (200 OK):
- Returns the binary file content
- Content-Disposition header includes original filename
- Content-Type matches the document's MIME type
- Download count is automatically incremented
Delete Document
Delete a document. By default, documents are soft-deleted (archived). Use hard delete to permanently remove the file.
Authentication: Required (Bearer token)
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
hard_delete | boolean | Permanently delete the document and file | false |
Example Request (Soft Delete):
curl -X DELETE https://api.crm.test/api/v1/crm/customers/100001/documents/5001 \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"Example Request (Hard Delete):
curl -X DELETE "https://api.crm.test/api/v1/crm/customers/100001/documents/5001?hard_delete=true" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Accept: application/json"Success Response (200 OK):
{
"message": "Document deleted successfully"
}File Integrity and Security
SHA-256 File Hashing
Every uploaded document has a SHA-256 hash calculated for integrity verification:
Benefits:
- Detects file corruption during transfer or storage
- Enables duplicate detection across the system
- Supports compliance and audit requirements
- Verifies file authenticity
Hash Storage:
- Calculated during upload
- Stored in
file_hashfield - Available via API (with appropriate permissions)
Access Control
Authentication:
- All document operations require authentication (Bearer token)
- Laravel Sanctum manages token-based authentication
Authorization:
- Document access follows entity-level permissions
- Users must have permission to view/manage the parent entity
- Sensitive documents require additional permissions
Tenant Isolation:
- Multi-tenant architecture ensures complete data isolation
- Documents are scoped to tenant database
- Cross-tenant access is impossible by design
Data Privacy
Public vs Private Documents:
- Public documents are accessible via direct URL (no authentication required)
- Private documents require authenticated download endpoint
- Default is private for security
Sensitive Documents:
- Marked with
is_sensitiveflag - Require elevated permissions for access
- File hash only visible to authorized users
- Additional audit logging for access
Document Versioning
Version History
The system maintains complete document history through archival:
How Versioning Works:
- When a new document replaces an existing one (same tags/purpose), the old document is archived
- Archived documents remain in the database with full metadata
- Files are retained in storage for audit purposes
- Version history is accessible via
include_archived=trueparameter
Example: Customer Profile Image Versioning
# Upload new profile image - old one automatically archived
POST /api/v1/crm/customers/100001/documents
{
"file": <new_image>,
"type": "image",
"tags": ["profile", "avatar"]
}
# View all versions (including archived)
GET /api/v1/crm/customers/100001/documents?tags=profile&include_archived=trueArchival vs Deletion
Soft Delete (Archive):
- Document marked as
is_archived: true - Metadata retained in database
- File may be retained in storage
- Reversible operation
- Default behavior for
DELETEendpoint
Hard Delete:
- Document permanently removed from database
- File deleted from storage
- Irreversible operation
- Requires
hard_delete=trueparameter
Metadata and Custom Fields
Standard Metadata
All documents include standard metadata fields:
| Field | Type | Description |
|---|---|---|
uploaded_by | integer | User ID who uploaded the document |
download_count | integer | Number of times document was downloaded |
last_downloaded_at | timestamp | Last download timestamp |
created_at | timestamp | Upload timestamp |
updated_at | timestamp | Last modification timestamp |
expires_at | timestamp | Optional expiration date |
Custom Metadata
The metadata JSON field allows entity-specific custom data:
Example Use Cases:
- Image dimensions (width, height)
- Display order for gallery images
- Source system for imported documents
- Processing status for uploaded forms
- User agent and IP address tracking
Example Metadata:
{
"metadata": {
"width": 1920,
"height": 1080,
"display_order": 1,
"source": "import_legacy_system",
"uploaded_from_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0..."
}
}Error Handling
Validation Errors
File Size Exceeded (422 Unprocessable Entity):
{
"message": "Document size must not exceed 50MB",
"errors": {
"file": ["Document size must not exceed 50MB"]
}
}Invalid Document Type (422 Unprocessable Entity):
{
"message": "The selected type is invalid.",
"errors": {
"type": ["The selected type is invalid."]
}
}Invalid Tags (422 Unprocessable Entity):
{
"message": "Invalid tag for customer documents.",
"errors": {
"tags.0": ["Invalid tag for customer documents. Allowed: profile, avatar, contract, identity, document, kyc, agreement, invoice, receipt"]
}
}Missing Required Field (422 Unprocessable Entity):
{
"message": "The file field is required.",
"errors": {
"file": ["The file field is required."]
}
}Resource Errors
Entity Not Found (404 Not Found):
{
"message": "Customer not found"
}Document Not Found (404 Not Found):
{
"message": "Document not found"
}Unauthorized Access (401 Unauthorized):
{
"message": "Unauthenticated"
}Forbidden Access (403 Forbidden):
{
"message": "This action is unauthorized"
}Best Practices
1. Document Organization
Use Appropriate Document Types:
- Select the most specific document type available
- Avoid using
otherunless truly miscellaneous - Document type affects default permissions and workflows
Tag Strategically:
- Use 1-3 tags per document
- Keep tags consistent within entity type
- Use tags that reflect your business processes
- Combine generic and specific tags (e.g.,
contract+service_agreement)
Name Documents Clearly:
- Use descriptive, human-readable names
- Include dates or versions in names when appropriate
- Example: "Service Agreement 2025", "Q4 2024 Financial Report"
2. Storage and Performance
Optimize File Sizes:
- Compress large files before upload
- Use appropriate image formats (WebP for web, JPEG for photos)
- Target reasonable file sizes for document types
Use Public Storage When Appropriate:
- Product images, marketing materials
- Public documentation, brochures
- Non-sensitive content
- Improves performance by serving from CDN
Private Storage for Sensitive Data:
- Contracts, financial documents
- Employee records, HR documents
- Customer KYC documents
- Anything containing PII or confidential data
3. Security and Compliance
Mark Sensitive Documents:
- Always set
is_sensitive: truefor confidential data - Enables additional audit logging
- Restricts access to authorized users
- Required for compliance (GDPR, HIPAA, etc.)
Use Expiration Dates:
- Set expiration for time-limited documents
- Examples: Temporary permits, trial agreements, promotional materials
- System can automatically flag expired documents
Leverage Access Controls:
- Rely on entity-level permissions
- Don't make sensitive documents public
- Regularly audit document access logs
4. Workflow Integration
Upload Documents in Context:
- Upload documents when creating related entities
- Example: Upload contract when closing a deal
- Maintains business context and traceability
Archive Old Versions:
- System handles this automatically for replacements
- Manual archive when document is superseded
- Retain for compliance and audit trail
Clean Up Periodically:
- Review and remove truly obsolete documents
- Follow data retention policies
- Use hard delete for expired, non-compliance documents
5. Error Handling and Validation
Client-Side Validation:
- Check file size before upload
- Validate file type on client
- Provide clear error messages to users
- Implement retry logic for network failures
Handle Upload Failures Gracefully:
- Check response status codes
- Parse validation error messages
- Retry transient failures
- Log errors for debugging
Business Scenarios
Scenario 1: Customer Onboarding with KYC Documents
Context: New customer registration requires identity verification documents
Workflow:
- Customer created in CRM
- Upload KYC documents (ID, proof of address, etc.)
- Mark documents as sensitive
- Set expiration dates for temporary documents
API Calls:
# Step 1: Create customer
POST /api/v1/crm/customers
{
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"type": "individual"
}
# Response: { "data": { "id": 100001 } }
# Step 2: Upload ID document
POST /api/v1/crm/customers/100001/documents
{
"file": <id_scan.pdf>,
"type": "form",
"tags": ["identity", "kyc"],
"name": "Driver's License",
"is_public": false,
"is_sensitive": true,
"expires_at": "2030-05-15T23:59:59Z"
}
# Step 3: Upload proof of address
POST /api/v1/crm/customers/100001/documents
{
"file": <utility_bill.pdf>,
"type": "form",
"tags": ["kyc", "document"],
"name": "Proof of Address - Utility Bill",
"is_public": false,
"is_sensitive": true
}
# Step 4: Verify all KYC documents uploaded
GET /api/v1/crm/customers/100001/documents?tags=kycScenario 2: Product Catalog with Images and Manuals
Context: Adding products with gallery images and technical documentation
Workflow:
- Create product in Operations module
- Upload thumbnail image (public, for catalog display)
- Upload gallery images (public, for product page)
- Upload product manual (public, for customer download)
- Upload technical specifications (private, for internal use)
API Calls:
# Step 1: Create product
POST /api/v1/operations/products
{
"name": "Industrial Widget XL-2000",
"sku": "WIDGET-XL-2000",
"type": "physical"
}
# Response: { "data": { "id": 50001 } }
# Step 2: Upload thumbnail
POST /api/v1/operations/products/50001/documents
{
"file": <thumbnail.jpg>,
"type": "image",
"tags": ["thumbnail", "primary"],
"name": "Product Thumbnail",
"is_public": true,
"metadata": {
"width": 800,
"height": 800,
"display_order": 1
}
}
# Step 3: Upload gallery images
POST /api/v1/operations/products/50001/documents
{
"file": <angle1.jpg>,
"type": "image",
"tags": ["gallery"],
"name": "Product Image - Front View",
"is_public": true,
"metadata": { "display_order": 2 }
}
# Step 4: Upload product manual (public)
POST /api/v1/operations/products/50001/documents
{
"file": <manual.pdf>,
"type": "manual",
"tags": ["manual"],
"name": "User Manual - Widget XL-2000",
"is_public": true
}
# Step 5: Upload internal specs (private)
POST /api/v1/operations/products/50001/documents
{
"file": <specs.pdf>,
"type": "specification",
"tags": ["specification", "datasheet"],
"name": "Technical Specifications (Internal)",
"is_public": false
}Scenario 3: Invoice Document Attachment
Context: Attach PDF invoice and payment receipt to sales invoice
Workflow:
- Create sales invoice
- Generate PDF invoice
- Upload PDF as document
- Customer makes payment
- Upload payment receipt
- Link both documents to invoice
API Calls:
# Step 1: Create invoice (already exists)
# Invoice ID: 80001
# Step 2: Upload generated PDF invoice
POST /api/v1/sales/invoices/80001/documents
{
"file": <invoice_80001.pdf>,
"type": "invoice",
"tags": ["invoice_pdf"],
"name": "Invoice #INV-80001",
"description": "Official invoice document",
"is_public": false
}
# Step 3: Upload payment receipt after payment
POST /api/v1/sales/invoices/80001/documents
{
"file": <receipt.pdf>,
"type": "receipt",
"tags": ["receipt", "proof_of_payment"],
"name": "Payment Receipt",
"description": "Stripe payment confirmation",
"is_public": false
}
# Step 4: Retrieve all invoice documents
GET /api/v1/sales/invoices/80001/documentsScenario 4: Employee Onboarding Documentation
Context: New employee requires contracts, certifications, and ID documents
Workflow:
- Create employee record
- Upload employment contract
- Upload ID documents
- Upload certifications
- Set expiration dates for time-limited documents
API Calls:
# Step 1: Create employee
POST /api/v1/hrm/employees
{
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@company.com",
"employee_number": "EMP-30001"
}
# Response: { "data": { "id": 30001 } }
# Step 2: Upload employment contract
POST /api/v1/hrm/employees/30001/documents
{
"file": <contract.pdf>,
"type": "contract",
"tags": ["contract"],
"name": "Employment Contract 2025",
"description": "Full-time employment agreement",
"is_public": false,
"is_sensitive": true
}
# Step 3: Upload ID documents
POST /api/v1/hrm/employees/30001/documents
{
"file": <passport.pdf>,
"type": "form",
"tags": ["id_document"],
"name": "Passport Copy",
"is_public": false,
"is_sensitive": true,
"expires_at": "2030-08-20T23:59:59Z"
}
# Step 4: Upload certification
POST /api/v1/hrm/employees/30001/documents
{
"file": <certification.pdf>,
"type": "certificate",
"tags": ["certification"],
"name": "Professional Certification - PMP",
"description": "Project Management Professional certification",
"is_public": false,
"expires_at": "2028-06-30T23:59:59Z"
}Troubleshooting
Upload Issues
Problem: File upload fails with 413 Payload Too Large
Solution:
- Check file size against entity-specific limits
- Verify nginx/Apache configuration for upload limits
- Confirm PHP
upload_max_filesizeandpost_max_sizesettings
Problem: Upload succeeds but document not visible in list
Solution:
- Verify document wasn't archived on upload
- Check that filter parameters don't exclude the document
- Confirm user has permissions to view the entity
- Check
include_archived=trueif document might be archived
Download Issues
Problem: Download endpoint returns 404
Solution:
- Confirm document ID is correct
- Verify file exists in storage
- Check storage disk configuration
- Ensure user has permission to access parent entity
Problem: Public document URL not accessible
Solution:
- Verify document is marked as
is_public: true - Confirm storage link is created (
php artisan storage:link) - Check
APP_URLenvironment variable is correct - Verify file exists in public storage directory
Permission Issues
Problem: 403 Forbidden when accessing document
Solution:
- Confirm user has permission on parent entity
- Check role-based access control policies
- Verify sensitive documents require elevated permissions
- Ensure user belongs to correct tenant
Module-Specific Documentation
For detailed information on document management for specific modules and entities, see:
- CRM Module Documents - Customers, Leads, Opportunities, Contacts, Activities
- Operations Module Documents - Products, Suppliers, Purchase Orders
- Sales Module Documents - Orders, Invoices, Payments
- Finance Module Documents - Journal Entries, Chart of Accounts
- HRM Module Documents - Employees, Leave Requests, Performance Reviews
Related Documentation
- Authentication Guide - API authentication and token management
- Error Handling - Complete error response documentation
API Reference
For complete API specifications including all endpoints, request/response schemas, and interactive examples:
- OpenAPI Specification:
/docs/openapi.yaml - Interactive API Documentation: Scribe-generated documentation
- Endpoint Group: Document Management (across all modules)