Stash API
The purpose of Stash is to provide a simple interface for storing your application's files via Amazon S3.
Authentication / Authorization
To authenticate with Stash, pass your client credentials using the Basic Authentication scheme Authorization: Basic <base64_encoded_credentials>.
To request your new Client ID and Client Secret credentials, please reach out to the Enterprise Applications team via email at its-ais-enterprise-apps@uiowa.edu. Existing clients can use your current Client ID but you will be assigned a new Client Secret.
Hosts
Production: https://stash.its.uiowa.edu
Test: https://stash-test.its.uiowa.edu
Library Support
The following libraries are written and maintained for Java developers. Follow the links below for up-to-date usage and release information.
Upload a File
Upload a file to S3 and optionally specify filename, expiration, and metadata
Request URL
http
POST /api/v1/files/uploadRequest Body
Uploads should be encoded as multipart/form-data using the names file and meta for the file and data parts respectively.
The meta portion of the request is optional and consists of JSON with the following attributes.
filename- An optional attribute allowing clients to override the original name of the multipart-upload.expiresIn- Optional duration after which the file upload will expire and become inaccessible. The expiration date will be set as a positive duration offset from the upload date. Negative values will result in an error.metadata- A simple map of key/value pairs optionally used to identify/categorize your data. Api Clients should consider limiting the amount of metadata stored in Stash as it is not meant to be used as a database.
Duration Format
This supports both the ISO-8601 standard and a simple formats shown below. Defaults to seconds if no unit is specified.
Simple format:
- ns for nanoseconds
- us for microseconds
- ms for milliseconds
- s for seconds
- m for minutes
- h for hours
- d for days
Non-Production Automatic Expiration
In non-prod environments file assets are set to automatically expire in 30 days.
Example: File upload with metadata and 10 minute expiration
Upon successful upload, your application should store the value of the uuid attribute for later reference. Note in the example below, we've set the name to admissions_supp_hawkid.txt to override the original name provided by the uploader.
http
POST /api/v1/files/upload
Content-Type: multipart/form-data; boundary=1234567890
--1234567890
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
This is a sample file.
--1234567890
Content-Disposition: form-data; name="meta";
Content-Type: application/json
{
"filename": "standardized.txt",
"expiresIn": "10m",
"metadata": {
"category": "SIMPLE"
}
}
--1234567890--json
{
"uuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c",
"filename": "standardized.txt",
"fileSize": 22,
"contentType": "text/plain",
"uploadDate": "2025-07-28T09:33:02.618756",
"expirationDate": "2025-07-28T09:43:02.618756",
"metadata": {
"category": "SIMPLE"
}
}Download via presigned URL
Get a temporary presigned URL for downloading or sharing. This is the preferred method of downloading as the file transfer is coordinated directly with AWS rather than Stash processing the download as well.
Authorization
A Presign URL is public, therefore, it is your application's responsibility for providing any sort of custom authorization layer to restrict access.
Request URL
http
GET /api/v1/files/{uuid}/presignRequest Parameters
inline - Optional boolean indicating whether you'd prefer the content-disposition header be specified as inline or attachment. Defaults to attachment.
expiresIn - Optional duration indicating how long the presign url is accessible. The expiration time can be set between 1 second and 7 days. Other values will result in error.
Duration Format
This supports both the ISO-8601 standard and a simple formats shown below. Defaults to seconds if no unit is specified.
Simple format:
- ns for nanoseconds
- us for microseconds
- ms for milliseconds
- s for seconds
- m for minutes
- h for hours
- d for days
Example
http
GET /api/v1/files/26d9d41a-347a-4b72-9aa5-ad1eeb67272c/presignjson
https://ais-entapps-stash-dev.s3.amazonaws.com/dev_app/2025/26d9d41a-347a-4b72-9aa5-ad1eeb67272c...View File Asset Meta
Get information about the current state of a file asset
Request URL
http
GET /api/v1/files/{uuid}/metaExample
http
GET /api/v1/files/26d9d41a-347a-4b72-9aa5-ad1eeb67272c/metajson
{
"uuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c",
"filename": "standardized.txt",
"fileSize": 22,
"contentType": "text/plain",
"uploadDate": "2025-07-28T09:33:02.618756",
"expirationDate": "2025-07-28T09:43:02.617212",
"metadata": {
"category": "SIMPLE"
}
}Update File Asset Meta
Update information about a file asset including filename, expiration, and metadata
Request URL
http
PUT /api/v1/files/{uuid}/metaRequest Body
filename - The name will only be updated if the value is non-blank. Otherwise, the property is ignored.
expiresIn - The expiration date will be set as a positive duration offset from the upload date. Negative values will result in an error. To clear a previously set expiration, the client should send a duration of zero.
metadata Updates are handled as follows:
- Key passed with a non-null value will be added/updated
- Key passed with a value of null or empty string will be removed from the existing metadata map
- Keys that are omitted from existing metadata map will be ignored
Example
http
PUT /api/v1/files/26d9d41a-347a-4b72-9aa5-ad1eeb67272c/metajson
{
"filename": "standardized_v2.txt",
"expiresIn": "20m",
"metadata": {
"category": null,
"category_2": "EXTREME"
}
}json
{
"uuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c",
"filename": "standardized_v2.txt",
"fileSize": 22,
"contentType": "text/plain",
"uploadDate": "2025-07-28T09:24:34.012119",
"expirationDate": "2025-07-28T09:44:34.012119",
"metadata": {
"category_2": "EXTREME"
}
}Delete File Asset
Delete a file asset
Note: File asset deletion is a soft operation. The asset becomes immediately inaccessible via the API, but the object itself will remain in the S3/Backups and is subject to current lifecycle configurations.
Request URL
http
DELETE /api/v1/files/{uuid}Example
http
DELETE /api/v1/files/26d9d41a-347a-4b72-9aa5-ad1eeb67272chttp
204 No ContentCreate Share
Grant another client access to a specific file asset.
Shares come in two forms:
- SINGLE_FILE — shares access to a single specific file asset. This is the standard sharing method available to all API clients.
- ALL_FILES — grants the grantee access to all files you own, including any you upload in the future. This type of share can only be configured by an administrator through the admin interface.
Share Validations
- Creating a SINGLE_FILE share when an ALL_FILES share already exists with that grantee returns 400.
- Creating an ALL_FILES share (admin only) when SINGLE_FILE shares already exist with that grantee returns 400.
To switch sharing styles, you must revoke the existing shares first. Reach out to Stash support if this situation arises.
Request URL
http
POST /api/v1/sharesRequest Body
granteeClientId- Required. The client ID of the application being granted access.fileAssetUuid- Required. The UUID of the specific file asset to share.
Example: Share a specific file asset
http
POST /api/v1/shares
Content-Type: application/json
{
"granteeClientId": "other-app-client-id",
"fileAssetUuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c"
}json
{
"ownerClientId": "my-app-client-id",
"granteeClientId": "other-app-client-id",
"fileAssetUuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c",
"type": "SINGLE_FILE",
"createdAt": "2025-07-28T09:33:02"
}List Shares
List active shares granted by the authenticated client.
Request URL
http
GET /api/v1/sharesRequest Parameters
page- Optional. Zero-based page index. Defaults to0.size- Optional. Number of results per page. Defaults to20.sort- Optional. Sort expression in the formatproperty,direction(e.g.,createdAt,desc).granteeClientId- Optional. Filter results to shares for a specific grantee client.fileAssetUuid- Optional. Filter results to shares covering a specific file asset. When provided, both SINGLE_FILE shares for that file and any ALL_FILES shares are returned, since an ALL_FILES share implicitly covers every file.
Example
http
GET /api/v1/shares?page=0&size=20&sort=createdAt,descjson
{
"content": [
{
"ownerClientId": "my-app-client-id",
"granteeClientId": "other-app-client-id",
"fileAssetUuid": "26d9d41a-347a-4b72-9aa5-ad1eeb67272c",
"type": "SINGLE_FILE",
"createdAt": "2025-07-28T09:33:02"
},
{
"ownerClientId": "my-app-client-id",
"granteeClientId": "another-client-id",
"fileAssetUuid": null,
"type": "ALL_FILES",
"createdAt": "2025-07-27T14:10:45"
}
],
"page": {
"totalElements": 2,
"totalPages": 1,
"number": 0,
"size": 20
}
}Revoke Share
Revoke a SINGLE_FILE share for a specific grantee and file asset.
Request URL
http
DELETE /api/v1/shares/{granteeClientId}Request Parameters
fileAssetUuid- Required. The UUID of the file asset share to revoke.
Example
http
DELETE /api/v1/shares/other-app-client-id?fileAssetUuid=26d9d41a-347a-4b72-9aa5-ad1eeb67272chttp
204 No ContentErrors
Stash implements the "Problem Details" specification, RFC7807, for reporting of HTTP request errors in a consistent JSON format. You can expect unsuccessful API requests to look like the examples below.
Example: A presign download request for a file asset that has expired
json
{
"status": 400,
"title": "Bad Request",
"detail": "The requested file asset is expired",
"instance": "/api/v1/files/26d9d41a-347a-4b72-9aa5-ad1eeb67272c/presign",
"type": "https://docs.ais.its.uiowa.edu/stash/api.html#errors"
}