GetSafeDocs API Documentation

Welcome to the GetSafeDocs API! This documentation covers all available endpoints for secure document sharing, messaging, tracking, document requests, and more.


Authentication

The API uses session-based authentication. After successful login, a session is established and subsequent requests are authenticated automatically.

Register

  • Endpoint: POST /api/register.php
  • Body (JSON): { "email": "user@example.com", "password": "yourpassword" }
  • Response: { "success": true, "account_id": 123 } or { "error": "..." }

Login

  • Endpoint: POST /api/login.php
  • Body (JSON): { "email": "user@example.com", "password": "yourpassword" }
  • Response: { "success": true, "account_id": 123 } or { "error": "..." }
  • Note: Establishes a session for subsequent authenticated requests

Logout

  • Endpoint: POST /api/logout.php
  • Response: { "success": true, "message": "Logged out successfully" }

Refresh Session

  • Endpoint: POST /api/refresh_token.php
  • Response: { "success": true, "account_id": 123 } or { "error": "Not authenticated" }

Messages

Send Message

  • Endpoint: POST /api/send_message.php
  • Content-Type: application/x-www-form-urlencoded
  • Fields:
    • recipient (string, required)
    • subject (string, required)
    • body (string, required)
    • uploaded_file_ids (string, optional) - Comma-separated list of file IDs from previous uploads
  • Response: { "success": true, "message_id": 123 } or { "error": "..." }
  • Note: Files must be uploaded separately using the file upload endpoints before sending the message

List Sent Messages

  • Endpoint: GET /api/list_messages.php?limit=20&offset=0
  • Response:
    {
    "success": true,
    "messages": [
    { "message_id": 123, "subject": "Subject", "created_at": "...", "status": "sent", "recipients": "..." }
    ],
    "total": 42,
    "limit": 20,
    "offset": 0
    }

List Received Messages

  • Endpoint: GET /api/list_received_messages.php?limit=20&offset=0
  • Response:
    {
    "success": true,
    "messages": [
    { "message_id": 456, "subject": "Subject", "created_at": "...", "status": "sent", "sender_email": "..." }
    ],
    "total": 42,
    "limit": 20,
    "offset": 0
    }

View Message Details

  • Endpoint: GET /api/message_details.php?message_id=123
  • Response:
    {
    "success": true,
    "message": {
    "message_id": 123,
    "subject": "...",
    "body": "...",
    "created_at": "...",
    "status": "...",
    "sender_email": "...",
    "recipients": ["..."],
    "attachments": [ { "file_id": 789, "file_name": "..." } ]
    }
    }

Delete Message

  • Endpoint: POST /api/delete_message.php
  • Body (JSON): { "message_id": 123 }
  • Response: { "success": true } or { "error": "..." }

Attachments

Download Attachment

  • Endpoint: GET /api/download_attachment.php?file_id=789
  • Response: File download (if authorized) or JSON error

File Uploads

All file uploads now use a secure multi-step signed URL process for improved security and performance. This applies to both authenticated users and document request uploads.

General File Upload Process

Step 1: Get Signed Upload URL

  • Endpoint: POST /get_signed_url.php
  • Authentication: Required (for authenticated uploads)
  • Content-Type: application/json
  • Body (JSON):
    {
    "filename": "document.pdf",
    "contentType": "application/pdf",
    "fileSize": 1024000
    }
  • Response:
    {
    "success": true,
    "signedUrl": "https://storage.googleapis.com/bucket/temp/path?signature=...",
    "tempBucketPath": "user_uploads/uuid/document.pdf",
    "uuid": "12345678-1234-1234-1234-123456789012",
    "uploadToken": "base64encodedtoken"
    }

Step 2: Upload File to GCP

  • Method: PUT
  • URL: Use the signedUrl from Step 1
  • Content-Type: Use the contentType from Step 1
  • Body: Raw file data
  • Response: HTTP 200 on success

Step 3: Process Upload

  • Endpoint: POST /process_cloud_upload.php
  • Authentication: Required (for authenticated uploads)
  • Content-Type: application/json
  • Body (JSON):
    {
    "tempBucketPath": "user_uploads/uuid/document.pdf",
    "filename": "document.pdf",
    "contentType": "application/pdf",
    "fileSize": 1024000,
    "uuid": "12345678-1234-1234-1234-123456789012",
    "uploadToken": "base64encodedtoken"
    }
  • Response:
    {
    "success": true,
    "file_id": "temp_1234567890",
    "scan_result": {
    "rating": 0,
    "risk": "Clean",
    "access_uuid": "access_1234567890"
    }
    }

Upload File

  • Endpoint: POST /api/upload_file.php
  • Authentication: Required
  • Content-Type: application/json
  • Body (JSON): Same as Step 3 above
  • Response: Same as Step 3 above
  • Note: This endpoint combines all three steps for convenience, but still uses the signed URL process internally

Get Document Request Signed URL

  • Endpoint: POST /api/get_document_request_signed_url.php
  • Authentication: Token-based (via access_token parameter)
  • Purpose: Get a signed URL for uploading files to a document request without requiring user authentication
  • Content-Type: application/json
  • Body (JSON):
    {
    "filename": "document.pdf",
    "contentType": "application/pdf",
    "fileSize": 1024000,
    "access_token": "abc123def456"
    }
  • Response: Same format as general signed URL endpoint
  • Validations:
    • Validates document request token is active and not expired
    • Enforces document request file size limits
    • Validates file types against allowed types (if specified)
    • Checks security restrictions (forbidden file types)
  • Note: This is a specialized version of /get_signed_url.php designed specifically for document request uploads with token-based authentication instead of session-based authentication

Benefits of Signed URL Uploads

  • Security: Upload tokens prevent replay attacks and unauthorized uploads
  • Performance: Direct upload to GCP without going through the web server
  • Scalability: Reduces server load and bandwidth usage
  • Reliability: Better error handling and progress tracking
  • Consistency: All uploads follow the same secure pattern
  • Token-based Access: Document requests can accept uploads without requiring user accounts

File Type Validation

All file uploads are validated using centralized functions in functions.php to ensure consistency across all endpoints.

For current file type support, see: File Types Reference (HTML) | JSON | Markdown

The system supports:

  • Free Tier: 60+ file types including documents, images, archives, and code files
  • Premium/Enterprise: All free tier types plus video, audio, and design files
  • Forbidden: Executable files and scripts blocked for security reasons across all tiers

File type lists are maintained in includes/functions.php via these functions:

  • getAllowedFileExtensions() - Free tier supported types
  • getPremiumFileExtensions() - Premium-only additional types
  • getForbiddenFileExtensions() - Security-blocked types

Validation Process:

  1. Client-side pre-validation - File type checking before upload
  2. Server-side extension validation - Forbidden extension check
  3. Tier-based restrictions - User tier determines allowed types
  4. Content-Type validation - MIME type verification
  5. Upload token validation - Cryptographic token verification
  6. MIME type verification - Post-upload content inspection
  7. Malware scanning - QuickSand static analysis

Error Responses:

  • Forbidden file type: { "success": false, "message": "File type 'exe' is not allowed for security reasons..." }
  • Unsupported for tier: { "success": false, "message": "File type 'mp4' is not supported for free accounts..." }
  • MIME mismatch: { "success": false, "message": "File content does not match the 'pdf' extension..." }

Message Tracking

  • Endpoint: GET /api/message_tracking.php?message_id=123
  • Response:
    {
    "success": true,
    "message_id": 123,
    "subject": "...",
    "created_at": "...",
    "tracking": [
    { "activity_type": "message_sent", "activity_timestamp": "...", "ip_address": "...", "user_agent": "...", "recipient_email": "..." }
    ]
    }

Replies

Add Reply

  • Endpoint: POST /api/add_reply.php
  • Body (JSON): { "message_id": 123, "reply_text": "...", "parent_reply_id": 5 }
  • Response: { "success": true, "reply_id": 42 } or { "error": "..." }

List Replies

  • Endpoint: GET /api/list_replies.php?message_id=123
  • Response:
    {
    "success": true,
    "replies": [
    { "reply_id": 42, "message_id": 123, "recipient_id": 7, "reply_text": "...", "created_at": "...", "is_read": 0, "parent_reply_id": null, "is_sender_reply": 1, "viewed_at": null }
    ]
    }

Mark Reply as Read

  • Endpoint: POST /api/mark_reply_read.php
  • Body (JSON): { "reply_id": 42 }
  • Response: { "success": true } or { "success": true, "already_read": true }

Document Requests

Document requests allow external users to upload files using a secure token without requiring an account.

Note: The API field is called access_token in both the documentation and implementation.

Create Document Request

  • Endpoint: POST /api/create_document_request.php
  • Authentication: Required (premium users only)
  • Body (JSON):
    {
    "request_name": "Contract Documents",
    "description": "Please upload the signed contract and supporting documents",
    "allow_multiple_submissions": true,
    "max_file_size_mb": 50,
    "max_files_per_submission": 10,
    "allowed_file_types": "pdf,doc,docx",
    "require_email": true,
    "require_subject": false,
    "require_message": true,
    "expiry_days": 30
    }
  • Response:
    {
    "success": true,
    "message": "Document request created successfully",
    "request": {
    "request_id": 123,
    "request_name": "Contract Documents",
    "description": "Please upload the signed contract and supporting documents",
    "access_token": "abc123def456",
    "allow_multiple_submissions": true,
    "max_file_size_mb": 50,
    "max_files_per_submission": 10,
    "allowed_file_types": "pdf,doc,docx",
    "require_email": true,
    "require_subject": false,
    "require_message": true,
    "expiry_date": "2024-02-15 10:30:00",
    "expiry_days": 30,
    "upload_url": "../document_request_upload.php?token=abc123def456",
    "created_at": "2024-01-16 10:30:00"
    }
    }
  • Error Responses:
    • { "success": false, "message": "Not authenticated" } (401)
    • { "success": false, "message": "Document request creation is a premium feature..." } (403)
    • { "success": false, "message": "Request name is required" } (400)
    • { "success": false, "message": "Maximum file size must be between 1 and X MB..." } (400)

Upload Document Request File

Note: This endpoint now uses a multi-step signed URL upload process for improved security and performance.

Step 1: Get Signed Upload URL (Document Requests)

  • Endpoint: POST /api/get_document_request_signed_url.php
  • Authentication: Not required (token-based via access_token)
  • Content-Type: application/json
  • Body (JSON):
    {
    "filename": "document.pdf",
    "contentType": "application/pdf",
    "fileSize": 1024000,
    "access_token": "abc123def456"
    }
  • Response:
    {
    "success": true,
    "signedUrl": "https://storage.googleapis.com/bucket/temp/path?signature=...",
    "tempBucketPath": "document_requests/uuid/document.pdf",
    "uuid": "12345678-1234-1234-1234-123456789012",
    "uploadToken": "base64encodedtoken"
    }
  • Error Responses:
    • { "success": false, "message": "Missing required parameters" } (400)
    • { "success": false, "message": "Token is required" } (400)
    • { "success": false, "message": "Invalid or inactive token" } (400)
    • { "success": false, "message": "This document request has expired" } (400)
    • { "success": false, "message": "File exceeds maximum size limit of X MB" } (400)
    • { "success": false, "message": "File type not allowed for security reasons" } (400)
    • { "success": false, "message": "File type 'ext' is not allowed. Allowed types: ..." } (400)
    • { "success": false, "message": "File type does not match content" } (400)

Step 2: Upload File to GCP

  • Method: PUT
  • URL: Use the signedUrl from Step 1
  • Content-Type: Use the contentType from Step 1
  • Body: Raw file data
  • Response: HTTP 200 on success

Step 3: Process Upload

  • Endpoint: POST /api/upload_document_request_file.php
  • Content-Type: application/json
  • Body (JSON):
    {
    "tempBucketPath": "user_uploads/uuid/document.pdf",
    "filename": "document.pdf",
    "contentType": "application/pdf",
    "fileSize": 1024000,
    "uuid": "12345678-1234-1234-1234-123456789012",
    "uploadToken": "base64encodedtoken",
    "access_token": "abc123def456"
    }
  • Response:
    {
    "success": true,
    "file_id": "docreq_temp_1234567890",
    "message": "File uploaded and scanned successfully",
    "scan_result": {
    "rating": 0,
    "risk": "Clean",
    "uuid": "12345678-1234-1234-1234-123456789012",
    "access_uuid": "access_1234567890",
    "scan_id": 12345
    }
    }
  • Error Responses:
    • { "success": false, "message": "Missing required parameters" }
    • { "success": false, "message": "Invalid upload token" }
    • { "success": false, "message": "File not found in temp bucket" }
    • { "success": false, "message": "File content does not match file type" }
    • { "success": false, "message": "Invalid or inactive token" }
    • { "success": false, "message": "This document request has expired" }
    • { "success": false, "message": "File exceeds maximum size limit of X MB" }
    • { "success": false, "message": "File type not allowed for security reasons" }

Get Submission Details

  • Endpoint: GET /api/get_submission_details.php?submission_id=123
  • Authentication: Required (account owner only)
  • Response:
    {
    "success": true,
    "html": "<div class=\"row\">...</div>"
    }
  • Note: Returns HTML content for displaying submission details including files, submitter info, and scan results

User Profile & Account Management

Get User Profile

  • Endpoint: GET /api/get_profile.php
  • Authentication: Required
  • Response:
    {
    "success": true,
    "profile": {
    "account_id": 123,
    "email": "user@example.com",
    "access_level": "premium",
    "mfa_enabled": true,
    "email_verified": true,
    "is_company_admin": false,
    "is_stripe_payer": true,
    "created_at": "2024-01-01 10:00:00",
    "last_login": "2024-01-15 14:30:00",
    "company": { "company_id": 5, "company_name": "Acme Corp" },
    "subscription": { "stripe_subscription_id": "sub_123" },
    "usage": {
      "messages_sent_this_month": 15,
      "messages_remaining": 85,
      "messages_limit": 100,
      "data_sent_mb": 25.5,
      "data_received_mb": 10.2,
      "data_limit_mb": 1000
    },
    "limits": {
      "max_attachment_size_mb": 50,
      "max_attachments": 10,
      "max_recipients": 25
    }
    }
    }

Update User Profile

  • Endpoint: POST /api/update_profile.php
  • Authentication: Required
  • Body (JSON):
    {
    "email": "newemail@example.com",
    "current_password": "oldpassword",
    "new_password": "newpassword",
    "mfa_enabled": true
    }
  • Response: { "success": true, "message": "Profile updated successfully" }

Get Usage Statistics

  • Endpoint: GET /api/get_usage_stats.php
  • Authentication: Required
  • Response:
    {
    "success": true,
    "usage_stats": {
    "current_month": {
      "messages_sent": 15,
      "messages_limit": 100,
      "messages_remaining": 85,
      "data_sent_mb": 25.5,
      "data_received_mb": 10.2,
      "data_limit_mb": 1000,
      "data_remaining_mb": 989.8
    },
    "limits": {
      "max_attachment_size_mb": 50,
      "max_attachments": 10,
      "max_recipients": 25
    },
    "access_level": "premium",
    "historical_data": [
      { "month": "2024-01", "messages_sent": 15, "data_sent_mb": 25.5 }
    ],
    "document_requests": {
      "total_requests": 5,
      "active_requests": 3,
      "expired_requests": 2
    },
    "submissions": {
      "total_submissions": 12,
      "submissions_last_30_days": 8
    }
    }
    }

Document Request Management

List Document Requests

  • Endpoint: GET /api/list_document_requests.php
  • Authentication: Required
  • Query Parameters: limit, offset, status (active/expired/all)
  • Response:
    {
    "success": true,
    "requests": [
    {
      "request_id": 123,
      "request_name": "Contract Documents",
      "description": "Please upload signed contracts",
      "access_token": "abc123def456",
      "is_active": true,
      "allow_multiple_submissions": true,
      "max_file_size_mb": 50,
      "max_files_per_submission": 10,
      "allowed_file_types": "pdf,doc,docx",
      "require_email": true,
      "require_subject": false,
      "require_message": true,
      "expiry_date": "2024-02-15 10:30:00",
      "expiry_status": "active",
      "created_at": "2024-01-16 10:30:00",
      "submission_count": 5,
      "last_submission": "2024-01-20 15:45:00",
      "upload_url": "../document_request_upload.php?token=abc123def456"
    }
    ],
    "pagination": {
    "total": 5,
    "limit": 20,
    "offset": 0,
    "has_more": false
    }
    }

Update Document Request

  • Endpoint: POST /api/update_document_request.php
  • Authentication: Required
  • Body (JSON):
    {
    "request_id": 123,
    "request_name": "Updated Contract Documents",
    "description": "Updated description",
    "is_active": true,
    "max_file_size_mb": 100,
    "expiry_days": 60
    }
  • Response: { "success": true, "message": "Document request updated successfully", "request": {...} }

Delete Document Request

  • Endpoint: POST /api/delete_document_request.php
  • Authentication: Required
  • Body (JSON):
    {
    "request_id": 123,
    "force_delete": false
    }
  • Response: { "success": true, "message": "Document request deleted successfully", "submissions_deleted": 5, "files_deleted": 12 }

Admin & Enterprise Management

Admin List Users

  • Endpoint: GET /api/admin/list_users.php
  • Authentication: Required (Admin only)
  • Query Parameters: limit, offset, access_level, company_id, search
  • Response:
    {
    "success": true,
    "users": [
    {
      "account_id": 123,
      "email": "user@example.com",
      "access_level": "premium",
      "is_company_admin": false,
      "is_stripe_payer": true,
      "email_verified": true,
      "mfa_enabled": true,
      "account_locked": false,
      "last_login": "2024-01-15 14:30:00",
      "failed_login_attempts": 0,
      "created_at": "2024-01-01 10:00:00",
      "company": { "company_id": 5, "company_name": "Acme Corp" }
    }
    ],
    "pagination": { "total": 150, "limit": 20, "offset": 0, "has_more": true }
    }

Admin Update User

  • Endpoint: POST /api/admin/update_user.php
  • Authentication: Required (Admin only)
  • Body (JSON):
    {
    "account_id": 123,
    "access_level": "enterprise",
    "is_company_admin": true,
    "account_locked": false,
    "company_id": 5
    }
  • Response: { "success": true, "message": "User updated successfully", "user": {...} }

Admin Get Security Logs

  • Endpoint: GET /api/admin/get_security_logs.php
  • Authentication: Required (Admin only)
  • Query Parameters: limit, offset, log_type (auth/activity/malware), start_date, end_date, ip_address
  • Response:
    {
    "success": true,
    "logs": [
    {
      "log_type": "authentication",
      "log_id": 123,
      "account_id": 456,
      "email": "user@example.com",
      "access_level": "premium",
      "ip_address": "192.168.1.1",
      "user_agent": "Mozilla/5.0...",
      "login_time": "2024-01-15 14:30:00",
      "status": "success",
      "login_successful": true
    }
    ],
    "pagination": { "total": 1000, "limit": 50, "offset": 0, "has_more": true }
    }

Admin Get Malware Detections

  • Endpoint: GET /api/admin/get_malware_detections.php
  • Authentication: Required (Admin only)
  • Query Parameters: limit, offset, rating (0/1/2), start_date, end_date, sender_id
  • Response:
    {
    "success": true,
    "detections": [
    {
      "detection_id": 123,
      "sender_id": 456,
      "sender_email": "user@example.com",
      "account_email": "user@example.com",
      "access_level": "premium",
      "file_name": "document.pdf",
      "file_path": "/path/to/file",
      "file_size": 1024000,
      "scan_uuid": "scan_123456",
      "scan_rating": 0,
      "scan_risk": "Clean",
      "detection_timestamp": "2024-01-15 14:30:00",
      "risk_level": "clean"
    }
    ],
    "summary": {
    "total_detections": 1000,
    "clean_files": 950,
    "suspicious_files": 40,
    "malicious_files": 10,
    "detections_last_7_days": 25,
    "detections_last_30_days": 100
    },
    "pagination": { "total": 1000, "limit": 50, "offset": 0, "has_more": true }
    }

Advanced Features

Archive Message

  • Endpoint: POST /api/archive_message.php
  • Authentication: Required
  • Body (JSON):
    {
    "message_id": 123,
    "archive": true
    }
  • Response: { "success": true, "message": "Message archived successfully", "message_id": 123, "archived": true }

Get File Metadata

  • Endpoint: GET /api/get_file_metadata.php?file_id=123
  • Authentication: Required
  • Response:
    {
    "success": true,
    "file": {
    "file_id": 123,
    "message_id": 456,
    "file_name": "document.pdf",
    "file_path": "/path/to/file",
    "file_size": 1024000,
    "mime_type": "application/pdf",
    "file_extension": "pdf",
    "file_type": "document",
    "file_icon": "file-pdf",
    "storage_location": "cloud",
    "preview_only": false,
    "scan_rating": 0,
    "scan_risk": "Clean",
    "scan_uuid": "scan_123456",
    "access_uuid": "access_123456",
    "scan_id": 789,
    "scan_timestamp": "2024-01-15 14:30:00",
    "message": {
      "message_id": 456,
      "subject": "Important Document",
      "message_text": "Please review this document",
      "created_at": "2024-01-15 10:00:00",
      "sender_email": "sender@example.com"
    },
    "statistics": {
      "download_count": 5,
      "view_count": 12,
      "total_accesses": 17
    },
    "recent_activity": [...]
    }
    }

Bulk Operations

  • Endpoint: POST /api/bulk_operations.php
  • Authentication: Required
  • Body (JSON):
    {
    "operation": "archive_messages",
    "targets": [123, 456, 789]
    }
  • Valid Operations: archive_messages, unarchive_messages, delete_messages, delete_document_requests
  • Response:
    {
    "success": true,
    "operation": "archive_messages",
    "summary": {
    "total_processed": 3,
    "successful": 3,
    "failed": 0
    },
    "results": [
    { "id": 123, "status": "archived" },
    { "id": 456, "status": "archived" },
    { "id": 789, "status": "archived" }
    ],
    "errors": []
    }

Get System Status

  • Endpoint: GET /api/get_system_status.php
  • Authentication: Required (Admin gets detailed info)
  • Response:
    {
    "success": true,
    "system_status": {
    "timestamp": "2024-01-15 14:30:00",
    "status": "operational",
    "basic": {
      "api_version": "1.0",
      "server_time": "2024-01-15 14:30:00",
      "timezone": "UTC"
    },
    "database": {
      "status": "connected",
      "driver": "mysql"
    },
    "user": {
      "account_id": 123,
      "access_level": "premium",
      "limits": { "max_attachment_size_mb": 50, "max_attachments": 10 }
    },
    "admin": {
      "database_stats": {
        "total_users": 1500,
        "total_messages": 50000,
        "total_files": 25000,
        "total_document_requests": 500,
        "total_storage_bytes": 1073741824,
        "total_storage_mb": 1024
      },
      "recent_activity": {
        "logins_last_24h": 150,
        "messages_last_24h": 500,
        "malware_detections_last_24h": 5
      },
      "health_checks": {
        "disk_space": { "status": "ok", "free_gb": 50.5 },
        "security": { "status": "ok", "failed_logins_last_hour": 2 }
      }
    }
    }
    }

Authentication & Authorization

  • Most endpoints require the user to be authenticated (session-based, via login/register endpoints).
  • Only authorized users (sender or recipient) can access, modify, or delete messages, attachments, and replies.
  • Exception: Document request file uploads (/api/upload_document_request_file.php) use token-based authentication and do not require a user account.
  • Admin Endpoints: Require admin access level for full system management capabilities.

Error Handling

  • All errors are returned as JSON: { "error": "Error message" }
  • HTTP status codes are set appropriately (400, 401, 403, 404, 405, 500)

Example Usage

Basic API Usage

  • Use tools like Postman or curl to interact with the API
  • For JSON requests, set Content-Type: application/json
  • For form data, set Content-Type: application/x-www-form-urlencoded

File Upload Example (JavaScript)

// Step 1: Get signed URL
const response = await fetch('/get_signed_url.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    filename: file.name,
    contentType: file.type,
    fileSize: file.size
  })
});
const { signedUrl, tempBucketPath, uuid, uploadToken } = await response.json();

// Step 2: Upload file directly to GCP
await fetch(signedUrl, {
  method: 'PUT',
  body: file
});

// Step 3: Process upload
const processResponse = await fetch('/process_cloud_upload.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    tempBucketPath,
    filename: file.name,
    contentType: file.type,
    fileSize: file.size,
    uuid,
    uploadToken
  })
});
const { file_id } = await processResponse.json();

// Step 4: Use file_id in message sending
await fetch('/api/send_message.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    recipient: 'user@example.com',
    subject: 'Test Message',
    body: 'Here is the document',
    uploaded_file_ids: file_id
  })
});

Document Request Upload Example (JavaScript)

// Step 1: Get signed URL for document request
const response = await fetch('/api/get_document_request_signed_url.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    filename: file.name,
    contentType: file.type || 'application/octet-stream',
    fileSize: file.size,
    access_token: 'abc123def456' // Document request access token
  })
});
const data = await response.json();
if (!data.success) {
  throw new Error(data.message || 'Failed to get upload URL');
}
const { signedUrl, tempBucketPath, uuid, uploadToken } = data;

// Step 2: Upload file directly to GCP
const uploadResponse = await fetch(signedUrl, {
  method: 'PUT',
  headers: {
    'Content-Type': file.type || 'application/octet-stream'
  },
  body: file
});
if (!uploadResponse.ok) {
  throw new Error(`Upload failed with status: ${uploadResponse.status}`);
}

// Step 3: Process upload and trigger malware scan
const processResponse = await fetch('/api/upload_document_request_file.php', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    tempBucketPath,
    filename: file.name,
    contentType: file.type || 'application/octet-stream',
    fileSize: file.size,
    uuid,
    uploadToken,
    access_token: 'abc123def456' // Document request access token
  })
});
const result = await processResponse.json();
if (!result.success) {
  throw new Error(result.message || 'Upload processing failed');
}
const { file_id, scan_result } = result;
// file_id can be used in form submission
// scan_result contains: { rating, risk, uuid, access_uuid, scan_id }

For more information, contact support at GetSafeDocs.