Skip to main content

Publisher

The publisher stores a blob on behalf of a client that does not talk to the storage nodes: it encodes the data, pays the storage and the gas in IOTA with its own account, uploads the slivers, certifies the blob and sends the Blob object to the address the client chooses. It also stores quilts.

Base URL: https://publisher.iotastorage.com.

The public publisher requires a token

Since the publisher pays with its own IOTA, the public one requires a token (Authorization: Bearer <token>) and is used by the project. Without it, it answers 401 UNAUTHENTICATED.

To store your own data, use the app with your wallet, or the reference JavaScript client: you pay in IOTA and the Blob is yours from the start. Anyone can read the result through the public aggregator.

MethodPathBody
PUT/v1/blobs?<parameters>The bytes of the blob.
PUT/v1/quilts?<parameters>The files, as multipart/form-data.

Parameters​

ParameterDefaultMeaning
epochs1Epochs to store the blob: an integer from 1 to 53.
deletable=trueStore a deletable blob (the default).
permanent=trueStore a permanent blob, which cannot be deleted. Not together with deletable=true.
send_object_tothe publisherIOTA address (0x…) that receives the Blob object. Without it, the Blob stays in the publisher's account.

Store a blob​

curl -X PUT "https://publisher.iotastorage.com/v1/blobs?epochs=5&send_object_to=0x<your address>" \
-H "Authorization: Bearer $TOKEN" \
--upload-file file

The answer describes the new Blob. For example, for a 1 MiB file stored for 5 epochs from epoch 1:

{
"newlyCreated": {
"blobObject": {
"id": "0x…",
"registeredEpoch": 1,
"blobId": "<blob ID>",
"size": 1048576,
"encodingType": "RS2",
"certifiedEpoch": 1,
"storage": {
"id": "0x…",
"startEpoch": 1,
"endEpoch": 6,
"storageSize": 5309400
},
"deletable": true
},
"resourceOperation": {
"registerFromScratch": { "encodedLength": 5309400, "epochsAhead": 5 }
},
"cost": 42000
}
}
FieldMeaning
blobObject.idID of the Blob object on IOTA.
blobObject.blobIdThe blob ID, to read it through the aggregator.
blobObject.sizeSize of the original data, in bytes.
blobObject.storageThe Storage resource: epochs and encoded size reserved.
resourceOperation.registerFromScratch.encodedLengthEncoded size that was paid for.
costWhat the contract charged for storage, in nanos of IOTA (gas not included).

Store a quilt​

PUT /v1/quilts stores several files as one quilt. The body is multipart/form-data:

  • each field is a file, and the field name is its identifier in the quilt (it cannot start with _);
  • an optional _metadata field holds a JSON list of { "identifier", "tags" } with text tags for some of the files.
curl -X PUT "https://publisher.iotastorage.com/v1/quilts?epochs=5" \
-H "Authorization: Bearer $TOKEN" \
-F "index.html=@index.html" \
-F "logo.svg=@logo.svg" \
-F '_metadata=[{"identifier": "logo.svg", "tags": {"kind": "image"}}]'
{
"blobStoreResult": {
"newlyCreated": { "blobObject": { … }, "resourceOperation": { … }, "cost": … }
},
"storedQuiltBlobs": [
{ "identifier": "index.html", "quiltPatchId": "<quilt patch ID>" },
{ "identifier": "logo.svg", "quiltPatchId": "<quilt patch ID>" }
]
}

Each file can then be read through the aggregator by its quilt patch ID. With 100 shards a quilt holds up to 66 files.

Limits and behavior​

  • At most 10 MiB per request (blob or whole quilt body); the network accepts blobs up to about 142 MiB through other clients. Empty blobs are rejected.
  • Writes are processed one at a time, since they all pay with the publisher's coins.
  • There is no alreadyCertified answer: every PUT registers a new Blob, even for data that is already stored.
  • CORS is enabled, with the authorization and content-type request headers allowed.

Errors​

Same JSON format as the aggregator:

CodestatusWhen
400INVALID_ARGUMENTInvalid epochs, permanent together with deletable, invalid send_object_to, empty blob, malformed multipart body or _metadata.
401UNAUTHENTICATEDMissing or wrong token.
405METHOD_NOT_ALLOWEDWrong method, or a server that only reads.
413PAYLOAD_TOO_LARGELarger than the publisher's limit or the network's largest blob.