Gated File Delivery
Deliver private files (ebooks, PDFs, downloads) only to authenticated tenant members. Files stay on a non-public bucket; members get short-lived signed URLs (or app-streamed bytes). Access is checked live, so refund/cancel/expiry revokes it instantly. Never exposes a permanent public URL.
Try it with your AI assistant
Once WebsitePublisher is connected to your AI assistant, paste one of these into the chat. Replace the parts in [brackets] with your own details.
@WebsitePublisher put my PDF guides in a members-only download area@WebsitePublisher give [member's email] access to my price list PDF so only they can download itWith WebsitePublisher, put my PDF guides in a members-only download areaWith WebsitePublisher, give [member's email] access to my price list PDF so only they can download itWith WebsitePublisher, put my PDF guides in a members-only download areaWith WebsitePublisher, give [member's email] access to my price list PDF so only they can download itEndpoints (16)
Get a short-lived download URL for a gated file. Requires a verified tenant_auth session (wst_ Bearer). Returns { url, expires_in, delivery, filename }. Entitlement is checked live.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | ID of the gated file (from put-file / list-files). |
Upload a file into the private library as a tenant member. Requires a verified tenant_auth session (wst_ Bearer). tenant_code is taken from the session, never from the body. No overwrite. With member_upload_scope uploader the file is private to the uploader, who can remove it with delete-mine; otherwise uploads are append-only. Returns { file_id, filename, size_bytes }.
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | No | Multipart file part. Preferred transport. |
base64 |
string | No | Base64 bytes. Fallback when multipart is unavailable. |
filename |
string | No | Display filename. Derived from the upload when omitted; required with base64. |
title |
string | No | Human label, stored in metadata for review. |
List the private files this tenant may reach. The read counterpart of download: same door, same entitlement, so it can never show a file download would refuse. Scoped to the session tenant, not to the caller alone — a colleague seeing your upload is the point — unless member_upload_scope is uploader: then members only see their own uploads (plus the files the owner published). Returns file_id, filename, content_type, size_bytes, added_by, source and created_at. Never storage_key.
| Field | Type | Required | Description |
|---|---|---|---|
limit |
integer | No | Rows to return, newest first (default 50, max 100). |
Permanently remove one of your own uploads (put-upload). Only when the project sets member_upload_scope uploader. Requires a verified tenant_auth session (wst_ Bearer). Any other file answers 404. Returns { deleted, file_id }.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | ID of your own upload (from put-upload / list-mine). |
Set project defaults: entitlement_mode (library|asset), delivery_mode (signed|stream), signed_ttl_secs (10..900), member upload settings incl. member_upload_scope (tenant|uploader) and member_upload_retention_days.
| Field | Type | Required | Description |
|---|---|---|---|
entitlement_mode |
string | No | library (tenant_code = whole library) | asset (explicit grants). |
delivery_mode |
string | No | signed (presigned URL, default) | stream (app-streamed). |
signed_ttl_secs |
integer | No | Lifetime of issued download URLs in seconds (10..900, default 120). |
member_upload_enabled |
boolean | No | Allow tenant members to upload via put-upload (default false). |
member_upload_max_bytes |
integer | No | Max upload size in bytes (default 26214400 = 25 MB). |
member_upload_mime_allow |
array | No | Allowed MIME types. Omit or null = platform default list. |
member_upload_scope |
string | No | tenant (default): member uploads are shared with the whole tenant. uploader: each upload is visible only to the member who uploaded it, who can delete it with delete-mine. Files you publish with put-file are not affected. |
member_upload_retention_days |
integer | No | 0 (default) keeps member uploads. 1..3650 deletes member uploads older than this many days, once a day. Files you publish with put-file are never deleted by this. |
Register a private file. Provide exactly one source: storage_key (already-uploaded private path), base64 (inline bytes), or source_url (https, our own public storage — fetched into private). Optional per-file tenant_code / entitlement_mode / delivery_mode overrides.
| Field | Type | Required | Description |
|---|---|---|---|
filename |
string | ✓ Yes | Display filename for the download. |
storage_key |
string | No | Existing path on the private disk. |
base64 |
string | No | Base64-encoded file bytes (small files). |
source_url |
string | No | https URL on our own public storage to move into private. |
content_type |
string | No | MIME type (default application/octet-stream). |
tenant_code |
string | No | library-mode scope (omit = any tenant of this site). |
entitlement_mode |
string | No | Per-file override of the project entitlement_mode. |
delivery_mode |
string | No | Per-file override of the project delivery_mode. |
metadata |
object | No | Custom metadata (e.g. product_id). |
Import one file the owner picked in their own connected storage into the private library: a private copy is stored and registered as a normal gated file, so download works exactly as for put-file. provider: "dropbox" (connect it first with dropbox.connect). ref: the file id from the Dropbox Chooser or dropbox search-files ("id:…"). The type is checked from the bytes against the project allowlist (member_upload_mime_allow, else the platform default: PDF, Office, CSV, text, images) and the plan storage limit is checked first. Later changes in the provider are not synced. Paid plans. Returns { id, filename, size_bytes, content_type, provider }.
| Field | Type | Required | Description |
|---|---|---|---|
provider |
string | ✓ Yes | Connected storage provider: dropbox. |
ref |
string | ✓ Yes | File reference in the provider, e.g. a Dropbox file id "id:…". |
filename |
string | No | Display filename for the download; default the name in the provider. |
tenant_code |
string | No | library-mode scope (omit = any tenant of this site). |
entitlement_mode |
string | No | Per-file override of the project entitlement_mode. |
delivery_mode |
string | No | Per-file override of the project delivery_mode. |
metadata |
object | No | Custom metadata (e.g. product_id). The import provenance is added by the platform. |
Grant access to a file (entitlement_mode = asset). grant_type: tenant_code | tenant_user | plan.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | Gated file ID. |
grant_type |
string | ✓ Yes | tenant_code | tenant_user | plan. |
grant_value |
string | ✓ Yes | The tenant_code, tenant_user id, or plan. |
Remove a previously granted access rule.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | Gated file ID. |
grant_type |
string | ✓ Yes | tenant_code | tenant_user | plan. |
grant_value |
string | ✓ Yes | The grant value to remove. |
List gated files for this project, optionally filtered by tenant_code. Each row carries archived_at (null = in member delivery).
| Field | Type | Required | Description |
|---|---|---|---|
tenant_code |
string | No | Filter by tenant_code. |
limit |
integer | No | Page size (default 50, max 200). |
offset |
integer | No | Pagination offset. |
Change a registered gated file: filename, tenant_code (empty = every tenant of this site), entitlement_mode or delivery_mode (empty = project default). Members see the change on their next list or download. Provenance of member uploads is kept.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | Gated file ID. |
filename |
string | No | New display filename. |
tenant_code |
string | No | library-mode scope; empty string = every tenant of this site. |
entitlement_mode |
string | No | library | asset; empty string = project default. |
delivery_mode |
string | No | signed | stream; empty string = project default. |
Take a file out of member delivery without deleting it: it disappears from list-mine, download answers 404 and stream links already issued stop working. archived:false restores it. The owner still sees it in list-files and can export it with owner-download. Reversible, so prefer it over delete-file for superseded versions.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | Gated file ID. |
archived |
boolean | No | true (default) archives, false restores. |
Permanently remove a gated file: its registration and grants, plus the stored bytes when gated-files stored them (put-file base64/source_url, put-upload) and no other registration uses them. A file registered from an existing storage_key keeps its object. Requires confirm:true. Cannot be undone; frees storage.
| Field | Type | Required | Description |
|---|---|---|---|
file_id |
integer | ✓ Yes | Gated file ID. |
confirm |
boolean | ✓ Yes | Must be true. |
Owner export: short-lived private download URLs (5 to 15 minutes) for up to 50 gated files at once, archived ones included. Never a public CDN link and no member entitlement involved. Use it to back up or hand over files; never put these URLs on a page. Returns {files:[{file_id, filename, size_bytes, archived, url}], not_found, expires_in}.
| Field | Type | Required | Description |
|---|---|---|---|
file_ids |
array | ✓ Yes | Gated file IDs, at most 50 (page through list-files for more). |
Owner read: the contents of up to 10 gated files (1 MB each, 3 MB per call, 60 calls per hour), archived ones included, for an assistant that cannot fetch owner-download URLs. Text comes back as utf8, anything else as base64, each with sha256. Files over 1 MB are listed in too_large: use owner-download for those. Files that did not fit in the 3 MB budget of this call are listed in deferred: call owner-read again with those ids. The contents enter the conversation: use it only for files the owner wants the assistant to read, never publish them. Returns {files:[{file_id, filename, content_type, size_bytes, archived, sha256, encoding, content}], not_found, too_large, missing, limits}.
| Field | Type | Required | Description |
|---|---|---|---|
file_ids |
array | ✓ Yes | Gated file IDs, at most 10. |
format |
string | No | auto (default: utf8 for valid UTF-8 text, else base64) | utf8 (falls back to base64 when the bytes are not valid UTF-8) | base64. |
Download statistics: files registered, downloads in the period, top files.
| Field | Type | Required | Description |
|---|---|---|---|
days |
integer | No | Look-back window in days (default 30, max 365). |
MCP Tool Names
When using this integration through an AI assistant (Claude, ChatGPT, Cursor, etc.), the endpoints are available as MCP tools:
| Endpoint | MCP Tool Name |
|---|---|
| download | gated-files_download |
| put-upload | gated-files_put_upload |
| list-mine | gated-files_list_mine |
| delete-mine | gated-files_delete_mine |
| configure | gated-files_configure |
| put-file | gated-files_put_file |
| import-external | gated-files_import_external |
| grant | gated-files_grant |
| revoke | gated-files_revoke |
| list-files | gated-files_list_files |
| update-file | gated-files_update_file |
| archive-file | gated-files_archive_file |
| delete-file | gated-files_delete_file |
| owner-download | gated-files_owner_download |
| owner-read | gated-files_owner_read |
| stats | gated-files_stats |
Website