Skip to Content
We are live but in Staging 🎉
Object StorageS3 Compatibility

S3 Compatibility

K3’s HTTP gateway speaks native S3 on the byte plane. Point any S3 SDK at it with your Dodil service-account credentials and existing code works — aws s3 sync, boto3.client('s3'), @aws-sdk/client-s3, MinIO mc — no code changes beyond the endpoint URL.

What this page covers: credentials, supported operations, auth modes, and end-to-end setup for the four most common clients.

Credentials & endpoint

Single source of credentials: your Dodil service account. The same <service_account_id> / <service_account_secret> pair you pass to dodil login doubles as your S3 access-key / secret-key — both are issued by Dodil IAM.

Value
Endpoint (staging)https://k3.dev.dodil.io
Endpoint (production)https://k3.dodil.io
Access key IDyour Dodil <service_account_id>
Secret access keyyour Dodil <service_account_secret>
Regionany string (e.g. us-east-1) — must be consistent client-side, K3 derives the signing key from whatever scope you send
Addressing stylepath-style only — virtual-host style (<bucket>.k3.dev.dodil.io) is not routed

Bearer JWT also works on the byte plane (see Auth modes below) if you don’t have SigV4 credentials handy — but SigV4 is what every standard S3 SDK speaks.

Setup — pick your client

# One-time configuration aws configure --profile dodil-k3 # AWS Access Key ID: <service_account_id> # AWS Secret Access Key: <service_account_secret> # Default region name: us-east-1 # Default output format: json # Test aws s3 ls \ --endpoint-url https://k3.dev.dodil.io \ --profile dodil-k3

Drop the per-command flags by exporting them once:

export AWS_PROFILE=dodil-k3 export AWS_ENDPOINT_URL=https://k3.dev.dodil.io # aws-cli v2.15+ aws s3 ls aws s3 cp ./hello.txt s3://kb-prod/greetings/hello.txt

What’s supported

K3 implements the S3 surface needed for production object storage and ingest. Anything not in the tables below is out of scope — K3 does not currently support object versioning, lifecycle / expiration policies, replication, SQS/SNS event notifications, customer-managed encryption keys, or object lock.

Object operations

S3 actionWire shapeSupportedNotes
PutObjectPUT /:bucket/:keyTriggers ingest discovery on success — see Pipelines
GetObjectGET /:bucket/:keyRange header supported
HeadObjectHEAD /:bucket/:key
DeleteObjectDELETE /:bucket/:keyCleans up downstream pipeline indexes
DeleteObjects (bulk)POST /:bucket?delete
ListObjectsV2GET /:bucket?list-type=2prefix / delimiter / continuation-token / max-keys
CreateMultipartUploadPOST /:bucket/:key?uploads
UploadPartPUT /:bucket/:key?partNumber&uploadId
CompleteMultipartUploadPOST /:bucket/:key?uploadIdTriggers ingest discovery
AbortMultipartUploadDELETE /:bucket/:key?uploadId
ListMultipartUploadsGET /:bucket?uploads

Bucket operations

S3 actionWire shapeSupportedNotes
CreateBucketPUT /:bucketEquivalent to CreateBucket admin RPC
DeleteBucketDELETE /:bucketBucket must be empty
ListBucketsGET /
HeadBucketHEAD /:bucket
PutBucketPolicy / GetBucketPolicy / DeleteBucketPolicy`PUTGETDELETE /:bucket?policy`
PutBucketCors / GetBucketCors / DeleteBucketCors`PUTGETDELETE /:bucket?cors`

Not supported

S3 actionWhy notWorkaround
PutBucketVersioning / object versionsNot in K3’s data modelUse explicit key versioning in object paths if needed
PutBucketLifecycleConfigurationNo lifecycle engineRoll your own expiration via Pipelines or scheduled cleanup
PutBucketNotificationConfiguration (SQS/SNS)Use K3’s native ingest planeDefine pipeline rules — every upload fires through them automatically
PutBucketReplicationSingle-region today
PutBucketEncryption (SSE-C, SSE-KMS w/ customer keys)All buckets are encrypted at rest at the backend levelCustomer-managed keys are roadmap
PutObjectAcl / GetObjectAcl (per-object ACL)K3 ACL is per-bucketUse Bucket Policy — same expressive power for S3 use cases
PutObjectLockConfiguration / retention / legal-holdNot implemented
Bucket / object taggingForwarded to backend, not validatedDon’t rely on it for production logic

Auth modes accepted on the byte plane

ModeHeader / query shapeWhen to use
SigV4 headerAuthorization: AWS4-HMAC-SHA256 Credential=…/yyyymmdd/<region>/s3/aws4_request,SignedHeaders=…,Signature=…Standard S3 SDKs — what every aws s3 / boto3 / @aws-sdk request sends
SigV4 query?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=…SDK-issued presigned URLs (aws s3 presign, generate_presigned_url, getSignedUrl)
SigV2 query?AWSAccessKeyId=&Signature=&Expires=Legacy clients that still use SigV2 presigning
Bearer JWTAuthorization: Bearer <token>Server-to-server when you already have a Dodil JWT — avoids the SigV4 dance
K3 token query?X-K3-Token=&X-K3-Expires=&X-K3-Org=URLs issued by GetObjectUrl — recommended for app-issued share links

Region from the credential scope (…/<yyyymmdd>/<region>/s3/aws4_request) is whatever the client picks — K3 derives the signing key from it, so any consistent region works.

End-to-end: aws-cli ↔ dodil k3

Objects uploaded via raw S3 are first-class K3 objects — admin RPCs see them, pipelines fire on them, presigned URLs work over them.

# 1. Create a bucket via S3 (equivalent to `dodil k3 bucket create`) aws s3 mb s3://kb-s3-demo # 2. Upload an object echo "hello from aws-cli" > hello.txt aws s3 cp hello.txt s3://kb-s3-demo/greetings/hello.txt # 3. Inspect via K3 admin — same object, enriched with ingest status dodil k3 object show greetings/hello.txt -b kb-s3-demo -o json # 4. Issue a K3-signed share URL (shorter than SigV4 presign) dodil k3 object url greetings/hello.txt -b kb-s3-demo --expires 3600

The takeaway: S3 in, K3 features out. You don’t have to choose a side — buckets are interoperable.

Error response shape

S3-style errors come back as XML on the byte plane (compatible with every S3 SDK), JSON envelope on the admin plane. The two most common byte-plane errors:

<!-- 403 — storage quota exhausted, ACL denial, or auth failure --> <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>AccessDenied</Code> <Message>access denied</Message> </Error>
<!-- 404 — bucket or key not found --> <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>NoSuchKey</Code> <Message>The specified key does not exist.</Message> </Error>

Standard SDKs surface these as typed exceptions (ClientError in boto3, S3ServiceException in the JS SDK). For admin RPCs (dodil k3 ... / gRPC), see Conventions for the JSON error envelope.

Next steps

  • Recipes — direct-from-browser upload, multipart for large files, static-site hosting
  • API Reference — gRPC + HTTP admin contracts
  • Pipelines — auto-indexing on upload (the K3-specific feature S3 doesn’t have)
  • Auth and Access — auth-mode internals