Skip to main content

File Uploads

Learn how to securely upload files to sajn for use in document fields.

Overview

Uploading a file uses a presigned flow that sends the bytes straight to storage, so there is no API-server size limit:
  1. Request a presigned URL — call POST /api/v1/files with the file’s metadata and checksum. You receive a fileId, a storage key, and a presigned uploadUrl.
  2. Upload the bytesPUT the raw file to the uploadUrl. Storage verifies the checksum on write.
  3. Confirm the upload (recommended) — call POST /api/v1/files/{id}/confirm to verify the stored object and flip the record from PENDING to CONFIRMED immediately.
  4. Use the storage key — reference the returned key in document fields.
Confirming is optional. If you skip step 3, the file is confirmed lazily the first time it is fetched via GET /api/v1/files/{id}. Calling confirm explicitly verifies the upload up front and is idempotent.
Removed: The legacy byte-through endpoint PUT /api/v1/putFile (hosted at https://upload.sajn.se) is no longer available. Use the presigned flow described below.

Benefits

  • No byte-through step: bytes go directly to cloud storage (up to 25 MB per file).
  • Integrity-checked: storage enforces the SHA-256 checksum you provide and rejects mismatched bytes.
  • Secure: files are scoped to your organization, private by default.

Step 1: Request a Presigned URL

Compute the file’s SHA-256 hash, base64-encoded, then call POST /api/v1/files:

Request

Request Fields

Response

  • fileId — the created file record ID. Its status is PENDING until the upload is confirmed on first access.
  • key — the storage key to reference in document fields.
  • uploadUrl — presigned PUT URL, valid for 1 hour.

Step 2: Upload the Bytes

PUT the raw file to the uploadUrl. You must send the Content-Type and the x-amz-checksum-sha256 headers — storage verifies the checksum and rejects the upload if it doesn’t match:
Do not send your sajn Authorization header to the presigned uploadUrl — authentication is already baked into the signed URL.
Right after the upload PUT returns 200, call POST /api/v1/files/{id}/confirm. The server reads the persisted object back from storage, verifies its size and checksum, then flips the file from PENDING to CONFIRMED:

Response

  • size — the byte size of the persisted object, read back from storage.
  • checksumVerified — whether the storage backend reported a SHA-256 that matched the checksum you supplied at create time.
Confirming is optional but recommended and idempotent — confirming an already-confirmed file returns its recorded state. If you skip it, the file is confirmed automatically the first time it is fetched via GET /api/v1/files/{id}.

File Visibility

Control who can access your uploaded files via the visibility field in Step 1:
  • PRIVATE (default) — access requires a fresh signed URL (valid for 60 minutes), retrieved via GET /api/v1/files/{id}.
  • PUBLIC — accessible via a permanent CloudFront URL.

Using Uploaded Files in Documents

After a successful upload, use the storage key in document field metadata. You can either create a new PDF field or update an existing one:
PDF fields use value for the file storage key, while TEXT and HTML fields use content for their data. See the API Reference for full details on each field type.

Create New PDF Field

Use the Create Document Field endpoint to add the uploaded PDF:

Update Existing PDF Field

Use the Update Document Field endpoint to replace an existing PDF:

Complete Upload Workflow

cURL Example

Node.js Example

File Requirements

Supported Formats

Limits

  • Maximum size: 25 MB per file (26214400 bytes).
  • Checksum: a valid base64-encoded SHA-256 of the exact bytes you upload is required.

Error Handling

Common Errors

File Too Large

Solution: Ensure the file is under the 25 MB limit and that size matches the actual byte count.

Checksum Mismatch

When the bytes you PUT don’t match the checksum you declared in Step 1, storage rejects the upload. Solution: Re-compute the base64-encoded SHA-256 over the exact bytes you upload, and send it both in the create request and in the x-amz-checksum-sha256 header.

Missing Authentication

Solution: Include a valid Authorization: Bearer header on the POST /api/v1/files call (but not on the presigned uploadUrl).

Best Practices

  1. Compute size and checksum together from the same byte buffer you upload.
  2. Validate file type and size client-side before requesting a presigned URL.
  3. Upload promptly — the presigned uploadUrl is only valid for 1 hour.
  4. Store storage keys for later reference in document fields.

Guides

API Reference