GetSafeDocs API & MCP Server Documentation

Welcome to the GetSafeDocs REST API and Model Context Protocol (MCP) Server! This documentation covers API key authentication, stateless file uploads, secure document sharing, tracking, document requests, mailing lists, malware scan reports, enterprise management, and connecting AI assistants via /mcp.

Base URL

  • API Base URL: https://getsafedocs.cloud.run
  • MCP Server URL: https://getsafedocs.cloud.run/mcp (alias: https://getsafedocs.cloud.run/api/mcp)

Authentication

You can authenticate any API request using a personal API Key without needing a password, browser cookies, or interactive MFA prompts. Works with all account types (including Google Sign-In, Passkey, and MFA-protected accounts).

How to Get Your API Key

  1. Sign in to GetSafeDocs and go to your Profile.
  2. Under Security Settings → Developer API Keys, enter a key name (e.g., CLI Script or CI/CD Pipeline), choose an optional expiration (Never expires, 30 days, 90 days, 1 year), and click Generate API Key.
  3. Copy your gsd_... key immediately (for security, only the SHA-256 hash is stored and the full key is shown only once).

Passing Your API Key in Requests

Include your API key in the X-API-Key header or the Authorization: Bearer header:

# Option A: X-API-Key header
curl -H "X-API-Key: gsd_your_api_key_here" \
  https://getsafedocs.cloud.run/api/whoami

# Option B: Authorization Bearer header
curl -H "Authorization: Bearer gsd_your_api_key_here" \
  https://getsafedocs.cloud.run/api/whoami

2. Verify Authentication (/api/whoami)

  • Endpoint: GET https://getsafedocs.cloud.run/api/whoami (alias: GET /api/me)
  • Authentication: Required (API Key or Session)
  • Response:
{
  "success": true,
  "auth_method": "api_key",
  "api_key_id": 4,
  "account": {
    "id": 123,
    "email": "user@example.com",
    "access_level": "premium",
    "is_company_admin": false,
    "company_id": null,
    "mfa_enabled": true
  },
  "limits": {
    "messages_per_month": 300,
    "max_attachment_size_mb": 128,
    "max_attachments": 20,
    "max_recipients": 30,
    "max_received_size_mb": 3000
  },
  "usage": {
    "message_count": 12,
    "sent_kb": 15420,
    "received_kb": 4100
  }
}

3. Managing API Keys via API

List Active API Keys

  • Endpoint: GET https://getsafedocs.cloud.run/api/api_keys
  • Authentication: Required
  • Response:
{
  "success": true,
  "count": 1,
  "api_keys": [
    {
      "id": 4,
      "name": "CI/CD Pipeline",
      "key_prefix": "gsd_8f9a1b2c...4e5f",
      "scopes": "full",
      "last_used_at": "2026-11-09 17:15:00",
      "last_used_ip": "203.0.113.10",
      "expires_at": null,
      "is_active": 1,
      "is_expired": 0,
      "created_at": "2026-11-09 16:00:00"
    }
  ]
}

Create a New API Key

  • Endpoint: POST https://getsafedocs.cloud.run/api/api_keys (alias: POST /api/create_api_key)
  • Authentication: Required
  • Body (JSON):
{
  "name": "Production Server",
  "expires_days": 90
}
  • Response:
{
  "success": true,
  "api_key": "gsd_8f9a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6",
  "key": {
    "id": 5,
    "name": "Production Server",
    "key_prefix": "gsd_8f9a1b2c...f5a6",
    "scopes": "full",
    "expires_at": "2027-02-07 17:20:00",
    "created_at": "2026-11-09 17:20:00"
  },
  "message": "API key generated. Copy this key now — for security, the full key will not be shown again."
}

Revoke an API Key

  • Endpoint: DELETE https://getsafedocs.cloud.run/api/api_keys or POST https://getsafedocs.cloud.run/api/revoke_api_key
  • Authentication: Required
  • Body (JSON): { "key_id": 5 }
  • Response: { "success": true, "message": "API key revoked", "key_id": 5 }

4. Legacy Session Authentication (Optional)

If you are building a session-based client instead of using API keys, session endpoints remain supported:

  • Register: POST https://getsafedocs.cloud.run/api/register ({ "email": "...", "password": "..." })
  • Login: POST https://getsafedocs.cloud.run/api/login ({ "email": "...", "password": "..." })
  • Logout: POST https://getsafedocs.cloud.run/api/logout
  • Refresh Session: POST https://getsafedocs.cloud.run/api/refresh_token

File Uploads & Stateless Message Sending

All file uploads use a 3-step direct-to-GCS signed URL workflow with automatic MIME inspection and QuickSand malware analysis. When using an API key, uploaded files are tracked statelessly by their uuid so no cookies or sessions are needed.

Step 1: Request a Signed Upload URL

  • Endpoint: POST https://getsafedocs.cloud.run/api/get_signed_url (also available at /get_signed_url)
  • Authentication: Required (X-API-Key or Authorization: Bearer)
  • Body (JSON):
{
  "filename": "contract.pdf",
  "contentType": "application/pdf",
  "fileSize": 1024000
}
  • Response:
{
  "success": true,
  "signedUrl": "https://storage.googleapis.com/bucket/uploads/...",
  "tempObject": "uploads/12345678-1234-1234-1234-123456789012_contract.pdf",
  "tempBucketPath": "uploads/12345678-1234-1234-1234-123456789012_contract.pdf",
  "uuid": "12345678-1234-1234-1234-123456789012",
  "kmsKeyName": "projects/.../cryptoKeys/..."
}

Step 2: Upload Raw File Bytes to GCS

  • Method: PUT to the signedUrl returned in Step 1
  • Headers:
  • Content-Type: Match the contentType from Step 1 (Note: CMEK encryption key is already embedded as a signed query parameter on signedUrl; do not pass an extra x-goog-encryption-kms-key-name header)
  • Body: Raw binary file content

Step 3: Process & Scan the Uploaded File

  • Endpoint: POST https://getsafedocs.cloud.run/api/upload_file (alias: POST /api/process_cloud_upload)
  • Authentication: Required (X-API-Key or Authorization: Bearer)
  • Body (JSON):
{
  "tempObject": "uploads/12345678-1234-1234-1234-123456789012_contract.pdf",
  "filename": "contract.pdf",
  "contentType": "application/pdf",
  "uuid": "12345678-1234-1234-1234-123456789012"
}
  • Response:
{
  "success": true,
  "file_id": "12345678-1234-1234-1234-123456789012",
  "uuid": "12345678-1234-1234-1234-123456789012",
  "file": {
    "uuid": "12345678-1234-1234-1234-123456789012",
    "access_uuid": "9f8e7d6c5b4a...",
    "scan_id": 42,
    "name": "contract.pdf",
    "size": 1024000,
    "type": "application/pdf",
    "scan_rating": 0,
    "scan_risk": "Clean"
  },
  "scan_result": {
    "rating": 0,
    "risk": "Clean",
    "uuid": "12345678-1234-1234-1234-123456789012",
    "access_uuid": "9f8e7d6c5b4a...",
    "scan_id": 42
  }
}

Delete a Temporary Uploaded File (Before Sending)

  • Endpoint: POST https://getsafedocs.cloud.run/api/delete_file
  • Authentication: Required
  • Body (JSON): { "uuid": "12345678-1234-1234-1234-123456789012" }

Messages & Document Sharing

Send a Secure Message

  • Endpoint: POST https://getsafedocs.cloud.run/api/send_message
  • Authentication: Required
  • Content-Type: application/json or application/x-www-form-urlencoded
  • Fields:
  • recipients (array of strings or comma-separated string) — Recipient email addresses. Omit and pass "generate_token_only": true to generate a manual share token without emailing.
  • mailing_list_id (integer, optional) — Send to all recipients in a saved external mailing list.
  • team_ids (array of integers, optional) — Expand internal Enterprise Teams into recipients (Enterprise tier).
  • subject (string, optional, default "Document Delivery") — Message subject.
  • body or message (string, optional if files are attached) — Message text.
  • file_uuids or uploaded_file_ids (array of UUID strings or comma-separated string, optional) — File UUIDs from /api/upload_file.
  • repo_file_ids (array of integers, optional) — Attach existing Enterprise Document Repository files (repo_file_id) directly without re-uploading (one-click resend).
  • save_to_repository (boolean, optional, default false) — Archive newly uploaded attachments into the Enterprise Document Repository upon sending.
  • classification (string, optional, default "None") — Enterprise classification marking (None, Confidential, NTK, Restricted, or custom company markings).
  • expiry_days (integer, optional, default 30, max 365) — Days until the message expires.
  • notify_on_activity (boolean, optional, default true) — Email sender when recipients view/download files.
  • preview_only (boolean, optional, default false) — Restrict recipients to safe sandbox viewing only (disable raw downloads).
  • send_email (boolean, optional, default true) — Automatically email share links to recipients.
  • generate_token_only (boolean, optional, default false) — Generate a shareable access_token and access_url without specifying recipient emails.
  • Example Request (JSON):
{
  "recipients": ["client@example.com", "legal@example.com"],
  "subject": "Signed Q4 Agreement",
  "body": "Please find the signed agreement attached.",
  "file_uuids": ["12345678-1234-1234-1234-123456789012"],
  "expiry_days": 30,
  "notify_on_activity": true,
  "preview_only": false
}
  • Response:
{
  "success": true,
  "message_id": 123,
  "subject": "Signed Q4 Agreement",
  "created_at": "2026-11-09 17:30:00",
  "expiry_date": "2026-12-09 17:30:00",
  "preview_only": false,
  "recipients": [
    {
      "recipient_id": 456,
      "email": "client@example.com",
      "access_token": "k9m2p4x7",
      "access_url": "https://getsafedocs.cloud.run/access_document?token=k9m2p4x7",
      "email_sent": true
    }
  ],
  "files": [
    {
      "file_id": 789,
      "file_name": "contract.pdf",
      "mime_type": "application/pdf",
      "uuid": "12345678-1234-1234-1234-123456789012",
      "access_uuid": "9f8e7d6c5b4a...",
      "scan_rating": 0,
      "scan_risk": "Clean",
      "preview_only": false
    }
  ]
}

List Sent Messages (Outbox)

  • Endpoint: GET https://getsafedocs.cloud.run/api/list_messages?limit=20&offset=0&search=
  • Authentication: Required
  • Response: Returns messages (each including recipients, files, file_count, unread_replies_count) and pagination.

List Received Messages (Inbox)

  • Endpoint: GET https://getsafedocs.cloud.run/api/list_received_messages?limit=20&offset=0&archived=0&unread_only=0&search=
  • Authentication: Required
  • Query Parameters:
  • archived: 0 (active inbox, default), 1 (archived), or all
  • unread_only: 1 or true to filter unread messages
  • search: Filter by subject, body, or sender email

View Message Details

  • Endpoint: GET https://getsafedocs.cloud.run/api/message_details?message_id=123
  • Authentication: Required (sender or recipient)
  • Response: Returns message, files, recipients (with access_token and access_url when requested by sender), and replies.

Message Activity & Tracking

  • Endpoint: GET https://getsafedocs.cloud.run/api/message_tracking?message_id=123
  • Authentication: Required (sender only)
  • Response: Returns activities / tracking (views, downloads, timestamps, IPs, user agents) and notifications.

Resend Recipient Notification Emails

  • Endpoint: POST https://getsafedocs.cloud.run/api/resend_notification
  • Authentication: Required (sender only)
  • Body (JSON):
{
  "message_id": 123,
  "emails": ["client@example.com"]
}

Archive / Unarchive Message

  • Endpoint: POST https://getsafedocs.cloud.run/api/archive_message (or POST /api/unarchive_message)
  • Authentication: Required
  • Body (JSON): { "message_id": 123, "archive": true } (set "archive": false to unarchive)

Delete Sent Message

  • Endpoint: POST https://getsafedocs.cloud.run/api/delete_message
  • Authentication: Required (sender only)
  • Body (JSON): { "message_id": 123 }
  • Note: If the sender is under a Visible Legal Hold, deletion returns HTTP 403. If under a Silent (Stealth) Legal Hold, the message is hidden from the sender's Outbox (sender_deleted = 1) while preserved in the Enterprise eDiscovery Vault.

Promote Attachment to Enterprise Repository

  • Endpoint: POST https://getsafedocs.cloud.run/api/save_file_to_repo
  • Authentication: Required (Enterprise sender or Company Admin)
  • Body (JSON): { "file_id": 789, "message_id": 123, "folder_name": "Contracts", "visibility": "private" }
  • Endpoint: POST https://getsafedocs.cloud.run/api/toggle_message_legal_hold
  • Authentication: Required (Enterprise Company Admin or System Admin)
  • Body (JSON): { "message_id": 123, "legal_hold": true }

Access Shared Message via Recipient Token (No Account Required)

  • Endpoint: GET https://getsafedocs.cloud.run/api/access_document?token=k9m2p4x7
  • Authentication: Token-based (token query parameter)
  • Response: Returns message, files, and replies.

Files, Downloads, ZIP Archives & Scan Reports

Get File Metadata & Access Statistics

  • Endpoint: GET https://getsafedocs.cloud.run/api/get_file_metadata?file_id=789 (or ?uuid=...)
  • Authentication: Required

Download Single Attachment (Signed URL)

  • Endpoint: GET https://getsafedocs.cloud.run/api/download_attachment?file_id=789 (or ?uuid=...&token=...)
  • Authentication: API Key, Session, or Recipient token
  • Response:
{
  "success": true,
  "signed_url": "https://storage.googleapis.com/...",
  "signedUrl": "https://storage.googleapis.com/...",
  "filename": "contract.pdf",
  "expires_in": 900
}

Download All Message Files as ZIP (Signed URL)

  • Endpoint: GET https://getsafedocs.cloud.run/api/download_zip?message_id=123 (or ?token=k9m2p4x7)
  • Authentication: API Key, Session, or Recipient token
  • Response:
{
  "success": true,
  "signed_url": "https://storage.googleapis.com/...",
  "signedUrl": "https://storage.googleapis.com/...",
  "file_count": 3
}

Get Malware Scan Report

  • Endpoint: GET https://getsafedocs.cloud.run/api/scan_report?uuid=12345678-... (or ?file_id=789 or ?scan_id=42)
  • Response: Returns cryptographic hashes (md5, sha1, sha256), risk_score, risk_rating, and detailed QuickSand static analysis results.

Replies

Add Reply

  • Endpoint: POST https://getsafedocs.cloud.run/api/add_reply
  • Authentication: API Key, Session, or Recipient token
  • Body (JSON): { "message_id": 123, "reply_text": "Thank you, received!", "token": "optional_recipient_token" }

List Replies

  • Endpoint: GET https://getsafedocs.cloud.run/api/list_replies?message_id=123
  • Authentication: API Key, Session, or ?token=recipient_token

Mark Reply as Read

  • Endpoint: POST https://getsafedocs.cloud.run/api/mark_reply_read
  • Authentication: Required
  • Body (JSON): { "reply_id": 42 }

Document Requests

Document requests allow external users to upload files to you using a secure access_token without needing a GetSafeDocs account.

Create Document Request

  • Endpoint: POST https://getsafedocs.cloud.run/api/create_document_request
  • Authentication: Required
  • Body (JSON):
{
  "request_name": "Tax Documents 2026",
  "description": "Please upload your signed tax forms and receipts",
  "allow_multiple_submissions": true,
  "max_file_size_mb": 50,
  "max_files_per_submission": 10,
  "allowed_file_types": "pdf,doc,docx,xlsx",
  "require_email": true,
  "require_subject": false,
  "require_message": true,
  "expiry_days": 30,
  "notify_emails": ["client@example.com"]
}

List Document Requests

  • Endpoint: GET https://getsafedocs.cloud.run/api/list_document_requests?status=all&limit=50&offset=0
  • Authentication: Required
  • Query Parameters: status (active, closed, expired, all), limit, offset

Get Document Request & Submissions

  • Endpoint: GET https://getsafedocs.cloud.run/api/get_document_request?request_id=123 (or ?request_token=abc123def456)
  • Authentication: Required
  • Response: Returns the request object and all submissions with their attached files.

Update Document Request

  • Endpoint: POST https://getsafedocs.cloud.run/api/update_document_request
  • Authentication: Required
  • Body (JSON):
{
  "request_id": 123,
  "request_name": "Updated Tax Documents",
  "description": "Updated instructions",
  "is_active": true,
  "max_file_size_mb": 100,
  "expiry_days": 60
}

Delete Document Request

  • Endpoint: POST https://getsafedocs.cloud.run/api/delete_document_request
  • Authentication: Required
  • Body (JSON): { "request_id": 123 }

Get Single Submission Details

  • Endpoint: GET https://getsafedocs.cloud.run/api/get_submission_details?submission_id=45
  • Authentication: Required

Public Upload to a Document Request (Token-Based)

  1. Get Signed Upload URL: POST https://getsafedocs.cloud.run/api/get_document_request_signed_url
  2. Body: { "filename": "form.pdf", "contentType": "application/pdf", "fileSize": 512000, "access_token": "abc123def456" }
  3. PUT File to GCS: PUT raw bytes to signedUrl
  4. Complete Submission: POST https://getsafedocs.cloud.run/api/upload_document_request_file
  5. Body: { "tempObject": "...", "uuid": "...", "filename": "form.pdf", "contentType": "application/pdf", "access_token": "abc123def456", "submitter_email": "client@example.com", "submitter_name": "Jane Doe", "notes": "Attached!" }

Mailing Lists

List Mailing Lists

  • Endpoint: GET https://getsafedocs.cloud.run/api/mailing_lists
  • Authentication: Required
  • Response: Returns all mailing lists owned by the account, including recipients and recipient_count.

Create Mailing List

  • Endpoint: POST https://getsafedocs.cloud.run/api/mailing_lists
  • Authentication: Required
  • Body (JSON):
{
  "name": "Board of Directors",
  "description": "Monthly board packet distribution list",
  "emails": ["director1@example.com", "director2@example.com"]
}

Update Mailing List

  • Endpoint: POST https://getsafedocs.cloud.run/api/mailing_lists/update
  • Authentication: Required
  • Body (JSON):
{
  "list_id": 10,
  "name": "Board of Directors",
  "add_emails": ["newdirector@example.com"],
  "remove_emails": ["olddirector@example.com"]
}

(You can also pass "emails": [...] to replace the entire recipient list.)

Delete Mailing List

  • Endpoint: POST https://getsafedocs.cloud.run/api/mailing_lists/delete (or DELETE /api/mailing_lists)
  • Authentication: Required
  • Body (JSON): { "list_id": 10 }

Get Mailing List Recipients

  • Endpoint: GET https://getsafedocs.cloud.run/api/mailing_lists/recipients?list_id=10
  • Authentication: Required

User Profile, Usage & File Types

  • Get Profile: GET https://getsafedocs.cloud.run/api/get_profile
  • Update Profile: POST https://getsafedocs.cloud.run/api/update_profile ({ "email_marketing_opt_in": false })
  • Get Usage Statistics: GET https://getsafedocs.cloud.run/api/get_usage_stats
  • Get Allowed File Types & Tier Limits: GET https://getsafedocs.cloud.run/api/file_types
  • System Status: GET https://getsafedocs.cloud.run/api/get_system_status

Bulk Operations

  • Endpoint: POST https://getsafedocs.cloud.run/api/bulk_operations
  • Authentication: Required
  • Body (JSON):
{
  "operation": "archive_messages",
  "targets": [123, 456, 789]
}
  • Supported Operations: archive_messages, unarchive_messages, mark_messages_read, delete_messages, delete_document_requests

Enterprise Document Repository (/api/repository/*)

  • List & Search Repository Files: GET https://getsafedocs.cloud.run/api/repository/files?folder=&classification=&scope=all&q=
  • Upload or Promote Files to Repository: POST https://getsafedocs.cloud.run/api/repository/upload
  • Body: { "file_uuids": ["..."], "folder_name": "Contracts", "classification": "Confidential", "visibility": "shared", "share_team_ids": [1], "can_view": true, "can_download": true, "can_resend": true, "can_delete": false } (or pass "file_id": 789 to promote an existing message attachment)
  • Update Repository File Metadata: POST https://getsafedocs.cloud.run/api/repository/update
  • Body: { "repo_file_id": 12, "folder_name": "Legal", "description": "Master MSA", "visibility": "company", "classification": "Confidential" }
  • Grant Granular Share (Team or User): POST https://getsafedocs.cloud.run/api/repository/share
  • Body: { "repo_file_id": 12, "target_type": "team", "target_team_id": 1, "can_view": true, "can_download": true, "can_resend": true, "can_delete": false }
  • Revoke Share: POST https://getsafedocs.cloud.run/api/repository/unshare ({ "share_id": 5 })
  • Toggle Repository File Legal Hold: POST https://getsafedocs.cloud.run/api/repository/legal_hold ({ "repo_file_id": 12, "legal_hold": true })
  • Download Repository File (Signed URL): GET https://getsafedocs.cloud.run/api/repository/download?repo_file_id=12
  • Delete Repository File: POST https://getsafedocs.cloud.run/api/repository/delete ({ "repo_file_id": 12, "purge_reason": "Superseded" })

Enterprise Company Admin (/api/enterprise/*)

  • Overview (Members, Seats, Teams, Held Messages / eDiscovery Vault, Invites, Settings): GET https://getsafedocs.cloud.run/api/enterprise/overview
  • Create / Rename Company: POST /api/enterprise/create_company / POST /api/enterprise/rename_company ({ "company_name": "Acme Corp" })
  • Update Security & Repository Governance Settings: POST https://getsafedocs.cloud.run/api/enterprise/update_settings
  • Body: { "classification_options": ["None", "Confidential", "NTK", "Restricted"], "disable_remote_preview": true, "auto_archive_to_repo": true, "repo_retention_days": 365 }
  • Invite Member: POST https://getsafedocs.cloud.run/api/enterprise/invite ({ "email": "teammate@company.com" })
  • Resend / Cancel Invite: POST /api/enterprise/resend_invite / POST /api/enterprise/cancel_invite ({ "invite_id": 10 })
  • Accept / Decline Invite (Invited User): POST https://getsafedocs.cloud.run/api/enterprise/accept_invite ({ "invite_token": "...", "decision": "accept" })
  • Set Member Role / Tier: POST https://getsafedocs.cloud.run/api/enterprise/set_member_role ({ "account_id": 456, "is_company_admin": true })
  • Remove Member: POST https://getsafedocs.cloud.run/api/enterprise/remove_member ({ "account_id": 456 })
  • Set User Legal Hold (Visible, Silent/Stealth, or Off): POST https://getsafedocs.cloud.run/api/enterprise/set_legal_hold
  • Body: { "account_id": 456, "legal_hold_mode": "silent", "legal_hold_reason": "Case #2026-09" }
  • Manage Internal Enterprise Teams: GET / POST https://getsafedocs.cloud.run/api/enterprise/teams
  • Actions (action): create_team, delete_team, add_team_member, remove_team_member

System Admin (/api/admin/*)

  • List Users: GET https://getsafedocs.cloud.run/api/admin/list_users?limit=50&offset=0
  • Update User: POST https://getsafedocs.cloud.run/api/admin/update_user
  • Security Logs: GET https://getsafedocs.cloud.run/api/admin/get_security_logs
  • Malware Detections: GET https://getsafedocs.cloud.run/api/admin/get_malware_detections
  • Rescan File: POST https://getsafedocs.cloud.run/api/rescan_file ({ "uuid": "..." })

Code Examples

Complete Python Example (Upload & Send with API Key)

import os
import requests

API_BASE = "https://getsafedocs.cloud.run"
API_KEY = os.environ["GETSAFEDOCS_API_KEY"]  # e.g. "gsd_..."
HEADERS = {"X-API-Key": API_KEY}

file_path = "contract.pdf"
file_size = os.path.getsize(file_path)

# 1. Get signed upload URL
sign_resp = requests.post(
    f"{API_BASE}/api/get_signed_url",
    headers=HEADERS,
    json={
        "filename": "contract.pdf",
        "contentType": "application/pdf",
        "fileSize": file_size,
    },
).json()

# 2. Upload file bytes to GCS (KMS key is pre-signed in the URL query string)
put_headers = {"Content-Type": "application/pdf"}

with open(file_path, "rb") as f:
    requests.put(sign_resp["signedUrl"], data=f, headers=put_headers).raise_for_status()

# 3. Process & malware-scan the uploaded file
upload_resp = requests.post(
    f"{API_BASE}/api/upload_file",
    headers=HEADERS,
    json={
        "tempObject": sign_resp["tempObject"],
        "uuid": sign_resp["uuid"],
        "filename": "contract.pdf",
        "contentType": "application/pdf",
    },
).json()

# 4. Send the secure message
send_resp = requests.post(
    f"{API_BASE}/api/send_message",
    headers=HEADERS,
    json={
        "recipients": ["recipient@example.com"],
        "subject": "Quarterly Contract",
        "body": "Please review the attached contract.",
        "file_uuids": [upload_resp["uuid"]],
        "expiry_days": 30,
    },
).json()

print("Sent message ID:", send_resp["message_id"])
print("Recipient access link:", send_resp["recipients"][0]["access_url"])

Complete JavaScript / Node.js Example (with API Key)

const API_BASE = 'https://getsafedocs.cloud.run';
const API_KEY = process.env.GETSAFEDOCS_API_KEY; // "gsd_..."
const authHeaders = {
  'Content-Type': 'application/json',
  'X-API-Key': API_KEY
};

// Step 1: Get signed URL
const signRes = await fetch(`${API_BASE}/api/get_signed_url`, {
  method: 'POST',
  headers: authHeaders,
  body: JSON.stringify({
    filename: file.name,
    contentType: file.type || 'application/pdf',
    fileSize: file.size
  })
});
const { signedUrl, tempObject, uuid } = await signRes.json();

// Step 2: Upload file directly to GCS
const putHeaders = { 'Content-Type': file.type || 'application/pdf' };
await fetch(signedUrl, { method: 'PUT', headers: putHeaders, body: file });

// Step 3: Process & scan upload
const procRes = await fetch(`${API_BASE}/api/upload_file`, {
  method: 'POST',
  headers: authHeaders,
  body: JSON.stringify({
    tempObject,
    uuid,
    filename: file.name,
    contentType: file.type || 'application/pdf'
  })
});
const { file_id } = await procRes.json();

// Step 4: Send message with attached file UUID
const sendRes = await fetch(`${API_BASE}/api/send_message`, {
  method: 'POST',
  headers: authHeaders,
  body: JSON.stringify({
    recipients: ['user@example.com'],
    subject: 'Secure Document Delivery',
    body: 'Here is the requested document.',
    file_uuids: [file_id]
  })
});
const result = await sendRes.json();
console.log('Message sent:', result);

Model Context Protocol (MCP) Server (/mcp)

GetSafeDocs provides a built-in Model Context Protocol (MCP) Server at https://getsafedocs.cloud.run/mcp (and /api/mcp) implementing JSON-RPC 2.0 over Streamable HTTP (2025-03-26 & 2024-11-05). You can connect AI assistants (Claude Desktop, Cursor, Antigravity, Windsurf, or custom MCP agents) directly using your personal gsd_... API Key.

Add the following to your AI client's MCP configuration file (e.g., mcp_config.json or .cursor/mcp.json):

{
  "mcpServers": {
    "getsafedocs": {
      "url": "https://getsafedocs.cloud.run/mcp",
      "headers": {
        "X-API-Key": "gsd_your_api_key_here"
      }
    }
  }
}

2. Connecting via Local STDIO Bridge (For Local Disk File Uploads)

If you want your desktop AI assistant to upload files directly from local disk paths (e.g., "Send ~/Documents/contract.pdf to alice@example.com"), download the zero-dependency Python STDIO script (curl -sSL https://getsafedocs.cloud.run/mcp/getsafedocs_mcp.py -o ~/getsafedocs_mcp.py):

{
  "mcpServers": {
    "getsafedocs": {
      "command": "python3",
      "args": ["/path/to/mcp/getsafedocs_mcp.py"],
      "env": {
        "GETSAFEDOCS_API_KEY": "gsd_your_api_key_here"
      }
    }
  }
}

3. Available MCP Tools (tools/list & tools/call)

Tool Name Description
whoami Get authenticated account profile, tier (free, premium, enterprise), quota limits, and monthly usage.
get_supported_file_types List allowed and forbidden file extensions and max file size limits per tier.
upload_inline_file Upload a file from content_text or content_base64 to Toronto staging (northamerica-northeast2) and run QuickSand malware analysis.
get_upload_signed_url Generate a GCS V4 Signed PUT URL (signedUrl, tempObject, uuid) for uploading large binary files.
process_and_scan_upload Verify a file uploaded via get_upload_signed_url and run QuickSand malware analysis.
send_secure_message Send a secure message with file_uuids, repo_file_ids (one-click resend from Enterprise Repository), or inline_files (uploads, scans, and sends in one call), recipients, mailing_list_id, team_ids (internal Enterprise Teams), save_to_repository, classification, expiry_days, preview_only, and send_emails.
list_messages List messages in outbox (sent) or inbox (received) with pagination.
get_message_details Get message details, attached files, malware scan ratings, recipient delivery/read status, activity audit logs, and replies.
reply_to_message Send a reply to a message thread using message_id or token.
manage_message Perform message & recipient lifecycle actions: extend_expiry, toggle_notify, set_classification, resend_notification, add_recipients (supports team_ids & mailing_list_id), remove_recipient, add_files (supports repo_file_ids & save_to_repository), remove_file, save_file_to_repo, toggle_legal_hold, toggle_preview_only, mark_read, mark_reply_read, archive, unarchive, or delete.
download_attachment Generate a short-lived GCS V4 signed download URL for a file (file_id or uuid) or a ZIP of all message files (as_zip: true), or save directly to local disk (save_to_path in STDIO bridge).
get_scan_report Inspect QuickSand malware analysis findings and cryptographic hashes (MD5, SHA-1, SHA-256, SHA-512) for a file uuid.
access_shared_document Access a shared document package using a token or message_id.
list_document_requests List all Document Request intake portals created by the user (optional status filter).
get_document_request Get details and client file submissions for a specific Document Request (request_id or request_token).
submit_to_document_request Upload and submit files (inline_files or local_file_paths in STDIO bridge) to a Document Request portal using its request_token.
create_document_request Create a token-protected Document Request intake portal (request_name, expiry_days, max_file_size_mb, allowed_extensions, notify_emails).
update_document_request Update, activate, deactivate, email (notify_emails), or delete a Document Request portal.
manage_mailing_lists List, inspect (get), create, update, or delete external recipient Mailing Lists.
enterprise_admin Enterprise Company Admins: overview (seat usage, members, internal teams, held_messages eDiscovery vault, invites, settings), create_company, rename_company, update_settings (classification_options, disable_remote_preview, auto_archive_to_repo, repo_retention_days), invite, resend_invite, cancel_invite, accept_invite, set_member_role, remove_member, set_user_legal_hold (visible, silent, off), toggle_message_legal_hold, list_teams, create_team, delete_team, add_team_member, and remove_team_member.
enterprise_repository Enterprise Document Repository: list (filter by folder, classification, scope, search), upload (via file_uuids, inline_files, local_file_paths, or promote file_id), update, share (grant can_view, can_download, can_resend, can_delete to a team or user), unshare, toggle_legal_hold, download (supports save_to_path in STDIO bridge), and delete.

4. Available MCP Resources (resources/list & resources/read)

  • getsafedocs://guide/quickstart — Complete MCP & API integration guide and workflow reference
  • getsafedocs://account/profile — Current account profile, tier limits, and monthly quota usage
  • getsafedocs://config/file-types — Supported & forbidden file extensions per tier
  • getsafedocs://messages/outbox — Recent Outbox (sent) messages
  • getsafedocs://messages/inbox — Recent Inbox (received) messages
  • getsafedocs://document-requests — Active Document Request intake portals
  • getsafedocs://mailing-lists — Saved recipient mailing lists
  • getsafedocs://repository — Enterprise Document Repository files, folders, classifications, and permissions
  • Resource Templates (resources/templates/list):
  • getsafedocs://messages/{message_id}
  • getsafedocs://scan-report/{uuid}
  • getsafedocs://document-requests/{request_id}

5. Example MCP JSON-RPC Call (tools/call)

curl -X POST https://getsafedocs.cloud.run/mcp \
  -H "Content-Type: application/json" \
  -H "X-API-Key: gsd_your_api_key_here" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "send_secure_message",
      "arguments": {
        "subject": "Security Audit Summary",
        "body": "Attached is the Q4 security summary.",
        "recipients": ["client@example.com"],
        "preview_only": true,
        "inline_files": [
          {
            "filename": "q4_summary.md",
            "content_text": "# Q4 Security Summary\n\nAll systems passed 99/100 OWASP assessment."
          }
        ]
      }
    }
  }'