Skip to main content

Documentation Index

Fetch the complete documentation index at: https://yanhgming.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

When a request fails, the Marlin API returns a JSON body with a single error object. The code field is a machine-readable string you can match on programmatically; message is a human-readable explanation intended for logs and debugging — do not display it verbatim to end users.

Error response format

{
  "error": {
    "code": "INVOICE_NOT_FOUND",
    "message": "No invoice with that ID exists on your account."
  }
}

HTTP status codes

StatusMeaning
400 Bad RequestThe request body or query parameters failed validation. Check the code and fix the request before retrying.
401 UnauthorizedThe Authorization header is missing, malformed, or the key has been revoked.
403 ForbiddenThe key is valid but does not have permission to perform this action (e.g. accessing another merchant’s resource).
404 Not FoundThe resource does not exist or does not belong to your account.
429 Too Many RequestsYou have exceeded the rate limit. Wait until X-RateLimit-Reset before retrying.
500 Internal Server ErrorAn unexpected error occurred on the Marlin server. Retry with exponential back-off.

Error codes

CodeStatusDescription
UNAUTHORIZED401Missing or invalid API key.
FORBIDDEN403The key exists but cannot access this resource.
CodeStatusDescription
VALIDATION_ERROR400One or more request fields failed schema validation. The details field contains a issues array with per-field messages.
CodeStatusDescription
INVOICE_NOT_FOUND404No invoice with that ID exists on your account.
INVOICE_NOT_OPEN400The void action requires the invoice to be in Open status.
CodeStatusDescription
NOT_FOUND404The subscription, plan, or customer does not exist.
VALIDATION_ERROR400The requested status transition is invalid (e.g. pausing an already-paused subscription).
CodeStatusDescription
INTERNAL500An unexpected server-side error. Retry with back-off.

Handling errors with the TypeScript SDK

The SDK exports MarlinAPIError — a typed exception that captures the HTTP status code, machine-readable code, and any additional details returned by the server.
import { Marlin, MarlinAPIError } from "@marlin/sdk";

const marlin = new Marlin({ apiKey: "sk_live_abc123" });

try {
  const invoice = await marlin.invoices.retrieve("inv_not_real");
} catch (err) {
  if (err instanceof MarlinAPIError) {
    console.error("Status :", err.statusCode); // e.g. 404
    console.error("Code   :", err.code);       // e.g. "INVOICE_NOT_FOUND"
    console.error("Message:", err.message);
    console.error("Details:", err.details);    // null | Record<string, unknown>
  } else {
    // Network error, timeout, etc.
    throw err;
  }
}

MarlinAPIError fields

statusCode
number
required
The HTTP status code returned by the API (e.g. 400, 401, 404, 500).
code
string
required
Machine-readable error code (e.g. INVOICE_NOT_FOUND, VALIDATION_ERROR).
message
string
required
Human-readable explanation of the error.
details
object | null
Optional structured context — for VALIDATION_ERROR responses this contains an issues array with per-field Zod validation messages.

Retrying requests

Only retry on 429 and 5xx responses; never retry on 4xx errors (except 429) because they indicate a problem with the request itself. Use exponential back-off starting at 1 second, and cap retries at 4–5 attempts. Check X-RateLimit-Reset for 429 responses to know the exact time the window resets.