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. A few surfaces are bearer-only in the other direction and reject sessions outright: the MCP endpoint and the internal staff API.

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 the Settings page in the dashboard. Each key can be scoped to specific permissions.

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
  • 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