Developers
A REST API for the parts of document exchange you shouldn't do by hand
Create rooms when a matter opens in your practice management system, invite the right people, and stream every access event into your own tooling. The API covers rooms, documents, invitations, permissions, retention and events.
API access is included on Enterprise and available as an add-on to Business.
The snippets on this page are illustrative — see the full reference at
developers.fileshare-portal.com.
Design principles
The API is a conventional JSON REST interface. Resources are addressed by stable,
prefixed identifiers (room_,
doc_, evt_), collections are
cursor-paginated, and every mutating request accepts an idempotency key so a retry after
a timeout cannot create a second room.
Two things are deliberately not in the API, because they would undermine the product's reason for existing:
- There is no endpoint that returns document content in bulk. Downloads are issued as short-lived, single-use URLs scoped to one document and one actor, and every issuance is an audited event.
- There is no way to delete or amend an audit event. The events collection is read-only over the API and over the interface, for everyone.
Base URL and versioning
All requests go to https://api.fileshare-portal.com/v1 over
TLS 1.3. Plain HTTP requests are refused rather than redirected. Breaking changes are
shipped as dated versions; pin yours with the
Vaultline-Version header and we will hold that behaviour for
at least 24 months.
Authentication
Authenticate with a bearer token in the Authorization
header. Keys are issued per environment and per integration from the admin console, carry
explicit scopes (rooms:write,
events:read, and so on), and can be restricted to a set of
source addresses. Keys are shown once at creation and stored as a hash — we cannot
recover one for you, only issue a replacement.
Handling keys. Treat an API key as you would a password to your document estate. Keep it in a secrets manager, never in source control or client-side code, and rotate on any suspicion of exposure — rotation takes effect immediately and old keys can be revoked without downtime by overlapping them.
Create a room
The most common integration: a matter opens in your practice management system, and a correctly configured room appears without anybody clicking through a wizard.
curl -X POST https://api.fileshare-portal.com/v1/rooms \
-H "Authorization: Bearer vlk_live_REPLACE_WITH_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Vaultline-Version: 2026-03-01" \
-d '{
"name": "Project Aurora - vendor due diligence",
"template": "due_diligence_standard",
"matter_reference": "AUR-2026-0142",
"retention_policy_id": "ret_7y_matter_close",
"settings": {
"watermark": "per_recipient",
"default_role": "reviewer",
"downloads_enabled": false,
"expires_at": "2026-08-31T23:59:59Z"
}
}'
{
"id": "room_9f2c1a7be40d",
"object": "room",
"name": "Project Aurora - vendor due diligence",
"status": "active",
"matter_reference": "AUR-2026-0142",
"template": "due_diligence_standard",
"created_at": "2026-07-14T09:21:44Z",
"expires_at": "2026-08-31T23:59:59Z",
"region": "eu-tallinn-1",
"settings": {
"watermark": "per_recipient",
"default_role": "reviewer",
"downloads_enabled": false
},
"counts": {
"documents": 0,
"members": 1,
"guests": 0
},
"retention": {
"policy_id": "ret_7y_matter_close",
"disposition_after": "matter_close",
"legal_hold": false
},
"url": "https://app.fileshare-portal.com/r/9f2c1a7be40d"
}
Invite a guest with a scoped role
Invitations carry a role, an expiry and an optional scope. The scope narrows access to particular folders or documents; the most restrictive applicable rule always wins.
curl -X POST https://api.fileshare-portal.com/v1/rooms/room_9f2c1a7be40d/invitations \
-H "Authorization: Bearer vlk_live_REPLACE_WITH_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "j.tamm@harbourlane.example",
"role": "view_only",
"expires_at": "2026-08-31T23:59:59Z",
"scope": { "folder_ids": ["fld_02_financials"] },
"message": "Access to the financial schedules for Project Aurora."
}'
Read the audit trail
Every event in the account is queryable by room, document, actor, type and time range. Events are hash-chained: each carries the hash of its predecessor, so a consumer can verify that nothing has been removed from a sequence.
curl -G https://api.fileshare-portal.com/v1/events \
-H "Authorization: Bearer vlk_live_REPLACE_WITH_YOUR_KEY" \
--data-urlencode "room_id=room_9f2c1a7be40d" \
--data-urlencode "type=document.viewed" \
--data-urlencode "occurred_after=2026-07-01T00:00:00Z" \
--data-urlencode "limit=50"
{
"object": "list",
"has_more": true,
"next_cursor": "evt_01J9WQ2M4C7XN0",
"data": [
{
"id": "evt_01J9WQ2M4C7XMZ",
"object": "event",
"type": "document.viewed",
"occurred_at": "2026-07-14T11:42:07.482Z",
"room_id": "room_9f2c1a7be40d",
"document_id": "doc_4b81e0c2",
"actor": {
"type": "guest",
"email": "j.tamm@harbourlane.example",
"display_name": "J. Tamm"
},
"context": {
"ip": "94.140.14.32",
"user_agent": "Mozilla/5.0",
"pages_viewed": 22,
"duration_seconds": 761
},
"hash": "sha256:6f1c...a09d",
"previous_hash": "sha256:11be...74c2"
}
]
}
Webhooks
Rather than polling, register an endpoint and we will POST events as they happen. Deliveries are retried with exponential backoff for up to 24 hours, and every delivery carries a signature you should verify before trusting the payload.
{
"id": "evt_01J9WQ7T1B0KDF",
"type": "document.downloaded",
"api_version": "2026-03-01",
"occurred_at": "2026-07-14T13:05:12.004Z",
"account_id": "acct_3d90fe11",
"data": {
"room_id": "room_9f2c1a7be40d",
"document_id": "doc_4b81e0c2",
"document_name": "02 - Financial statements 2023-2025.pdf",
"actor": {
"type": "guest",
"email": "j.tamm@harbourlane.example"
}
}
}
Vaultline-Signature: t=1752498312,v1=5257a1c9e0b47f3d8c...
Vaultline-Delivery: dlv_01J9WQ7T1B0KDF
Compute HMAC-SHA256 over timestamp + "." + raw_body using
your endpoint's signing secret, compare in constant time, and reject deliveries with a
timestamp older than five minutes. Endpoints should respond
2xx within 10 seconds and do their real work asynchronously.
Event types
| Event | Emitted when |
|---|---|
room.created | A room was created, by any means. |
room.archived | A room was archived to a sealed, read-only record. |
room.expired | A room passed its expiry date and closed to all guests. |
document.uploaded | A document or a new version was added. |
document.viewed | A document was opened in the viewer. Includes pages and duration. |
document.downloaded | A document left the platform as a file. |
document.printed | A print job was produced through the viewer. |
document.deleted | A document was removed by a user with sufficient rights. |
invitation.sent | An invitation was issued to a guest. |
invitation.accepted | A guest completed first access. |
invitation.revoked | Access was withdrawn before its expiry. |
permission.changed | A role or scope was altered on a room, folder or document. |
access.denied | An access attempt failed. Includes expired and revoked tokens. |
retention.scheduled | A disposal was scheduled against a retention rule. |
retention.disposed | Content was destroyed and a disposal certificate issued. |
legal_hold.applied | A legal hold was applied, suspending disposal. |
legal_hold.released | A legal hold was lifted. |
signature.sent | A document was handed to the e-signature provider. |
signature.completed | An executed copy was returned and filed. |
Errors
Errors use conventional status codes and return a structured body. Every response —
success or failure — carries a request_id; quote it if you
contact support.
{
"error": {
"type": "invalid_request_error",
"code": "role_not_permitted_on_plan",
"message": "The role 'auditor' requires a Business or Enterprise plan.",
"param": "role",
"doc_url": "https://developers.fileshare-portal.com/errors#role_not_permitted_on_plan",
"request_id": "req_01J9WQ8ZC3M7PA"
}
}
Rate limits
Business add-on keys are limited to 120 requests per minute; Enterprise keys to 600,
raisable on request. Limits are advertised on every response through
RateLimit-Limit,
RateLimit-Remaining and
RateLimit-Reset. On 429 respect
the Retry-After header.
SDKs
Official clients wrap authentication, pagination, retries with idempotency, and webhook signature verification. All are MIT licensed and published from our public repositories.
Node.js
npm i @vaultline/sdk
TypeScript types included. Node 18+.
Python
pip install vaultline
Sync and async clients. Python 3.9+.
Go
go get go.vaultline.dev/sdk
Context-aware, zero dependencies.
.NET
dotnet add package Vaultline
.NET 6 and later.
OpenAPI
A published OpenAPI 3.1 description for generating your own client.
Sandbox
A separate sandbox account with seeded rooms and synthetic documents, free on every plan.
Building an integration?
Tell us what system you are connecting and we will get you a sandbox account and an engineer on the call.