# Authors · Management API

> Management API reference for authors: GET /sites/{id}/authors, POST /sites/{id}/authors, PATCH /sites/{id}/authors/{authorId}.

> Markdown version of https://kanorio.com/en/developers/management-api/authors. Append `.md` to any developer docs URL for this format. Index: https://kanorio.com/llms.txt · MCP: https://app.kanorio.com/api/mcp

Base URL: `https://app.kanorio.com/api/v1` · [Errors](https://kanorio.com/en/developers/basics/errors) · [Pagination](https://kanorio.com/en/developers/basics/pagination)

### List authors

`GET /sites/{id}/authors`

- Stability: beta
- Permission: `posts:view`
- Rate limit: default (120/minute per token)
- MCP tool: `authors_list`

List the site's shared author list: post authors and deliverable instructors are the same people. Use ids in posts.create / posts.update authorIds and deliverables.update authorIds. Errors: FORBIDDEN, INVALID_CURSOR.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Website id. Get it from sites.list or from sites.create. |
| `limit` | query | integer | no | Maximum number of items to return, 1–100. Defaults to 20. |
| `cursor` | query | string | no | Opaque cursor from the previous page's nextCursor. Omit for the first page. |

**Response** (200)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | object[] | yes | — |
| `data[].id` | string | yes | — |
| `data[].slug` | string | yes | Use it in Delivery API filters: /api/v1/products?author=<slug> (courses they teach) and the blog author filter. |
| `data[].name` | string | yes | — |
| `data[].title` | string \| null | yes | Job title or credential shown next to the name, e.g. Head Chef. |
| `data[].avatar` | string \| null | yes | Displayable image URL. |
| `data[].avatarAssetId` | string \| null | yes | Media library asset id of the avatar, when it is in the library. |
| `data[].bio` | string \| null | yes | — |
| `data[].url` | string \| null | yes | Personal website or social profile; the name on courses links here. |
| `data[].counts` | object | yes | — |
| `data[].counts.posts` | integer | yes | Published posts. |
| `data[].counts.deliverables` | integer | yes | Deliverables where this person is an instructor. |
| `hasMore` | boolean | yes | True when another page exists; pass nextCursor to fetch it. |
| `nextCursor` | string \| null | yes | Cursor for the next page, or null on the last page. |

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `FORBIDDEN` | 403 | — |
| `INVALID_CURSOR` | 400 | — |

```bash
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/authors" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
```

```json
{
  "data": [
    {
      "id": "author_example01",
      "slug": "sunny",
      "name": "Sunny",
      "title": "Head Baker",
      "avatar": "https://imagedelivery.net/example/sunny/avatar",
      "avatarAssetId": "asset_example01",
      "bio": "Runs the bakehouse and teaches the sourdough course.",
      "url": "https://sunny.example.com",
      "counts": {
        "posts": 12,
        "deliverables": 1
      }
    }
  ],
  "hasMore": false,
  "nextCursor": null
}
```

### Create an author

`POST /sites/{id}/authors`

- Stability: beta
- Permission: `blog:manage`
- Rate limit: default (120/minute per token)
- MCP tool: `authors_create`

Add a person to the site's shared author list (post authors and deliverable instructors are the same list). Then attach them with deliverables.update { authorIds } or posts.update { authorIds }. A blog author page only exists once they have a published post. Errors: FORBIDDEN, VALIDATION, SLUG_TAKEN, ASSET_NOT_FOUND (avatarAssetId not in this site's media library), ASSET_NOT_ALLOWED (avatar must be an image).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Website id. Get it from sites.list or from sites.create. |

**Request body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | — |
| `slug` | string | no | Generated from name when omitted. |
| `title` | string | no | Job title or credential, e.g. Head Chef. Empty string clears it. |
| `avatarAssetId` | string \| null | no | Image asset id from the media library (media.upload first); null removes the avatar. |
| `bio` | string | no | — |
| `url` | string | no | Personal website or social profile. Empty string clears it. |

**Response** (201)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `author` | object | yes | — |
| `author.id` | string | yes | — |
| `author.slug` | string | yes | Use it in Delivery API filters: /api/v1/products?author=<slug> (courses they teach) and the blog author filter. |
| `author.name` | string | yes | — |
| `author.title` | string \| null | yes | Job title or credential shown next to the name, e.g. Head Chef. |
| `author.avatar` | string \| null | yes | Displayable image URL. |
| `author.avatarAssetId` | string \| null | yes | Media library asset id of the avatar, when it is in the library. |
| `author.bio` | string \| null | yes | — |
| `author.url` | string \| null | yes | Personal website or social profile; the name on courses links here. |
| `author.counts` | object | yes | — |
| `author.counts.posts` | integer | yes | Published posts. |
| `author.counts.deliverables` | integer | yes | Deliverables where this person is an instructor. |

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `FORBIDDEN` | 403 | — |
| `VALIDATION` | 400 | — |
| `SLUG_TAKEN` | 409 | — |
| `ASSET_NOT_FOUND` | 404 | avatarAssetId not in this site's media library |
| `ASSET_NOT_ALLOWED` | 422 | avatar must be an image |

```bash
curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/authors" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Sunny","title":"Head Baker","avatarAssetId":"asset_example01","url":"https://sunny.example.com"}'
```

```json
{
  "author": {
    "id": "author_example01",
    "slug": "sunny",
    "name": "Sunny",
    "title": "Head Baker",
    "avatar": "https://imagedelivery.net/example/sunny/avatar",
    "avatarAssetId": "asset_example01",
    "bio": null,
    "url": "https://sunny.example.com",
    "counts": {
      "posts": 0,
      "deliverables": 0
    }
  }
}
```

### Update an author

`PATCH /sites/{id}/authors/{authorId}`

- Stability: beta
- Permission: `blog:manage`
- Rate limit: default (120/minute per token)
- MCP tool: `authors_update`

Update a person on the shared author list; the change shows on their posts and the courses they teach. Only provided fields change. Errors: AUTHOR_NOT_FOUND, FORBIDDEN, VALIDATION, SLUG_TAKEN, ASSET_NOT_FOUND (avatarAssetId not in this site's media library), ASSET_NOT_ALLOWED (avatar must be an image).

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Website id. Get it from sites.list or from sites.create. |
| `authorId` | path | string | yes | — |

**Request body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | no | — |
| `slug` | string | no | — |
| `title` | string | no | Job title or credential, e.g. Head Chef. Empty string clears it. |
| `avatarAssetId` | string \| null | no | Image asset id from the media library (media.upload first); null removes the avatar. |
| `bio` | string | no | — |
| `url` | string | no | Personal website or social profile. Empty string clears it. |

**Response** (200)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `author` | object | yes | — |
| `author.id` | string | yes | — |
| `author.slug` | string | yes | Use it in Delivery API filters: /api/v1/products?author=<slug> (courses they teach) and the blog author filter. |
| `author.name` | string | yes | — |
| `author.title` | string \| null | yes | Job title or credential shown next to the name, e.g. Head Chef. |
| `author.avatar` | string \| null | yes | Displayable image URL. |
| `author.avatarAssetId` | string \| null | yes | Media library asset id of the avatar, when it is in the library. |
| `author.bio` | string \| null | yes | — |
| `author.url` | string \| null | yes | Personal website or social profile; the name on courses links here. |
| `author.counts` | object | yes | — |
| `author.counts.posts` | integer | yes | Published posts. |
| `author.counts.deliverables` | integer | yes | Deliverables where this person is an instructor. |

**Errors**

| Code | Status | When |
| --- | --- | --- |
| `AUTHOR_NOT_FOUND` | 404 | — |
| `FORBIDDEN` | 403 | — |
| `VALIDATION` | 400 | — |
| `SLUG_TAKEN` | 409 | — |
| `ASSET_NOT_FOUND` | 404 | avatarAssetId not in this site's media library |
| `ASSET_NOT_ALLOWED` | 422 | avatar must be an image |

```bash
curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/authors/{authorId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Head Baker & Instructor"}'
```

```json
{
  "author": {
    "id": "author_example01",
    "slug": "sunny",
    "name": "Sunny",
    "title": "Head Baker & Instructor",
    "avatar": null,
    "avatarAssetId": null,
    "bio": null,
    "url": null,
    "counts": {
      "posts": 12,
      "deliverables": 1
    }
  }
}
```
