GetObjectRetention
GetObjectRetention returns the retention of an object version: its mode, governance or
compliance, and the date until which it is locked. Without versionId it reads the current
version. Retention exists only in a bucket with Object Lock enabled, and
setting or extending one is the job of PutObjectRetention.
- Reading a retention takes the Read retention permission on the access key.
x-amz-expected-bucket-owneris welcome and has nothing to check: a key only ever reaches buckets of its own account.- A key containing a
.or..path segment (a/../b) cannot be put in a URL, so STRG answers400 InvalidURIfor it.
When you'd use it
- Checking a backup is really protected. A nightly backup job that uploads with a retention can read it back afterwards, confirming each version is locked in the mode and until the date it expects.
- Audits and compliance reports. A script preparing a records report reads the retain-until date of every version it lists, so the report says exactly how long each one is kept.
- Before a clean-up. A job about to delete old versions can first learn which of them are still locked, and until when, rather than finding out from a failed delete.
- An agent explaining what it sees. An agent asked why a file cannot be removed reads its retention and can tell the person the mode and the date the lock ends.
Request
GET /photos/2024/cat.jpg?retention HTTP/1.1
Host: my-bucket.s3.eu-central-1.strg.com
Authorization: AWS4-HMAC-SHA256 Credential=...
x-amz-date: 20260926T120000Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
The path-style form is GET /my-bucket/photos/2024/cat.jpg?retention on
s3.eu-central-1.strg.com, which a bucket name containing a dot needs -
Addressing explains both.
Permissions
The access key needs Read retention (object-retention:read). For a key limited to certain
buckets or to a key prefix, the bucket and the object key are within them.
Access keys has the details.
URI parameters
| Name | Type | Required | Description |
|---|---|---|---|
Bucket | String | Yes | The bucket holding the object. |
Key | String | Yes | The object key. A key containing a . or .. path segment answers 400 InvalidURI. |
retention | - | Yes | Selects this operation. Takes no value. |
versionId | String | No | The version whose retention to read; without it, the current version's. A version ID is an opaque string. |
Any other query parameter is answered with 501 NotImplemented, so a client knows straight
away. The X-Amz-* parameters of a presigned URL and the x-id parameter the JavaScript SDK
adds are welcome.
Request headers
| Name | Type | Required | Description |
|---|---|---|---|
x-amz-expected-bucket-owner | String | No | Welcome, with nothing to check: an access key only ever reaches its own account's buckets. |
x-amz-request-payer | String | No | Not applicable: STRG has no Requester Pays buckets. |
Request body
None.
Response
A successful request answers 200 OK with the retention in the body.
Response headers
| Name | Description |
|---|---|
x-amz-request-id | The request ID, handy for a support request. |
Response body
<?xml version="1.0" encoding="UTF-8"?>
<Retention xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Mode>GOVERNANCE</Mode>
<RetainUntilDate>2026-12-31T00:00:00.000Z</RetainUntilDate>
</Retention>
| Element | Type | Description |
|---|---|---|
Retention | Container | The object version's retention. |
Mode | String | GOVERNANCE or COMPLIANCE. How it works explains what each allows. |
RetainUntilDate | Timestamp | The date and time, in UTC, until which the version cannot be deleted permanently. |
Errors
These are the errors this request can return, and the situation behind each one.
| Code | HTTP status | When |
|---|---|---|
InvalidRequest | 400 | The bucket does not have Object Lock enabled, so no object in it has a retention to read. |
NotImplemented | 501 | The request carries a query parameter other than retention and versionId (presigning's X-Amz-* parameters and x-id aside). |
NoSuchBucket | 404 | The bucket does not exist, it is in a region other than the endpoint's, or the account has no storage in this endpoint's region. |
NoSuchKey | 404 | The object does not exist. |
AccessDenied | 403 | The access key lacks Read retention, or the bucket or key is outside its buckets or prefix. |
InvalidAccessKeyId | 403 | The access key does not exist, has expired or been revoked - or it was created moments ago and is not usable yet in a region where the account already stores data, in which case the same request works shortly afterwards. |
InvalidURI | 400 | The key contains a . or .. path segment. |
SignatureDoesNotMatch | 403 | The request signature does not match. |
RequestTimeTooSkewed | 403 | The request time is more than 15 minutes from the server's. |
AuthorizationHeaderMalformed | 400 | The signature's credential scope names a region other than the endpoint's. |
SlowDown | 503 | Too many requests. The Retry-After header says when a retry is welcome; the AWS SDKs retry on their own. |
ServiceUnavailable | 503 | A temporary failure; the same request can be retried. |
InternalError | 500 | An unexpected failure; the same request can be retried. |
Differences from Amazon S3
The table lists each place where STRG behaves differently, and what that means for a client.
| Aspect | Amazon S3 | STRG |
|---|---|---|
| Permissions | s3:GetObjectRetention | Read retention (object-retention:read) on the access key |
x-amz-expected-bucket-owner | Checked against the bucket owner | Welcome, with nothing to check |
| Bucket in another region | 301 redirect with x-amz-bucket-region | 404 NoSuchBucket. A bucket is reached through its own regional endpoint |
| Nothing stored in the endpoint's region yet | Any valid key reaches the endpoint | 404 NoSuchBucket, since the account has no buckets there |
Keys with . or .. segments | Allowed | 400 InvalidURI, because such a key cannot be put in a URL. DeleteObjects can still delete one |
Examples
Reading the retention of the current version of photos/2024/cat.jpg:
- AWS CLI
- Python (boto3)
- JavaScript (AWS SDK v3)
aws s3api get-object-retention \
--bucket my-bucket \
--key photos/2024/cat.jpg \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1
import boto3
s3 = boto3.client(
"s3",
endpoint_url="https://s3.eu-central-1.strg.com",
region_name="eu-central-1",
)
response = s3.get_object_retention(Bucket="my-bucket", Key="photos/2024/cat.jpg")
retention = response["Retention"]
print(retention["Mode"], retention["RetainUntilDate"])
import { GetObjectRetentionCommand, S3Client } from "@aws-sdk/client-s3";
const client = new S3Client({
endpoint: "https://s3.eu-central-1.strg.com",
region: "eu-central-1",
});
const response = await client.send(
new GetObjectRetentionCommand({
Bucket: "my-bucket",
Key: "photos/2024/cat.jpg",
}),
);
console.log(response.Retention?.Mode, response.Retention?.RetainUntilDate);
Reading the retention of a specific version, with VERSION_ID set to a version ID from
ListObjectVersions:
- AWS CLI
- Python (boto3)
- JavaScript (AWS SDK v3)
aws s3api get-object-retention \
--bucket my-bucket \
--key photos/2024/cat.jpg \
--version-id "$VERSION_ID" \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1
import os
import boto3
s3 = boto3.client(
"s3",
endpoint_url="https://s3.eu-central-1.strg.com",
region_name="eu-central-1",
)
response = s3.get_object_retention(
Bucket="my-bucket",
Key="photos/2024/cat.jpg",
VersionId=os.environ["VERSION_ID"],
)
print(response["Retention"])
import { GetObjectRetentionCommand, S3Client } from "@aws-sdk/client-s3";
const client = new S3Client({
endpoint: "https://s3.eu-central-1.strg.com",
region: "eu-central-1",
});
const response = await client.send(
new GetObjectRetentionCommand({
Bucket: "my-bucket",
Key: "photos/2024/cat.jpg",
VersionId: process.env.VERSION_ID,
}),
);
console.log(response.Retention);