Home
API Integrations

REST API

Use the Nitrosend REST API from any language, tool, or automation platform

The Nitrosend REST API works with any HTTP client. Use it to integrate email marketing into your app, connect to automation platforms like Zapier or n8n, or build custom tools in any programming language.

Info

All plans, including free plans, have full access to Nitrosend MCP/API/CLI. REST API access is not restricted to paid plans; plan limits apply to usage volume and paid add-ons.

Base URL

https://api.nitrosend.com/v1/my

All endpoints are prefixed with /v1/my and scoped to your account.

Authentication

Every request requires a Bearer token in the Authorization header:

Authorization: Bearer <your-nitrosend-api-key>

Get your API key from Brand > API Keys in the Nitrosend dashboard.

Quick examples

Send an email

curl -X POST https://api.nitrosend.com/v1/my/messages \
  -H "Authorization: Bearer $NITROSEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "to": "user@example.com",
    "subject": "Welcome to our platform",
    "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    "body": "Welcome! Thanks for signing up."
  }'

List campaigns

curl https://api.nitrosend.com/v1/my/campaigns \
  -H "Authorization: Bearer $NITROSEND_API_KEY"

Create a contact

curl -X POST https://api.nitrosend.com/v1/my/contacts \
  -H "Authorization: Bearer $NITROSEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "opt_in": true
  }'

Get account status

curl https://api.nitrosend.com/v1/my/account \
  -H "Authorization: Bearer $NITROSEND_API_KEY"

Language examples

Python

import requests

API_KEY = "nskey_live_your_key_here"
BASE_URL = "https://api.nitrosend.com/v1/my"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# Send an email
response = requests.post(f"{BASE_URL}/messages", headers=HEADERS, json={
    "channel": "email",
    "to": "user@example.com",
    "subject": "Hello from Python",
    "html": "<h1>Hi!</h1>",
    "body": "Hi!"
})
print(response.json())

# List campaigns
campaigns = requests.get(f"{BASE_URL}/campaigns", headers=HEADERS)
print(campaigns.json())

JavaScript / Node.js

const API_KEY = "nskey_live_your_key_here";
const BASE_URL = "https://api.nitrosend.com/v1/my";
const headers = {
  Authorization: `Bearer ${API_KEY}`,
  "Content-Type": "application/json",
};

// Send an email
const response = await fetch(`${BASE_URL}/messages`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    channel: "email",
    to: "user@example.com",
    subject: "Hello from Node.js",
    html: "<h1>Hi!</h1>",
    body: "Hi!",
  }),
});
console.log(await response.json());

// List campaigns
const campaigns = await fetch(`${BASE_URL}/campaigns`, { headers });
console.log(await campaigns.json());

Ruby

require "net/http"
require "json"

API_KEY = "nskey_live_your_key_here"
BASE_URL = "https://api.nitrosend.com/v1/my"

def nitrosend_request(method, path, body = nil)
  uri = URI("#{BASE_URL}#{path}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = case method
            when :get then Net::HTTP::Get.new(uri)
            when :post then Net::HTTP::Post.new(uri)
            end

  request["Authorization"] = "Bearer #{API_KEY}"
  request["Content-Type"] = "application/json"
  request.body = body.to_json if body

  JSON.parse(http.request(request).body)
end

# Send an email
result = nitrosend_request(:post, "/messages", {
  channel: "email",
  to: "user@example.com",
  subject: "Hello from Ruby",
  html: "<h1>Hi!</h1>",
  body: "Hi!"
})
puts result

Transactional messages

POST /v1/my/messages queues a single transactional email or SMS and returns the message resource. Delivery happens through Nitrosend's normal background sender, so the response means "accepted for sending", not "delivered".

For email, pass channel: "email", to, subject, and one of html, body, or template_id. body is plain text; HTML belongs in html. Optional per-message delivery options are available for email only:

{
  "channel": "email",
  "from": "Acme <hello@example.com>",
  "to": "user@example.com",
  "subject": "Your receipt",
  "html": "<p>Thanks for your purchase.</p>",
  "body": "Thanks for your purchase.",
  "reply_to": "support@example.com",
  "headers": { "X-Entity-Ref-ID": "order_123" },
  "tags": { "kind": "receipt", "plan": "pro" }
}

from / from_email must resolve to a verified sender identity for the brand. Reserved provider headers and reserved Nitrosend tag keys are rejected. System tags such as account_id, brand_id, and message_id are always controlled by Nitrosend.

Pass an Idempotency-Key header on retries. Reusing the same key with the same payload returns the original message. Reusing the key with a different payload returns 409 idempotency_conflict.

Suppressions

GET /v1/my/suppressions lists the account's active email suppressions by default. Use it to inspect hard bounces, soft-bounce suppressions, complaints, manual suppressions, and the bounded provider diagnostic text retained from the source feedback event.

Common filters include email, reason, source_provider, and active=false for expired suppressions.

Delivery capacity

GET /v1/my/delivery/status returns the current Brand's read-only delivery projection: commercial, exact-sender, and Nitrosend brand-subdomain capacity, plus pacing and a bounded public reason/remediation. This endpoint never authorizes or reserves a send. The actual send still passes through the single delivery authority, so clients must not calculate headroom from a plan name.

Explicit prepaid validation

Email validation is never included or triggered by import, schedule, or send. Quote exactly one current-Brand audience first:

curl -X POST https://api.nitrosend.com/v1/my/validation_operations/quote \
  -H "Authorization: Bearer $NITROSEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"list_id": 42}'

After inspecting the candidate counts, funding state, and maximum prepaid charge, start the durable operation with a stable idempotency key:

curl -X POST https://api.nitrosend.com/v1/my/validation_operations \
  -H "Authorization: Bearer $NITROSEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: validation-list-42-2026-08" \
  -d '{"list_id": 42}'

The request must contain exactly one of contact_channel_ids, contact_ids, list_id, or segment_id. Reusing the key with the same audience returns or resumes the same operation; changing the audience conflicts. Poll the operation and list its retained per-candidate items. Validation does not prove consent or increase sender capacity.

Endpoint reference

ActionMethodEndpoint
Messages
Send a messagePOST/messages
List messagesGET/messages
Suppressions
List suppressionsGET/suppressions
Delivery
Get capacity and pacing statusGET/delivery/status
Email validation
Quote validationPOST/validation_operations/quote
Start or resume validationPOST/validation_operations
Get validation operationGET/validation_operations/{id}
List validation resultsGET/validation_operations/{id}/items
Events
Track a contact eventPOST/events
List eventsGET/events
Campaigns
List campaignsGET/campaigns
Create campaignPOST/campaigns
Get campaignGET/campaigns/{id}
Update campaignPATCH/campaigns/{id}
Send campaignPOST/campaigns/{id}/send
Contacts
List contactsGET/contacts
Create contactPOST/contacts
Bulk import contactsPOST/imports
Poll import statusGET/imports/{id}
Lists
List contact listsGET/lists
Create listPOST/lists
Add/remove contacts by emailPOST/lists/{id}/contacts/bulk
Templates
List templatesGET/templates
Create templatePOST/templates
Get templateGET/templates/{id}
Update templatePATCH/templates/{id}
Send test emailPOST/templates/{id}/send_test
Flows
List flowsGET/flows
Create flowPOST/flows
Segments
List segmentsGET/segments
Account
Get account infoGET/account

See the full API Reference for detailed request/response schemas.

Bulk imports

Use POST /v1/my/imports with multipart/form-data to upload a CSV. The response includes an import id; poll GET /v1/my/imports/{id} for status, row counts, and row-level errors. For contact imports, pass options with list_ids so imported contacts are assigned to the target list:

curl -X POST https://api.nitrosend.com/v1/my/imports \
  -H "Authorization: Bearer $NITROSEND_API_KEY" \
  -F "file=@contacts.csv" \
  -F "resource=contacts" \
  -F 'options={"list_ids":[88]}'

Pagination

List endpoints return paginated results. Pagination headers are included in the response:

HeaderDescription
X-Total-CountTotal number of records
X-Total-PagesTotal number of pages
X-Page-NumberCurrent page number

Use ?page=2&limit=25 query parameters to navigate pages.

Error handling

Errors return JSON with a consistent structure:

{
  "error": true,
  "code": "validation_error",
  "message": "Email is required",
  "validation_errors": {
    "email": ["can't be blank"]
  }
}
Status codeMeaning
200Success
201Created
401Invalid or missing API key
404Resource not found
422Validation error
429Rate limited

OpenAPI spec

The full API specification is available as OpenAPI 3.1 YAML:

https://api.nitrosend.com/openapi.yaml

Import this into any tool that supports OpenAPI — Postman, Insomnia, Swagger UI, or API clients in any language.