For the complete documentation index, see llms.txt. This page is also available as Markdown.

REST API

This page describes the REST surface exposed by antd 0.14.0. By default, antd listens on http://127.0.0.1:8082.

REST request and response bodies are JSON except for data streaming responses. Binary payloads use base64-encoded data fields; signed quotes and their commitment sidecars use the base64 fields described under Quote verification.

antd has no authentication. Loopback binding limits access to the local machine, but any process that can connect can invoke write, wallet, and local-filesystem endpoints. If you expose the listener on another interface, put a firewall or authenticated proxy in front of it. Configure Cross-Origin Resource Sharing (CORS) with an exact origin list, for example --cors http://127.0.0.1:8000. Bare --cors allows no origins; --cors '*' allows any webpage to call the API, including wallet endpoints, and is unsafe outside development. CORS does not restrict non-browser clients.

Handler responses include an x-request-id header that you can match with daemon logs. When CORS is enabled, preflight responses bypass that middleware and do not include the header.

The downloadable OpenAPI schema is incomplete for external signing: it omits multi-batch Merkle fields and incorrectly rejects public in-memory preparation. Use the request and response fields below rather than generating an external-signer client from that schema alone.

Limits

  • The maximum REST request body is 100 MiB. Base64 encoding and the surrounding JSON count toward this limit, so the maximum raw in-memory payload is smaller.

  • POST /v1/verify/quotes has its own 40 MiB request-body limit; see Verify Quotes.

  • Hex-decoded DataMaps are limited to 10 MiB on POST /v1/data/get, POST /v1/data/stream, and POST /v1/files/get.

  • File endpoints pass a local path rather than transferring file bytes through the REST body limit.

Health

Health Check

Endpoint: GET /health

Returns antd liveness, the selected network, and a live connectivity snapshot. HTTP 200 and status: "ok" do not mean that reads or writes will succeed.

Response:

All fields shown are always present; the counts and times are illustrative. On a local devnet, payment_token_address and payment_vault_address may be empty strings, and build_commit is empty when the binary was built outside a git checkout.

Field
Type
Meaning

write_ready

boolean

Best-effort connectivity signal: max(routing_table_size, connected_peers) >= rebootstrap_threshold. false signals degraded connectivity; true does not check wallet configuration or funds and does not guarantee storage

connected_peers

integer

Identity-verified live peer connections

routing_table_size

integer

Entries in the Kademlia DHT routing table

rebootstrap_threshold

integer

Routing-table floor for automatic peer rediscovery; 3

last_store_ok_secs_ago

integer or null

Seconds since the last successful data, file, or chunk write, or upload finalization, in this process; null until one succeeds. An all-already-stored finalization also updates this marker

Example:

Data

Store Public Data

Endpoint: POST /v1/data/public

Stores public data and returns the public address that can be shared with readers.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded payload

payment_mode

string

No

auto, merkle, or single

Response:

payment_mode_used reports the resolved mode, so a request using auto returns either single or merkle. chunks_stored counts the data chunks plus the DataMap chunk that antd stores separately to produce address.

Example:

Get Public Data

Endpoint: GET /v1/data/public/{addr}

Fetches public data by address.

Parameters:

Name
Type
Required
Description

addr

path

Yes

64-character hex data address

Response:

Example:

Stream Public Data

Endpoint: GET /v1/data/public/{addr}/stream

Streams a public object by address, decrypting one batch at a time instead of buffering the whole object into a JSON body. Use this for large objects. antd resolves nested DataMaps before opening the response so the byte length describes the plaintext object, not an intermediate serialized map. Resolution failures return an error before streaming begins.

The response framing depends on the Accept header:

  • Default (any Accept other than application/x-ndjson): a raw application/octet-stream body of the decrypted plaintext. The Content-Length header is set from the object's original size, so a client detects a failed download as a short read.

  • Accept: application/x-ndjson: newline-delimited JSON (NDJSON) frames, one JSON object per line, so the caller can drive a determinate progress bar. A leading {"type":"meta","total_size":<bytes>} frame is followed by interleaved {"type":"progress",...} and {"type":"data","chunk":"<base64>"} frames, and an {"type":"error","message":"..."} frame if the download fails partway. Each progress frame carries phase, fetched (chunks fetched so far), and total (chunks for the phase). The download starts from a resolved map, so no resolving_map progress is emitted; expect resolved and fetching phases. Treat an error frame as a failed download even if progress frames follow it.

Parameters:

Name
Type
Required
Description

addr

path

Yes

64-character hex data address

Example:

Store Private Data

Endpoint: POST /v1/data

Stores private data. The DataMap is returned to the caller and is not stored on-network.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded payload

payment_mode

string

No

auto, merkle, or single

Response:

payment_mode_used reports the resolved mode, so a request using auto returns either single or merkle.

Example:

Get Private Data

Endpoint: POST /v1/data/get

Retrieves private data using a caller-held DataMap. Uses POST so the hex-encoded DataMap (which can be many KB) goes in the request body rather than a URL query string.

Parameters:

Name
Type
Required
Description

data_map

string

Yes

Hex-encoded serialized DataMap

Response:

Example:

Stream Private Data

Endpoint: POST /v1/data/stream

Streams private data from a caller-held DataMap without buffering the complete plaintext in a JSON response. The response framing follows Stream Public Data: raw application/octet-stream by default, or NDJSON progress and data frames when the request accepts application/x-ndjson.

Parameters:

Name
Type
Required
Description

data_map

string

Yes

Hex-encoded serialized DataMap

Example:

Estimate Data Cost

Endpoint: POST /v1/data/cost

Returns an advisory storage and gas estimate for a data payload without uploading it. antd samples up to five chunk addresses spread across the payload and extrapolates from the first sample that returns live quotes. The gas value is a fixed heuristic, not a live gas-price query.

The response does not expose estimate confidence. If cost is "0" and chunk_count is greater than five, only the sampled chunks were known to be stored; unsampled chunks may still require payment. This endpoint also excludes the separate DataMap store performed by a public direct write, which POST /v1/data/public counts in chunks_stored.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded payload

payment_mode

string

No

auto, merkle, or single

Response:

payment_mode is the mode selected for the estimate, not the requested auto value.

Example:

Chunks

Store a Chunk

Endpoint: POST /v1/chunks

Stores a raw chunk.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded chunk bytes

Response:

The direct chunk-write path does not return its prepaid storage cost, so cost is always an empty string. Use an explicit data or file cost endpoint when you need an advisory estimate.

Example:

Get a Chunk

Endpoint: GET /v1/chunks/{addr}

Retrieves a raw chunk by address.

Parameters:

Name
Type
Required
Description

addr

path

Yes

64-character hex chunk address

Response:

Example:

Prepare a Single-Chunk Upload

Endpoint: POST /v1/chunks/prepare

Prepares one raw chunk for the external-signer flow. antd computes the chunk address, checks whether the chunk is already stored, and returns either the existing address or the payment details needed before finalizing.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded raw chunk bytes

include_signed_quotes

boolean

No

Defaults to false. Request signed quotes for offline verification when payment is required

Response:

When the chunk already exists on-network:

When payment is required, the default response is:

With include_signed_quotes: true, a payment-required response also includes the signed quote entries. An already-stored chunk response omits them, even when requested.

Example:

Finalize a Single-Chunk Upload

Endpoint: POST /v1/chunks/finalize

Stores a chunk prepared by POST /v1/chunks/prepare after the external signer has submitted the matching payment transaction. The prepare state lives only in the running antd process. It becomes eligible for cleanup after one hour, and the cleanup task runs every five minutes.

The first finalize attempt removes the prepared chunk before transaction hashes are parsed or the store is attempted. The upload_id cannot be retried, including after malformed hashes or a network failure; prepare the chunk again to obtain a new ID.

Parameters:

Name
Type
Required
Description

upload_id

string

Yes

Value returned by POST /v1/chunks/prepare

tx_hashes

object

Yes

Map of quote_hash to the transaction hash returned by the external payment

Response:

Example:

Files

These endpoints work on paths visible to the machine running antd.

Upload a Public File

Endpoint: POST /v1/files/public

Uploads a local file publicly. The data chunks and the DataMap chunk are paid for in one batch and stored on-network, and the response returns the DataMap's network address.

Parameters:

Name
Type
Required
Description

path

string

Yes

Local file path

payment_mode

string

No

auto, merkle, or single

Response:

storage_cost_atto, gas_cost_wei, and chunks_stored include the DataMap chunk, the same extra chunk that POST /v1/files/cost adds with is_public: true. payment_mode_used is the resolved single or merkle mode.

Example:

Download a Public File

Endpoint: POST /v1/files/public/get

Downloads a public file using its on-network DataMap address.

Parameters:

Name
Type
Required
Description

address

string

Yes

64-character hex on-network DataMap address

dest_path

string

Yes

Local destination path

Response: HTTP 200 OK with no JSON body

Example:

Upload a Private File

Endpoint: POST /v1/files

Uploads a local file privately. The DataMap is returned to the caller and is not stored on-network.

Parameters:

Name
Type
Required
Description

path

string

Yes

Local file path

payment_mode

string

No

auto, merkle, or single

Response:

payment_mode_used is the resolved single or merkle mode.

Example:

Download a Private File

Endpoint: POST /v1/files/get

Downloads a file using a caller-held DataMap (no address lookup required).

Parameters:

Name
Type
Required
Description

data_map

string

Yes

Hex-encoded serialized DataMap

dest_path

string

Yes

Local destination path

Response: HTTP 200 OK with no JSON body

Example:

Estimate File Cost

Endpoint: POST /v1/files/cost

Returns an advisory upload estimate for a local file. antd samples up to five data-chunk addresses spread across the file and extrapolates from the first sample that returns live quotes. The gas value is a fixed heuristic, not a live gas-price query.

With is_public: true, antd adds one DataMap chunk to chunk_count and approximates its storage cost from the sampled per-data-chunk price. It does not quote that DataMap chunk separately, so a public zero-cost estimate does not prove that the DataMap store is free. For a private estimate, zero is exact when every data chunk was sampled and already stored; if more than five data chunks exist, zero means only that every sample was already stored.

Parameters:

Name
Type
Required
Description

path

string

Yes

Local file path

is_public

boolean

No

Defaults to true; the equivalent gRPC field defaults to false

payment_mode

string

No

auto, merkle, or single

Response:

payment_mode is the mode selected for the estimate, not the requested auto value.

Example:

Wallet

Get Wallet Address

Endpoint: GET /v1/wallet/address

Returns the configured wallet address.

Response:

Example:

Get Wallet Balance

Endpoint: GET /v1/wallet/balance

Returns token and gas balances.

Response:

Example:

Approve Wallet Spend

Endpoint: POST /v1/wallet/approve

Approves token spend for payment contracts.

Parameters: None

Response:

Example:

External signer flow

Prepare a Data Upload

Endpoint: POST /v1/data/prepare

Prepares an in-memory data upload for external signing. This endpoint always returns the wave-batch payment shape, regardless of chunk count.

Parameters:

Name
Type
Required
Description

data

string

Yes

Base64-encoded payload

visibility

string

No

"private" (default) or "public". When "public", the serialized DataMap is bundled into the same external-signer payment batch and published on-network on finalize; data_map_address is then present in the finalize response.

include_signed_quotes

boolean

No

Defaults to false. Include signed wave-batch quotes and available commitment sidecars for offline verification

Response:

The response uses payment_type: "wave_batch".

File prepares can instead return this Merkle variant:

Each pool_commitments entry contains exactly 16 candidate payments. The example above abbreviates that repeated structure.

merkle_batches holds one entry per on-chain payment. A single Merkle tree covers up to 256 fresh chunks (roughly 1 GiB); a larger upload splits across several batches, and the external signer calls payForMerkleTree2() once per entry. The top-level depth, pool_commitments, and merkle_payment_timestamp are legacy single-batch fields, present only when merkle_batches has exactly one entry and mirroring that entry. They are omitted for a multi-batch upload, so read payment details from merkle_batches.

Both variants include total_chunks and already_stored_count. total_chunks is the full chunk count for the upload, including chunks already on-network; already_stored_count is how many of those were already stored and so excluded from payment and from the PUT. The difference between the two counts is why a prepared upload can cost less than the raw file size implies; use it for reconciliation only, and construct the payment from the returned payments or merkle_batches entries.

With include_signed_quotes: true, wave-batch prepares also return signed_quotes, containing the signed quote entries for the payments. This array is empty when no payment is needed. Without the opt-in, the field is omitted. Merkle prepares omit it even when requested.

Example:

Prepare a File Upload

Endpoint: POST /v1/upload/prepare

Prepares a file upload for external signing.

antd starts file uploads of 64 or more chunks on the Merkle path and smaller uploads on the wave-batch path. The initial selection is not final: when the already-stored preflight leaves fewer than 64 chunks to pay for, or too few Merkle-capable peers are reachable, antd prepares a wave-batch payment instead. Branch on the returned payment_type, not on the submitted chunk count.

Parameters:

Name
Type
Required
Description

path

string

Yes

Local file path

visibility

string

No

"private" (default) or "public". "public" bundles the serialized DataMap chunk into the same payment batch and stores it on-network; its address is returned on finalize via data_map_address.

include_signed_quotes

boolean

No

Defaults to false. Include signed quotes for wave-batch responses only; Merkle responses omit them

Response: The wave-batch or Merkle shape shown under POST /v1/data/prepare

Example:

Finalize an Upload

Endpoint: POST /v1/upload/finalize

Finalizes a prepared upload after the external signer has submitted the matching payment transaction.

Prepared state is held only by the running antd process; restarting it invalidates every upload_id. State becomes eligible for cleanup after one hour, with cleanup running every five minutes. Payment fields, including a transaction hash for every expected wave-batch quote, are validated before state is consumed, so a bad request leaves the paid-for upload in place and you can correct it and retry the same ID. Once validation succeeds, finalize consumes the prepared state and stores the chunks. A storage shortfall after payment returns PARTIAL_UPLOAD and, when its retryable flag is true, keeps the paid attempt under the same upload_id for a retry. Any other later failure, such as a payment-verification error or a failed store_data_map store, requires a new prepare call and payment reconciliation.

Parameters:

Name
Type
Required
Description

upload_id

string

Yes

Value returned by a prepare endpoint, or the same value again after a retryable PARTIAL_UPLOAD

tx_hashes

object

No

Wave-batch only: map of quote_hash to tx_hash

winner_pool_hashes

array

No

Merkle: one winner pool hash per entry in the prepare response's merkle_batches, in the same order. An empty string or null in a slot marks a batch the signer did not pay; keep unpaid slots in place rather than compacting or reordering the list

winner_pool_hash

string

No

Merkle, legacy single-batch: winner pool hash emitted by MerklePaymentMade. Accepted only when the upload has exactly one batch; do not combine it with winner_pool_hashes

store_data_map

boolean

No

If true, also stores the DataMap on-network

Provide tx_hashes when the prepare response returned payment_type: "wave_batch". When that response reported no payments because every chunk is already stored on the Autonomi Network, send an empty tx_hashes object; finalize completes without any on-chain payment. When it returned payment_type: "merkle", provide winner_pool_hashes with one hash per merkle_batches entry; a single-batch upload may instead provide winner_pool_hash.

Response:

address is only present when store_data_map is true; that path uses the wallet configured in antd to store the DataMap. data_map_address is only present when the upload was prepared with visibility:"public"; it is the Autonomi Network address of the bundled DataMap chunk whose payment was included in the same external-signer batch as the data chunks.

Examples:

Wave-batch upload where every chunk is already stored, so prepare reported no payments:

Multi-batch Merkle upload, one winner hash per merkle_batches entry:

When part of an upload stores but the rest is still unstored after retries, finalize returns 502 with the PARTIAL_UPLOAD code, machine-readable counts, and a retryable flag:

The stored chunks persist. Branch on code rather than the HTTP status, then on retryable:

  • retryable: true: antd keeps the payment proofs and the unstored chunks under the same upload_id. Repeat the same finalize request with that upload_id to store the remainder against the same on-chain payment. Do not prepare again or pay again. antd ignores tx_hashes, winner_pool_hash, and winner_pool_hashes on this resume, but still rejects a field that belongs to the other payment type. Bound the retry loop, because a persistent failure returns PARTIAL_UPLOAD on every call. The retained attempt is process-local: it becomes eligible for cleanup one hour after the partial upload is reported and is lost if antd restarts.

  • retryable: false: nothing was retained. A Merkle finalize returns this when one or more winner_pool_hashes slots are unpaid, because only a fully paid batch list takes the resumable path. Re-prepare the same content and finalize again to pay for and store only the missing remainder.

A partial upload is reported only when at least one Merkle batch was paid. When every winner_pool_hashes slot is empty, finalize returns 402 with the PAYMENT_REQUIRED code instead.

Quote verification

Use signed quotes to check payment details before paying through an external signer. Verification runs on an antd instance you trust, not the counterparty's instance. It does not need a wallet, contact the Autonomi Network, pay, store data, or consume an upload_id.

Signed quote entries

Opt in with include_signed_quotes: true on a data, file, or chunk prepare request. Each returned signed_quotes entry has these fields:

Name
Type
Description

quote_hash

string

Hex hash with 0x prefix; match it to the corresponding payments entry by hash, not array position

quote

string

Base64-encoded MessagePack signed quote; pass unchanged as signed_quote to verification

commitment_sidecar

string, optional

Base64-encoded MessagePack storage commitment, the signed record bound to the quote; omitted when unavailable or the quote does not bind one

Treat the serialized quote and sidecar as opaque bytes. A quote that binds a commitment fails verification without its matching sidecar. Merkle prepares do not expose signed quotes through this option. The Python antd and Node.js @withautonomi/antd 0.2.0 clients do not expose the opt-in or verification helpers; use these REST fields directly rather than assuming those packages provide matching methods.

Verify Quotes

Endpoint: POST /v1/verify/quotes

Checks each quote's hash, ML-DSA-65 signature, rewards address, and payment amount. The amount must equal three times the signed quote price. It also checks the storage-commitment binding and requires the price to match the pricing formula for the claimed committed-key count.

Parameters:

Name
Type
Required
Description

entries

array

Yes

Up to 1024 quote/payment entries; an empty array returns valid: false

Each entry contains:

Name
Type
Required
Description

quote_hash

string

Yes

32-byte hex hash from the payment entry

rewards_address

string

Yes

Hex payment recipient with 0x prefix

amount

string

Yes

Payment amount in atto tokens, as a decimal integer string

signed_quote

string

Yes

Unchanged quote from the matching signed quote entry

commitment_sidecar

string

Conditional

Unchanged sidecar; required when the quote binds a storage commitment

Limits:

  • At most 1024 entries per call.

  • Request bodies on this route are limited to 40 MiB. A larger body is rejected with 413 before it is parsed.

  • Per entry, a signed_quote longer than 21,848 base64 characters (16 KiB decoded) or a commitment_sidecar longer than 10,924 base64 characters (8 KiB decoded) receives a valid: false verdict without being decoded.

  • The endpoint has no authentication or rate limiting, like the wallet endpoints. Keep antd on loopback or behind your own access control.

Response: HTTP 200 with valid and an entries array in request order. Overall valid is true only for a nonempty array where every entry passes. Invalid quote contents produce per-entry false verdicts, not a successful payment authorization. More than 1024 entries returns 400 / BAD_REQUEST, and a body over 40 MiB returns 413; malformed request bodies and field types can receive framework rejection responses instead.

Each verdict contains:

Name
Type
Description

quote_hash

string

Echo of the submitted hash

valid

boolean

Whether every verification check passed

error

string, optional

First failed check; omitted when valid

timestamp_unix_secs

integer, optional

Signed quote timestamp in Unix seconds

content

string, optional

Chunk address as 64 hexadecimal characters

price

string, optional

Signed quote price in atto tokens, before the three-times payment multiplier

rewards_address

string, optional

Recipient claimed by the signed quote

committed_key_count

integer, optional

Claimed storage-commitment key count; zero for a quote without a commitment

pinned

boolean, optional

Whether the quote binds a storage commitment

Extracted fields can be present after decoding even if a later check fails. They are claims, not trusted values unless verification succeeds. Your application must separately enforce expiry, replay prevention, equality with the intended set of chunks, and limits on plausible key counts. A valid signature and pricing check alone do not authorize payment.

Example: Check the endpoint with an empty batch, without preparing or paying for an upload:

Expected response:

A deliberately malformed quote also returns HTTP 200, with a failed verdict:

Expected response:

These checks exercise empty and malformed input only; they do not demonstrate valid-signature verification or a paid upload.

Error codes

HTTP status
Handler code
Meaning
Resolution

400

BAD_REQUEST

Invalid base64, hex, DataMap, payment mode, visibility, payment fields, local path, or more than 1024 verification entries

Correct the request. Malformed JSON may instead receive a framework-generated rejection body. Invalid quote contents in /v1/verify/quotes return per-entry verdicts under HTTP 200

402

PAYMENT_REQUIRED

Payment failed or no Merkle batch was paid

Fund the configured wallet or submit the required external payment

404

NOT_FOUND

No DataMap is stored at the requested address, a chunk needed for retrieval is missing, or a prepared upload_id or in-memory chunk was not found

Confirm the address or DataMap, and check connected_peers in /health, because a lookup with no connected peers also returns NOT_FOUND. For an upload_id, prepare again if process-local state expired, was consumed, or was lost on restart

404

Framework response

No route matched the requested path

Correct the endpoint path

405

Framework response

The route does not support the HTTP method

Use the method documented for the endpoint

409

ALREADY_EXISTS

The requested record is already stored

Use the returned or computed content address instead of repeating the write

413

TOO_LARGE, or framework rejection

A handler rejected an in-memory operation, the request body exceeded 100 MiB, or a /v1/verify/quotes body exceeded 40 MiB

Use a file endpoint or reduce the request body

415

Framework response

A JSON endpoint did not receive Content-Type: application/json

Add the JSON content-type header

422

Framework response

JSON parsed but could not be converted to the endpoint's request fields

Check required fields and their types

500

INTERNAL_ERROR

Serialization, encryption, protocol, or internal task failure

Inspect the error message and match x-request-id with antd logs before retrying

501

NOT_IMPLEMENTED

The requested behavior is not implemented

Use a supported endpoint

502

NETWORK_ERROR

antd could not complete a network operation

Confirm peer connectivity and retry

502

PARTIAL_UPLOAD

Some chunks stored while others are still unstored after retries

Check retryable. When true, repeat the same external-signer finalize call with the same upload_id. When false, nothing was retained: retry the direct upload, or prepare the same content again and finalize to store only the remainder. The response includes chunks_stored, chunks_failed, total_chunks, and retryable

503

SERVICE_UNAVAILABLE

A direct write or wallet operation needs a wallet that is not configured in antd

Set AUTONOMI_WALLET_KEY, or use the external-signer prepare/finalize flow for writes

504

TIMEOUT

A network operation exceeded its deadline

Check connectivity and retry

Handler-generated errors always include a human-readable error and a machine-readable code:

A lookup of a well-formed public address with no stored DataMap returns 404:

A 404 does not prove that the data is absent: when antd has no connected peers, a lookup also returns NOT_FOUND. Check connected_peers in Health Check before treating the address as unused.

Prefer code over the HTTP status where they diverge. For example, PARTIAL_UPLOAD arrives as 502, the same status as NETWORK_ERROR. PARTIAL_UPLOAD also includes chunks_stored, chunks_failed, total_chunks, and retryable.

Last updated