Skip to content

Create a category

POST
/categories
curl --request POST \
--url https://flow.work.optidata.cloud/api/categories \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "name": "Onboarding", "description": "Everything a new hire needs in the first month.", "visibility": "restricted" }'

Creates a category owned by the caller, together with its Overview page. The name must be unique within the company; its slug is derived from it.

visibility is required here — the request currently fails with a server error when it is omitted. On update it stays optional.

Media typeapplication/json
object
name
required

Category name, unique within the company.

string
<= 255 characters
description
string | null
<= 255 characters
visibility
required

Who can see a category. restricted: only the people and groups it is shared with. internal: everyone in the company. public: anyone with the link, including people who are not signed in.

string
Allowed values: restricted internal public
Examples
Examplerestricted
{
"name": "Onboarding",
"description": "Everything a new hire needs in the first month.",
"visibility": "restricted"
}

The category was created.

Media typeapplication/json
object
id
required
integer
name
required
string
slug
required

URL-friendly form of the name.

string
description
string | null
visibility
required

Who can see a category. restricted: only the people and groups it is shared with. internal: everyone in the company. public: anyone with the link, including people who are not signed in.

string
Allowed values: restricted internal public
is_public
required

Shortcut for visibility == public.

boolean
identifier

Short public identifier of the category.

string | null
user_id

Id of the user who owns the category, when it has one.

integer | null
group_id

Set when the category mirrors a group: it is shared with the group’s members, and its name and description follow the group’s.

integer | null
cuid

Identifier of the company the category belongs to.

string
created_at
string format: date-time
updated_at
string format: date-time
deleted_at

Set when the category is in the trash.

string | null format: date-time
Examples
Examplecreated
{
"name": "Onboarding",
"slug": "onboarding",
"cuid": "7f3c2a10-5b8e-4d21-9c6a-0e4f1b2d3c4a",
"description": "Everything a new hire needs in the first month.",
"visibility": "restricted",
"group_id": null,
"user_id": 20,
"identifier": "jYpV3A",
"updated_at": "2026-10-19T13:50:38.000000Z",
"created_at": "2026-10-19T13:50:38.000000Z",
"id": 993,
"is_public": false
}

No authentication key was sent.

Media typeapplication/json

Authentication failures use an error key rather than message.

object
error
required
string
Examples
Examplemissing

No bearer token sent

{
"error": "JWT passport exception: Missing bearer token in request"
}

The authentication key is expired or not recognised. Get a fresh one and retry.

Media typeapplication/json

Authentication failures use an error key rather than message.

object
error
required
string
Examples
Exampleexpired
{
"error": "JWT passport expired: Passport expired"
}

The body failed validation — for instance, a category with that name already exists.

Media typeapplication/json
object
message
required

The first validation message.

string
errors
required

Validation messages keyed by field name.

object
key
additional properties
Array<string>
Examples
Exampleduplicate
{
"message": "A category with this name already exists.",
"errors": {
"name": [
"A category with this name already exists."
]
}
}