---
title: PutObjectRetention · S3 API
description: Sets or extends the retention of one object version.
doc_version: 0.1.0-preview
last_updated: 2026-09-14
---

# PutObjectRetention

`PUT /{bucket}/{key}?retention`

Sets or extends the retention of one object version.

Storage keeps the version until the date that you send. You can add retention or move the date later. You cannot shorten it.

- Role: Editor or higher.
- Support: partial.
- Auth: AWS Signature Version 4 with your API key. See [S3 API](/api/s3.md).
- Needs versionId. COMPLIANCE only. Retention can be added or extended, never shortened.

## Example request

```http
PUT /support-tickets/a.json?retention&versionId=ver_5f0c8a8e3d2b4c1e9a7f6b5d4c3b2a19 HTTP/1.1
Host: wspq7ws2np5l8z4.storage.beta.graphon.sh
x-amz-date: 20261007T093000Z
x-amz-content-sha256: ec468f6091e11c1f437d9b2f410bc4e1d794693892d6c5e996accd210ff799d6
Authorization: AWS4-HMAC-SHA256 Credential=<ACCESS_KEY_ID>/20261007/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=<SIGNATURE>
Content-Length: 156

<Retention xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Mode>COMPLIANCE</Mode>
  <RetainUntilDate>2027-01-01T00:00:00Z</RetainUntilDate>
</Retention>
```

## Path parameters

- `bucket` (string, required): The bucket name.
- `key` (string, required): The object key. Keep each `/` as it is. Percent-encode the other reserved characters.

## Query parameters

- `retention` (flag, required): Selects this operation. Send it with no value.
- `versionId` (string, required): The version to retain.

## Headers

- `x-amz-expected-bucket-owner` (string, optional): The workspace ID that must own the bucket. Another owner returns `403 AccessDenied`.

## Request body

- `Retention` (object, required): The root element.
  - `Mode` (string, required): Send `COMPLIANCE`.
  - `RetainUntilDate` (string, required): An ISO 8601 date in the future.

## Responses

### 200 · OK

Storage saved the retention.

```http
HTTP/1.1 200 OK
x-amz-request-id: 4F8A2C7D1E6B4093A5C2D8E1F7B3A960
```

## Errors

Any request can also get the common errors on [S3 API](/api/s3.md).

### 400 · `InvalidRequest`

The request has no versionId, the mode is not COMPLIANCE, or the date is not in the future.

Send a versionId, COMPLIANCE mode, and a future RetainUntilDate.

### 403 · `AccessDenied`

The new date is earlier than the current one, or the key does not have the Editor role.

Send a date on or after the current RetainUntilDate.

### 404 · `NoSuchKey`

The bucket has no object at this key, or no version with this versionId.

Check the key and the versionId.

### 405 · `MethodNotAllowed`

The versionId names a delete marker, which has no bytes.

Use the versionId of a version that holds data. ListObjectVersions shows each one.

### 404 · `NoSuchBucket`

No bucket has this name, or the bucket was deleted.

Check the bucket name. ListBuckets shows the buckets of the workspace.

## Other request languages

### aws CLI

```bash
# The graphon profile from the S3 API overview.
export AWS_PROFILE=graphon

VERSION_ID="ver_5f0c8a8e3d2b4c1e9a7f6b5d4c3b2a19"  # A VersionId from list-object-versions
aws s3api put-object-retention \
  --bucket support-tickets \
  --key a.json \
  --version-id "$VERSION_ID" \
  --retention Mode=COMPLIANCE,RetainUntilDate=2027-01-01T00:00:00Z
```

### Python (boto3)

```python
# Replace wspq7ws2np5l8z4 with your workspace ID.
import os
from datetime import datetime, timezone

import boto3
from botocore.config import Config

api_key = os.environ["GRAPHON_API_KEY"]
access_key_id = api_key.split("_", 1)[1].split(".")[0]

s3 = boto3.client(
    "s3",
    endpoint_url="https://wspq7ws2np5l8z4.storage.beta.graphon.sh",
    region_name="us-east-1",
    aws_access_key_id=access_key_id,
    aws_secret_access_key=api_key,
    config=Config(signature_version="s3v4", s3={"addressing_style": "path"}),
)

response = s3.put_object_retention(
    Bucket="support-tickets",
    Key="a.json",
    VersionId="ver_5f0c8a8e3d2b4c1e9a7f6b5d4c3b2a19",
    Retention={
        "Mode": "COMPLIANCE",
        "RetainUntilDate": datetime(2027, 1, 1, tzinfo=timezone.utc),
    },
)
print(response["ResponseMetadata"]["HTTPStatusCode"])
```

### JavaScript (AWS SDK)

```javascript
// Replace wspq7ws2np5l8z4 with your workspace ID.
import { S3Client, PutObjectRetentionCommand } from '@aws-sdk/client-s3';

const apiKey = process.env.GRAPHON_API_KEY;
if (!apiKey) throw new Error('Set GRAPHON_API_KEY.');
const accessKeyId = apiKey.split('_')[1].split('.')[0];

const s3 = new S3Client({
  endpoint: 'https://wspq7ws2np5l8z4.storage.beta.graphon.sh',
  region: 'us-east-1',
  forcePathStyle: true,
  credentials: { accessKeyId, secretAccessKey: apiKey },
});

const response = await s3.send(new PutObjectRetentionCommand({
  Bucket: 'support-tickets',
  Key: 'a.json',
  VersionId: 'ver_5f0c8a8e3d2b4c1e9a7f6b5d4c3b2a19',
  Retention: {
    Mode: 'COMPLIANCE',
    RetainUntilDate: new Date('2027-01-01T00:00:00Z'),
  },
}));
console.log(response.$metadata.httpStatusCode);
```

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
