> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://api.docs.modulards.com/authentication/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api.docs.modulards.com/_mcp/server. # Authentication The Public API authenticates every request with a **personal access token**. Send it as a bearer token: ```bash curl https://api.modulards.com/api/public/v1/sites \ -H "Authorization: Bearer $MODULAR_DS_TOKEN" ``` A session cookie from the dashboard never authenticates a Public API request, even when you are logged in. ## Creating a token Create a token in Modular DS under **My profile > API > Create key**. The token belongs to your membership in the organization you create it in: it acts in that organization only, with the role you have there (see [Organizations](/organizations)). If your membership is removed, the token stops working. Keep tokens secret. Anyone holding a token can do in that organization everything its abilities and your role allow. ## Read-only and read and write tokens When you create a token you choose whether it can write: | Token | Can call | | -------------- | ------------------------------ | | Read-only | `GET` requests only | | Read and write | Every request your role allows | A read-only token that sends a `POST`, `PATCH`, `PUT` or `DELETE` gets a `403`: ```json { "errors": [ { "status": "403", "title": "Forbidden", "detail": "This token is read-only." } ], "jsonapi": { "version": "1.1" } } ``` A few reads hand out credentials and therefore need a read and write token too. Reading a website's manual connection credentials is one of them. ## Failed authentication A missing, malformed, unknown or expired token answers `401`: ```json { "errors": [ { "status": "401", "title": "Unauthenticated", "detail": "Unauthenticated." } ], "jsonapi": { "version": "1.1" } } ``` The token is checked before the URL is resolved, so an unauthenticated request answers `401` whether or not the resource it names exists. ## Credential handling Ordinary responses never carry a credential value: * **Manual connection credentials** are revealed through a signed URL that is valid for 10 minutes and can be used once. * **The connection plugin** is downloaded from a presigned URL that is valid for one hour. * **Backup archives** cannot be downloaded through the Public API. Downloads and restorations stay in the dashboard. > Personal access tokens, and what a token can do