Noma

Upload an Asset

Upload an Asset

Uploads a new file into the project asset library.

The HTTP path is POST /api/files. The body must be multipart/form-data with a single field file.

To set alt text, title, and other descriptive fields after upload, use Bulk Asset Operations (PATCH /api/files/bulk/metadata). The upload endpoint validates and stores the binary only; optional metadata fields some clients send alongside the file are not applied by this route.

Request

POST /api/files HTTP/1.1
Host: app.nomacms.com
project-id: <project-uuid>
Authorization: Bearer <api-token>
Accept: application/json
Content-Type: multipart/form-data; boundary=...

Requires the create ability on the token.

Form fields

FieldRequiredDescription
fileYesThe file to upload.

Limits (server defaults)

RuleValue
Allowed extensionsCommon image, video, audio, office, and text types (for example jpg, png, webp, pdf, mp4, mp3; full list is defined in the product configuration).

If validation fails, the API responds with 422 and a message / errors payload.

Response (201)

JSON object with the same fields as Get an Asset (one new asset).

Errors

StatusWhen
400Missing project-id or project cannot be resolved (see Authentication)
401Missing or invalid bearer token
403Token does not have create (or *)
404No project with that UUID
413Request body too large (for example reverse proxy or PHP limits below application validation)
422Validation failed (missing file, wrong MIME type, or size over limit)
429Rate limited

Example

import { createClient } from "@nomacms/js-sdk"
 
const client = createClient({
  projectId: process.env.NOMA_PROJECT_ID!,
  apiKey: process.env.NOMA_API_KEY!,
})
 
// Pass a browser `File` or Node `Buffer` — see /js-sdk/assets/
const created = await client.assets.upload(fileOrBuffer)
console.log(created)
import axios from "axios"
import FormData from "form-data"
import fs from "node:fs"
 
async function main() {
  const form = new FormData()
  form.append("file", fs.createReadStream("./photo.jpg"))
 
  const { data } = await axios.post("https://app.nomacms.com/api/files", form, {
    headers: {
      ...form.getHeaders(),
      "project-id": process.env.NOMA_PROJECT_ID!,
      Authorization: `Bearer ${process.env.NOMA_API_KEY}`,
      Accept: "application/json",
    },
    maxBodyLength: Infinity,
    maxContentLength: Infinity,
  })
  console.log(data)
}
 
void main()
<?php
 
$ch = curl_init('https://app.nomacms.com/api/files');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'project-id: ' . getenv('NOMA_PROJECT_ID'),
        'Authorization: Bearer ' . getenv('NOMA_API_KEY'),
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile(__DIR__ . '/photo.jpg'),
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
curl -sS -X POST \
  -H "project-id: $NOMA_PROJECT_ID" \
  -H "Authorization: Bearer $NOMA_API_KEY" \
  -H "Accept: application/json" \
  -F "file=@./photo.jpg" \
  "https://app.nomacms.com/api/files"
package main
 
import (
	"bytes"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)
 
func main() {
	var body bytes.Buffer
	writer := multipart.NewWriter(&body)
	part, _ := writer.CreateFormFile("file", "photo.jpg")
	f, _ := os.Open("photo.jpg")
	_, _ = io.Copy(part, f)
	_ = f.Close()
	_ = writer.Close()
 
	req, err := http.NewRequest("POST", "https://app.nomacms.com/api/files", &body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	req.Header.Set("project-id", os.Getenv("NOMA_PROJECT_ID"))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("NOMA_API_KEY"))
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	_, _ = io.Copy(os.Stdout, res.Body)
}
require "net/http"
require "uri"
 
uri = URI("https://app.nomacms.com/api/files")
req = Net::HTTP::Post.new(uri)
req["project-id"] = ENV.fetch("NOMA_PROJECT_ID")
req["Authorization"] = "Bearer #{ENV.fetch('NOMA_API_KEY')}"
req["Accept"] = "application/json"
 
form_data = [["file", File.open("photo.jpg")]]
req.set_form form_data, "multipart/form-data"
 
Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  puts http.request(req).body
end
import os
from pathlib import Path
import urllib.request
 
boundary = "----PythonFormBoundary7MA4YWxkTrZu0gW"
file_path = Path("photo.jpg")
body = (
    f"--{boundary}\r\n"
    f'Content-Disposition: form-data; name="file"; filename="{file_path.name}"\r\n'
    f"Content-Type: application/octet-stream\r\n\r\n".encode()
    + file_path.read_bytes()
    + f"\r\n--{boundary}--\r\n".encode()
)
req = urllib.request.Request(
    "https://app.nomacms.com/api/files",
    data=body,
    method="POST",
    headers={
        "project-id": os.environ["NOMA_PROJECT_ID"],
        "Authorization": f"Bearer {os.environ['NOMA_API_KEY']}",
        "Accept": "application/json",
        "Content-Type": f"multipart/form-data; boundary={boundary}",
    },
)
with urllib.request.urlopen(req) as res:
    print(res.read().decode())
  • Bulk Asset Operations - Multi-file upload and metadata updates
  • Get an Asset - Response shape
  • Authentication - Headers and abilities
  • JavaScript SDK - assets.upload

Search documentation

Find guides and reference pages