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

# List websites

GET https://api.modulards.com/api/public/v1/sites

Returns the websites your token can reach, ordered by name unless you sort otherwise. Use it to find websites by team, tag, connection state, WordPress or PHP version, or name, and to read the details of many websites at once.

A plain listing leaves out some attributes because they cost more to compute; ask for them with `fields[sites]`. To find out which websites are covered by Patch & Protect, filter with `filter[patchstack]` or read `has_patchstack`.

Reference: https://api.docs.modulards.com/modular-ds-public-api/websites/manage-websites/list-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

### Query parameters

- `page[number]` (string, optional) — Page to return, starting at 1. Default 1.
- `page[size]` (string, optional) — Number of websites per page, 1 to 50. Default 15.
- `sort` (string, optional) — Sort order: `name` (default, ascending), `created_at`, `is_favorite` (starred websites first with `-is_favorite`), `updatable_items_count` or `vulnerable_items_count`. Prefix with `-` for descending.
- `include` (string, optional) — Related records to embed, comma-separated: `team`, `tags`, `site_preset_backup`, `site_preset_uptime`, `site_preset_malware_scan`, `site_preset_broken_link`, `site_preset_patchstack`. The last five embed the settings the website uses for backups, Uptime Monitor, Malware Scanner, Broken Links Checker and Patch & Protect.
- `fields[sites]` (string, optional) — Attributes to return, comma-separated; only those are returned. These computed attributes are left out unless you name them: `note` (the private note), `is_favorite`, `updatable_items_count`, `vulnerable_items_count` and `has_patchstack` (whether Patch & Protect is switched on for the website).
- `filter[s]` (string, optional) — Free-text search on the website's name, slug or address.
- `filter[team][]` (string, optional) — Team ids. Several values match websites in any of these teams.
- `filter[tags][]` (string, optional) — Tag ids. Several values match websites carrying any of these tags.
- `filter[connected]` (string, optional) — `1` for websites whose connection works, `0` for websites that are not connected.
- `filter[patchstack]` (string, optional) — `1` for websites with Patch & Protect switched on, `0` for websites without it.
- `filter[core_version][]` (string, optional) — Exact WordPress versions, for example `6.8.1`. Several values match any of them.
- `filter[engine_version][]` (string, optional) — Exact PHP versions, for example `8.2.27`. Several values match any of them.
- `filter[alerts][]` (string, optional) — Notification configuration ids. Several values match websites associated with any of them.
- `filter[id][]` (string, optional) — Website ids. Several values match any of them.

## Response

### 200

200 - websites

- `data` (list of ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItems, optional)
- `jsonapi` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaJsonapi, optional)
- `links` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaLinks, optional)
- `meta` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaMeta, optional)

## Errors

### 403 Forbidden Error

403 Forbidden - Public API disabled / 403 Forbidden - Request quota used up

- `errors` (list of ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaErrorsItems, optional)
- `jsonapi` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaJsonapi, optional)

## Types

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItems

- `attributes` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItemsAttributes, optional)
- `id` (string, optional)
- `links` (ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItemsLinks, optional)
- `type` (string, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaJsonapi

- `version` (string, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaLinks

- `first` (string, optional)
- `last` (string, optional)
- `next` (any, optional, nullable)
- `prev` (any, optional, nullable)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaMeta

- `current_page` (double, optional)
- `from` (double, optional)
- `last_page` (double, optional)
- `links` (list of ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaMetaLinksItems, optional)
- `path` (string, optional)
- `per_page` (double, optional)
- `to` (double, optional)
- `total` (double, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaErrorsItems

- `detail` (string, optional)
- `status` (string, optional)
- `title` (string, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItemsAttributes

- `connection_status` (string, optional)
- `connector_version` (string, optional)
- `core_version` (string, optional)
- `created_at` (string, optional)
- `created_by` (double, optional)
- `db_engine` (string, optional)
- `db_engine_version` (string, optional)
- `deleted_at` (any, optional, nullable)
- `display_host` (string, optional)
- `ecommerce_engine` (string, optional, nullable)
- `ecommerce_version` (string, optional, nullable)
- `engine` (string, optional)
- `engine_version` (string, optional)
- `host` (string, optional)
- `is_connected` (boolean, optional)
- `is_main_site` (boolean, optional)
- `is_multisite` (boolean, optional)
- `locale` (string, optional)
- `name` (string, optional)
- `path` (any, optional, nullable)
- `provider` (string, optional)
- `scheme` (string, optional)
- `slug` (string, optional)
- `synced_at` (string, optional)
- `timezone` (string, optional)
- `updated_at` (string, optional)
- `uri` (string, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaDataItemsLinks

- `self` (string, optional)

### ApiPublicV1SitesGetResponsesContentApplicationJsonSchemaMetaLinksItems

- `active` (boolean, optional)
- `label` (string, optional)
- `url` (string, optional, nullable)

## Examples

**Response**

```json
{
  "data": [
    {
      "attributes": {
        "connection_status": "established",
        "connector_version": "3.4.2",
        "core_version": "6.6.2",
        "created_at": "2026-01-14T09:30:00.000000Z",
        "created_by": 42,
        "db_engine": "mysql",
        "db_engine_version": "8.0.36",
        "deleted_at": null,
        "display_host": "acme-corp.com",
        "ecommerce_engine": "woocommerce",
        "ecommerce_version": "9.2.3",
        "engine": "php",
        "engine_version": "8.3.10",
        "host": "acme-corp.com",
        "is_connected": true,
        "is_main_site": true,
        "is_multisite": false,
        "locale": "en_US",
        "name": "Acme Corp",
        "path": null,
        "provider": "wp",
        "scheme": "https",
        "slug": "acme-corp",
        "synced_at": "2026-09-16T08:12:00.000000Z",
        "timezone": "Europe/Madrid",
        "updated_at": "2026-09-16T08:12:00.000000Z",
        "uri": "https://acme-corp.com"
      },
      "id": "101",
      "links": {
        "self": "{{base_url}}/api/public/v1/sites/101"
      },
      "type": "sites"
    },
    {
      "attributes": {
        "connection_status": "lost",
        "connector_version": "3.4.1",
        "core_version": "6.6.1",
        "created_at": "2026-03-02T11:15:00.000000Z",
        "created_by": 42,
        "db_engine": "mysql",
        "db_engine_version": "8.0.36",
        "deleted_at": null,
        "display_host": "blog.acme-corp.com",
        "ecommerce_engine": null,
        "ecommerce_version": null,
        "engine": "php",
        "engine_version": "8.2.20",
        "host": "blog.acme-corp.com",
        "is_connected": false,
        "is_main_site": true,
        "is_multisite": false,
        "locale": "en_US",
        "name": "Acme Blog",
        "path": null,
        "provider": "wp",
        "scheme": "https",
        "slug": "acme-blog",
        "synced_at": "2026-09-10T21:05:00.000000Z",
        "timezone": "Europe/Madrid",
        "updated_at": "2026-09-10T21:05:00.000000Z",
        "uri": "https://blog.acme-corp.com"
      },
      "id": "102",
      "links": {
        "self": "{{base_url}}/api/public/v1/sites/102"
      },
      "type": "sites"
    }
  ],
  "jsonapi": {
    "version": "1.1"
  },
  "links": {
    "first": "{{base_url}}/api/public/v1/sites?page%5Bnumber%5D=1",
    "last": "{{base_url}}/api/public/v1/sites?page%5Bnumber%5D=1",
    "next": null,
    "prev": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "active": false,
        "label": "&laquo; Previous",
        "url": null
      },
      {
        "active": true,
        "label": "1",
        "url": "{{base_url}}/api/public/v1/sites?page%5Bnumber%5D=1"
      },
      {
        "active": false,
        "label": "Next &raquo;",
        "url": null
      }
    ],
    "path": "{{base_url}}/api/public/v1/sites",
    "per_page": 15,
    "to": 2,
    "total": 2
  }
}
```

**SDK Code**

```python 200 - websites
import requests

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

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

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

print(response.json())
```

```javascript 200 - websites
const url = 'https://api.modulards.com/api/public/v1/sites';
const options = {method: 'GET', 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 - websites
package main

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

func main() {

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

	req, _ := http.NewRequest("GET", 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 - websites
require 'uri'
require 'net/http'

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

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

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

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

```java 200 - websites
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

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

```php 200 - websites
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

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

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

```csharp 200 - websites
using RestSharp;

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

```swift 200 - websites
import Foundation

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

let request = NSMutableURLRequest(url: NSURL(string: "https://api.modulards.com/api/public/v1/sites")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
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()
```