> 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.

# Create tasks on websites

POST https://api.modulards.com/api/public/v1/site-tasks
Content-Type: application/json

Logs the same task on each website you list in `sites`, up to 50. Use it to record work such as "renewed the SSL certificate" on every website it touched. One task is created for each website.

Websites that cannot be processed are reported in `meta.skipped`, each with a `reason_code` and a message, and do not fail the call. Only a website your token cannot reach is skipped (`PERMISSION_DENIED`, with a null `site_name`), because a task does not need a connected website. When every website was skipped, the answer is `200` with an empty list instead of `201`.

Attached files are moved onto the first task created. Every other task receives its own copy a few seconds later. A file that could not be attached is reported in `meta.warnings` and does not fail the call. The answer does not include the attachments: read a task with "Retrieve a task" and `include=files` to see them.

Your role must be allowed to create tasks; without it the request answers 404.

**Body**

* `sites` (array of integers, required): ids of the websites to act on, 1 to 50.
* `title` (string, required): at most 255 characters.
* `date` (string, required): the day the work happened, as `YYYY-MM-DD`.
* `content` (string, optional): what was done, as HTML. It is cleaned on the server and holds at most 2500 characters once tags are stripped.
* `time_spent` (number, optional): minutes spent, decimals allowed, 0 or more.
* `is_pending` (boolean, optional): `false` when omitted.
* `files` (array, optional): up to 4 entries of `{uuid, name}`. `uuid` is the id returned by "Upload a file" (the only source a new task can take files from); `name` is an optional display name of at most 255 characters.

**Errors**

* **422**: `sites` is missing, empty, has more than 50 ids, repeats an id or contains an id that is not a website; `title` or `date` is missing; a `files.*.uuid` is unknown or was not uploaded by you.

Reference: https://api.docs.modulards.com/modular-ds-public-api/tasks/website-tasks/create-tasks-on-websites

## 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 (application/json)

This endpoint expects an object.

- `content` (string, optional)
- `date` (string, optional)
- `files` (list of ApiPublicV1SiteTasksPostRequestBodyContentApplicationJsonSchemaFilesItems, optional)
- `is_pending` (boolean, optional)
- `sites` (list of double, optional)
- `time_spent` (double, optional)
- `title` (string, optional)

## Response

### 200

200 OK - every website was skipped

- `data` (list of any, optional)
- `jsonapi` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaJsonapi, optional)
- `meta` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaMeta, optional)

### 201

201 Created - one task logged, one website skipped

- `data` (list of ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItems, optional)
- `jsonapi` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaJsonapi, optional)
- `meta` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaMeta, optional)

## Types

### ApiPublicV1SiteTasksPostRequestBodyContentApplicationJsonSchemaFilesItems

- `name` (string, optional)
- `uuid` (string, optional)

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaJsonapi

- `version` (string, optional)

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaMeta

- `skipped` (list of ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaMetaSkippedItems, optional)
- `warnings` (list of string, optional) — Sentence for each attached file that could not be attached; present only when there is one.

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItems

- `attributes` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItemsAttributes, optional)
- `id` (string, optional)
- `links` (ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItemsLinks, optional)
- `type` (string, optional)

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaMetaSkippedItems

- `message` (string, optional) — Sentence explaining the reason.
- `reason_code` (string, optional) — Why it was skipped, for example `PERMISSION_DENIED`.
- `site_id` (integer, optional, nullable) — Id of the website that was skipped; null when the entry is not about a website.
- `site_name` (string, optional, nullable) — Name of the skipped website, when known.
- `site_task_id` (integer, optional, nullable) — Always null for a skipped website: no task was created.

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItemsAttributes

- `content` (string, optional)
- `created_at` (string, optional)
- `date` (string, optional)
- `is_pending` (boolean, optional)
- `site_id` (double, optional)
- `time_spent` (double, optional)
- `title` (string, optional)
- `updated_at` (string, optional)

### ApiPublicV1SiteTasksPostResponsesContentApplicationJsonSchemaDataItemsLinks

- `self` (string, optional)

## Examples

### 200 OK - every website was skipped

**Response**

```json
{
  "data": [],
  "jsonapi": {
    "version": "1.1"
  },
  "meta": {
    "skipped": [
      {
        "message": "Website 13 is outside your access; it was not touched.",
        "reason_code": "PERMISSION_DENIED",
        "site_id": 13,
        "site_name": null,
        "site_task_id": null
      }
    ]
  }
}
```

**SDK Code**

```python 200 OK - every website was skipped
import requests

url = "https://api.modulards.com/api/public/v1/site-tasks"

headers = {"Authorization": "Bearer <token>"}

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

print(response.json())
```

```javascript 200 OK - every website was skipped
const url = 'https://api.modulards.com/api/public/v1/site-tasks';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

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

```go 200 OK - every website was skipped
package main

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

func main() {

	url := "https://api.modulards.com/api/public/v1/site-tasks"

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

	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 200 OK - every website was skipped
require 'uri'
require 'net/http'

url = URI("https://api.modulards.com/api/public/v1/site-tasks")

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

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

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

```java 200 OK - every website was skipped
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.modulards.com/api/public/v1/site-tasks")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php 200 OK - every website was skipped
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.modulards.com/api/public/v1/site-tasks', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

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

```csharp 200 OK - every website was skipped
using RestSharp;

var client = new RestClient("https://api.modulards.com/api/public/v1/site-tasks");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift 200 OK - every website was skipped
import Foundation

let headers = ["Authorization": "Bearer <token>"]

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

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()
```

### 201 Created - one task logged, one website skipped

**Response**

```json
{
  "data": [
    {
      "attributes": {
        "content": "<p>Renewed the certificate through the hosting panel.</p>",
        "created_at": "2026-09-17T09:00:00.000000Z",
        "date": "2026-09-17",
        "is_pending": false,
        "site_id": 12,
        "time_spent": 30,
        "title": "Renew the SSL certificate",
        "updated_at": "2026-09-17T09:00:00.000000Z"
      },
      "id": "501",
      "links": {
        "self": "{{base_url}}/api/public/v1/site-tasks/501"
      },
      "type": "site-tasks"
    }
  ],
  "jsonapi": {
    "version": "1.1"
  },
  "meta": {
    "skipped": [
      {
        "message": "Website 13 is outside your access; it was not touched.",
        "reason_code": "PERMISSION_DENIED",
        "site_id": 13,
        "site_name": null,
        "site_task_id": null
      }
    ]
  }
}
```

**SDK Code**

```python 201 Created - one task logged, one website skipped
import requests

url = "https://api.modulards.com/api/public/v1/site-tasks"

headers = {"Authorization": "Bearer <token>"}

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

print(response.json())
```

```javascript 201 Created - one task logged, one website skipped
const url = 'https://api.modulards.com/api/public/v1/site-tasks';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

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

```go 201 Created - one task logged, one website skipped
package main

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

func main() {

	url := "https://api.modulards.com/api/public/v1/site-tasks"

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

	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 - one task logged, one website skipped
require 'uri'
require 'net/http'

url = URI("https://api.modulards.com/api/public/v1/site-tasks")

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

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

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

```java 201 Created - one task logged, one website skipped
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.modulards.com/api/public/v1/site-tasks")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php 201 Created - one task logged, one website skipped
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.modulards.com/api/public/v1/site-tasks', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

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

```csharp 201 Created - one task logged, one website skipped
using RestSharp;

var client = new RestClient("https://api.modulards.com/api/public/v1/site-tasks");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift 201 Created - one task logged, one website skipped
import Foundation

let headers = ["Authorization": "Bearer <token>"]

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

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()
```

### Create tasks on websites

**Request**

```json
{
  "content": "Renewed the certificate through the hosting panel.",
  "date": "2026-09-17",
  "files": [
    {
      "name": "invoice.png",
      "uuid": "9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f"
    }
  ],
  "is_pending": false,
  "sites": [
    12,
    13
  ],
  "time_spent": 30,
  "title": "Renew the SSL certificate"
}
```

**Response**

```json
{
  "data": [],
  "jsonapi": {
    "version": "1.1"
  },
  "meta": {
    "skipped": [
      {
        "message": "Website 13 is outside your access; it was not touched.",
        "reason_code": "PERMISSION_DENIED",
        "site_id": 13,
        "site_name": null,
        "site_task_id": null
      }
    ]
  }
}
```

**SDK Code**

```python Create tasks on websites
import requests

url = "https://api.modulards.com/api/public/v1/site-tasks"

payload = {
    "content": "Renewed the certificate through the hosting panel.",
    "date": "2026-09-17",
    "files": [
        {
            "name": "invoice.png",
            "uuid": "9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f"
        }
    ],
    "is_pending": False,
    "sites": [12, 13],
    "time_spent": 30,
    "title": "Renew the SSL certificate"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Create tasks on websites
const url = 'https://api.modulards.com/api/public/v1/site-tasks';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"content":"Renewed the certificate through the hosting panel.","date":"2026-09-17","files":[{"name":"invoice.png","uuid":"9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f"}],"is_pending":false,"sites":[12,13],"time_spent":30,"title":"Renew the SSL certificate"}'
};

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

```go Create tasks on websites
package main

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

func main() {

	url := "https://api.modulards.com/api/public/v1/site-tasks"

	payload := strings.NewReader("{\n  \"content\": \"Renewed the certificate through the hosting panel.\",\n  \"date\": \"2026-09-17\",\n  \"files\": [\n    {\n      \"name\": \"invoice.png\",\n      \"uuid\": \"9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f\"\n    }\n  ],\n  \"is_pending\": false,\n  \"sites\": [\n    12,\n    13\n  ],\n  \"time_spent\": 30,\n  \"title\": \"Renew the SSL certificate\"\n}")

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

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

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

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

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

}
```

```ruby Create tasks on websites
require 'uri'
require 'net/http'

url = URI("https://api.modulards.com/api/public/v1/site-tasks")

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

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"content\": \"Renewed the certificate through the hosting panel.\",\n  \"date\": \"2026-09-17\",\n  \"files\": [\n    {\n      \"name\": \"invoice.png\",\n      \"uuid\": \"9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f\"\n    }\n  ],\n  \"is_pending\": false,\n  \"sites\": [\n    12,\n    13\n  ],\n  \"time_spent\": 30,\n  \"title\": \"Renew the SSL certificate\"\n}"

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

```java Create tasks on websites
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.modulards.com/api/public/v1/site-tasks")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"content\": \"Renewed the certificate through the hosting panel.\",\n  \"date\": \"2026-09-17\",\n  \"files\": [\n    {\n      \"name\": \"invoice.png\",\n      \"uuid\": \"9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f\"\n    }\n  ],\n  \"is_pending\": false,\n  \"sites\": [\n    12,\n    13\n  ],\n  \"time_spent\": 30,\n  \"title\": \"Renew the SSL certificate\"\n}")
  .asString();
```

```php Create tasks on websites
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.modulards.com/api/public/v1/site-tasks', [
  'body' => '{
  "content": "Renewed the certificate through the hosting panel.",
  "date": "2026-09-17",
  "files": [
    {
      "name": "invoice.png",
      "uuid": "9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f"
    }
  ],
  "is_pending": false,
  "sites": [
    12,
    13
  ],
  "time_spent": 30,
  "title": "Renew the SSL certificate"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

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

```csharp Create tasks on websites
using RestSharp;

var client = new RestClient("https://api.modulards.com/api/public/v1/site-tasks");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"content\": \"Renewed the certificate through the hosting panel.\",\n  \"date\": \"2026-09-17\",\n  \"files\": [\n    {\n      \"name\": \"invoice.png\",\n      \"uuid\": \"9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f\"\n    }\n  ],\n  \"is_pending\": false,\n  \"sites\": [\n    12,\n    13\n  ],\n  \"time_spent\": 30,\n  \"title\": \"Renew the SSL certificate\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Create tasks on websites
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "content": "Renewed the certificate through the hosting panel.",
  "date": "2026-09-17",
  "files": [
    [
      "name": "invoice.png",
      "uuid": "9c6a0b1e-3f2d-4b7a-9e21-1a2b3c4d5e6f"
    ]
  ],
  "is_pending": false,
  "sites": [12, 13],
  "time_spent": 30,
  "title": "Renew the SSL certificate"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.modulards.com/api/public/v1/site-tasks")! 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()
```