Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: MindCloud Public API Keys 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: API Keys
paths:
/v2/api-keys:
get:
operationId: v2-list-api-keys
summary: 'List API keys for the company: name, last use, and revocation state'
description: 'List API keys for the company: name, last use, and revocation state. Key material is never included.
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 api_key:manage.'
tags:
- API Keys
security:
- apiKey:
- api_key:manage
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, accessLevel, permissions, usedOn, revokedOn, createdOn, createdBy, 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, accessLevel, usedOn, revokedOn, createdOn, createdBy, updatedOn. Default: -createdOn.'
- name: where
in: query
required: false
schema:
type: string
maxLength: 2048
description: 'RSQL filter expression. Filterable fields: id, name, accessLevel, usedOn, revokedOn, createdOn, createdBy, 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: accessLevel
in: query
required: false
schema:
type: string
enum:
- read_only
- run_workflows
- full_access
- none
description: 'Filter on accessLevel: `accessLevel=value` matches it exactly. Bracket operators: `accessLevel[ne]`, `accessLevel[gt]`, `accessLevel[gte]`, `accessLevel[lt]`, `accessLevel[lte]`, `accessLevel[contains]`, `accessLevel[starts]`, `accessLevel[ends]`, and `accessLevel[in]` / `accessLevel[nin]` with comma-separated values.'
- name: usedOn
in: query
required: false
schema:
type: string
description: 'Filter on usedOn: `usedOn=value` matches it exactly. A date or timestamp, such as 2026-10-01 or 2026-10-01T12:00:00Z. Bracket operators: `usedOn[ne]`, `usedOn[gt]`, `usedOn[gte]`, `usedOn[lt]`, `usedOn[lte]`, and `usedOn[in]` / `usedOn[nin]` with comma-separated values.'
- name: revokedOn
in: query
required: false
schema:
type: string
description: 'Filter on revokedOn: `revokedOn=value` matches it exactly. A date or timestamp, such as 2026-10-01 or 2026-10-01T12:00:00Z. Bracket operators: `revokedOn[ne]`, `revokedOn[gt]`, `revokedOn[gte]`, `revokedOn[lt]`, `revokedOn[lte]`, and `revokedOn[in]` / `revokedOn[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: createdBy
in: query
required: false
schema:
type: string
description: 'Filter on createdBy: `createdBy=value` matches it exactly. Bracket operators: `createdBy[ne]`, `createdBy[gt]`, `createdBy[gte]`, `createdBy[lt]`, `createdBy[lte]`, `createdBy[contains]`, `createdBy[starts]`, `createdBy[ends]`, and `createdBy[in]` / `createdBy[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.'
responses:
'200':
description: Success.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
data:
type: array
items:
$ref: '#/components/schemas/ApiKeySummary'
meta:
$ref: '#/components/schemas/ListMeta'
required:
- success
- data
- meta
default:
description: Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
operationId: v2-create-api-key
summary: Create an API key for the company with an explicit set of permissions, all…
description: 'Create an API key for the company with an explicit set of permissions, all within the calling key''s own. The key material is returned once, in this response, and can never be retrieved again.
Requires the API key permission api_key:manage.'
tags:
- API Keys
security:
- apiKey:
- api_key:manage
parameters: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
minLength: 1
maxLength: 256
permissions:
maxItems: 27
type: array
items:
type: string
enum:
- workflow:view
- workflow:create
- workflow:edit
- workflow:delete
- workflow:run
- log:view
- credential:view
- credential:edit
- credential:delete
- universal:read
- universal:create
- universal:update
- universal:delete
- member:view
- member:create
- member:edit
- member:delete
- member:owner_edit
- role:manage
- company:view
- company:edit
- subscription:view
- api_key:manage
- embedded:view
- embedded:create
- child_company:access
- child_company:manage
accessLevel:
type: string
enum:
- read_only
- run_workflows
- full_access
required:
- name
responses:
'201':
description: Success.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
data:
$ref: '#/components/schemas/ApiKey'
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), or it sends both permissions and accessLevel (API_KEY_PERMISSIONS_CONFLICT).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: The calling key lacks api_key:manage (API_KEY_PERMISSION_DENIED), or the new key would hold a permission the calling key cannot use (API_KEY_PERMISSION_EXCEEDS_ACTOR).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
default:
description: Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/v2/api-keys/{apiKeyId}:
delete:
operationId: v2-revoke-api-key
summary: Revoke an API key
description: 'Revoke an API key. The key stops working immediately. Revoking an already revoked key changes nothing and succeeds.
Requires the API key permission api_key:manage.'
tags:
- API Keys
security:
- apiKey:
- api_key:manage
parameters:
- name: apiKeyId
in: path
required: true
schema:
type: string
minLength: 1
responses:
'200':
description: Success.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
data:
$ref: '#/components/schemas/DeletedResource'
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
default:
description: Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
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).
schemas:
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
ApiKey:
type: object
properties:
id:
type:
- string
- 'null'
description: Unique id of the key.
name:
type:
- string
- 'null'
description: The name the key was created with.
accessLevel:
type:
- string
- 'null'
enum:
- read_only
- run_workflows
- full_access
- none
- null
description: 'A summary of the key permissions: full_access, run_workflows, read_only, or none. Derived from permissions; it is never set directly.'
permissions:
type: array
items:
type: string
description: The permissions the key holds. A request may use one only while the key's creator also holds it.
key:
type: string
description: The key itself. It appears only in this response; MindCloud keeps only a hash.
createdOn:
type:
- string
- 'null'
format: date-time
description: When the key was created.
required:
- id
- name
- accessLevel
- permissions
- key
- createdOn
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
DeletedResource:
type: object
properties:
id:
type: string
description: The id of the resource that was deleted.
required:
- id
ApiKeySummary:
type: object
properties:
id:
type:
- string
- 'null'
description: Unique id of the key.
name:
type:
- string
- 'null'
description: The name the key was created with.
accessLevel:
type:
- string
- 'null'
enum:
- read_only
- run_workflows
- full_access
- none
- null
description: 'A summary of the key permissions: full_access, run_workflows, read_only, or none. Derived from permissions; it is never set directly.'
permissions:
type: array
items:
type: string
description: The permissions the key holds. A request may use one only while the key's creator also holds it.
usedOn:
type:
- string
- 'null'
format: date-time
description: The last time the key was used. Old dates are rotation candidates.
revokedOn:
type:
- string
- 'null'
format: date-time
description: When the key was revoked. Empty while it is active.
createdOn:
type:
- string
- 'null'
format: date-time
description: When the key was created.
createdBy:
type:
- string
- 'null'
description: Who created it.
updatedOn:
type:
- string
- 'null'
format: date-time
description: When it was last changed.
required:
- id
- name
- accessLevel
- permissions
- usedOn
- revokedOn
- createdOn
- createdBy
- updatedOn
securitySchemes:
apiKey:
type: http
scheme: bearer
description: 'Company-scoped MindCloud API key sent as `Authorization: Bearer <key>`. 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.'