Storage API Reference

REST endpoints for buckets (CRUD) and objects (CRUD), multipart upload, presigned URLs, versioning. Example requests and responses.

NFYio provides an S3-compatible storage API. Use the AWS SDK, AWS CLI, or direct REST calls. This reference covers the main REST endpoints and patterns.

Base URL: https://storage.yourdomain.com (or your configured endpoint)

Buckets

Create Bucket

PUT /{bucket-name} HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

cURL (using AWS CLI profile):

aws --endpoint-url https://storage.yourdomain.com s3 mb s3://my-bucket

Response: 200 OK (bucket created)

List Buckets

GET / HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response:

<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult>
  <Buckets>
    <Bucket>
      <Name>my-bucket</Name>
      <CreationDate>2026-03-01T12:00:00.000Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>

Delete Bucket

DELETE /{bucket-name} HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Note: Bucket must be empty. Delete all objects first.

Get Bucket Versioning

GET /{bucket-name}?versioning HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response:

<VersioningConfiguration>
  <Status>Enabled</Status>
</VersioningConfiguration>

Put Bucket Versioning

PUT /{bucket-name}?versioning HTTP/1.1
Host: storage.yourdomain.com
Content-Type: application/xml
Authorization: AWS4-HMAC-SHA256 Credential=...

<VersioningConfiguration>
  <Status>Enabled</Status>
</VersioningConfiguration>

Objects

Put Object

PUT /{bucket-name}/{object-key} HTTP/1.1
Host: storage.yourdomain.com
Content-Type: application/octet-stream
Content-Length: 1234
Authorization: AWS4-HMAC-SHA256 Credential=...

[binary body]

cURL:

curl -X PUT "https://storage.yourdomain.com/my-bucket/path/to/file.txt" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary @file.txt

Response: 200 OK with optional headers:

ETag: "d41d8cd98f00b204e9800998ecf8427e"
x-amz-version-id: 3/L4kqtJl40Nr8X8gdRQBOFU

Get Object

GET /{bucket-name}/{object-key} HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response: 200 OK with object body and headers:

Content-Type: application/octet-stream
Content-Length: 1234
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Last-Modified: Mon, 01 Mar 2026 12:00:00 GMT

List Objects

GET /{bucket-name}?list-type=2&prefix=path/&max-keys=1000 HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response:

<ListBucketResult>
  <Name>my-bucket</Name>
  <Prefix>path/</Prefix>
  <KeyCount>2</KeyCount>
  <Contents>
    <Key>path/file1.txt</Key>
    <LastModified>2026-03-01T12:00:00.000Z</LastModified>
    <Size>1024</Size>
    <ETag>"abc123"</ETag>
  </Contents>
  <Contents>
    <Key>path/file2.txt</Key>
    <LastModified>2026-03-01T12:05:00.000Z</LastModified>
    <Size>2048</Size>
    <ETag>"def456"</ETag>
  </Contents>
</ListBucketResult>

Delete Object

DELETE /{bucket-name}/{object-key} HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response: 204 No Content

Copy Object

PUT /{bucket-name}/{dest-key} HTTP/1.1
Host: storage.yourdomain.com
x-amz-copy-source: /source-bucket/source-key
Authorization: AWS4-HMAC-SHA256 Credential=...

Response: 200 OK with copy metadata in XML body.

Multipart Upload

For large files (>100MB), use multipart upload for better throughput and resumability.

Initiate Multipart Upload

POST /{bucket-name}/{object-key}?uploads HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response:

<InitiateMultipartUploadResult>
  <Bucket>my-bucket</Bucket>
  <Key>large-file.zip</Key>
  <UploadId>upload-id-abc123</UploadId>
</InitiateMultipartUploadResult>

Upload Part

PUT /{bucket-name}/{object-key}?partNumber=1&uploadId=upload-id-abc123 HTTP/1.1
Host: storage.yourdomain.com
Content-Length: 5242880
Authorization: AWS4-HMAC-SHA256 Credential=...

[binary part data]

Response: 200 OK with ETag header. Store the ETag for the complete step.

Complete Multipart Upload

POST /{bucket-name}/{object-key}?uploadId=upload-id-abc123 HTTP/1.1
Host: storage.yourdomain.com
Content-Type: application/xml
Authorization: AWS4-HMAC-SHA256 Credential=...

<CompleteMultipartUpload>
  <Part>
    <PartNumber>1</PartNumber>
    <ETag>"etag1"</ETag>
  </Part>
  <Part>
    <PartNumber>2</PartNumber>
    <ETag>"etag2"</ETag>
  </Part>
</CompleteMultipartUpload>

Abort Multipart Upload

DELETE /{bucket-name}/{object-key}?uploadId=upload-id-abc123 HTTP/1.1
Host: storage.yourdomain.com
Authorization: AWS4-HMAC-SHA256 Credential=...

Response: 204 No Content

Presigned URLs

Generate time-limited URLs for upload or download without exposing credentials.

Request (via API):

curl -X POST https://api.yourdomain.com/v1/presigned-url \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "my-bucket",
    "key": "documents/report.pdf",
    "method": "GET",
    "expires_in": 3600
  }'

Response:

{
  "url": "https://storage.yourdomain.com/my-bucket/documents/report.pdf?X-Amz-Algorithm=...&X-Amz-Credential=...&X-Amz-Date=...&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=...",
  "expires_at": "2026-03-01T13:00:00Z"
}

JavaScript (AWS SDK):

const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
const { GetObjectCommand } = require('@aws-sdk/client-s3');

const url = await getSignedUrl(client, new GetObjectCommand({
  Bucket: 'my-bucket',
  Key: 'documents/report.pdf',
}), { expiresIn: 3600 });

Versioning Endpoints

OperationMethodEndpoint
Get object versionGET/{bucket}/{key}?versionId={id}
List object versionsGET/{bucket}?versions&prefix={prefix}
Delete object versionDELETE/{bucket}/{key}?versionId={id}

Next Steps