API Documentation

The FileCourier API enables you to programmatically request documents from external users. When a request is processed, an email or SMS containing a unique secure upload link is sent to the recipient. Once files are uploaded, FileCourier delivers them to your application via webhook.

Quick Start

To get started, create a Project in your dashboard. Each project has a Client ID and Client Secret for API authentication.

Authentication

All API requests require authentication using HTTP Basic Auth. Use your Project's Client ID as the username and Client Secret as the password.

Getting Your Credentials
  1. Go to Projects in your dashboard
  2. Create a new project or select an existing one
  3. Copy your Client ID and Client Secret
Authorization Header

Combine your Client ID and Client Secret with a colon (:), then Base64 encode the string:

Format
Authorization: Basic base64(client_id:client_secret)
Example
cURL
curl -X POST https://api.filecourier.io/api/ext/sessions \
  -H "Content-Type: application/json" \
  -u "fc_7fce16d7095f13f27cd6dbbdced3dc3c:fcs_0bebd9ebed980d243a176ef5eacdb22e86b10bcaed" \
  -d '{
    "recipient": {
      "email": "customer@example.com",
      "name": "John Doe"
    }
  }'

The -u flag in cURL automatically handles the Base64 encoding for Basic Auth.

Keep your credentials secret. The Client Secret is only shown once when you create a project. Do not expose credentials in client-side code or public repositories.

Base URL

All API requests should be made to the following base URL:

Production
https://api.filecourier.io

External API endpoints are prefixed with /api/ext/. For example:

  • POST /api/ext/sessions - Create a new upload session
  • GET /api/ext/sessions/{sessionId} - Get session status
  • DELETE /api/ext/sessions/{sessionId} - Cancel a session
POST /api/ext/sessions

Create Session

Creates a new upload session and sends a notification (email and/or SMS) to the recipient with a secure upload link. The uploaded documents will be delivered to your application via the specified webhook URL.

Request Headers
Name Type Description
Content-Type string Must be application/json
Authorization string REQUIRED Basic Auth with Client ID and Client Secret
Basic base64(client_id:client_secret)
Request Body
Name Type Description
requestor_name string REQUIRED Name of the person or company requesting documents (shown to recipient)
requestor_email string REQUIRED Email address of the requestor (for reply-to)
recipient_email string REQUIRED Email address of the person who should upload documents
recipient_phone string OPTIONAL Phone number for SMS notification (format: +15551234567)
subject string REQUIRED Subject line for the email notification
message string REQUIRED Custom message shown to the recipient explaining what documents are needed
documents array OPTIONAL Array of document names/types being requested (e.g., ["ID Verification", "Proof of Address"])
reference_id string OPTIONAL Your internal reference ID for this request (e.g., order number, customer ID)
callback_url string REQUIRED Webhook URL where uploaded files will be delivered
callback_api_key string OPTIONAL API key to include in Authorization header when calling your callback URL
expires_at string OPTIONAL ISO 8601 datetime when the upload link expires (default: 7 days)
brand_name string OPTIONAL Company name to display on the upload portal
brand_logo_url string OPTIONAL URL to your logo for the upload portal
Example Request
cURL
curl --location --request POST 'https://api.filecourier.io/api/ext/sessions' \
  --header 'Content-Type: application/json' \
  -u 'your_client_id:your_client_secret' \
  --data-raw '{
    "recipient": {
      "email": "customer@example.com",
      "name": "John Doe"
    },
    "documents": ["Government ID", "Proof of Address"],
    "message": "Please upload the following documents.",
    "webhook_url": "https://api.acmecorp.com/webhooks/filecourier",
    "expires_in_days": 7
  }'
JavaScript
// Create Base64 encoded credentials
const credentials = btoa('your_client_id:your_client_secret');

const response = await fetch('https://api.filecourier.io/api/ext/sessions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Basic ${credentials}`
  },
  body: JSON.stringify({
    recipient: {
      email: 'customer@example.com',
      name: 'John Doe'
    },
    documents: ['Government ID', 'Proof of Address'],
    message: 'Please upload the following documents.',
    webhook_url: 'https://api.acmecorp.com/webhooks/filecourier'
  })
});

const data = await response.json();
Response
200 OK - Request created successfully
Response
{
  "status": true,
  "message": "Request created successfully",
  "data": {
    "request_id": "req_abc123xyz",
    "upload_url": "https://secure.filecourier.io/u/abc123xyz",
    "expires_at": "2025-02-15T23:59:59Z",
    "notification_sent": {
      "email": true,
      "sms": true
    }
  }
}
400 Bad Request - Invalid request parameters
Error Response
{
  "status": false,
  "error": "recipient_email is required"
}
401 Unauthorized - Invalid or missing API key
Error Response
{
  "status": false,
  "error": "Invalid API key"
}
GET /api/ext/sessions/{sessionId}

Get Session Status

Retrieves the current status of an upload session, including whether files have been uploaded and delivered.

Path Parameters
Name Type Description
sessionId string REQUIRED The session ID returned when creating the session
Example Request
cURL
curl --location --request GET 'https://api.filecourier.io/api/ext/sessions/sess_abc123xyz' \
  -u 'your_client_id:your_client_secret'
Response
Response
{
  "status": true,
  "data": {
    "request_id": "req_abc123xyz",
    "reference_id": "CUST-12345",
    "recipient_email": "[email protected]",
    "status": "completed",
    "created_at": "2025-01-22T10:30:00Z",
    "expires_at": "2025-02-15T23:59:59Z",
    "uploaded_at": "2025-01-22T14:22:15Z",
    "delivered_at": "2025-01-22T14:22:18Z",
    "files": [
      {
        "name": "drivers-license.pdf",
        "size": 245832,
        "type": "application/pdf"
      },
      {
        "name": "utility-bill.pdf",
        "size": 189234,
        "type": "application/pdf"
      }
    ]
  }
}
Status Values
Status Description
pending Request created, notification sent, waiting for recipient to upload
uploaded Files uploaded by recipient, webhook delivery in progress
completed Files successfully delivered to your callback URL
expired Upload link expired before recipient uploaded files
cancelled Request was cancelled via API
failed Webhook delivery failed after all retry attempts
DELETE /api/ext/sessions/{sessionId}

Cancel Session

Cancels a pending upload session. The upload link will no longer be valid. Cannot cancel sessions that have already been completed.

Example Request
cURL
curl --location --request DELETE 'https://api.filecourier.io/api/ext/sessions/sess_abc123xyz' \
  -u 'your_client_id:your_client_secret'
Response
Response
{
  "status": true,
  "message": "Session cancelled successfully"
}

Webhook Events

When files are uploaded, FileCourier sends a POST request to your callback_url with the file details and presigned download URLs.

Webhook Payload
files.delivered
{
  "event": "files.delivered",
  "timestamp": "2025-01-22T14:22:18Z",
  "data": {
    "request_id": "req_abc123xyz",
    "reference_id": "CUST-12345",
    "recipient_email": "[email protected]",
    "files": [
      {
        "name": "drivers-license.pdf",
        "size": 245832,
        "type": "application/pdf",
        "url": "https://files.filecourier.io/abc123/drivers-license.pdf?signature=...",
        "expires_at": "2025-01-23T14:22:18Z"
      },
      {
        "name": "utility-bill.pdf",
        "size": 189234,
        "type": "application/pdf",
        "url": "https://files.filecourier.io/abc123/utility-bill.pdf?signature=...",
        "expires_at": "2025-01-23T14:22:18Z"
      }
    ]
  }
}
File URLs expire after 1 hour. Download the files immediately upon receiving the webhook. Files are automatically deleted shortly after delivery to ensure your data doesn't linger.
Handling Webhooks
webhook-handler.js
// Express.js webhook handler example
app.post('/webhooks/filecourier', async (req, res) => {
  const { event, data } = req.body;
  
  if (event === 'files.delivered') {
    const { request_id, reference_id, files } = data;
    
    // Download each file
    for (const file of files) {
      const response = await fetch(file.url);
      const buffer = await response.arrayBuffer();
      
      // Save to your storage
      await saveFile(reference_id, file.name, buffer);
    }
    
    // Update your database
    await updateOrder(reference_id, { documentsReceived: true });
  }
  
  // Always respond with 200 to acknowledge receipt
  res.status(200).json({ received: true });
});
Retry Policy

If your endpoint returns a non-2xx response, FileCourier will retry the webhook delivery:

  • 1st retry: 1 minute after initial attempt
  • 2nd retry: 5 minutes after 1st retry
  • 3rd retry: 30 minutes after 2nd retry
  • 4th retry: 2 hours after 3rd retry
  • 5th retry: 24 hours after 4th retry

After all retries are exhausted, the request status will be set to failed. You can check the admin dashboard to manually retry or download the files.

Webhook Security

To verify that webhooks are genuinely from FileCourier, we include a signature in the X-FileCourier-Signature header.

Verifying Signatures
verify-signature.js
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/filecourier', (req, res) => {
  const signature = req.headers['x-filecourier-signature'];
  const isValid = verifyWebhookSignature(
    req.body, 
    signature, 
    process.env.FILECOURIER_WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  // Process webhook...
});

Your webhook secret is available in your API settings.

Need Help?

If you have questions or run into issues, we're here to help.