HyoNovaDocumentation

API conventions

The conventions HyoNova APIs follow — base URL, JSON errors, request IDs, HTTP status codes, cursor pagination, idempotency keys and rate limits — as the Mail API applies them.

AvailableWorks today for workspaces whose plan includes it.ReferenceFor: DevelopersLast updated: Introduced:
On this page

HyoNova's APIs share a small set of conventions for errors, pagination, retries and limits. The Mail API follows them today. A general public API is planned and will follow the same conventions.

Requests and responses#

  • Requests and responses use JSON (Content-Type: application/json).
  • Every response carries an X-Request-Id header. Include it when you contact HyoNova about a problem.
  • Responses to API requests are not cached (Cache-Control: no-store).

Errors#

Every error has the same shape, whatever the endpoint:

json
{
  "error": {
    "code": "SENDER_NOT_VERIFIED",
    "message": "Add and verify a sender before sending."
  }
}
  • code is a stable, machine-readable string. Branch on it, not on the message.
  • message is a human-readable explanation. It can change and is not meant for parsing.

Unexpected server errors return a generic message (INTERNAL_ERROR). Details are logged on HyoNova's side under the request ID, never returned in the response.

HTTP status codes#

StatusMeaningExamples of code
200Success—
202Accepted for processing, such as an email queued for delivery—
400The request is invalidVALIDATION_ERROR
401No credential, or the credential is no longer validAUTHENTICATION_REQUIRED, API_KEY_INVALID, API_KEY_EXPIRED
402Not enough credits for this requestINSUFFICIENT_CREDITS
403Authenticated, but not allowed to do thisFORBIDDEN, FEATURE_NOT_ENTITLED
404The resource does not exist or is not visible to youNOT_FOUND
409Conflict with the current stateSENDER_NOT_VERIFIED, IDEMPOTENCY_CONFLICT
413The request body is too large—
429Too many requests—
500Unexpected error on HyoNova's sideINTERNAL_ERROR

Records that belong to another company are never visible, whatever the request or the key.

Pagination#

List endpoints — GET /mail/v1/messages and GET /mail/v1/contacts — use an opaque cursor.

  • Pass limit to choose the page size. The default is 25 and the maximum is 100.
  • The response has items and nextCursor. When nextCursor is null, there are no more pages.
  • To get the next page, pass the nextCursor value back as cursor. Do not build or change cursors yourself.
json
{
  "items": [{ "id": "…" }, { "id": "…" }],
  "nextCursor": "b3f1…"
}

Idempotency#

POST endpoints accept an Idempotency-Key header. Send a new unique value for each logical operation, and reuse the same value when you retry that operation after a timeout or a network error.

  • The first answer under a key is kept for 24 hours for that API key. A retry with the same key and body gets the same answer again, with Idempotent-Replayed: true.
  • The same key with a different body answers 409 IDEMPOTENCY_CONFLICT.
  • On POST /mail/v1/send, the key also names the message for your whole company: a later call with the same key returns the original message with "replayed": true and sends nothing new. Use a key that names the message, such as order-1001-confirmation, up to 160 characters.

Rate limits#

The Mail API accepts up to 600 requests per minute per API key (300 per minute for POST /mail/v1/conversions). Every response carries x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset. When you exceed the limit you receive the HTTP status 429 with a retry-after header in seconds. Detect it by the status code, wait, and use increasing delays between attempts.

Example: handling errors#

Node.js / TypeScript
async function sendWithRetry(body: unknown, idempotencyKey: string) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const response = await fetch('https://api.hyonova.com/mail/v1/send', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.HYO_MAIL_API_KEY}`, // YOUR_API_KEY
        'Content-Type': 'application/json',
        'Idempotency-Key': idempotencyKey, // the same key on every retry
      },
      body: JSON.stringify(body),
    });
    if (response.status === 202) return response.json();
    if (response.status === 429 || response.status >= 500) {
      const wait = Number(response.headers.get('retry-after')) || 2 ** attempt;
      await new Promise((r) => setTimeout(r, wait * 1000)); // back off, then retry
      continue;
    }
    const { error } = await response.json();
    const requestId = response.headers.get('X-Request-Id');
    throw new Error(`${error.code} (${requestId}): ${error.message}`); // do not retry
  }
  throw new Error('Gave up after 5 attempts');
}

Status#

FeatureStatusNotes
Transactional email APIAvailableWorks today for workspaces whose plan includes it.Send email from your own systems with API keys, a message log and signed webhooks. Part of Hyo Mail.
Signed webhooksAvailableWorks today for workspaces whose plan includes it.Receive signed Hyo Mail delivery, engagement, contact and store events at your HTTPS endpoint, with automatic and manual retries.
SMTP relay for Hyo MailPlannedOn the HyoNova roadmap. Not built yet and has no release date.Send through Hyo Mail over SMTP.
Public HyoNova APIPlannedOn the HyoNova roadmap. Not built yet and has no release date.A supported, documented API for your company’s people, work and customer data.
MCP serverPlannedOn the HyoNova roadmap. Not built yet and has no release date.Let AI assistants work with your HyoNova data through the Model Context Protocol, with your permission.
↑↓ to navigate · Enter to open · Esc to close