# Storage API integration quickstart Use REST V2 for new storage integrations where an equivalent exists. The [REST reference](filesfm_api_v2.md) also covers V1 capabilities that do not have V2 equivalents, including restore, version history, ZIPs, and thumbnails. ## Authentication and request format Base URL: `https://api.files.fm`. V2 actions use **POST form fields**, not a JSON request body. Use `user` and `user_access_token` from a dedicated integration account. File uploads use multipart form data. MCP Bearer and DVS JSON examples are separate contracts. ## Create, upload, list, and download ```bash # Examples contain placeholders. These commands create and upload data. curl --fail-with-body --silent --show-error --max-time 30 \ 'https://api.files.fm/api_v2/create_folder' \ --data-urlencode 'user=YOUR_USER' \ --data-urlencode 'user_access_token=YOUR_API_TOKEN' \ --data-urlencode 'folder_name=Integration test' --data-urlencode 'access_type=PRIVATE' ``` Retain the returned `folder_hash` and capability keys. Hashes and keys are opaque strings. A private folder is an appropriate default for business data. ```bash curl --fail-with-body --silent --show-error --max-time 120 \ 'https://api.files.fm/api_v2/upload_file' \ -F 'user=YOUR_USER' -F 'user_access_token=YOUR_API_TOKEN' \ -F 'folder_hash=RETURNED_FOLDER_HASH' -F 'file=@local-file.txt' ``` Retain the returned `file_hash`. Upload one file per request; account limits apply. List with `get_folder_content` using the folder hash and form auth. The result is an array, not a DVS `items/total` envelope. This V2 listing has no documented pagination parameters; do not invent `page` or `limit` support. ```bash curl --fail-with-body --silent --show-error --max-time 30 \ 'https://api.files.fm/api_v2/download_file' \ --data-urlencode 'user=YOUR_USER' --data-urlencode 'user_access_token=YOUR_API_TOKEN' \ --data-urlencode 'file_hash=RETURNED_FILE_HASH' --output downloaded-file.txt ``` Download returns raw file bytes. Verify the HTTP result before treating the output as a successful file. ## JavaScript on a trusted server ```js async function storage(action, params) { const body = new URLSearchParams({ ...params, user: process.env.FILESFM_USER, user_access_token: process.env.FILESFM_API_TOKEN }); const response = await fetch(`https://api.files.fm/api_v2/${action}`, { method: 'POST', body, signal: AbortSignal.timeout(30000) }); if (!response.ok) throw new Error(`Storage HTTP ${response.status}`); return response.json(); } // Creates a private folder; run only when authorized. const folder = await storage('create_folder', { folder_name: 'Integration test', access_type: 'PRIVATE' }); const items = await storage('get_folder_content', { folder_hash: folder.folder_hash }); ``` For multipart upload use `FormData` with `file` as a Blob and do not manually set its Content-Type boundary. Use `response.arrayBuffer()` for download instead of `.json()`. ## PHP 7.4+ ```php getenv('FILESFM_USER'), 'user_access_token' => getenv('FILESFM_API_TOKEN'), 'folder_hash' => getenv('FILESFM_FOLDER_HASH')]; $curl = curl_init('https://api.files.fm/api_v2/get_folder_content'); curl_setopt_array($curl, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => http_build_query($params), CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 30]); $body = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ($body === false || $status !== 200) { throw new RuntimeException('Storage request failed: ' . $status); } $items = json_decode($body, true, 512, JSON_THROW_ON_ERROR); ``` ## Errors, limits, and retries V2 failures may have an empty body despite the JSON Content-Type. Some permission and not-found conditions use `405`, not `403/404`. Check the endpoint's documented statuses; legacy scripts can return plain text or endpoint-specific error objects. No universal REST quota is published. Anonymous V1 folder listing is separately throttled and delayed; authenticated V2 listing does not inherit that anonymous interface. Observe actual `429` and retry guidance. Retry reads with bounded backoff; reconcile create/upload outcomes before retrying writes. No general idempotency-key contract is documented.