Upload API
Upload files to permanent Arweave storage via ArDrive Turbo.
Base URL: https://api.inkdprotocol.com
POST /v1/upload
Upload a file to Arweave. Returns a permanent ar:// content hash.
POST /v1/upload
Content-Type: multipart/form-dataNo payment required. Upload is free — you pay when pushing the version to the registry.
Request fields (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file | File | ✅ | The file to upload |
contentType | string | — | MIME type override. Defaults to detected type. |
Response
{
"arweaveHash": "ar://QmAbc123xyz...",
"url": "https://arweave.net/QmAbc123xyz...",
"bytes": 14336,
"contentType": "application/javascript"
}Example
curl -X POST https://api.inkdprotocol.com/v1/upload \
-F "file=@./dist/agent.js"{
"arweaveHash": "ar://QmAbc123xyz...",
"url": "https://arweave.net/QmAbc123xyz...",
"bytes": 14336,
"contentType": "application/javascript"
}Then push the version with the returned hash:
inkd version push --id 10 --hash ar://QmAbc123xyz --tag v1.0.0GET /v1/upload/price
Estimate the cost for a given file size before uploading.
GET /v1/upload/price?bytes=102400| Param | Type | Description |
|---|---|---|
bytes | number | File size in bytes |
{
"bytes": 102400,
"arweaveCost": "184000",
"markup": "36800",
"total": "220800",
"totalUsd": "$0.22"
}All USDC values use 6 decimals. total / 1e6 = USD amount.
| File size | Total cost |
|---|---|
| 1 KB | ~$0.0022 |
| 10 KB | ~$0.022 |
| 100 KB | ~$0.22 |
| 1 MB | ~$2.21 |
Rates adjust with Arweave network conditions. Always call this endpoint before showing a cost estimate to users.
Retrieving content
Once uploaded, content is permanently accessible:
# Public Arweave gateway
https://arweave.net/{txid}
# ar:// shorthand (resolved by compatible clients)
ar://QmAbc123xyz...Content is immutable — the same URL returns the same bytes forever.
SDK usage
The SDK handles upload automatically when you pass file to pushVersion:
import { ProjectsClient } from "@inkd/sdk"
const client = new ProjectsClient({ privateKey: process.env.INKD_PRIVATE_KEY! })
// Auto-upload + push in one call
await client.pushVersion({
projectId: 10,
file: "./dist/agent.js",
versionTag: "v1.0.0",
})
// Or upload separately and use the hash
const { arweaveHash } = await client.upload(
require("fs").readFileSync("./dist/agent.js"),
"application/javascript"
)
await client.pushVersion({ projectId: 10, arweaveHash, versionTag: "v1.0.0" })