Skip to main content

Upload an object

Uploads a file and returns its stored representation, including the URL you serve it from.

POST /api/v1/objects

Permission: write · Content-Type: multipart/form-data

Request

Headers

HeaderRequiredNotes
X-API-KeyYesA key with write permission.
X-App-IdIf the key is app-restrictedYour mobile bundle id (e.g. com.example.myapp).

Do not set Content-Type manually in browsers/fetch — let the client set the multipart boundary.

Form fields

FieldRequiredTypeDescription
fileYesfileThe file to store. Validated against the max upload size (default 10 MB; configurable per deployment) and any configured allowed-MIME list.
visibilityNopublic | privateAccess control. Omitted → private. Integrations send public.
expires_in_daysNointeger (1–3650)Auto-delete this many days from now.
expires_atNoISO-8601 datetime (future)Auto-delete at this absolute time. Wins over expires_in_days if both are sent.

Examples

curl
curl -X POST https://fileshub.zaions.com/api/v1/objects \
-H "X-API-Key: fh_live_xxx" \
-F "file=@/path/to/report.pdf" \
-F "visibility=public" \
-F "expires_in_days=7"
fetch
const form = new FormData();
form.append('file', file); // a File/Blob
form.append('visibility', 'public');

const res = await fetch('https://fileshub.zaions.com/api/v1/objects', {
method: 'POST',
headers: { 'X-API-Key': 'fh_live_xxx' },
body: form,
});
const object = await res.json();
PHP (Guzzle)
$response = $client->post('https://fileshub.zaions.com/api/v1/objects', [
'headers' => ['X-API-Key' => 'fh_live_xxx'],
'multipart' => [
['name' => 'file', 'contents' => fopen('/path/report.pdf', 'r')],
['name' => 'visibility', 'contents' => 'public'],
],
]);
$object = json_decode((string) $response->getBody(), true);

Response

201 Created

{
"public_id": "01JDKQXXXXXXXXXXXXXXXXXXXXX",
"project_id": "01JDKPXXXXXXXXXXXXXXXXXXXXX",
"visibility": "public",
"mime_type": "application/pdf",
"size_bytes": 1048576,
"url": "https://fileshub.zaions.com/api/v1/objects/01JDKQXXXXXXXXXXXXXXXXXXXXX",
"expires_at": "2026-06-30T12:00:00+00:00"
}

Persist url (and optionally public_id) on your own record. expires_at is null when no expiry was requested.

Errors

StatusWhenBody
401No / invalid X-API-Key.{ "message": "API key is required..." }
403Key lacks write, or origin/app not allowed.{ "message": "..." }
422Validation failed (no file, file too large, bad visibility, disallowed MIME).{ "message": "<first validation error>" }
429Rate limit exceeded.{ "message": "..." }
500Server error while storing.{ "message": "An error occurred while uploading the file." }

Notes

  • The public_id is a ULID: time-sortable and URL-safe.
  • The stored file keeps its original filename for downloads (Content-Disposition).
  • Set visibility deliberately — see File visibility.