Files
Durable storage for what does not belong in Postgres — an upload, a generated PDF, a CSV somebody imported. The bytes never pass through your container: you get an id and a short-lived signed URL, and the client sends them straight to object storage.
Every call below goes to the address in your
SAASIE_ANALYTICS_URL
environment variable, with
Authorization: Bearer <token>. Read both from
the environment — they are injected, and hardcoding either is how
an app breaks when the platform moves.
See getting the credential.
POST
/v1/files
Provision a file, and get a link to upload it
Returns an id and a short-lived PUT URL. Send the bytes straight to that URL from wherever they are — they must not pass through your app.
Request body
| Field | Type | |
|---|---|---|
contentType |
string | What you will upload. Sent to the store with the bytes. length 1–200, defaults to application/octet-stream |
size* |
integer | How many bytes you are about to upload. Checked against the allowance before the link is signed — send the real length, since what arrives is checked too. 0–9007199254740991 |
name |
string | A display name, kept as metadata. It is not part of the id and two files may share one. length 1–200 |
200 — The file, and where to put the bytes
| Field | Type | |
|---|---|---|
file* |
object | — |
upload* |
object | — |
When it does not work
400 | Not a usable size or content type |
401 | Missing or invalid service token |
403 | The Saasie is stopped |
413 | Larger than one file may be, or than the allowance left |
501 | This deployment has no files battery |
502 | The object store could not be reached |
GET
/v1/files
What this Saasie has stored
Available files, newest first. Pass status=pending for provisions that have not been uploaded to yet, or status=rejected for ones that arrived and did not fit.
200 — A page of files
| Field | Type | |
|---|---|---|
files* |
object[] | — |
storedBytes* |
number | — |
bytesPerSaasie* |
number | — |
nextBefore* |
number | null | — |
When it does not work
401 | Missing or invalid service token |
403 | The Saasie is stopped |
501 | This deployment has no files battery |
GET
/v1/files/{id}
One file's metadata
Also the cheapest way to ask whether an upload landed: a pending file is checked against the store on every read.
200 — The file
| Field | Type | |
|---|---|---|
id* |
string | — |
status* |
string | pending is provisioned and not yet uploaded; available is confirmed by the store; rejected arrived and did not fit, and its bytes are gone. pending · available · rejected |
size* |
number | null | What actually arrived. Null while pending. |
declaredSize* |
number | — |
contentType* |
string | — |
name* |
string | null | — |
createdAt* |
number | — |
availableAt* |
number | null | — |
When it does not work
400 | Not a file id |
401 | Missing or invalid service token |
403 | The Saasie is stopped |
404 | No such file |
501 | This deployment has no files battery |
502 | The object store could not be reached |
DELETE
/v1/files/{id}
Delete a file
The bytes go, and the allowance comes back. Deleting one that is already gone succeeds — a retry after a timeout should not be an error.
When it does not work
400 | Not a file id |
401 | Missing or invalid service token |
403 | The Saasie is stopped |
404 | No such file |
501 | This deployment has no files battery |
502 | The object store could not be reached |
POST
/v1/files/{id}/link
A short-lived link to the bytes
GET to read, PUT to replace. The URL is the whole of the authorization on it, so treat it as one — it works for anybody holding it until it expires.
Request body
| Field | Type | |
|---|---|---|
method |
string | GET to read the bytes, PUT to replace them. A PUT link on an available file makes it pending again until the new bytes land. GET · PUT, defaults to GET |
200 — Where to send the bytes, and until when
| Field | Type | |
|---|---|---|
url* |
string | — |
method* |
string | GET · PUT |
expiresAt* |
number | — |
When it does not work
400 | Not a file id |
401 | Missing or invalid service token |
403 | The Saasie is stopped |
404 | No such file |
409 | A GET link for a file whose bytes are not there |
501 | This deployment has no files battery |
502 | The object store could not be reached |
Generated from
openapi.json, which the
service renders from its own routes. * marks
a required field. Every error body is
{ "error": { "code", "message", "details"? } }.