> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://api.docs.modulards.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api.docs.modulards.com/_mcp/server.

# Upload a file

POST https://api.modulards.com/api/public/v1/uploads
Content-Type: multipart/form-data

Uploads one file to attach to a task, and returns the id to send in the `files` of "Create tasks on websites" or "Update a task". A file that no task takes is removed automatically after one day, and there is no request to read an upload back.

Uploading needs its own permission, held by the same roles that can create tasks: your role must be allowed to upload files, otherwise the request answers 404. The request is limited to 20 per minute per token on top of the general limit.

**Body**
- `file` (file, required): sent as `multipart/form-data`, at most 6 MB, with one of the extensions `gif`, `jpeg`, `jpg`, `png`, `webp`, `tif` or `tiff`.

**Errors**
- **422**: `file` is missing, larger than 6 MB or has a disallowed extension.
- **429**: the 20-per-minute limit was reached.

Reference: https://api.docs.modulards.com/modular-ds-public-api/tasks/uploads/upload-a-file

## Authentication

- `Authorization` header (bearer token, required) — Personal access token created in the Modular DS dashboard; read-only tokens can only call GET endpoints.

## Request

### Body (multipart/form-data)

This endpoint expects a multipart form containing an optional file.

- `file` (file, optional) — Required. At most 6 MB. Allowed extensions: gif, jpeg, jpg, png, webp, tif, tiff.

## Response

### 201

201 Created

- `data` (ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaData, optional)
- `jsonapi` (ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaJsonapi, optional)

## Types

### ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaData

- `attributes` (ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaDataAttributes, optional)
- `id` (string, optional)
- `type` (string, optional)

### ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaJsonapi

- `version` (string, optional)

### ApiPublicV1UploadsPostResponsesContentApplicationJsonSchemaDataAttributes

- `mime_type` (string, optional)
- `name` (string, optional)
- `size` (double, optional)

## Examples

**Request**

```json
{
  "file": "<file: <file1>>"
}
```

**Response**

```json
{
  "data": {
    "attributes": {
      "mime_type": "image/png",
      "name": "invoice.png",
      "size": 48213
    },
    "id": "9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f",
    "type": "uploads"
  },
  "jsonapi": {
    "version": "1.1"
  }
}
```

**SDK Code**

```python 201 Created
import requests

url = "https://api.modulards.com/api/public/v1/uploads"

files = { "file": "open('<file1>', 'rb')" }
headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript 201 Created
const url = 'https://api.modulards.com/api/public/v1/uploads';
const form = new FormData();
form.append('file', '<file1>');

const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go 201 Created
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.modulards.com/api/public/v1/uploads"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby 201 Created
require 'uri'
require 'net/http'

url = URI("https://api.modulards.com/api/public/v1/uploads")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java 201 Created
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.modulards.com/api/public/v1/uploads")
  .header("Authorization", "Bearer <token>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php 201 Created
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.modulards.com/api/public/v1/uploads', [
  'multipart' => [
    [
        'name' => 'file',
        'filename' => '<file1>',
        'contents' => null
    ]
  ]
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp 201 Created
using RestSharp;

var client = new RestClient("https://api.modulards.com/api/public/v1/uploads");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift 201 Created
import Foundation

let headers = ["Authorization": "Bearer <token>"]
let parameters = [
  [
    "name": "file",
    "fileName": "<file1>"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.modulards.com/api/public/v1/uploads")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```