Authentication
The Flow Myna API uses API keys to authenticate requests. This guide explains how to create, use, and manage your API keys.
API Key Format
Flow Myna API keys follow a specific format for easy identification:
API Key Format
fm_live_<32_random_characters>
Example: fm_live_abc123xyz789def456ghi012jkl345mn- Name
Prefix- Type
- fm_live_
- Description
- All Flow Myna API keys start with this prefix (8 characters)
- Name
Random Part- Type
- string
- Description
- 32 URL-safe random characters
- Name
Total Length- Type
- 40 chars
- Description
- The complete key is always 40 characters
Using Your API Key
Include your API key in every request using the Authorization header with a Bearer token:
Authorization Header
curl -X POST 'https://api.flowmyna.com/v1/event' \
-H 'Authorization: Bearer fm_live_your_key_here' \
-H 'Content-Type: application/json' \
-d '{"event": "Test Event", "objects": [{"type": "Test", "id": "1"}]}'Alternatively, you can use the custom header:
Custom Header
curl -X POST 'https://api.flowmyna.com/v1/event' \
-H 'X-FlowMyna-Api-Key: fm_live_your_key_here' \
-H 'Content-Type: application/json' \
-d '{"event": "Test Event", "objects": [{"type": "Test", "id": "1"}]}'We recommend using the Authorization: Bearer header as it follows OAuth 2.0 standards and is widely supported by HTTP clients.
API Key → Dataset Linking
A key design decision: each API key is linked to exactly one dataset. This means:
- No dataset_id in requests — You don't need to specify where data goes
- Clear data lineage — All data from a key flows to one dataset
- Simple key management — Each integration gets its own key
When creating an API key, you'll either create a new dataset or select an existing one. The key will permanently write to that dataset.
Security Best Practices
Key Storage
Flow Myna never stores your full API key. We only store:
- Prefix — First 12 characters for identification (e.g.,
fm_live_abc1) - SHA256 Hash — Cryptographic hash of the full key for verification
This means if our database were ever compromised, attackers couldn't retrieve your actual keys.
Recommendations
- Use environment variables — Never hardcode keys in source code
- Use secrets managers — AWS Secrets Manager, HashiCorp Vault, etc.
- Never commit keys — Add them to .gitignore
- Rotate periodically — Create new keys and revoke old ones
- Use separate keys — Different keys for dev, staging, production
Environment Variable Usage
import os
from flowmyna import FlowMyna
# Load from environment variable
client = FlowMyna(api_key=os.environ['FLOWMYNA_API_KEY'])Key Lifecycle
API keys have the following states:
| State | Can Authenticate? | Description |
|---|---|---|
| Active | ✅ Yes | Key can be used for API requests |
| Revoked | ❌ No | Key was manually deactivated |
| Expired | ❌ No | Key passed its expiration date (if set) |
Revoking is permanent. Once you revoke a key, it cannot be reactivated. You'll need to create a new key.
What a Key Can Do
By default a key can do everything in its workspace:
- ✅ Write events — Track events to the linked dataset
- ✅ Write objects — Identify/upsert objects
- ✅ Create types — Auto-create event and object types
- ✅ Read process data — Through the MCP server, for agents you run
- ❌ Manage workspace — No admin access, ever
Scopes
Narrow a key to part of the API by giving it scopes when you create it. A key that only feeds your tracker has no business reading your process data, and vice versa.
| Scope | Grants |
|---|---|
ingest:write | Sending events and objects — /v1/event, /v1/event/batch, /v1/object/upsert, /v1/object/batch, /v1/track |
process:read | Reading your process data through the MCP server |
Creating a scoped key
{
"name": "Website tracker",
"dataset_id": "550e8400-e29b-41d4-a716-446655440000",
"scopes": ["ingest:write"]
}Leave scopes off and the key does everything in its workspace, exactly as before. Existing keys are unaffected. Using a key where its scopes don't reach returns 403, not 401 — the key is fine, it just isn't allowed there, so rotating it won't help. An unrecognised scope name is rejected when the key is created, so a typo can't quietly leave you with a key that does less than you meant.