qwicmail
qwicmail docs

Official SDKs

Idiomatic clients for six runtimes. Every SDK ships the same surface: a typed send, a webhook-signature verifier, and automatic retry on 429 and 5xx responses. Each is semver-versioned and published to its language's standard registry.

At a glance

SDKInstallPackageMin runtime
TypeScript / Nodenpm install @qwicmail/sdk@qwicmail/sdk (npm)Node 18+, modern browsers
Pythonpip install qwicmailqwicmail (PyPI)Python 3.9+
Gogo get gitlab.com/teqpace/qwicmail-goqwicmail-goGo 1.21+
Rubygem install qwicmailqwicmail (RubyGems)Ruby 3.0+
PHPcomposer require qwicmail/qwicmail-phpqwicmail/qwicmail-phpPHP 8.1+
Java / Kotlinsee belowcom.qwicmail:qwicmail-javaJDK 11+

Initialise the client

import { Qwicmail } from "@qwicmail/sdk";

const qm = new Qwicmail({
  apiKey:  process.env.QWICMAIL_API_KEY!,
  baseUrl: "https://api.qwicmail.com",        // default
  timeout: 30_000,                            // ms, default
  maxRetries: 3,                              // default; set 0 to disable
});
import os
from qwicmail import Qwicmail

qm = Qwicmail(
    api_key=os.environ["QWICMAIL_API_KEY"],
    base_url="https://api.qwicmail.com",   # default
    timeout=30.0,                          # seconds, default
    max_retries=3,                         # default
)
import "gitlab.com/teqpace/qwicmail-go"

qm := qwicmail.New(os.Getenv("QWICMAIL_API_KEY"),
    qwicmail.WithBaseURL("https://api.qwicmail.com"),  // default
    qwicmail.WithTimeout(30 * time.Second),
    qwicmail.WithMaxRetries(3),
)
require "qwicmail"

qm = Qwicmail::Client.new(
  api_key:     ENV.fetch("QWICMAIL_API_KEY"),
  base_url:    "https://api.qwicmail.com",  # default
  timeout:     30,                          # seconds, default
  max_retries: 3,                           # default
)
use Qwicmail\Client;

$qm = new Client(getenv("QWICMAIL_API_KEY"), [
    "base_url"    => "https://api.qwicmail.com",
    "timeout"     => 30,
    "max_retries" => 3,
]);
import com.qwicmail.Qwicmail;
import java.time.Duration;

var qm = Qwicmail.builder()
    .apiKey(System.getenv("QWICMAIL_API_KEY"))
    .baseUrl("https://api.qwicmail.com")     // default
    .timeout(Duration.ofSeconds(30))
    .maxRetries(3)
    .build();

Send a message

The send call accepts either an html/text body directly, or a template_id + data pair if you want server-side rendering. See Templates for the templating side; the SDKs accept both shapes via the same method.

const res = await qm.emails.send({
  from:    "alerts@mail.example.com",
  to:      ["customer@example.org"],
  subject: "Order shipped",
  html:    "<p>Your order is on the way.</p>",
});

console.log(res.message_ids);  // [ "8a3f1f5b-…" ]
res = qm.emails.send(
    from_="alerts@mail.example.com",
    to=["customer@example.org"],
    subject="Order shipped",
    html="<p>Your order is on the way.</p>",
)

print(res.message_ids)
res, err := qm.Emails.Send(ctx, &qwicmail.SendRequest{
    From:    "alerts@mail.example.com",
    To:      []string{"customer@example.org"},
    Subject: "Order shipped",
    HTML:    "<p>Your order is on the way.</p>",
})
if err != nil {
    return err
}
log.Println(res.MessageIDs)
res = qm.emails.send(
  from:    "alerts@mail.example.com",
  to:      ["customer@example.org"],
  subject: "Order shipped",
  html:    "<p>Your order is on the way.</p>",
)

puts res.message_ids
$res = $qm->emails->send([
    "from"    => "alerts@mail.example.com",
    "to"      => ["customer@example.org"],
    "subject" => "Order shipped",
    "html"    => "<p>Your order is on the way.</p>",
]);

print_r($res->messageIds);
SendResponse res = qm.emails().send(SendRequest.builder()
    .from("alerts@mail.example.com")
    .to("customer@example.org")
    .subject("Order shipped")
    .html("<p>Your order is on the way.</p>")
    .build());

System.out.println(res.messageIds());

Automatic retry policy

Every SDK retries idempotent requests on transport errors, 429, and 5xx with exponential backoff plus jitter. Retry-After is honoured exactly when present. Non-idempotent POST /emails calls are only retried when an Idempotency-Key is set — the SDKs generate one automatically unless you supply your own.

ConditionAction
Network / timeoutRetry up to max_retries times.
429 Too Many RequestsSleep Retry-After, then retry.
5xxExponential backoff (250ms, 1s, 4s) + jitter, then retry.
4xx (other)Surface as a typed error; no retry.

Errors

Every SDK exposes a typed error hierarchy. The shape is the same across languages:

  • AuthError401, key missing or revoked.
  • ScopeError403 scope_required.
  • TenantNotActiveError403 tenant_not_active (suspended / throttled / pending).
  • ValidationError4xx validation failures.
  • RateLimitError429 after retries exhausted.
  • ServerError5xx after retries exhausted.
  • NetworkError — DNS / TCP / TLS / timeout, no HTTP response received.

Webhook signature verification

Every SDK exposes a one-line verifier — see the full recipe and language samples on the Webhooks page.

Installing the Java/Kotlin SDK

The same artifact works from both languages.

<dependency>
  <groupId>com.qwicmail</groupId>
  <artifactId>qwicmail-java</artifactId>
  <version>0.1.0</version>
</dependency>
implementation("com.qwicmail:qwicmail-java:0.1.0")
implementation 'com.qwicmail:qwicmail-java:0.1.0'

Source & issues

Every SDK lives in the qwicmail monorepo under sdks/<lang>. Issues and PRs are welcome on GitLab.