API Reference

Nexo Share provides a REST API on each self-hosted instance for automation and integration. This documentation site publishes the machine-readable contract at /openapi.json. The live API is not hosted on nexoshare.nl — call your own deployment.

Base URL

https://{your-server}/api

Replace with your domain in production (for example https://share.company.com/api).

Authentication

The web UI uses secure HTTP-only cookies after login.

Token-based (API)

For programmatic access, include the JWT in the Authorization header:

Authorization: Bearer YOUR_JWT_TOKEN

Obtain a token via the login endpoint (and verify-2fa when required).

Rate limits

  • Login: 5 attempts per 15 minutes per IP
  • Password reset: 3 requests per hour per IP
  • Uploads: 10,000 chunks per hour per IP
  • Downloads: 100 per hour per IP

Rate limit responses return HTTP 429 with a JSON error body.

Error responses

All product API endpoints return structured JSON errors agents can parse (not HTML):

{
  "error": "Human-readable error message"
}

Common status codes: 400 validation, 401 unauthorized, 403 forbidden, 404 not found, 409 conflict, 410 gone (expired), 413 payload too large, 429 rate limited, 500 server error.

The documentation site discovery API (/api/v1/docs on nexoshare.nl) uses RFC 9457 application/problem+json with code, detail, and resolution_hint.

Authentication endpoints

Login

POST /api/auth/login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "SecurePassword123"
}

200 — success or 2FA required:

{
  "success": true,
  "user": {
    "id": 1,
    "email": "[email protected]",
    "name": "John Doe",
    "is_admin": false
  }
}
{
  "requires2FA": true,
  "email": "[email protected]"
}

Verify 2FA

POST /api/auth/verify-2fa
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "SecurePassword123",
  "code": "123456"
}

Logout

POST /api/auth/logout

Share endpoints

Initialize share

POST /api/shares/init
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "name": "Project Files",
  "password": "optional-password",
  "expirationVal": 7,
  "expirationUnit": "Days",
  "recipients": "[email protected]",
  "message": "Here are the files you requested",
  "maxDownloads": 5
}

Returns { "success": true, "shareId": "..." }.

Upload chunks

POST /api/shares/{shareId}/chunk
Authorization: Bearer YOUR_TOKEN
Content-Type: multipart/form-data

Fields: chunk, chunkIndex, fileName, fileId. Split large files into ~50MB pieces.

Finalize

POST /api/shares/{shareId}/finalize
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

Body includes a files array with fileName, originalName, fileId, size, and optional mimeType. Response includes shareUrl.

List / delete / download

  • GET /api/shares — list shares
  • DELETE /api/shares/{shareId} — delete
  • GET /api/shares/{shareId}/download — ZIP download (public share id)

Reverse share endpoints

  • POST /api/reverse — create drop-off link
  • GET /api/reverse — list
  • GET /api/reverse/{reverseId}/files — list guest uploads
  • DELETE /api/reverse/{reverseId} — delete

Public endpoints

  • GET /api/public/shares/{shareId} — public share metadata
  • POST /api/shares/{shareId}/verify — unlock password-protected share
  • GET /api/public/reverse/{reverseId} — public reverse share metadata

Users and config (admin)

  • GET|POST /api/users, PUT|DELETE /api/users/{userId}
  • GET|PUT /api/config

OpenAPI and function calling

Import https://nexoshare.nl/openapi.json for typed operations (operationId on every path), request/response schemas, and bearer auth. See also /developers and the in-container CLI.

Example: upload with cURL

TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"SecurePass123"}' \
  | jq -r '.token')

SHARE_ID=$(curl -s -X POST http://localhost:3000/api/shares/init \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"API Upload","expirationVal":1,"expirationUnit":"Days"}' \
  | jq -r '.shareId')

curl -X POST "http://localhost:3000/api/shares/$SHARE_ID/chunk" \
  -H "Authorization: Bearer $TOKEN" \
  -F "[email protected]" \
  -F "chunkIndex=0" \
  -F "fileName=document.pdf" \
  -F "fileId=$(uuidgen)"

curl -X POST "http://localhost:3000/api/shares/$SHARE_ID/finalize" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"files":[{"fileName":"document.pdf","originalName":"document.pdf","fileId":"unique-id","size":1048576,"mimeType":"application/pdf"}]}'