SonarSend API Getting started Errors & troubleshooting

Errors & troubleshooting

This page covers the most common API integration errors.

Error shape#

Most external API errors use this shape:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable explanation"
  }
}

Some low-level infrastructure errors may still appear differently while the API is evolving, but the goal is to return domain-specific 400/403/404 responses wherever possible.

Authentication and scope errors#

API_KEY_FORBIDDEN#

Meaning:

  • the route is not part of the public API for service-account keys

A 403 here is not a scope problem and adding scopes will not fix it. The capability is one the app keeps to itself; see what service-account keys cannot do.

ACTION_NOT_AVAILABLE#

Meaning:

  • the endpoint is public, but the specific action asked for is not available to API keys

Today this is reset_status on POST /api/contacts/bulk — see bulk actions. Every other action on that endpoint works normally.

INSUFFICIENT_SCOPE#

Meaning:

  • the key is valid, but it lacks the required scope

Example:

{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "This key is missing a required scope: broadcasts:schedule"
  }
}

Broadcast validation errors#

INVALID_EMAIL_TYPE#

Meaning:

  • email_type_key was not found for the tenant

INVALID_MTA_CONFIG#

Meaning:

  • mta_config_key was not found for the tenant

INVALID_SEGMENT#

Meaning:

  • one of the supplied segment keys was not found for the tenant

INVALID_SENDING_IDENTITY#

Meaning:

  • one of the supplied sender email addresses was not found for the tenant

INVALID_TEMPLATE#

Meaning:

  • content.template_slug was not found for the tenant

INVALID_METADATA#

Meaning:

  • broadcast metadata fails validation

Typical causes:

  • key doesn’t match /^[a-z][a-z0-9_]{0,63}$/
  • nested objects in values
  • more than 20 keys
  • serialized size exceeds 8KB

INVALID_METADATA_FILTER#

Meaning:

  • the metadata query parameter on the list endpoint is not valid JSON or not a plain object

INVALID_STATUS#

Meaning:

  • the status query parameter on the list endpoint contains an unrecognized status value

NO_CONTENT#

Meaning:

  • required content fields are missing

Typical causes:

  • missing content.subject
  • missing both content.body_html and content.body_mjml (unless using template-mode with template_slug + template_binding)

INVALID_VARIANTS#

Meaning:

  • the A/B variant payload is incomplete or malformed

Typical causes:

  • fewer than 2 variants
  • missing id, name, or positive weight
  • no meaningful content override on a variant

ADVANCED_SPLIT_TEST_UNSUPPORTED#

Meaning:

  • the request used advanced split-test fields not supported in the public API

Rate limits#

Each API key gets its own budget of 1000 requests per minute. The limit is per key, not per workspace, so one integration cannot starve another — and a runaway loop in one place doesn’t take down the rest of your automation.

Every response carries the current state:

HeaderMeaning
X-RateLimit-LimitRequests allowed in the window
X-RateLimit-RemainingRequests left
X-RateLimit-ResetSeconds until the window resets

Exceeding it returns 429:

{
  "statusCode": 429,
  "error": {
    "code": "RATE_LIMITED",
    "message": "API key rate limit exceeded (1000 requests/minute). Retry after 42 seconds."
  }
}

Back off using X-RateLimit-Reset rather than retrying immediately.

If you are hitting this, the usual cause is per-record requests where a bulk endpoint exists. POST /api/contacts/bulk and PUT /api/contacts handle many contacts per call, GET /api/broadcasts/metrics-bulk covers a whole dashboard in one request, and a contact export reads out an entire audience for the price of a handful of polls.

A few endpoints — login, password reset, and other unauthenticated surfaces — carry their own stricter limits that apply regardless of credentials.

Scheduling errors#

NO_SEGMENT#

Meaning:

  • the broadcast does not have an included audience

NO_MTA#

Meaning:

  • the broadcast does not have a valid MTA configuration

NO_IDENTITY#

Meaning:

  • the broadcast cannot resolve a valid sender identity or was given an invalid empty sender list

NOT_DRAFT#

Meaning:

  • the requested action only applies to drafts

Troubleshooting checklist#

If a broadcast request fails:

  1. Confirm the tenant slug in the URL is correct.
  2. Confirm the API key has the expected scopes.
  3. Confirm email_type_key exists in GET /api/email-types.
  4. Confirm mta_config_key matches a sending provider configured in the app, or omit it and let SonarSend resolve the delivery path.
  5. Confirm include_segment_keys / exclude_segment_keys exist in GET /api/segments.
  6. Confirm sending_identity_emails exist in GET /api/sending-identities.
  7. If using template-mode, confirm content.template_slug exists in GET /api/templates.
  8. If scheduling fails, confirm the draft is complete enough to send.