Kraiter
API Reference

API Overview

Authentication, error handling, pagination, and rate limits for the Kraiter API.

The Kraiter API is a RESTful JSON API for managing contacts, templates, sequences, segments, campaigns, and transactional email. All endpoints are scoped to your organisation via JWT authentication.

Base URL

All API requests are made to:

https://api.kraiter.com

Every endpoint is prefixed with /api — for example, https://api.kraiter.com/api/contacts.

Authentication

Authenticate every request by including a Bearer token in the Authorization header. You can generate API keys from the Kraiter dashboard under Settings > API Keys.

curl https://api.kraiter.com/api/contacts \
  -H "Authorization: Bearer YOUR_API_KEY"
import { Mailer } from "@kraiter/sdk";

const kraiter = new Mailer({ apiKey: "YOUR_API_KEY" });

The API key determines your tenant (organisation) context. All resources returned are scoped to that tenant — you do not need to pass an organisation ID explicitly. See API Keys for details on key format, limits, and management.

Requests without a valid token receive a 401 Unauthorised response.

Request format

All request bodies must be JSON with the Content-Type: application/json header. Query parameters are used for filtering and pagination on GET endpoints.

Response format

Successful responses return a JSON object. Single-resource endpoints return the resource directly. List endpoints return an object with an items array and pagination metadata (nextCursor for cursor-paginated endpoints, or hasMore for the timeline and scheduled-send endpoints).

{
  "items": [{ "contactId": "cnt_01H...", "email": "alice@example.com" }],
  "nextCursor": "eyJpZCI6ImNudF8wMUgi..."
}

Errors

When a request fails, the API returns an error object with a machine-readable code and a human-readable message:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request body",
    "details": { "fields": { "email": ["Invalid email address"] } }
  }
}

The error object always includes a details object (empty {} when there is nothing to add). For 5xx responses in production, details is omitted (returned as {}) so internal error text is never leaked.

Common error codes

HTTP StatusCodeDescription
400VALIDATION_ERRORThe request body or query parameters are invalid.
401UNAUTHORIZEDMissing or invalid authentication token.
402PLAN_LIMIT_EXCEEDEDA plan limit (contacts, templates, sequences) was reached.
402BILLING_SUSPENDEDBilling is suspended for the organisation.
403FORBIDDENThe token does not have permission for this action.
404NOT_FOUNDThe requested resource does not exist. Resource-specific variants exist too (e.g. CONTACT_NOT_FOUND, TEMPLATE_NOT_FOUND, SEQUENCE_NOT_FOUND, SEGMENT_NOT_FOUND, DOMAIN_NOT_FOUND, SEND_NOT_FOUND, SCHEDULED_SEND_NOT_FOUND).
409CONTACT_EXISTSA contact with this email already exists.
409SEGMENT_REFERENCEDThe segment cannot be deleted because it is referenced by another segment.
422DOMAIN_NOT_VERIFIEDThe domain is not verified.
422CIRCULAR_DEPENDENCYSegment rules would create a circular dependency.
429RATE_LIMITEDToo many requests — see Rate limiting.
500INTERNAL_ERRORAn unexpected server error occurred.

Pagination

List endpoints use cursor-based pagination. Pass cursor and limit as query parameters to page through results.

ParameterTypeDefaultDescription
cursorstringOpaque cursor from a previous response's nextCursor.
limitnumber20Number of items to return (max 100).

When there are more results, the response includes a nextCursor field. When there are no more results, nextCursor is null or absent.

# First page
curl "https://api.kraiter.com/api/contacts?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Next page
curl "https://api.kraiter.com/api/contacts?limit=10&cursor=eyJpZCI6ImNudF8wMUgi..." \
  -H "Authorization: Bearer YOUR_API_KEY"
// Iterate through all contacts
let cursor: string | undefined;
do {
  const page = await kraiter.contacts.list({ limit: 50, cursor });
  for (const contact of page.items) {
    console.log(contact.email);
  }
  cursor = page.nextCursor ?? undefined;
} while (cursor);

Rate limiting

The API allows 100 requests per minute per tenant. When you exceed this limit, requests return 429 Too Many Requests with a Retry-After header indicating how many seconds to wait.

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 12 seconds."
  }
}

The Retry-After response header contains the number of seconds to wait before making another request.

Best practices

  • Cache responses where possible to reduce request volume.
  • Use list endpoints with pagination rather than fetching resources individually.
  • Implement exponential back-off when receiving 429 responses.
  • Contact support if you consistently need higher limits.

Idempotency

PUT endpoints (templates, sequences) are idempotent — calling them with the same ID and body produces the same result. Use PUT to create or update resources without worrying about duplicate creation.

Resources

Explore the full reference for each resource: