Authenticating with the Macha API
Generate API keys, choose the right scopes, and authenticate requests with Bearer tokens.
The Macha API authenticates every request with a Bearer token. Tokens are organization-scoped, scope-restricted, revocable, and never reused. There is no OAuth flow today, just static API keys that you generate from the dashboard.
Token format
API keys have a fixed prefix that identifies them as Macha tokens, followed by 32 characters of random entropy:
mka_live_jbUaWzqeKB004Gr8FIHpRPoyVOq2Yzx9
└── 9 ──┘└────────── 32 ──────────────────┘
prefix random suffix
The prefix is what Macha uses to narrow the key lookup before doing the bcrypt compare on the suffix, this keeps key validation under a millisecond at any scale. The whole token is bcrypt-hashed at rest with a cost factor that's adjusted as compute gets cheaper. Even with full database access, Macha cannot recover the original token.
Passing the token
Send the full token in the Authorization header on every request:
GET /api/v1/agents HTTP/1.1
Host: dashboard.getmacha.com
Authorization: Bearer mka_live_jbUaWzqeKB004Gr8FIHpRPoyVOq2Yzx9
Accept: application/json
Sending the token via query string, request body, or cookie is not supported and never will be. Bearer header only.
Example: curl
curl https://dashboard.getmacha.com/api/v1/agents \
-H "Authorization: Bearer $MACHA_API_KEY"
Example: Node.js (fetch)
const res = await fetch('https://dashboard.getmacha.com/api/v1/agents', {
headers: {
'Authorization': `Bearer ${process.env.MACHA_API_KEY}`,
},
});
const json = await res.json();
Example: Python (requests)
import os, requests
r = requests.get(
'https://dashboard.getmacha.com/api/v1/agents',
headers={'Authorization': f'Bearer {os.environ["MACHA_API_KEY"]}'},
)
data = r.json()
Scopes
Every API key has a list of scopes that restrict what it can do. Scopes follow a {resource}:{action} naming convention. There is no super-scope, a key with every scope still has to list each one explicitly.
Full scope catalog
| Resource | Read | Write | Delete |
|---|---|---|---|
| Agents | agents:read | agents:write | agents:delete |
| Conversations | conversations:read | conversations:write | conversations:delete |
| Connectors | connectors:read | connectors:write | connectors:delete |
| Custom tools | custom_tools:read | custom_tools:write | custom_tools:delete |
| Sources | sources:read | sources:write | sources:delete |
| Chatbots | chatbots:read | chatbots:write | chatbots:delete |
| Triggers | triggers:read | triggers:write | triggers:delete |
| Team | team:read | team:write | team:delete |
| Analytics | analytics:read | ||
| Organization | org:read |
analytics and org are read-only resources by design, analytics is computed from underlying data (no write surface), and org settings stay dashboard-managed for now (billing, branding, etc.).
Per-endpoint scope
Each endpoint's required scope is listed in its reference page. As shorthand:
| HTTP method | Scope required |
|---|---|
| GET | {resource}:read |
| POST / PATCH | {resource}:write |
| DELETE | {resource}:delete |
The OpenAPI spec exposes the exact scope under x-required-scope on each operation, so SDK generators and MCP servers can warn customers about missing scopes before making the call.
Authentication failures
Two distinct failure modes:
| Status | Code | Meaning | Fix |
|---|---|---|---|
401 | unauthorized | Missing, malformed, revoked, or unknown key. | Check the token. If revoked, create a new one. |
403 | insufficient_scope | Valid key, but it lacks the scope this endpoint requires. | Create a new key with the missing scope. |
A 403 means "this key is real, but you didn't grant it permission", not a bug in your code. Fix it by creating a new key with broader scopes (or asking the org admin to).
Key lifecycle
Create
In the dashboard at Settings → API Keys. The full token is shown once at creation time. Macha cannot show it again, copy it immediately into your secret store.
Use
Passed as a Bearer token on every request. Macha updates the key's last_used_at timestamp asynchronously so the dashboard can show stale-key warnings, but this is fire-and-forget, your request latency is not affected.
Revoke
Click revoke in the dashboard. The key is marked inactive immediately; any further requests get 401 unauthorized. The audit history of what the key did is retained.
Rotate
Macha doesn't support in-place rotation today. The rotation pattern is:
- Create a new key with the same scopes as the old one
- Update your integration to use the new key
- Verify the new key is working (check logs / dashboard's
last_used_at) - Revoke the old key
This is overlap rotation, both keys are valid during the transition, then the old one is cut. Cleaner than in-place rotation; harder to lock yourself out.
Security best practices
- Use environment variables. Never commit a key to source control. Macha scans public GitHub for the
mka_live_prefix and will revoke leaked keys automatically. - One key per integration. Don't share a key across multiple services, if one leaks, you can revoke without breaking the others.
- Smallest scope that works. An "agent reader" integration shouldn't have
agents:write. Scope keys tightly. - Log
request_idon errors. Macha can trace any request by its ID. Support is impossible without it. - Rotate regularly. Six months is a reasonable cadence. The overlap rotation pattern above makes it cheap.
What Macha sees
Every authenticated request is associated with the API key's organization. The key does not impersonate a user, resources created via the API show up in audit logs as "created via API key <key label>" rather than tied to a specific person.
If you need per-user attribution, create one key per user and label it accordingly. Macha treats each key as a distinct identity for audit purposes.
Anyone with your key has full org-level access at the scopes you granted. Store keys in a proper secrets manager (1Password, AWS Secrets Manager, Doppler, etc.), not in .env files checked into Git.
© 2026 AGZ Technologies Private Limited