Buckets & objects
List buckets and search their indexed objects.
List buckets
GET /v1/buckets returns every bucket in the key's workspace:
curl https://bucketpilot.io/api/v1/buckets \
-H "Authorization: Bearer $BUCKETPILOT_KEY"{
"buckets": [
{
"id": 12,
"name": "prod-data",
"awsBucketName": "acme-prod-data",
"region": "us-east-1",
"provider": "aws",
"objectCount": 48210,
"totalSizeBytes": 734003200000,
"indexStatus": "ready",
"indexedObjectCount": 48210,
"lastIndexedAt": "2026-07-15T04:12:09.000Z",
"createdAt": "2026-03-02T18:30:11.000Z"
}
]
}GET /v1/buckets/{id} returns one bucket in the same shape. provider is the hosting cloud — aws, r2 (Cloudflare R2), or gcs (Google Cloud Storage); R2 buckets report region auto.
Search objects
GET /v1/buckets/{id}/objects reads the search index (metadata only — key, size, storage class; never file contents), so the bucket must be indexed first. Results are paged.
| Parameter | Type | Description |
|---|---|---|
search | string | Text match on the key; * and ? work as wildcards (reports/*.csv). |
prefix | string | Limit to keys under a prefix. |
storageClass | string | e.g. STANDARD, GLACIER, DEEP_ARCHIVE. |
page, pageSize | integer | Pagination — default 50, max 200 per page. |
sortBy | string | key, size, or lastModified. |
sortDir | string | asc or desc. |
curl "https://bucketpilot.io/api/v1/buckets/12/objects?search=*.parquet&sortBy=size&sortDir=desc" \
-H "Authorization: Bearer $BUCKETPILOT_KEY"import requests
resp = requests.get(
"https://bucketpilot.io/api/v1/buckets/12/objects",
params={"search": "*.parquet", "sortBy": "size", "sortDir": "desc"},
headers={"Authorization": f"Bearer {KEY}"},
)
for obj in resp.json()["objects"]:
print(obj["key"], obj["size"]){
"objects": [
{
"key": "events/2026/06/day-30.parquet",
"size": 52428800,
"lastModified": "2026-07-01T00:14:55.000Z",
"etag": "\"9b2cf535f27731c974343645a3985328\"",
"storageClass": "STANDARD",
"contentType": "application/octet-stream"
}
],
"page": 1,
"pageSize": 50,
"totalCount": 1284
}Download objects
POST /v1/buckets/{id}/objects/download returns a short-lived presigned URL — your download comes straight from your own S3, BucketPilot never proxies the bytes. Send the object key in the body; expiresIn (seconds, 60–86400, default 3600) and versionId are optional.
curl -X POST https://bucketpilot.io/api/v1/buckets/12/objects/download \
-H "Authorization: Bearer $BUCKETPILOT_KEY" \
-H "Content-Type: application/json" \
-d '{ "key": "reports/2026/june.csv", "expiresIn": 600 }'{
"downloadUrl": "https://acme-prod-data.s3.us-east-1.amazonaws.com/reports/2026/june.csv?X-Amz-...",
"key": "reports/2026/june.csv",
"expiresAt": "2026-07-16T10:24:03.000Z"
}The URL carries Content-Disposition: attachment, so fetching it saves the file rather than rendering it.
Trigger indexing
Needs a read/write key. POST /v1/buckets/{id}/index starts (or resumes) building the search index — the same operation as Index this bucket in the app, with the same guardrails: it returns 403 INDEX_LIMIT_REACHED if your plan's indexed-object allowance is used up, 409 LARGE_BUCKET for very large scan-mode buckets (pass ?force=true to scan anyway, or switch the bucket to daily inventory indexing in the app), and 409 if an index job is already running. Add ?fresh=true to rebuild from scratch instead of resuming a checkpoint.
curl -X POST "https://bucketpilot.io/api/v1/buckets/12/index" \
-H "Authorization: Bearer $BUCKETPILOT_KEY"Returns 202 { "status": "indexing" }; poll GET /v1/buckets/{id} for indexStatus to become ready.
Object metadata, tags & versions
Read a single object's details live from your storage — no index needed:
- •
GET /v1/buckets/{id}/objects/metadata?key=…— size, content type, etag, last-modified, storage class, version id, and any user metadata. Add&versionId=…for a specific version. - •
GET /v1/buckets/{id}/objects/tags?key=…— the object's tag set. - •
GET /v1/buckets/{id}/objects/versions?prefix=…— object versions and delete markers (passmaxKeys≤ 1000, andkeyMarker/versionIdMarkerfrom the previous page to continue).
curl "https://bucketpilot.io/api/v1/buckets/12/objects/metadata?key=reports/2026/june.csv" \
-H "Authorization: Bearer $BUCKETPILOT_KEY"Upload objects (read/write key)
Uploading is two steps, so the bytes go straight to your storage and never through BucketPilot. Needs a read/write key.
- 1.
POST /v1/buckets/{id}/objects/uploadwith the target key (and optionalcontentType) returns a short-lived presigneduploadUrl. - 2.
PUTyour file to that URL. - 3.
POST /v1/buckets/{id}/objects/confirmwith the same key so BucketPilot indexes it — now it shows up in listings and cost.
# 1. get a presigned upload URL
UP=$(curl -s -X POST https://bucketpilot.io/api/v1/buckets/12/objects/upload \
-H "Authorization: Bearer $BUCKETPILOT_KEY" -H "Content-Type: application/json" \
-d '{ "key": "reports/2026/july.csv", "contentType": "text/csv" }')
# 2. PUT the bytes to the returned uploadUrl
curl -X PUT -T ./july.csv -H "Content-Type: text/csv" "$(echo "$UP" | jq -r .uploadUrl)"
# 3. confirm so it's indexed
curl -X POST https://bucketpilot.io/api/v1/buckets/12/objects/confirm \
-H "Authorization: Bearer $BUCKETPILOT_KEY" -H "Content-Type: application/json" \
-d '{ "key": "reports/2026/july.csv" }'Delete, copy, folders, tags & storage class (read/write key)
All need a read/write key. Each keeps the search index in sync automatically.
- •Delete —
POST /v1/buckets/{id}/objects/deletewith{ "keys": ["a.txt", "b/c.txt"] }(up to 1000). Returns{ deleted, errors }. - •Copy / move —
POST /v1/buckets/{id}/objects/copywith{ "sourceKey", "destinationKey", "move": false }(same bucket; setmove: trueto delete the source). - •Create folder —
POST /v1/buckets/{id}/folderswith{ "name": "invoices", "prefix": "2026/" }. - •Set tags —
PUT /v1/buckets/{id}/objects/tagswith{ "key", "tags": [{ "key": "team", "value": "finance" }] }(replaces the whole set). - •Change storage class —
PUT /v1/buckets/{id}/objects/storage-classwith{ "key", "storageClass": "GLACIER_IR" }(STANDARD, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, GLACIER_IR, DEEP_ARCHIVE, REDUCED_REDUNDANCY).
curl -X POST https://bucketpilot.io/api/v1/buckets/12/objects/delete \
-H "Authorization: Bearer $BUCKETPILOT_KEY" -H "Content-Type: application/json" \
-d '{ "keys": ["tmp/old.log", "tmp/older.log"] }'A read-only key on any of these returns 403 READ_ONLY_KEY.