- Docs
- Api%2Freference%2Fstorage%2FCreateAsset
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.
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"
}