openapi: 3.2.0 info: title: MindCloud Public Companies API version: 2.0.0 description: REST surface under /v2. Authenticate with a company-scoped API key sent as a bearer token. Each key holds a set of permissions; each operation lists the ones it requires as the apiKey security roles. A request may use a permission only while the user who created the key also holds it. servers: - url: https://connect.mindcloud.co security: - apiKey: [] tags: - name: Companies paths: /v2/companies: get: operationId: v2-list-companies summary: List companies with subscription info (plan, legacy flag, member count) description: 'List companies with subscription info (plan, legacy flag, member count). Each filterable field is also a query parameter: `status=active` matches it exactly, and bracket operators (eq, ne, gt, gte, lt, lte, contains, starts, ends, in, nin) compare, e.g. `createdOn[gte]=2026-01-01` or `status[in]=failed,cancelled`. contains, starts, and ends apply to text fields only. Requires the API key permission company:view.' tags: - Companies security: - apiKey: - company:view parameters: - name: fields in: query required: false schema: type: string description: 'Comma-separated fields to return; all of them when left out, and id always. Each item then carries only those keys, whatever its schema requires. Fields: id, name, description, timezone, plan, memberCount, isPersonal, isDeleted, subscriptionIsLegacy, subscriptionUpdatedOn, createdOn, updatedOn.' - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/offset' - name: sort in: query required: false schema: type: string description: 'Comma-separated sort fields; prefix one with - for descending. Sortable fields: id, name, description, timezone, plan, memberCount, isPersonal, isDeleted, subscriptionIsLegacy, subscriptionUpdatedOn, createdOn, updatedOn. Default: name.' - name: where in: query required: false schema: type: string maxLength: 2048 description: 'RSQL filter expression. Filterable fields: id, name, description, timezone, plan, memberCount, isPersonal, isDeleted, subscriptionIsLegacy, subscriptionUpdatedOn, createdOn, updatedOn. Operators: ==, !=, >, >=, <, <=, =in=, =out=, =like=. Logical: ; (AND), , (OR); AND binds tighter than OR. Example: "status==active;name=like=Sales*"' - name: id in: query required: false schema: type: string description: 'Filter on id: `id=value` matches it exactly. Bracket operators: `id[ne]`, `id[gt]`, `id[gte]`, `id[lt]`, `id[lte]`, `id[contains]`, `id[starts]`, `id[ends]`, and `id[in]` / `id[nin]` with comma-separated values.' - name: name in: query required: false schema: type: string description: 'Filter on name: `name=value` matches it exactly. Bracket operators: `name[ne]`, `name[gt]`, `name[gte]`, `name[lt]`, `name[lte]`, `name[contains]`, `name[starts]`, `name[ends]`, and `name[in]` / `name[nin]` with comma-separated values.' - name: description in: query required: false schema: type: string description: 'Filter on description: `description=value` matches it exactly. Bracket operators: `description[ne]`, `description[gt]`, `description[gte]`, `description[lt]`, `description[lte]`, `description[contains]`, `description[starts]`, `description[ends]`, and `description[in]` / `description[nin]` with comma-separated values.' - name: timezone in: query required: false schema: type: string description: 'Filter on timezone: `timezone=value` matches it exactly. Bracket operators: `timezone[ne]`, `timezone[gt]`, `timezone[gte]`, `timezone[lt]`, `timezone[lte]`, `timezone[contains]`, `timezone[starts]`, `timezone[ends]`, and `timezone[in]` / `timezone[nin]` with comma-separated values.' - name: plan in: query required: false schema: type: string description: 'Filter on plan: `plan=value` matches it exactly. Bracket operators: `plan[ne]`, `plan[gt]`, `plan[gte]`, `plan[lt]`, `plan[lte]`, `plan[contains]`, `plan[starts]`, `plan[ends]`, and `plan[in]` / `plan[nin]` with comma-separated values.' - name: memberCount in: query required: false schema: type: integer description: 'Filter on memberCount: `memberCount=value` matches it exactly. Bracket operators: `memberCount[ne]`, `memberCount[gt]`, `memberCount[gte]`, `memberCount[lt]`, `memberCount[lte]`, and `memberCount[in]` / `memberCount[nin]` with comma-separated values.' - name: isPersonal in: query required: false schema: type: boolean description: 'Filter on isPersonal: `isPersonal=value` matches it exactly. Bracket operators: `isPersonal[ne]`, `isPersonal[gt]`, `isPersonal[gte]`, `isPersonal[lt]`, `isPersonal[lte]`, and `isPersonal[in]` / `isPersonal[nin]` with comma-separated values.' - name: isDeleted in: query required: false schema: type: boolean description: 'Filter on isDeleted: `isDeleted=value` matches it exactly. Bracket operators: `isDeleted[ne]`, `isDeleted[gt]`, `isDeleted[gte]`, `isDeleted[lt]`, `isDeleted[lte]`, and `isDeleted[in]` / `isDeleted[nin]` with comma-separated values.' - name: subscriptionIsLegacy in: query required: false schema: type: boolean description: 'Filter on subscriptionIsLegacy: `subscriptionIsLegacy=value` matches it exactly. Bracket operators: `subscriptionIsLegacy[ne]`, `subscriptionIsLegacy[gt]`, `subscriptionIsLegacy[gte]`, `subscriptionIsLegacy[lt]`, `subscriptionIsLegacy[lte]`, and `subscriptionIsLegacy[in]` / `subscriptionIsLegacy[nin]` with comma-separated values.' - name: subscriptionUpdatedOn in: query required: false schema: type: string description: 'Filter on subscriptionUpdatedOn: `subscriptionUpdatedOn=value` matches it exactly. A date or timestamp, such as 2026-10-01 or 2026-10-01T12:00:00Z. Bracket operators: `subscriptionUpdatedOn[ne]`, `subscriptionUpdatedOn[gt]`, `subscriptionUpdatedOn[gte]`, `subscriptionUpdatedOn[lt]`, `subscriptionUpdatedOn[lte]`, and `subscriptionUpdatedOn[in]` / `subscriptionUpdatedOn[nin]` with comma-separated values.' - name: createdOn in: query required: false schema: type: string description: 'Filter on createdOn: `createdOn=value` matches it exactly. A date or timestamp, such as 2026-10-01 or 2026-10-01T12:00:00Z. Bracket operators: `createdOn[ne]`, `createdOn[gt]`, `createdOn[gte]`, `createdOn[lt]`, `createdOn[lte]`, and `createdOn[in]` / `createdOn[nin]` with comma-separated values.' - name: updatedOn in: query required: false schema: type: string description: 'Filter on updatedOn: `updatedOn=value` matches it exactly. A date or timestamp, such as 2026-10-01 or 2026-10-01T12:00:00Z. Bracket operators: `updatedOn[ne]`, `updatedOn[gt]`, `updatedOn[gte]`, `updatedOn[lt]`, `updatedOn[lte]`, and `updatedOn[in]` / `updatedOn[nin]` with comma-separated values.' - $ref: '#/components/parameters/CompanyId' responses: '200': description: Success. content: application/json: schema: type: object properties: success: type: boolean const: true data: type: array items: $ref: '#/components/schemas/Company' meta: $ref: '#/components/schemas/ListMeta' required: - success - data - meta default: description: Error. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /v2/companies/{companyId}: patch: operationId: v2-update-company summary: Update the company name, description, or timezone description: 'Update the company name, description, or timezone. The path company id must be the company the request acts on: the API key''s company, or the one X-Company-Id names. Requires the API key permission company:edit.' tags: - Companies security: - apiKey: - company:edit parameters: - name: companyId in: path required: true schema: type: string minLength: 1 - $ref: '#/components/parameters/CompanyId' requestBody: required: false content: application/json: schema: type: object properties: name: type: string minLength: 1 maxLength: 128 description: type: string maxLength: 2048 timezone: type: string minLength: 1 responses: '200': description: Success. content: application/json: schema: type: object properties: success: type: boolean const: true data: $ref: '#/components/schemas/CompanyProfile' meta: type: object description: 'Response metadata, on endpoints that answer it: the usage window, a step count, or the provider paging of a Universal action run.' required: - success - data '400': description: The request body is invalid (INVALID_QUERY), carries none of name, description or timezone (NO_FIELDS_TO_UPDATE), or names an unsupported timezone key (INVALID_TIMEZONE). content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: The path company id is not the company the request acts on (COMPANY_SCOPE_MISMATCH). content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: The company was not found, or is deleted (NOT_FOUND). content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '409': description: Another company already has this name (DUPLICATE_COMPANY_NAME). content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' default: description: Error. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' components: schemas: CompanyProfile: type: object properties: id: type: - string - 'null' description: Unique id of the company. name: type: - string - 'null' description: The company's name. description: type: - string - 'null' description: The company's description. isPersonal: type: - boolean - 'null' description: True for personal workspaces rather than team companies. timezone: type: - string - 'null' description: The company's timezone key, an abbreviation such as EDT or PST rather than an IANA zone name. isDeleted: type: - boolean - 'null' description: True after the company was deleted. createdOn: type: - string - 'null' format: date-time description: When the company was created. updatedOn: type: - string - 'null' format: date-time description: When it was last changed. required: - id - name - description - isPersonal - timezone - isDeleted - createdOn - updatedOn ErrorResponse: type: object properties: success: type: boolean const: false error: type: object properties: code: type: string description: 'Fixed by the status: 400 VALIDATION_FAILED, 401 UNAUTHORIZED, 403 FORBIDDEN, 404 NOT_FOUND, 409 CONFLICT, 410 GONE, 413 PAYLOAD_TOO_LARGE, 421 and 503 UNAVAILABLE, 429 RATE_LIMITED, 500 INTERNAL_ERROR, 502 PROVIDER_ERROR.' examples: - VALIDATION_FAILED - UNAUTHORIZED - FORBIDDEN - NOT_FOUND - CONFLICT - GONE - PAYLOAD_TOO_LARGE - RATE_LIMITED - INTERNAL_ERROR - PROVIDER_ERROR - UNAVAILABLE message: type: string details: type: object description: The specific cause (reason) and any evidence for it. Absent when the code says everything. properties: reason: type: string description: The specific cause, for example UNKNOWN_FILTER_FIELD or CONNECTION_IN_USE. field: type: string description: The parameter, filter, sort, or body field a 400 refused. accepted: type: array items: {} description: 'What a 400 would have accepted instead: parameter names, field names, or enum values.' provider: type: object description: 'On 502 PROVIDER_ERROR: the provider answer that failed.' properties: status: type: integer description: The provider's HTTP status. code: type: string description: The provider's own error code, when it sends one. required: - code - message required: - success - error ListMeta: type: object properties: pagination: type: object properties: totalCount: type: integer description: Matching records. A list read in SQL stops counting at 10000. totalCountExact: type: boolean description: False when totalCount stopped at that cap. hasNextPage: type: boolean description: True when another page follows. Page with this, not totalCount. hasPreviousPage: type: boolean required: - totalCount - totalCountExact - hasNextPage - hasPreviousPage required: - pagination Company: type: object properties: id: type: - string - 'null' description: Unique id of the company. name: type: - string - 'null' description: The company's name. description: type: - string - 'null' description: The company's description. timezone: type: - string - 'null' description: The company's timezone key, an abbreviation such as EDT or PST rather than an IANA zone name. plan: type: - string - 'null' description: 'Your plan: Basic, Professional, or Enterprise.' memberCount: type: - integer - 'null' description: How many people are in the company. isPersonal: type: - boolean - 'null' description: True for personal workspaces rather than team companies. isDeleted: type: - boolean - 'null' description: True after the company was deleted. subscriptionIsLegacy: type: - boolean - 'null' description: True while the company is on a legacy plan. subscriptionUpdatedOn: type: - string - 'null' format: date-time description: When the subscription last changed. createdOn: type: - string - 'null' format: date-time description: When the company was created. updatedOn: type: - string - 'null' format: date-time description: When it was last changed. required: - id - name - description - timezone - plan - memberCount - isPersonal - isDeleted - subscriptionIsLegacy - subscriptionUpdatedOn - createdOn - updatedOn parameters: offset: name: offset in: query required: false schema: type: integer minimum: 0 default: 0 description: Number of results to skip for pagination (default 0). limit: name: limit in: query required: false schema: type: integer minimum: 1 maximum: 1000 default: 100 description: Maximum number of results to return (1-1000, default 100). CompanyId: name: X-Company-Id in: header required: false schema: type: string example: K3vX9qLm2RtA description: Optional. The id of a child organization of your API key's company to act on. Leave it out to act on the key's own company. See [Child organizations](https://mindcloud.co/docs/api/rest/introduction/child-organizations). securitySchemes: apiKey: type: http scheme: bearer description: 'Company-scoped MindCloud API key sent as `Authorization: Bearer `. Each key holds permissions from the MindCloud roles catalog (workflow:view, workflow:run, universal:read, api_key:manage, ...), chosen when it is created; each operation lists the ones it requires as this scheme''s roles. A request may use a permission only while the user who created the key still holds it in the company the request acts on; a missing one answers 403 with details.reason API_KEY_PERMISSION_DENIED and details.required, and a key whose creator left the organization answers API_KEY_CREATOR_INACTIVE. The key''s accessLevel (full_access, run_workflows, read_only, or none) summarizes its permissions. Create a key at https://app.mindcloud.co/user/api-keys.'