Upload an asset

Upload a file and keep it with your organization, ready to use behind an object, a template or a face. Send it as `multipart/form-data`, with the file itself in the `file` part. **What you can upload.** Images (`gif`, `jpeg`, `png`, `webp`), PDFs, JSON and plain text, up to 10 MiB. The kind of file is worked out from its own contents, not from the type your client claims, so anything else comes back as `400`. One consequence worth knowing: an SVG or an HTML page counts as plain text, is stored as plain text, and cannot run as a page. **Where it goes.** Choose `gcs` for ordinary storage, or `ipfs` to publish the file to the InterPlanetary File System, where its address is permanent and anyone who has it can read the file. The choice is fixed once the file is uploaded. **Who can see it.** Private is the default: the file is reachable only through a download link that expires. Set `is_public` to make it readable by anyone with the address. Files published to IPFS have to be public, so a private IPFS upload comes back as `400`. Requires the `storage.create` permission.

POST
/assets
AuthorizationBearer <token>

The access token returned after a successful sign-in, sent as Authorization: Bearer <access_token>.

It identifies the person and the organization they are working in, and it lasts about fifteen minutes. When it runs out, use their refresh token at POST /auth/refresh-token instead of asking them to sign in again.

In: header

Request Body

multipart/form-data

The file and its metadata.

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://api.dual.network/assets" \  -F file="<binary PNG data>" \  -F provider="gcs" \  -F is_public="false" \  -F tag="event-poster"
{
  "id": "665f1c2d4b1a2c3d4e5f6a10",
  "name": "poster.png",
  "tag": "default",
  "provider": "gcs",
  "folder": "assets",
  "wallet_id": "665f1c2d4b1a2c3d4e5f6a01",
  "url": "https://storage.googleapis.com/example-bucket/665f.../assets/665f1c2d4b1a2c3d4e5f6a10",
  "path": "665f1c2d4b1a2c3d4e5f6aa0/assets/665f1c2d4b1a2c3d4e5f6a10",
  "size": 184320,
  "type": "image/png",
  "hash": "9a0f2c1b7d4e5f60718293a4b5c6d7e8",
  "is_public": false,
  "when_created": "2026-02-14T08:03:00Z"
}
{
  "code": 3,
  "message": "Key: 'limit' Error:Field validation for 'limit' failed on the 'lte' tag"
}

{
  "code": 16,
  "message": "no auth provided"
}

{
  "code": 13,
  "message": "internal error"
}
{
  "code": 13,
  "message": "internal error"
}