Authentication
How to create service accounts, generate API tokens, and authenticate requests to the Mandraki Bot API.
Overview
The Mandraki Bot API uses bearer token authentication with mak_-prefixed API tokens. Tokens are issued to service accounts, which represent non-human identities within your organization.
Service Accounts
A service account is the identity your integration uses to interact with Mandraki. Each service account belongs to a single organization and can hold multiple API tokens.
Types
| Type | Purpose |
|---|---|
BOT | Automated agents that post messages, create tasks, and interact as a named bot user |
INTEGRATION | Backend services that sync data, process webhooks, or automate workflows |
Creating a Service Account
Service accounts are created through the Mandraki settings UI under Settings > Integrations. You can also create them via the management API.
Required fields:
| Field | Type | Description |
|---|---|---|
name | string (1-100 chars) | Display name shown when the bot posts messages |
type | BOT or INTEGRATION | Account type (default: BOT) |
slug | string (optional) | URL-safe identifier (^[a-z0-9-]+$, max 50 chars) |
description | string (optional) | Human-readable description (max 500 chars) |
iconUrl | URL (optional) | Avatar URL for the bot |
API Tokens
Each service account can have multiple API tokens with different scopes and expiration dates. This lets you issue narrowly-scoped tokens for different use cases.
Token Format
Tokens use the mak_ prefix followed by a base64url-encoded 256-bit random secret:
mak_dGhpcyBpcyBhIHNhbXBsZSB0b2tlbg...
The raw token is shown only once at creation time. Mandraki stores a SHA-256 hash of the token — if you lose it, you must create a new one.
Creating a Token
When creating a token, you specify:
| Field | Type | Default | Description |
|---|---|---|---|
label | string (1-100 chars) | required | Human-readable name for this token |
scopes | string[] | required | List of permission scopes (at least one) |
resourceScopes | object | optional | Restrict access to specific teams, channels, projects, or folders |
rateLimit | integer (1-10,000) | 1000 | Maximum requests per hour |
expiresAt | ISO 8601 datetime | optional | Token expiration date (no expiry if omitted) |
Authentication Header
Include the token in every request using the Authorization header:
curl -X GET "https://app.mandraki.cloud/api/v1/orgs/{orgId}/bot/teams" \
-H "Authorization: Bearer mak_dGhpcyBpcyBhIHNhbXBsZSB0b2tlbg..."
Token Validation
On each request, the API:
- Extracts the bearer token from the
Authorizationheader - Verifies the
mak_prefix - Hashes the token with SHA-256 and looks up the hash
- Checks the token is active and not expired
- Verifies the token’s organization matches the
{orgId}in the URL - Checks rate limits
- Validates required scopes for the endpoint
If any step fails, the request is rejected with 401 Unauthorized or 403 Forbidden.
Scopes
Scopes control what operations a token can perform. Each Bot API endpoint requires specific scopes. See Scopes and Permissions for the full list.
A token created with ["tasks:read", "teams:read"] can list tasks and teams but cannot create or modify them.
Admin Scopes
Three scopes require the service account creator to have the ADMIN role in the organization:
admin:users— Manage usersadmin:channels— Manage all channelsadmin:audit— Read audit logs
Attempting to create a token with admin scopes from a non-admin account will fail.
Resource Scopes
You can restrict a token to operate only on specific resources by setting resourceScopes:
{
"label": "Engineering bot",
"scopes": ["tasks:read", "tasks:write", "channels:read"],
"resourceScopes": {
"teams": ["team-uuid-1"],
"channels": ["channel-uuid-1", "channel-uuid-2"],
"projects": ["project-uuid-1"]
}
}
This token can only access tasks in project-uuid-1, read messages in the two specified channels, and interact with team-uuid-1. Requests targeting other resources return 403 Forbidden.
Available resource scope types:
| Key | Type | Restricts Access To |
|---|---|---|
teams | UUID[] | Specific teams |
channels | UUID[] | Specific channels |
projects | UUID[] | Specific task projects |
folders | UUID[] | Specific Drive folders |
If resourceScopes is omitted or a specific key is empty, access is unrestricted for that resource type.
Rate Limits
Each token has an independent rate limit (default: 1,000 requests per hour). The limit is configurable per token up to 10,000 requests per hour.
When the limit is exceeded, the API returns:
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "Rate limit exceeded"
}
Security Best Practices
- Principle of least privilege: Grant only the scopes your integration needs.
- Use resource scopes: Restrict tokens to specific teams, channels, or projects when possible.
- Set expiration dates: Use
expiresAtfor tokens that should be time-limited. - Rotate tokens regularly: Create a new token, update your integration, then revoke the old one.
- Never commit tokens to version control: Use environment variables or a secrets manager.
- Use separate tokens per environment: Don’t share tokens between development and production.