The Upload Source endpoint allows you to programmatically upload documents to your GraphorLM project using the REST API. This enables integration with external applications, automated workflows, and custom document ingestion pipelines.

Endpoint Overview

HTTP Method

POST

Authentication

This endpoint requires authentication using an API token. You must include your API token as a Bearer token in the Authorization header.

Learn how to create and manage API tokens in the API Tokens guide.

Request Format

Headers

HeaderValueRequired
AuthorizationBearer YOUR_API_TOKEN✅ Yes
Content-Typemultipart/form-data✅ Yes

Request Body

The request must be sent as multipart/form-data with the following field:

FieldTypeDescriptionRequired
fileFileThe document file to upload✅ Yes

File Requirements

Response Format

Success Response (200 OK)

{
  "status": "New",
  "message": "File document.pdf processed successfully",
  "file_name": "document.pdf",
  "file_size": 2048576,
  "file_type": "pdf",
  "file_source": "local file",
  "project_id": "550e8400-e29b-41d4-a716-446655440000",
  "project_name": "My Project",
  "partition_method": "basic"
}

Response Fields

FieldTypeDescription
statusstringProcessing status (New, Processing, Completed, Failed)
messagestringHuman-readable success message
file_namestringName of the uploaded file
file_sizeintegerSize of the file in bytes
file_typestringFile extension/type
file_sourcestringSource type (always “local file” for uploads)
project_idstringUUID of the target project
project_namestringName of the target project
partition_methodstringDocument processing method used

Code Examples

JavaScript/Node.js

const uploadDocument = async (apiToken, filePath) => {
  const formData = new FormData();
  const fileStream = fs.createReadStream(filePath);
  formData.append('file', fileStream);

  const response = await fetch('https://sources.graphorlm.com/upload', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiToken}`
    },
    body: formData
  });

  if (response.ok) {
    const result = await response.json();
    console.log('Upload successful:', result);
    return result;
  } else {
    throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
  }
};

// Usage
uploadDocument('grlm_your_api_token_here', './document.pdf')
  .then(result => console.log('Document uploaded:', result.file_name))
  .catch(error => console.error('Error:', error));

Python

import requests

def upload_document(api_token, file_path):
    url = "https://sources.graphorlm.com/upload"
    
    headers = {
        "Authorization": f"Bearer {api_token}"
    }
    
    with open(file_path, "rb") as file:
        files = {"file": (file_path, file)}
        
        response = requests.post(url, headers=headers, files=files, timeout=300)
        
        if response.status_code == 200:
            result = response.json()
            print(f"Upload successful: {result['file_name']}")
            return result
        else:
            response.raise_for_status()

# Usage
try:
    result = upload_document("grlm_your_api_token_here", "document.pdf")
    print(f"Document uploaded: {result['file_name']}")
except requests.exceptions.RequestException as e:
    print(f"Error uploading document: {e}")

cURL

curl -X POST https://sources.graphorlm.com/upload \
  -H "Authorization: Bearer grlm_your_api_token_here" \
  -F "file=@document.pdf"

PHP

<?php
function uploadDocument($apiToken, $filePath) {
    $url = "https://sources.graphorlm.com/upload";
    
    $headers = [
        "Authorization: Bearer " . $apiToken
    ];
    
    $postData = [
        'file' => new CURLFile($filePath)
    ];
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 300);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode === 200) {
        return json_decode($response, true);
    } else {
        throw new Exception("Upload failed with HTTP code: " . $httpCode);
    }
}

// Usage
try {
    $result = uploadDocument("grlm_your_api_token_here", "document.pdf");
    echo "Document uploaded: " . $result['file_name'] . "\n";
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Error Responses

Common Error Codes

Status CodeError TypeDescription
400Bad RequestInvalid file type, missing filename, or malformed request
401UnauthorizedInvalid or missing API token
403ForbiddenAccess denied to the specified project
404Not FoundProject not found
413Payload Too LargeFile exceeds 100MB limit
500Internal Server ErrorServer-side processing error

Error Response Format

{
  "detail": "File type '.xyz' is not supported. Allowed types: .pdf, .md, .png, .jpg, ..."
}

Error Examples

Document Processing

After a successful upload, GraphorLM automatically processes your document:

Processing Stages

  1. Upload Complete - File is securely stored in your project
  2. Text Extraction - Content is extracted using advanced OCR and parsing
  3. Structure Recognition - Document elements are identified and classified
  4. Ready for Use - Document is available for chunking and retrieval

Processing Methods

The system automatically selects the optimal processing method based on file type:

File TypeDefault MethodDescription
PDF, DocumentsBasicFast processing with heuristic classification
ImagesOCROptical character recognition for text extraction
Text filesBasicDirect text processing
SpreadsheetsBasicTable structure preservation

You can reprocess documents with different methods using the Process Source endpoint after upload.

Best Practices

File Preparation

  • Optimize file size: Compress large files when possible while maintaining quality
  • Use descriptive names: Include relevant keywords in filenames for easy identification
  • Check file integrity: Ensure files are not corrupted before upload

Error Handling

  • Implement retry logic: Handle temporary network issues with exponential backoff
  • Validate before upload: Check file types and sizes client-side before making requests
  • Monitor upload status: Use the response to track processing progress

Security

  • Protect API tokens: Never expose tokens in client-side code or public repositories
  • Use HTTPS only: All API requests are automatically secured with TLS encryption
  • Rotate tokens regularly: Update API tokens periodically for enhanced security

Integration Examples

Batch Upload Script

import os
import requests
from pathlib import Path

def batch_upload_documents(api_token, directory_path):
    """Upload all supported documents from a directory."""
    supported_extensions = {'.pdf', '.doc', '.docx', '.txt', '.md', '.html'}
    uploaded_files = []
    failed_files = []
    
    for file_path in Path(directory_path).iterdir():
        if file_path.suffix.lower() in supported_extensions:
            try:
                result = upload_document(api_token, str(file_path))
                uploaded_files.append(result['file_name'])
                print(f"✅ Uploaded: {file_path.name}")
            except Exception as e:
                failed_files.append((file_path.name, str(e)))
                print(f"❌ Failed: {file_path.name} - {e}")
    
    print(f"\nSummary: {len(uploaded_files)} uploaded, {len(failed_files)} failed")
    return uploaded_files, failed_files

# Usage
uploaded, failed = batch_upload_documents("grlm_your_token", "./documents/")

Upload with Progress Tracking

const uploadWithProgress = async (apiToken, file, onProgress) => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    formData.append('file', file);

    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable) {
        const percentComplete = (event.loaded / event.total) * 100;
        onProgress(percentComplete);
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error(`Upload failed: ${xhr.status}`));
      }
    });

    xhr.addEventListener('error', () => reject(new Error('Upload failed')));

    xhr.open('POST', 'https://sources.graphorlm.com/upload');
    xhr.setRequestHeader('Authorization', `Bearer ${apiToken}`);
    xhr.send(formData);
  });
};

Troubleshooting

Next Steps

After successfully uploading your documents: