Overview
The SecureLync Partner API allows any authorised partner to integrate encrypted, malware-scanned file sharing directly into their platform — regardless of technology stack or hosting provider.
Partners can create share links, manage tokens, scan files for threats, and embed the SecureLync widget into their UI. All files are AES-256-GCM encrypted client-side before upload. The server never sees plaintext.
Authentication
All server-side requests must include your partner API key as a Bearer token:
Authorization: Bearer your_partner_api_key_here
Your API key must never be exposed client-side. All calls using the API key must be made from your backend server.
Session Tokens (Widget Auth)
For browser-side widget use, your server calls POST /v1/session to obtain a short-lived session token (15 minutes). This token is safe to include in page HTML — it cannot be used to access the API key and expires automatically.
The widget uses the session token to authenticate API calls from the browser. This is the correct pattern for all widget integrations.
Base URL
https://api.securelync.com/v1
All endpoints are HTTPS only. Every response is JSON with an ok boolean.
Error Handling
{
"ok": false,
"error": "X-Partner-User-ID header required."
}
| Status | Meaning |
|---|---|
200 | Success |
201 | Resource created |
400 | Bad request — missing or invalid parameters |
401 | Unauthorised — invalid or missing API key |
404 | Resource not found |
429 | Rate limited |
500 | Server error — contact support |
Roles
| Role | Permissions |
|---|---|
admin | Create tokens, list ALL organisation tokens, revoke any token, view any token status |
vendor | Create tokens, list own tokens, revoke own tokens |
client | Create tokens, list own tokens, revoke own tokens |
Health Check
No authentication required.
{ "ok": true, "status": "ok", "version": "2.0.0", "service": "SecureLync Partner API" }
Create User
Creates a SecureLync account for a user on your platform. Idempotent — safe to call on every login.
| Field | Type | Notes |
|---|---|---|
user_id required | string | Your platform's unique user ID |
email required | string | User's email address |
username required | string | User's display name |
role optional | string | admin | vendor | client. Default: client |
{ "ok": true, "message": "User created.", "securelink_user_id": 42, "username": "yourpartner__user_123", "partner_user_id": "user_123", "partner_role": "vendor" }
Create Session Token
Creates a short-lived session token (15 min) for widget authentication. Call from your server on each page load that includes the widget.
| Field | Type | Notes |
|---|---|---|
user_id required | string | Your platform user ID |
role optional | string | User's role. Default: client |
{ "ok": true, "session_token": "bXNtfG1z...", "expires_at": "2026-04-11T17:00:00.000Z", "expires_in_seconds": 900 }
Security Scan
Check a file's SHA-256 hash against MalwareBazaar, CIRCL Hashlookup, and VirusTotal before upload. The file itself is never sent — only its hash fingerprint. The widget calls this automatically.
| Field | Type | Notes |
|---|---|---|
hash required | string | SHA-256 hex of the file plaintext (64 chars) |
ext optional | string | File extension e.g. pdf |
{ "ok": true, "malicious": 0, "suspicious": 0, "total": 72, "not_found": false, "blocked": false, "sources": ["malwarebazaar", "circl-hashlookup", "virustotal"] }
If blocked is true, the file must not be uploaded. The widget enforces this automatically.
Create Token
Creates a share token for a partner user. Call this before uploading files.
Headers
| Header | Notes |
|---|---|
X-Partner-User-ID required | Your platform user ID |
X-Partner-Role optional | User's role |
Body
| Field | Type | Notes |
|---|---|---|
label optional | string | Max 64 chars |
expires_in_days optional | integer | 1–7. Default: 7 |
max_downloads optional | integer | Omit for unlimited |
{ "ok": true, "token_id": 88, "token": "a3f8c2...", "share_url": "https://securelync.com/app?t=a3f8c2...", "expires_at": "2026-04-18T10:00:00.000Z", "expires_in_days": 7, "max_downloads": null, "label": "Contract docs" }
Upload File
Upload an AES-256-GCM encrypted file blob for a token. Accepts multipart/form-data. The widget handles this automatically including client-side encryption.
Headers
| Header | Notes |
|---|---|
X-Partner-User-ID required | Your platform user ID |
Form Fields
| Field | Type | Notes |
|---|---|---|
file required | binary | Encrypted blob: IV[12] + tag[16] + ciphertext |
enc_key required | string | AES-256 key as 64-char hex |
enc_iv required | string | IV as 24-char hex |
original_name required | string | Original filename |
file_size optional | integer | Original file size in bytes |
mime_type optional | string | MIME type |
{ "ok": true, "file_key": "a1b2c3d4e5f6", "share_url": "https://securelync.com/app?t=a3f8c2...", "original_name": "contract.pdf", "file_size": 245760 }
List Tokens
Headers
| Header | Notes |
|---|---|
X-Partner-User-ID required | Pass admin role to see all org tokens |
X-Partner-Role optional | User's role |
Token Status
{ "ok": true, "token_id": 88, "active": true, "expired": false, "download_capped": false, "download_count": 1, "max_downloads": null, "expires_at": "2026-04-18T10:00:00.000Z" }
Revoke Token
Permanently revokes a token and deletes associated files. Cannot be undone.
{ "ok": true, "message": "Token revoked." }
Widget Overview
The SecureLync widget is a self-contained JavaScript modal that embeds encrypted file sharing into any web page. It handles the full flow: security scanning, client-side AES-256-GCM encryption, upload, and share link generation.
The widget calls the Partner API via your server-side proxy — so it works on any hosting provider including those with strict CSP policies like InfinityFree.
Widget Installation
On standard hosting (cPanel, Xneelo, VPS, cloud), the widget script loads directly:
<script>
window.SecureLyncConfig = {
session_token: '<?= $session_token ?>', // from PHP: sl_get_session_token()
user_id: '<?= $user_id ?>',
role: '<?= $role ?>', // 'admin' | 'vendor' | 'client'
trigger_id: 'my-share-btn', // ID of button that opens widget
api_base: '/sl-proxy.php?path=/v1', // your proxy path
};
</script>
<script src="https://api.securelync.com/widget.js" defer></script>
On InfinityFree (which blocks external scripts via CSP), download widget.js and serve it locally — see the proxy setup section below.
Proxy Setup
The proxy is a thin server-side file that forwards widget API calls to api.securelync.com. It adds your API key server-side so it never reaches the browser. This is required on any host with a restrictive connect-src CSP (such as InfinityFree), and recommended everywhere for security.
Save sl-proxy.php to your web root and point the widget's api_base at it. No other configuration is needed — it reads your API key from your existing config file.
PHP Integration
Add these functions to your integration file (e.g. includes/securelync.php). Define SL_API_KEY in your config before including this file.
<?php
// ── Core request helper ───────────────────────────────────────────────────
function sl_request(string $method, string $endpoint, array $extra_headers = [], ?array $body = null): array {
$ch = curl_init('https://api.securelync.com/v1' . $endpoint);
$headers = [
'Authorization: Bearer ' . SL_API_KEY,
'Content-Type: application/json',
'Accept: application/json',
];
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => array_merge($headers, $extra_headers),
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => true,
]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) return ['ok' => false, 'error' => 'Connection error: ' . $err];
return json_decode($response, true) ?? ['ok' => false, 'error' => 'Invalid response'];
}
// ── Ensure user exists (call on every login — idempotent) ─────────────────
function sl_ensure_user(int $uid, string $email, string $name, string $role = 'client'): array {
return sl_request('POST', '/users/create', [], [
'user_id' => (string)$uid,
'email' => $email,
'username' => $name,
'role' => $role,
]);
}
// ── Map your roles to SecureLync roles ────────────────────────────────────
// Customise this for your platform's role system
function sl_role_for_user(): string {
if (function_exists('isAdmin') && isAdmin()) return 'admin';
$mode = $_SESSION['role'] ?? $_SESSION['active_mode'] ?? 'client';
return in_array($mode, ['vendor', 'agent', 'staff']) ? 'vendor' : 'client';
}
// ── Get session token for widget (call on each page load) ─────────────────
function sl_get_session_token(int $uid, string $role): string {
$res = sl_request('POST', '/session', [], [
'user_id' => (string)$uid,
'role' => $role,
]);
return $res['session_token'] ?? '';
}
// ── Server-side token creation (without widget) ───────────────────────────
function sl_create_token(int $uid, string $role, string $label = '', int $expires_days = 7, ?int $max_downloads = null): array {
return sl_request('POST', '/tokens/create', [
'X-Partner-User-ID: ' . $uid,
'X-Partner-Role: ' . $role,
], array_filter([
'label' => $label ?: null,
'expires_in_days' => $expires_days,
'max_downloads' => $max_downloads,
], fn($v) => $v !== null));
}
// ── List tokens ───────────────────────────────────────────────────────────
function sl_list_tokens(int $uid, string $role): array {
return sl_request('GET', '/tokens', [
'X-Partner-User-ID: ' . $uid,
'X-Partner-Role: ' . $role,
]);
}
// ── Revoke token ──────────────────────────────────────────────────────────
function sl_revoke_token(int $uid, string $role, int $token_id): array {
return sl_request('DELETE', '/tokens/' . $token_id, [
'X-Partner-User-ID: ' . $uid,
'X-Partner-Role: ' . $role,
]);
}
PHP + InfinityFree
InfinityFree enforces a server-level CSP that blocks external scripts and fetch calls. Two steps are required:
Step 1: Download widget.js from https://api.securelync.com/widget.js and upload it to your htdocs root. Reference it locally:
<script src="/widget.js" defer></script>
Step 2: Upload sl-proxy.php to your htdocs root. The proxy forwards API calls server-side, bypassing the CSP restriction. Set your api_base to point to it:
api_base: '/sl-proxy.php?path=/v1'
When you migrate from InfinityFree to paid hosting (cPanel, Xneelo, etc.), no code changes are needed — the proxy works identically on all PHP hosting.
widget.js. On paid hosting with no CSP restrictions, you can switch to the external script tag and updates are automatic.
Full page example (InfinityFree)
<?php
require_once __DIR__ . '/includes/config.php'; // defines SL_API_KEY
require_once __DIR__ . '/includes/securelync.php';
$uid = (int)$_SESSION['user_id'];
$role = sl_role_for_user();
// Ensure SL account exists for this user
sl_ensure_user($uid, $_SESSION['email'], $_SESSION['name'], $role);
// Get widget session token
$token = sl_get_session_token($uid, $role);
?>
<button id="sl-share-btn">🔒 Share File</button>
<script>
window.SecureLyncConfig = {
session_token: '<?= htmlspecialchars($token, ENT_QUOTES) ?>',
user_id: '<?= $uid ?>',
role: '<?= htmlspecialchars($role, ENT_QUOTES) ?>',
trigger_id: 'sl-share-btn',
api_base: '/sl-proxy.php?path=/v1',
};
</script>
<script src="/widget.js" defer></script>
PHP + Xneelo / cPanel
On standard cPanel or Xneelo hosting, you control your CSP headers so the external script tag works directly. The proxy is still recommended for security (keeps the API key server-side).
<?php
// Add to your page's HTTP headers (e.g. in .htaccess or at top of PHP)
header("Content-Security-Policy: script-src 'self' 'unsafe-inline' https://api.securelync.com; connect-src 'self'");
require_once __DIR__ . '/includes/securelync.php';
$uid = (int)$_SESSION['user_id'];
$role = sl_role_for_user();
sl_ensure_user($uid, $_SESSION['email'], $_SESSION['name'], $role);
$token = sl_get_session_token($uid, $role);
?>
<button id="sl-share-btn">🔒 Share File</button>
<script>
window.SecureLyncConfig = {
session_token: '<?= htmlspecialchars($token, ENT_QUOTES) ?>',
user_id: '<?= $uid ?>',
role: '<?= htmlspecialchars($role, ENT_QUOTES) ?>',
trigger_id: 'sl-share-btn',
api_base: '/sl-proxy.php?path=/v1', // keep proxy for API key security
};
</script>
<script src="https://api.securelync.com/widget.js" defer></script>
Node.js Integration
// securelync.js — server-side helper module
const SL_API = 'https://api.securelync.com/v1';
const SL_KEY = process.env.SL_API_KEY;
async function slRequest(method, endpoint, extraHeaders = {}, body = null) {
const res = await fetch(SL_API + endpoint, {
method,
headers: {
'Authorization': 'Bearer ' + SL_KEY,
'Content-Type': 'application/json',
'Accept': 'application/json',
...extraHeaders,
},
body: body ? JSON.stringify(body) : undefined,
});
return res.json();
}
export async function slEnsureUser(userId, email, username, role = 'client') {
return slRequest('POST', '/users/create', {}, { user_id: userId, email, username, role });
}
export async function slGetSessionToken(userId, role = 'client') {
const res = await slRequest('POST', '/session', {}, { user_id: userId, role });
return res.session_token ?? null;
}
export async function slCreateToken(userId, role, label = '', expiresInDays = 7) {
return slRequest('POST', '/tokens/create',
{ 'X-Partner-User-ID': userId, 'X-Partner-Role': role },
{ label, expires_in_days: expiresInDays }
);
}
// Express.js route example
// app.get('/chat', async (req, res) => {
// const token = await slGetSessionToken(req.user.id, req.user.role);
// res.render('chat', { slToken: token, slUserId: req.user.id });
// });
For the proxy in Node.js, use a simple route that forwards requests:
// Express proxy route
app.all('/sl-proxy', async (req, res) => {
const path = req.query.path || '';
if (!path.startsWith('/v1/')) return res.status(404).json({ ok: false, error: 'Invalid path' });
const upstream = await fetch('https://api.securelync.com' + path, {
method: req.method,
headers: {
'Authorization': 'Bearer ' + process.env.SL_API_KEY,
'Content-Type': req.headers['content-type'] || 'application/json',
'X-Partner-User-ID': req.headers['x-partner-user-id'] || '',
'X-Partner-Role': req.headers['x-partner-role'] || '',
},
body: ['POST','PUT','PATCH'].includes(req.method) ? req : undefined,
duplex: 'half',
});
res.status(upstream.status);
upstream.body.pipeTo(new WritableStream({
write(chunk) { res.write(chunk); },
close() { res.end(); },
}));
});
Python Integration
import os, requests
SL_API = 'https://api.securelync.com/v1'
SL_KEY = os.environ['SL_API_KEY']
def sl_request(method, endpoint, extra_headers=None, body=None):
headers = {
'Authorization': f'Bearer {SL_KEY}',
'Content-Type': 'application/json',
'Accept': 'application/json',
**(extra_headers or {}),
}
r = requests.request(method, SL_API + endpoint, headers=headers,
json=body, timeout=15)
return r.json()
def sl_ensure_user(user_id, email, username, role='client'):
return sl_request('POST', '/users/create', body={
'user_id': str(user_id), 'email': email,
'username': username, 'role': role,
})
def sl_get_session_token(user_id, role='client'):
res = sl_request('POST', '/session', body={'user_id': str(user_id), 'role': role})
return res.get('session_token')
def sl_create_token(user_id, role, label='', expires_in_days=7):
return sl_request('POST', '/tokens/create',
extra_headers={'X-Partner-User-ID': str(user_id), 'X-Partner-Role': role},
body={'label': label, 'expires_in_days': expires_in_days})
# Django/Flask view example:
# def chat_view(request):
# token = sl_get_session_token(request.user.id, request.user.role)
# return render(request, 'chat.html', {'sl_token': token})
For the Python proxy (Django/Flask), forward requests similarly to the Node.js example, injecting the API key server-side.
Security Notes
File encryption: All files are AES-256-GCM encrypted in the browser before upload. The server stores only encrypted blobs. Decryption keys are never stored server-side unencrypted.
Security scanning: Every file is hash-checked against MalwareBazaar, CIRCL Hashlookup, and VirusTotal before encryption. Only the SHA-256 fingerprint is sent — never the file itself.
Data isolation: Partner users are namespaced to your partner ID and are invisible to direct SecureLync users and other partners.
Expiry: All tokens expire within 7 days maximum. Encrypted file bytes are deleted automatically on expiry.
Hosting Compatibility
| Hosting | External script tag | Proxy required | Notes |
|---|---|---|---|
| InfinityFree | ❌ CSP blocked | ✅ Required | Serve widget.js locally; keep updated manually |
| cPanel / Xneelo | ✅ Works | Recommended | Add CSP header to allow api.securelync.com |
| VPS / Dedicated | ✅ Works | Recommended | Full control over headers and config |
| Vercel / Netlify | ✅ Works | Recommended | Use serverless function as proxy |
| Node.js / Python | ✅ Works | Recommended | Use middleware route as proxy |