Self-Hosting Storage
An S3 compatible object storage service that integrates with Postgres.
- Uses Postgres as it's datastore for storing metadata
- Authorization rules are written as Postgres Row Level Security policies
- Integrates with S3 as the storage backend (with more in the pipeline!)
- Extremely lightweight and performant
Create a bucket
post
/bucket/Body
- nameRequiredstring
- idOptionalstring
- publicOptionalboolean
- typeOptionalenum
- file_size_limitOptionalany of the following options
- allowed_mime_typesOptionalArray<string>
Response codes
- 200
- 4XX
Response (200)
{ "name": "avatars"}{ "description": "Successful response", "type": "object", "properties": { "name": { "type": "string", "example": "avatars" } }, "required": [ "name" ]}Gets all buckets
head
/bucketQuery parameters
- limitOptionalinteger
- offsetOptionalinteger
- sortColumnOptionalenum
- sortOrderOptionalenum
- searchOptionalstring
Response codes
- 200
- 4XX
Response (200)
[ { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" }]{ "description": "Successful response", "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "public": { "type": "boolean" }, "type": { "type": "string", "enum": [ "STANDARD", "ANALYTICS" ] }, "file_size_limit": { "type": [ "null", "integer" ] }, "allowed_mime_types": { "type": [ "null", "array" ], "items": { "type": "string" } }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name" ], "additionalProperties": false, "example": { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" } }}Empty a bucket
post
/bucket/{bucketId}/emptyPath parameters
- bucketIdRequiredstring
Response codes
- 200
- 4XX
Response (200)
{ "message": "Empty bucket has been queued. Completion may take up to an hour."}{ "description": "Successful response", "type": "object", "properties": { "message": { "type": "string", "example": "Empty bucket has been queued. Completion may take up to an hour." } }}Get details of a bucket
head
/bucket/{bucketId}Path parameters
- bucketIdRequiredstring
Response codes
- 200
- 4XX
Response (200)
{ "id": "lorem", "name": "lorem", "owner": "lorem", "owner_id": "lorem", "public": true, "type": "STANDARD", "created_at": "lorem", "updated_at": "lorem"}{ "description": "Successful response", "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "public": { "type": "boolean" }, "type": { "type": "string", "enum": [ "STANDARD", "ANALYTICS" ] }, "file_size_limit": { "type": [ "null", "integer" ] }, "allowed_mime_types": { "type": [ "null", "array" ], "items": { "type": "string" } }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name" ], "additionalProperties": false}Update properties of a bucket
put
/bucket/{bucketId}Path parameters
- bucketIdRequiredstring
Body
Response codes
- 200
- 4XX
Response (200)
{ "message": "Successfully updated"}{ "description": "Successful response", "type": "object", "properties": { "message": { "type": "string", "example": "Successfully updated" } }, "required": [ "message" ]}Delete a bucket
delete
/bucket/{bucketId}Path parameters
- bucketIdRequiredstring
Response codes
- 200
- 4XX
Response (200)
{ "message": "Successfully deleted"}{ "description": "Successful response", "type": "object", "properties": { "message": { "type": "string", "example": "Successfully deleted" } }}Delete an object
delete
/object/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Response codes
- 200
- 4XX
Response (200)
{ "message": "Successfully deleted"}{ "description": "Successful response", "type": "object", "properties": { "message": { "type": "string", "example": "Successfully deleted" } }}Get object
get
/object/{bucketName}/{*}Serve objects
Path parameters
- bucketNameRequiredstring
- *Requiredstring
Response codes
- 4XX
Update the object at an existing key
put
/object/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Response codes
- 200
- 4XX
Response (200)
{ "Id": "lorem", "Key": "avatars/folder/cat.png"}{ "description": "Successful response", "type": "object", "properties": { "Id": { "type": "string" }, "Key": { "type": "string", "example": "avatars/folder/cat.png" } }, "required": [ "Key" ]}Upload a new object
post
/object/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Response codes
- 200
- 4XX
Response (200)
{ "Id": "lorem", "Key": "avatars/folder/cat.png"}{ "description": "Successful response", "type": "object", "properties": { "Id": { "type": "string" }, "Key": { "type": "string", "example": "avatars/folder/cat.png" } }, "required": [ "Key" ]}Delete multiple objects
delete
/object/{bucketName}Path parameters
- bucketNameRequiredstring
Body
- prefixesRequiredArray<string>
Response codes
- 200
- 4XX
Response (200)
[ { "name": "folder/cat.png", "bucket_id": "avatars", "owner": "317eadce-631a-4429-a0bb-f19a7a517b4a", "id": "eaa8bdb5-2e00-4767-b5a9-d2502efe2196", "updated_at": "2021-04-06T16:30:35.394674+00:00", "created_at": "2021-04-06T16:30:35.394674+00:00", "last_accessed_at": "2021-04-06T16:30:35.394674+00:00", "metadata": { "size": 1234 } }]{ "description": "Successful response", "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "bucket_id": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "version": { "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "created_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "last_accessed_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "user_metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "buckets": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "public": { "type": "boolean" }, "type": { "type": "string", "enum": [ "STANDARD", "ANALYTICS" ] }, "file_size_limit": { "type": [ "null", "integer" ] }, "allowed_mime_types": { "type": [ "null", "array" ], "items": { "type": "string" } }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name" ], "additionalProperties": false, "example": { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" } } }, "required": [ "name" ], "additionalProperties": false, "title": "objectSchema", "example": { "name": "folder/cat.png", "bucket_id": "avatars", "owner": "317eadce-631a-4429-a0bb-f19a7a517b4a", "id": "eaa8bdb5-2e00-4767-b5a9-d2502efe2196", "updated_at": "2021-04-06T16:30:35.394674+00:00", "created_at": "2021-04-06T16:30:35.394674+00:00", "last_accessed_at": "2021-04-06T16:30:35.394674+00:00", "metadata": { "size": 1234 } } }}Retrieve an object
get
/object/authenticated/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Query parameters
- downloadOptionalstring
Response codes
- 4XX
Generate a presigned url to retrieve an object
post
/object/sign/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Body
- expiresInRequiredinteger
- transformOptionalobject
Response codes
- 200
- 4XX
Response (200)
{ "signedURL": "/object/sign/avatars/folder/cat.png?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJhdmF0YXJzL2ZvbGRlci9jYXQucG5nIiwiaWF0IjoxNjE3NzI2MjczLCJleHAiOjE2MTc3MjcyNzN9.s7Gt8ME80iREVxPhH01ZNv8oUn4XtaWsmiQ5csiUHn4"}{ "description": "Successful response", "type": "object", "properties": { "signedURL": { "type": "string", "example": "/object/sign/avatars/folder/cat.png?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJhdmF0YXJzL2ZvbGRlci9jYXQucG5nIiwiaWF0IjoxNjE3NzI2MjczLCJleHAiOjE2MTc3MjcyNzN9.s7Gt8ME80iREVxPhH01ZNv8oUn4XtaWsmiQ5csiUHn4" } }, "required": [ "signedURL" ]}Retrieve an object via a presigned URL
head
/object/sign/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Query parameters
- downloadOptionalstring
- tokenRequiredstring
Response codes
- 4XX
Generate presigned urls to retrieve objects
post
/object/sign/{bucketName}Path parameters
- bucketNameRequiredstring
Body
- expiresInRequiredinteger
- pathsRequiredArray<string>
Response codes
- 200
- 4XX
Response (200)
[ { "error": "Either the object does not exist or you do not have access to it", "path": "folder/cat.png", "signedURL": "/object/sign/avatars/folder/cat.png?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJhdmF0YXJzL2ZvbGRlci9jYXQucG5nIiwiaWF0IjoxNjE3NzI2MjczLCJleHAiOjE2MTc3MjcyNzN9.s7Gt8ME80iREVxPhH01ZNv8oUn4XtaWsmiQ5csiUHn4" }]{ "description": "Successful response", "type": "array", "items": { "type": "object", "properties": { "error": { "type": [ "null", "string" ], "example": "Either the object does not exist or you do not have access to it" }, "path": { "type": "string", "example": "folder/cat.png" }, "signedURL": { "type": [ "null", "string" ], "example": "/object/sign/avatars/folder/cat.png?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJhdmF0YXJzL2ZvbGRlci9jYXQucG5nIiwiaWF0IjoxNjE3NzI2MjczLCJleHAiOjE2MTc3MjcyNzN9.s7Gt8ME80iREVxPhH01ZNv8oUn4XtaWsmiQ5csiUHn4" } }, "required": [ "error", "path", "signedURL" ] }}Moves an object
post
/object/moveBody
- bucketIdRequiredstring
- sourceKeyRequiredstring
- destinationBucketOptionalstring
- destinationKeyRequiredstring
Response codes
- 200
- 4XX
Response (200)
{ "message": "Successfully moved"}{ "description": "Successful response", "type": "object", "properties": { "message": { "type": "string", "example": "Successfully moved" } }, "required": [ "message" ]}Search for objects under a prefix
post
/object/list/{bucketName}Path parameters
- bucketNameRequiredstring
Body
- prefixRequiredstring
- limitOptionalinteger
- offsetOptionalinteger
- sortByOptionalobject
- searchOptionalstring
Response codes
- 200
- 4XX
Response (200)
[ { "name": "folder/cat.png", "bucket_id": "avatars", "owner": "317eadce-631a-4429-a0bb-f19a7a517b4a", "id": "eaa8bdb5-2e00-4767-b5a9-d2502efe2196", "updated_at": "2021-04-06T16:30:35.394674+00:00", "created_at": "2021-04-06T16:30:35.394674+00:00", "last_accessed_at": "2021-04-06T16:30:35.394674+00:00", "metadata": { "size": 1234 } }]{ "description": "Successful response", "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "bucket_id": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "version": { "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "created_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "last_accessed_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "user_metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "buckets": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "public": { "type": "boolean" }, "type": { "type": "string", "enum": [ "STANDARD", "ANALYTICS" ] }, "file_size_limit": { "type": [ "null", "integer" ] }, "allowed_mime_types": { "type": [ "null", "array" ], "items": { "type": "string" } }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name" ], "additionalProperties": false, "example": { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" } } }, "required": [ "name" ], "additionalProperties": false, "example": { "name": "folder/cat.png", "bucket_id": "avatars", "owner": "317eadce-631a-4429-a0bb-f19a7a517b4a", "id": "eaa8bdb5-2e00-4767-b5a9-d2502efe2196", "updated_at": "2021-04-06T16:30:35.394674+00:00", "created_at": "2021-04-06T16:30:35.394674+00:00", "last_accessed_at": "2021-04-06T16:30:35.394674+00:00", "metadata": { "size": 1234 } } }}Retrieve object info
head
/object/info/{bucketName}/{*}Object Info
Path parameters
- bucketNameRequiredstring
- *Requiredstring
Query parameters
- heightOptionalinteger
- widthOptionalinteger
- resizeOptionalenum
- formatOptionalenum
- qualityOptionalinteger
Response codes
- 4XX
Copies an object
post
/object/copyBody
- bucketIdRequiredstring
- sourceKeyRequiredstring
- destinationBucketOptionalstring
- destinationKeyRequiredstring
- metadataOptionalobject
- copyMetadataOptionalboolean
Response codes
- 200
- 4XX
Response (200)
{ "Id": "lorem", "Key": "folder/destination.png", "name": "lorem", "bucket_id": "lorem", "owner": "lorem", "owner_id": "lorem", "version": "lorem", "id": "lorem", "updated_at": "lorem", "created_at": "lorem", "last_accessed_at": "lorem", "metadata": {}, "user_metadata": {}, "buckets": { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" }}{ "description": "Successful response", "type": "object", "properties": { "Id": { "type": "string" }, "Key": { "type": "string", "example": "folder/destination.png" }, "name": { "type": "string" }, "bucket_id": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "version": { "type": "string" }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "updated_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "created_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "last_accessed_at": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "user_metadata": { "anyOf": [ { "type": "object", "additionalProperties": true }, { "type": "null" } ] }, "buckets": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "owner": { "type": "string" }, "owner_id": { "type": "string" }, "public": { "type": "boolean" }, "type": { "type": "string", "enum": [ "STANDARD", "ANALYTICS" ] }, "file_size_limit": { "type": [ "null", "integer" ] }, "allowed_mime_types": { "type": [ "null", "array" ], "items": { "type": "string" } }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": [ "id", "name" ], "additionalProperties": false, "example": { "id": "bucket2", "name": "bucket2", "public": false, "file_size_limit": 1000000, "allowed_mime_types": [ "image/png", "image/jpeg" ], "owner": "4d56e902-f0a0-4662-8448-a4d9e643c142", "created_at": "2021-02-17T04:43:32.770206+00:00", "updated_at": "2021-02-17T04:43:32.770206+00:00" } } }, "required": [ "Key" ]}Retrieve an object from a public bucket
get
/object/public/{bucketName}/{*}Path parameters
- bucketNameRequiredstring
- *Requiredstring
Query parameters
- downloadOptionalstring
Response codes
- 4XX
Get object info
get
/object/info/public/{bucketName}/{*}returns object info
Path parameters
- bucketNameRequiredstring
- *Requiredstring
Query parameters
- heightOptionalinteger
- widthOptionalinteger
- resizeOptionalenum
- formatOptionalenum
- qualityOptionalinteger
Response codes
- 4XX