Storage provider endpoints let you configure where NekoHub stores uploaded assets. You can maintain multiple profiles and designate one as the default. All endpoints require authentication via JWT Bearer token or API key.
Supported provider types:
local — local filesystem storage
s3 — S3-compatible object storage (AWS S3, MinIO, R2, etc.)
github-repo — GitHub repository storage
Get storage providers overview
GET /api/v1/system/storage/providers
Returns all configured storage profiles, the active default profile, and runtime information about the currently active storage backend.
Required permission: providers.read
Response
All configured storage profiles. Unique internal name for the profile.
Human-readable display name.
Provider type: local, s3, or github-repo.
Whether this profile is enabled.
Whether this is the default profile for new uploads.
What this provider supports. Can serve files publicly.
Can serve files privately.
Can change file visibility after upload.
Can generate direct public URLs.
Whether access must go through the NekoHub proxy.
recommendedForPrimaryStorage
Whether this provider is recommended as primary storage.
Whether backed by an external platform.
Whether this provider is experimental.
requiresTokenForPrivateRead
Whether a token is needed for private reads.
Non-sensitive configuration summary (root path, bucket, endpoint host, etc.).
The profile currently marked as default, or null.
The effective profile used for writes, or null.
Information about the currently active runtime storage backend. Capabilities of the active runtime provider.
Whether the runtime is driven by the database profile configuration.
matchesDefaultProfileType
Whether the runtime provider type matches the default profile.
Runtime and profile alignment status. How the runtime was selected.
Whether a default profile is configured.
Whether the default profile is enabled.
providerTypeMatchesDefaultProfile
Whether the runtime and default profile types match.
Human-readable alignment status message.
Example
curl http://localhost:5121/api/v1/system/storage/providers \
-H "Authorization: Bearer <token>"
Create a storage profile
POST /api/v1/system/storage/providers
Creates a new storage provider profile.
Required permission: providers.create
Request body
Unique internal name for the profile (e.g. my-s3-bucket).
Human-readable name shown in the UI.
Provider type. One of: local, s3, github-repo.
Whether the profile is enabled. Defaults to true.
Whether to set this as the default profile. Defaults to false.
Provider-specific non-sensitive configuration (e.g. bucket name, region, root path, repository owner/name).
Provider-specific sensitive configuration (e.g. access key, secret key, GitHub token). Values in this object are stored encrypted and are not returned in GET responses.
Response — 201 Created
Returns the created storage profile object.
Example — create an S3 profile
curl -X POST http://localhost:5121/api/v1/system/storage/providers \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "my-s3",
"displayName": "My S3 Bucket",
"providerType": "s3",
"isEnabled": true,
"isDefault": false,
"configuration": {
"bucketOrContainer": "nekohub-assets",
"region": "us-east-1",
"publicBaseUrl": "https://cdn.example.com"
},
"secretConfiguration": {
"accessKey": "AKIAIOSFODNN7EXAMPLE",
"secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}'
Update a storage profile
PATCH /api/v1/system/storage/providers/{id}
Updates an existing storage provider profile. Only fields you include are changed.
Required permission: providers.update
Path parameters
The unique identifier of the profile to update.
Request body
New internal name. Omit to leave unchanged.
New display name. Omit to leave unchanged.
New enabled state. Omit to leave unchanged.
Updated non-sensitive configuration. Omit to leave unchanged.
Updated sensitive configuration. Omit to leave unchanged.
Response — 200 OK
Returns the updated storage profile object.
Example
curl -X PATCH http://localhost:5121/api/v1/system/storage/providers/01956f8d-0000-0000-0000-000000000010 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"displayName": "Primary S3 Bucket", "isEnabled": true}'
Delete a storage profile
DELETE /api/v1/system/storage/providers/{id}
Deletes a storage provider profile. Existing assets stored under this profile are not automatically migrated or deleted.
Required permission: providers.delete
Path parameters
The unique identifier of the profile to delete.
Response
ID of the deleted profile.
Whether this profile was the default at time of deletion.
Example
curl -X DELETE http://localhost:5121/api/v1/system/storage/providers/01956f8d-0000-0000-0000-000000000010 \
-H "Authorization: Bearer <token>"
Set default storage profile
POST /api/v1/system/storage/providers/{id}/set-default
Marks the specified profile as the default storage profile for new asset uploads.
Required permission: settings.update
Path parameters
The unique identifier of the profile to set as default.
Response — 200 OK
Returns the updated storage profile object.
Example
curl -X POST http://localhost:5121/api/v1/system/storage/providers/01956f8d-0000-0000-0000-000000000010/set-default \
-H "Authorization: Bearer <token>"
Browse a GitHub Repo directory
GET /api/v1/system/storage/providers/{id}/github-repo/browse
Lists files and directories within a GitHub-based storage profile. Only available for profiles with providerType: github-repo.
Required permission: providers.read
Path parameters
The unique identifier of a github-repo storage profile.
Query parameters
Directory path to browse. Defaults to the repository root.
Whether to list contents recursively.
Maximum recursion depth when recursive is true.
Filter by entry type: file, dir, or omit for all.
Filter entries by name keyword.
Page number. Defaults to 1.
Response
The path that was browsed.
Whether more pages are available.
Full path within the repository.
Whether this entry is a directory.
Whether this entry is a file.
File size in bytes (files only).
Public URL for the file, if applicable.
Example
curl "http://localhost:5121/api/v1/system/storage/providers/01956f8d-0000-0000-0000-000000000010/github-repo/browse?path=images&page=1&pageSize=20" \
-H "Authorization: Bearer <token>"
Upsert a file in a GitHub Repo
POST /api/v1/system/storage/providers/{id}/github-repo/upsert
Creates or updates a single file in a GitHub-based storage profile.
Required permission: providers.update
Path parameters
The unique identifier of a github-repo storage profile.
Request body
Path within the repository where the file should be written (e.g. images/2026/photo.png).
Base64-encoded content of the file to write.
Optional commit message. Defaults to a generated message if omitted.
For updates: the current file’s Git blob SHA. Required when updating an existing file to prevent conflicts. Omit when creating a new file.
Response
The path where the file was written.
Whether the operation was a create or update.
Public URL for the file, if applicable.
Returns 409 Conflict if the expectedSha does not match the current file SHA.
Example
curl -X POST http://localhost:5121/api/v1/system/storage/providers/01956f8d-0000-0000-0000-000000000010/github-repo/upsert \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"path": "images/hello.txt",
"contentBase64": "SGVsbG8sIHdvcmxkIQ==",
"commitMessage": "Add hello.txt"
}'