Skip to content

Objects service

/objects is Pantahub's content-addressed blob store — every artifact a device runs (kernels, system images, app squashfs files) is an object, identified by its sha256, stored in S3-compatible storage and served through pre-signed URLs so uploads and downloads never stream through the API. Concepts: Objects.

Upload flow

Three steps: register the object, fetch the signed PUT URL, upload the bytes directly to storage.

sh
FILE=myfile.squashfs
SIZE=$(stat -c%s "$FILE")
SHA=$(sha256sum "$FILE" | cut -d' ' -f1)

# 1. register
ID=$(curl -s -X POST https://api.pantahub.com/objects/ \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "{\"objectname\":\"$FILE\",\"size\":\"$SIZE\",\"sha256sum\":\"$SHA\"}" \
  | jq -r .id)

# 2. get the signed URLs (valid ~15 minutes)
PUTURL=$(curl -s https://api.pantahub.com/objects/$ID \
  -H "Authorization: Bearer $TOKEN" | jq -r '."signed-puturl"')

# 3. upload straight to storage
curl -s -X PUT --data-binary @"$FILE" "$PUTURL"

Registering a sha that already exists returns a 409 with the existing object — deduplication is the point of content addressing: a revision that reuses artifacts uploads nothing.

Download flow

The same GET /objects/<id> response carries a signed-geturl:

sh
GETURL=$(curl -s https://api.pantahub.com/objects/$ID \
  -H "Authorization: Bearer $TOKEN" | jq -r '."signed-geturl"')
curl -s -o "$FILE" "$GETURL"

Devices resolve the objects referenced by their trail steps the same way.

Storage backends

Where the bytes land is a server-side concern (self-hosting): production runs against real S3 (AWS credentials + PANTAHUB_S3PATH=production), while the dev deployments ship localstack or a plain local directory (PANTAHUB_STORAGE_DRIVER=local). The API is identical either way.

In practice you rarely call this service directly — pvr, the UI's Manage tab and the Apps flows register and upload objects for you.

Endpoint reference

Try any of these live in the API Reference:

EndpointReference
POST /objectsRegister object
GET /objectsList objects
GET /objects/{id}Get object + signed URLs
PUT /objects/{id}Update object
DELETE /objects/{id}Delete object