NevarMail

Authenticate API requests

Create an API key, pick the right scopes, and read the responses the API sends back.

NevarMail supports two authentication methods: session-based authentication for the dashboard, and API key authentication for programmatic access.

Session authentication

When you sign in through the NevarMail dashboard, a session cookie is automatically managed. All requests from the dashboard UI use this session for authentication. No additional configuration is required.

A signed-in session can also call the /api/v1/* endpoints documented here: where an API key is checked for a scope, a session is authorized against your role's permissions instead. That is what lets the dashboard call the same endpoints your integration does.

The reverse is not true — API keys cannot be used against dashboard-only routes, which answer 403 SESSION_ONLY. One surface is bearer-only in the other direction and rejects sessions outright: the MCP endpoint.

For an integration, use an API key: it is scoped, revocable, and not tied to a person who might leave.

API key authentication

For programmatic access, include your API key in the request headers against the /api/v1/* endpoints:

curl -X POST https://app.nevarmail.com/api/v1/email/send \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"to":"user@example.com","subject":"Hello","text":"Hi there"}'

For local development, use http://localhost:3400 in place of https://app.nevarmail.com.

Generating API keys

API keys can be generated from Settings → API Keys in the dashboard. Each key can be scoped to specific permissions. A key also has a type: API keys are for your own code and work on /api/v1/*; MCP keys are for an AI agent and work only on the MCP endpoint (Connect an AI agent).

Key reach: one project or the whole organization

The dashboard creates organization-wide keys only: a key created there reaches every project the key owner can open and may send as any of their use cases. To pin a key to one project, create it over the API (below). A send with such an organization-wide key must name its use_case_id; one that names none is refused with 422 USE_CASE_REQUIRED.

When creating keys over the API (POST /api/api-keys, a signed-in session only) you can pin a key to one project by passing project_id: every API and MCP call made with the key then stays inside that project, data in other projects reads as not found (404), and a send that names no use_case_id runs as that project's default use case. Optionally pass use_case_ids to limit which use cases the key may send as; a send as any other use case is refused with 403 USE_CASE_NOT_ALLOWED. use_case_ids requires project_id, and every id must belong to that project. Reach is set when the key is created and can't be edited; rotating a key keeps its project and use cases, so to change a key's reach, create a new key and revoke the old one.

Key scopes

ScopeDescription
email:sendSend Email -- gates single sends, scheduled sends, and list sends
templates:readTemplates (read)
templates:writeTemplates (write)
senders:readSenders (read)
senders:writeSenders (write)
analytics:readAnalytics (read)
campaigns:readCampaigns (read)
lists:readLists (read)
lists:writeLists (write)
sequences:readSequences (read)
sequences:writeSequences (write)
domains:readDomains (read)
domains:writeDomains (write)
contacts:readContacts (read)
contacts:writeContacts (write)
providers:readProviders (read)
org:readOrganization (read)
org:writeOrganization (write)
inbox:readInbox (read)
inbox:sendInbox (send)
webhooks:readWebhook endpoints (read)
webhooks:writeWebhook endpoints (write)
use-cases:readUse cases (read)
use-cases:writeUse cases (write)
*Full access (all scopes)

Connecting an app with OAuth

Apps such as Claude's connector can ask for access through NevarMail's sign-in and consent screen instead of an API key. The consent screen lists what the app will get and anything it asked for that your role in the organization doesn't allow, under "Not granted". You can only give an app access you have yourself: approving grants just the scopes your role backs, and the token the app receives reports that narrower list. If your role allows none of what the app asked for, approval fails with invalid_scope and no access is granted.

The grant follows your role over time. When the app refreshes its token, the new token carries only what your role allows at that moment, so a role change narrows connected apps too; removing you from the organization ends their access at the next refresh.

Request headers

All API requests should include:

HeaderRequiredDescription
Content-TypeYes (POST/PUT)Must be application/json
AuthorizationYesBearer YOUR_API_KEY

Response format

Success responses use a standard envelope with the result under data, a requestId for support/debugging, and pagination on list endpoints:

{
  "data": { "id": "...", "status": "sent" },
  "requestId": "req_...",
  "pagination": { "page": 1, "perPage": 25, "total": 3 }
}

Error responses always return an error field with a human-readable message. Most errors also include a machine-readable code and the requestId; an invalid API key returns only error, with no code field:

{
  "error": "Template not found",
  "code": "NOT_FOUND",
  "requestId": "req_..."
}
{
  "error": "Invalid API key"
}

Error codes

CodeMeaning
(no code field)Invalid or missing API key -- response is {"error": "Invalid API key"} with a 401 status and no code
SCOPE_DENIEDThe API key's granted scopes do not include the scope the endpoint requires
PERMISSION_DENIEDThe caller's role does not hold the RBAC permission the action requires
VALIDATION_ERRORThe request body failed schema validation
NOT_FOUNDThe requested resource does not exist (or is not visible to this org)
RATE_LIMITEDThis key has used its per-minute allowance -- 429, with Retry-After
SESSION_ONLYThe route only accepts a signed-in browser session, not an API key -- 403. Use the /api/v1/ equivalent

Rate limiting

API-key requests are limited to 60 per minute per key, regardless of plan; an individual key can be given a higher limit on request. See Rate Limits for the headers and how to back off.

Security best practices

  • Rotate keys regularly -- Generate new API keys periodically and revoke old ones
  • Use minimal scopes -- Only grant the permissions each key actually needs
  • Scope keys to one project (over the API) -- An organization-wide key reaches every project the key owner can open; keep it for integrations that really need them all
  • Keep keys secret -- Never expose API keys in client-side code or public repositories
  • Use environment variables -- Store keys in environment variables, not in code

On this page