Install guide

Connect Mailcheer to your application

The REST API replaces a transactional sending service. The fields and response match Resend: a migration is just the base URL and the key.

  1. Create an API key

    In your Mailcheer workspace: Settings → API → New key. Name it, tick the permissions, save. The key is shown ONCE — copy it immediately. It starts with mch_live_ followed by thirty-two characters.

  2. Set the key in the service environment

    Like any secret: in environment variables, never in the repository.

    MAILCHEER_API_KEY=mch_live_…
  3. If you're coming from Resend: copy the minimal client

    One file, no dependency, the same signature as the SDK you're leaving. The rest of your sending code is unchanged: it still reads { data, error } and data.id.

    curl -O https://mailcheer.com/mailcheer-client.ts
    
    // then, in your code:
    - const resend = new Resend(process.env.RESEND_API_KEY);
    + const mailcheer = new Mailcheer(process.env.MAILCHEER_API_KEY);
    
    const { data, error } = await mailcheer.emails.send({ from, to, subject, html });
    if (error) throw new Error(`Email delivery failed: ${error.message}`);
  4. Or send without copying anything

    No library is needed: a plain HTTP call is enough. The response is a 202 with the message ID — the email is accepted, not yet delivered.

    const res = await fetch("https://mailcheer.com/api/v1/emails", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.MAILCHEER_API_KEY}`,
        "Content-Type": "application/json",
        // A unique value per send: a retry will not create a duplicate.
        "Idempotency-Key": invoiceId,
      },
      body: JSON.stringify({
        from: "Your brand <hello@yourdomain.com>",
        to: customer.email,
        subject: "Your invoice",
        html: "<p>Here it is.</p>",
      }),
    });
    
    if (!res.ok) {
      // Always the same shape: { error: { code, message, details } }.
      // Write your code against "code", never against "message".
      const { error } = await res.json();
      throw new Error(`${error.code} — ${error.message}`);
    }
    
    const { id } = await res.json();
  5. Check whether the message was delivered

    The status evolves after sending: sent, then delivered, bounced or complained. A bouncing address is automatically added to the suppression list — your application does not need to handle it.

    curl https://mailcheer.com/api/v1/emails/ID \
      -H "Authorization: Bearer $MAILCHEER_API_KEY"
  6. Check that it's connected

    Ask for the account status. This is read-only: nothing is modified, nothing is sent. The response names your workspace and lists your verified sending domains — those are the addresses you can send from.

    curl -s https://mailcheer.com/api/v1/me \
      -H "Authorization: Bearer $MAILCHEER_API_KEY"

Troubleshooting

Every API error carries a readable code. Here are the ones you encounter when connecting.

422 suppressed_recipient on a transactional emailThe recipient's address bounced, they complained, or you removed it by hand: those three reasons refuse individual sends too. A plain unsubscribe only refuses sends that carry unsubscribe_url.
401 invalid_api_keyThe key is incomplete (a newline crept in during copy-paste) or has been replaced. Create a new one.
401 revoked_api_keyThe key was cut under Settings → API. Create another one.
403 insufficient_scopeThe key does not have the required permission. Permissions are chosen at creation and cannot be changed: create a key with the right scope.
422 unverified_from_domainThe sending address is not on a verified domain in the workspace. The error message lists the ones that are. To add one: Domains → Add a domain, then set the DNS records.
429 rate_limit_exceededMore than 600 requests per minute for this key. The Retry-After header says how many seconds to wait.