MessagePipedocs
API Reference

Errors

The standard error envelope and the canonical code to HTTP status table.

Every error response has the same shape:

{
  "error": {
    "code": "credits_exhausted",
    "message": "Workspace has no email credits remaining.",
    "details": { "channel": "email" },
    "request_id": "req_06F4Y9CP1GQB39AA",
    "documentation_url": "https://docs.dev.messagepipe.dev/errors/credits_exhausted"
  }
}

details is optional and varies by code; the other four fields are always present. The request_id is the value of X-Request-Id on the same response, quote it to support.

Codes

CodeStatusMeaning
invalid_json400The request body wasn't valid JSON.
validation_failed400A required field is missing or malformed. details.field names it, and details.constraint says which rule it broke. key:case means a field was spelled with different case than documented (Subject for subject).
template_not_found400The referenced template doesn't exist in this project.
unauthorized401Missing or invalid credential (Bearer token, session cookie).
credits_exhausted402Workspace has zero credits on this channel.
forbidden403Authenticated, but not allowed (role, scope).
insufficient_scope403API key doesn't carry the scope this endpoint requires.
sender_not_allowed403An email from isn't on the project's sender domains. details.domain is the domain you sent; details.allowed_domains lists the allowed ones.
not_found404The resource doesn't exist or isn't visible to you.
conflict409The resource's state prevents the operation.
idempotency_in_progress409A previous request with this Idempotency-Key is still running.
idempotency_mismatch422Request body differs from the first call with this key.
rate_limit_exceeded429See the Retry-After header.
internal_error500A bug. Open a ticket with the request_id.
provider_error502An upstream provider returned a 5xx after the worker exhausted retries.
service_unavailable503Planned maintenance or a hard outage.

Failures after the 202

These codes describe a request that was rejected. A send that is accepted returns 202 Accepted and can still fail later, at render or at the provider. That failure has no HTTP status: it lands on the send itself, as failure_code and failure_reason on GET /v1/sends/{id} (Delivery logs).

One of those codes comes from your own project settings: provider_not_pinned means the project pins its providers exclusively and none of the pinned ones could take the send. The send is not routed to any other provider, and its credits are refunded.

A missing template variable is neither. It renders as an empty string, with no error and no failure — a forgotten variable ships a message with a blank subject or a hole in the body. Use the default helper to make the fallback explicit (Template syntax).