NewDash Dots are hereMini apps in Dash, with payments built inLearn more

Developer Resources · API Basics

Errors

How the Monime API reports errors, what each status code means, which errors to retry, and how to handle them in your integration.

Every Monime API response says whether the request succeeded. A failed request returns an HTTP status of 400 or above and an error object that says why, so your code can decide whether to fix the request, retry it, or stop.

The error response

A successful response has "success": true and a result. A failed one has "success": false and an error:

JSON
{
  "success": false,
  "messages": [],
  "error": {
    "code": 409,
    "reason": "idempotency_key_in_use",
    "message": "Conflict: Idempotency key reused with a non-identical request.",
    "details": []
  }
}
FieldWhat it is
codeThe HTTP status code, repeated in the body
reasonA short, stable name for the error, such as too_many_requests. Branch on this in your code
messageA sentence for people, which can change: log it, but don't match on it
detailsMore about the error, such as the fields at fault, when there is more to say

Every response also carries a Monime-Request-Id header. Log it with each failure, and include it when you contact Monime support: it identifies the exact request.

Status codes

StatusWhat it meansWhat to do
2xxThe request succeededUse the result
400–499The request can't succeed as it is, such as invalid inputFix the request; sending it again unchanged fails again
401The access token is missing, invalid or expiredCheck the Authorization header, or create a new token. See Authentication
403The token is valid, but lacks the permission or Space access the request needsCheck the token's scopes and the Monime-Space-Id header
404The object doesn't exist, in this Space and environmentCheck the ID, the Space and whether you used a test or live token
409idempotency_key_in_use: an Idempotency-Key was reused for a different requestFix how your code chooses keys. See Idempotency
429too_many_requests: a rate limit was reached. Nothing happenedWait the seconds in Retry-After, then retry. See Rate limiting
500–599Something failed at MonimeRetry with backoff, with the same Idempotency-Key

Retry or fix?

  • Retry network errors, 429 and 5xx responses. Wait between attempts, longer each time, and add a little randomness so many clients don't retry at once. On 429, wait at least Retry-After seconds.
  • Send every retry of a create with the same Idempotency-Key, method, URL and body, so a retry after a timeout can never create a second payout or payment.
  • Don't retry other 4xx errors without changing the request: fix what the error names first.
  • If you can't tell whether a create succeeded, such as after a timeout, GET the object before trying again. A 404 means it was never created.

Handle errors in code

monime.ts
type MonimeError = { code: number; reason: string; message: string; details: unknown[] };

export async function callMonime(path: string, init: RequestInit, attempts = 5): Promise<unknown> {
  for (let attempt = 1; ; attempt++) {
    let response: Response;
    try {
      response = await fetch(`https://api.monime.io${path}`, init);
    } catch (networkError) {
      if (attempt === attempts) throw networkError;
      await wait(backoff(attempt));
      continue;
    }

    const payload = await response.json();
    if (payload.success) return payload.result;

    const error: MonimeError = payload.error;
    const requestId = response.headers.get('Monime-Request-Id');
    const retryable = response.status === 429 || response.status >= 500;
    if (!retryable || attempt === attempts) {
      console.error(`Monime ${error.reason} (request ${requestId}): ${error.message}`);
      throw Object.assign(new Error(error.message), { reason: error.reason, requestId });
    }

    // On 429, Retry-After says how long to wait; otherwise back off.
    const retryAfter = Number(response.headers.get('Retry-After'));
    await wait(retryAfter > 0 ? retryAfter * 1000 : backoff(attempt));
  }
}

const backoff = (attempt: number) => 2 ** attempt * 500 + Math.random() * 250;
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

Pass the same init, including its Idempotency-Key header, to every attempt, so each retry is identical.

Errors in webhooks

Webhook deliveries are retried by Monime when your endpoint doesn't answer with a 2xx. See Delivery and retries for how to answer them, and Troubleshoot for common failures.

Keep reading