Misar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisar PlatformMisar IdentityMisar Posts API
Api Reference

API Keys

Create, list, and revoke API keys programmatically via GET/POST/DELETE /v1/keys

API keys authenticate all programmatic access to the MisarMail API. Keys start with msk_ and are only shown once at creation — store them immediately in a secrets manager or environment variable.

Authentication

These endpoints manage keys, so they require a logged-in session cookie (dashboard login), not an API key.

Plan gate

The number of active API keys is limited by plan (Free: 1, Pro: 5, Max: unlimited). Creating a key when at the limit returns 403.

Endpoints

MethodPathDescription
GET/api/v1/keysList all API keys (no raw values returned)
POST/api/v1/keysCreate a new API key
DELETE/api/v1/keys?id=<uuid>Revoke a key

List API keys

GET/mail/v1/keys

List all API keys for your account. Raw key values are never returned — only the prefix (msk_ + 8 chars) for identification.

Response fields

successboolean

true when the request succeeded.

keysArray<ApiKey>

All keys for the account. Each key includes id, name, key_prefix, scopes, allowed_account_id, is_active, last_used_at, created_at, and expires_at.

curl https://api.misar.io/mail/v1/keys \
  -H "Cookie: <session_cookie>"
{
  "success": true,
  "keys": [
    {
      "id":                  "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name":                "Production sends",
      "key_prefix":          "msk_a1b2c3d4",
      "scopes":              "send,analytics",
      "allowed_account_id":  null,
      "is_active":           true,
      "last_used_at":        "2026-04-19T10:22:00Z",
      "created_at":          "2026-03-01T09:00:00Z",
      "expires_at":          null
    }
  ]
}

Create an API key

POST/mail/v1/keys

Create a new API key. The raw key (msk_...) is returned only in this response — it cannot be retrieved later.

Request body

namestringbodyrequired

Human-readable label (max 80 chars).

scopesstring[]bodydefault: ["send"]

Scopes granted to the key. See the scope table below.

allowedAccountIdUUIDbody

Restrict key to a single email account.

expiresAtISO 8601body

Optional expiry — must be a future datetime.

Response fields

successboolean

true when the key was created.

keystring

The raw API key — shown exactly once.

keyIdUUID

Identifier for the created key.

prefixstring

Key prefix (msk_ + 8 chars) for identification.

namestring

The label supplied at creation.

scopesstring

Comma-separated granted scopes.

createdAtISO 8601

Creation timestamp.

expiresAtISO 8601 | null

Expiry timestamp, or null if non-expiring.

curl -X POST https://api.misar.io/mail/v1/keys \
  -H "Cookie: <session_cookie>" \
  -H "Content-Type: application/json" \
  -d '{
    "name":   "CI pipeline key",
    "scopes": ["send", "analytics"]
  }'
{
  "success":   true,
  "key":       "msk_a1b2c3d4e5f6...",
  "keyId":     "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "prefix":    "msk_a1b2c3d4",
  "name":      "CI pipeline key",
  "scopes":    "send,analytics",
  "createdAt": "2026-04-20T12:00:00Z",
  "expiresAt": null
}
{
  "success": false,
  "error":   "API key limit reached (5 / 5). Upgrade to Max for unlimited keys.",
  "feature": "api_keys",
  "current": 5,
  "limit":   5,
  "required_plan": "max"
}

Save the key value now. It is shown exactly once. If lost, delete this key and create a new one.

Scopes

ScopeAccess granted
sendPOST /v1/send — all email sending
send:transactionalPOST /v1/send — transactional only
send:marketingPOST /v1/send — marketing only
contactsRead/write contacts, segments, scoring
campaignsCreate, update, send campaigns
templatesCreate and update email templates
automationsCreate and update automation workflows
analyticsRead analytics, reports, tracking data
validatePOST /v1/validate — email address validation
readRead-only access to all owned resources
writeWrite access to all owned resources
sandboxSend in sandbox mode (not delivered)

Grant only the minimum scopes needed. A key with send cannot read contacts or campaigns — scope separation limits blast radius if a key is compromised.

Revoke an API key

DELETE/mail/v1/keys

Revoke a key immediately. Revoked keys return 401 on all subsequent API calls.

Query parameters

idUUIDqueryrequired

ID of the key to revoke.

Response fields

successboolean

true when the key was revoked.

curl -X DELETE \
  "https://api.misar.io/mail/v1/keys?id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Cookie: <session_cookie>"
{ "success": true }

Error responses

CodeReason
400id missing or not a valid UUID
404Key not found or belongs to another user

Account-Scoped Keys

To restrict a key so it can only send from one specific email account (useful for multi-account setups or client isolation):

{
  "name":             "Client A sends only",
  "scopes":           ["send"],
  "allowedAccountId": "550e8400-e29b-41d4-a716-446655440000"
}

When allowedAccountId is set, any send request where from.email doesn't match that account returns 403.

Key Rotation Pattern

Rotate keys without downtime:

  1. POST /api/v1/keys — create new key with identical scopes
  2. Deploy new key to your service
  3. Verify traffic is using the new key (last_used_at on old key stops updating)
  4. DELETE /api/v1/keys?id=<old_id> — revoke the old key

Examples

# Create a send-only key expiring in 90 days
curl -X POST https://api.misar.io/mail/v1/keys \
  -H "Cookie: <session_cookie>" \
  -H "Content-Type: application/json" \
  -d '{
    "name":      "Transactional key (90d)",
    "scopes":    ["send:transactional"],
    "expiresAt": "2026-07-20T00:00:00Z"
  }'
const res = await fetch("https://api.misar.io/mail/v1/keys", {
  method: "POST",
  headers: { "Cookie": sessionCookie, "Content-Type": "application/json" },
  body: JSON.stringify({
    name:   "Transactional key (90d)",
    scopes: ["send:transactional"],
    expiresAt: new Date(Date.now() + 90 * 86400_000).toISOString(),
  }),
});
const { key } = await res.json();
// Store `key` in your secrets manager immediately