NapX PMS Docs

Files

File upload, attachment, and retrieval API in NapX PMS.

Files

NapX PMS provides a file storage API that lets you upload documents and media, attach them to platform entities, and generate time-limited download URLs. Files are stored in S3 (or an in-memory fallback for development) under a tenant-scoped key scheme.

Endpoints

MethodPathDescription
POST/v1/files/upload-urlCreate a presigned upload URL for direct-to-S3 uploads
POST/v1/files/uploadUpload a file (up to 10 MB); optionally attach to an entity
GET/v1/files/:id/urlGet a presigned download URL
POST/v1/files/attachAttach an already-uploaded file to a platform entity
GET/v1/files/attachmentsList files attached to an entity (?entityType=&entityId=)
DELETE/v1/files/attachments/:idDelete an attachment and remove the backing file if it is no longer referenced
DELETE/v1/files/:idDelete a file record, all its attachments, and the backing S3 object

Response Shape

  • POST /v1/files/upload returns { file: FileRecord, attachment?: FileAttachmentRecord }. The attachment field is included only when entityType and entityId query params are provided.
  • POST /v1/files/upload-url returns { uploadUrl, fileId, expiresIn } so the client can upload bytes directly to S3 after the file row has been created.
  • GET /v1/files/:id/url returns { url: string } — a presigned URL valid for 15 minutes by default (configurable via ?expiresIn=<seconds>).
  • POST /v1/files/attach returns a FileAttachmentRecord.
  • GET /v1/files/attachments returns an array of FileAttachmentRecord rows.
  • DELETE /v1/files/attachments/:id returns 204 No Content.
  • DELETE /v1/files/:id returns 204 No Content. Resolves silently when the file does not exist or belongs to another tenant (no information leakage).

Polymorphic Attachment Targets

Files can be attached to any of the following entity types:

entityTypeDescription
propertyA property record
roomA room within a property
spaceA bookable space
spaceTypeA space type/category
guestA guest profile
reservationA reservation record
userA platform user account

Security Model

  • Every request requires Authorization: Bearer <session-token>.
  • Tenant context is derived from validated auth claims; files outside the caller's tenant are not accessible.
  • Presigned download URLs are generated by the storage provider and expire after the configured window (default: 900 seconds).

File Size Limit

Uploads are capped at 10 MB per file. Multipart uploads are validated server-side, and direct uploads via /v1/files/upload-url require fileSize and reject the request before URL issuance when the declared size is missing or above the limit.

In addition, direct-upload issuance is subject to a tenant monthly upload quota (configured via FILES_TENANT_MONTHLY_UPLOAD_LIMIT_BYTES; default 5 GB). When the quota would be exceeded, upload URL issuance is rejected with 400 Bad Request.

File Deletion

DELETE /v1/files/:id is intended for cleaning up orphaned file records — for example, when a presigned upload to S3 fails after the file row has been created. The call:

  1. Deletes all fileAttachment rows linked to the file.
  2. Removes the backing S3 object (best-effort; a storage failure is logged as a warning and does not abort the database cleanup).
  3. Deletes the file row itself.

All three steps are wrapped in a single transaction. Requesting deletion of a non-existent file or a file belonging to a different tenant returns 204 silently.

Error Handling

  • 400 Bad Request when file size exceeds 10 MB or an invalid entityType is provided.
  • 401 Unauthorized when the bearer token is missing or invalid.
  • 404 Not Found when a file ID does not exist for the tenant.

Example

POST /v1/files/upload?entityType=reservation&entityId=0d2d70e1-aeab-432f-ae94-9f3f5a42ba55
Authorization: Bearer <session-token>
Content-Type: multipart/form-data

[file field: signed-lease.pdf]

See the API reference for the detailed endpoint contract including all query parameters and response fields.

On this page