Authentication
Authenticate MindCloud API requests with API keys, their permissions, and company scoping.
Every request needs an API key in the Authorization header:
curl https://connect.mindcloud.co/v2/me \
-H "Authorization: Bearer $MINDCLOUD_API_KEY"A key belongs to one company, and every resource you read is scoped to that company automatically. There is nothing to configure per request. The one exception is a parent organization working inside its child organizations, which names the child in the optional X-Company-Id header.
Permissions
Every key holds a set of permissions, chosen when it is created and editable later in the app. Give a key only what its client needs. Each endpoint's page lists the permission it requires.
| Area | Permission | Lets the key |
|---|---|---|
| Workflows | workflow:view | List and read workflows and their versions |
workflow:create | Create and duplicate workflows | |
workflow:edit | Update workflows | |
workflow:delete | Delete workflows | |
workflow:run | Start and cancel runs | |
| Runs | log:view | List and read runs, steps, and operations |
| Connections | credential:view | List and read connections |
credential:edit | Test connections | |
credential:delete | Delete connections | |
| Universal API | universal:read | Run read actions and resolve lookups |
universal:create, universal:update, universal:delete | Run actions of that operation | |
| Members and roles | member:view | List members and roles |
member:create, member:edit, member:delete | Invite, change, and remove members | |
member:owner_edit | Invite, change, or remove an Owner | |
role:manage | Create, update, and delete roles | |
| Company | company:view | List companies and environments |
company:edit | Update the company profile | |
subscription:view | Read usage | |
| API keys | api_key:manage | List, create, change, and revoke API keys |
| Embedded | embedded:view | List an end user's connections |
embedded:create | Create connect links | |
| Child organizations | child_company:access | Act in a child organization with X-Company-Id |
child_company:manage | Create and release child organizations |
Universal discovery (listing apps and actions, reading an action) and GET /v2/me need no permission. Running a Universal action needs the permission for the action's declared operation, and all four when it declares none.
A new key starts with the view permissions. A key never holds more than the person who creates it or edits it, and a key can create only keys whose permissions it can use itself.
The key's accessLevel (full_access, run_workflows, read_only, or none) summarizes its permissions. The company MCP endpoint (/mcp) requires a key whose permissions add up to full_access. Embedded MCP tool access explains which tools each permission unlocks.
A key is never stronger than its creator
A key is tied to the person who created it. On every request it may use a permission only while that person also holds it, right now, in the company the request acts on. Demote the creator, and the key loses what the creator lost on the next request. Nothing is cached.
A key uses a permission only while its creator still holds it. If the creator's account is removed, or they leave the company, the key stops working: every endpoint that needs a permission answers 403 with reason API_KEY_CREATOR_INACTIVE. Have a current member create a replacement key.
What a key acts as
Member and role writes need an acting user, because the rules protecting Owners compare who is asking against who is being changed. A key acts as the person who created it, with that person's authority and no more:
- It cannot change its creator's own role, or remove its creator from the company.
- It can assign a role (by invite or role change) only when its creator holds every permission that role grants and the key holds each of them that a key can hold. Only someone who holds everything the Owner role grants can make an Owner.
- It can change or remove an Owner only when its creator and the key both hold
member:owner_edit. - The last Owner cannot be demoted or removed, whoever asks.
- It can give a role, a member, or a new key only permissions its creator holds and the key holds too.
Rejected keys
A missing, malformed, unknown, or revoked key returns 401 in the same error envelope as every other error:
{
"success": false,
"error": { "code": "UNAUTHORIZED", "message": "Unauthorized. API key is invalid." }
}A key without a permission an endpoint needs returns 403 with code FORBIDDEN, details.reason API_KEY_PERMISSION_DENIED, and the missing permissions in details.required:
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "This API key needs the workflow:run permission for this operation.",
"details": { "reason": "API_KEY_PERMISSION_DENIED", "required": ["workflow:run"] }
}
}The same answer comes when the key holds the permission but its creator no longer does.
Verify a key
GET /v2/me describes the calling key, its effective scope, and the capabilities its company has enabled. permissions is what the key holds; effectivePermissions is what it may use right now:
{
"success": true,
"data": {
"apiKey": {
"id": "apikey_K7dM2qP9xL4s",
"name": "Reporting",
"companyId": "Cp5nB8mGh3Kw",
"accessLevel": "read_only",
"isAdmin": false,
"permissions": ["company:view", "credential:view", "embedded:view", "log:view", "member:view", "subscription:view", "workflow:view"],
"effectivePermissions": ["company:view", "credential:view", "embedded:view", "log:view", "member:view", "subscription:view", "workflow:view"]
},
"companyId": "Cp5nB8mGh3Kw",
"company": { "id": "Cp5nB8mGh3Kw", "name": "Acme", "embedded": { "isEnabled": false } }
}
}Key handling
Keep keys on the server and out of client-side code. Keys can be managed entirely over the API: audit them with GET /v2/api-keys, mint new ones with POST /v2/api-keys, and shut one off with DELETE /v2/api-keys/:apiKeyId. A revoked key stops working immediately, and new key material is shown once, in the create response.