OpenSend docs
Official SDKs
OpenSend ships first-party SDKs for the languages most teams use to send mail from production services. All SDKs target OpenSend Cloud by default at https://opensend.namuh.co and can point at a self-hosted deployment by setting a base URL. The Java/Kotlin and PHP packages are intentionally partial today; their supported resources are listed below before any copyable examples.
Use an OpenSend API key that starts with os_. Keep keys in server-side environment variables and never expose them to browser JavaScript, mobile apps, or public repositories.
SDK status
| SDK | Package | Best for | Status |
|---|---|---|---|
| TypeScript / JavaScript | opensend on npm | Node.js, Bun, Next.js, serverless functions, React Email rendering | First-party package |
| Python | packages/python-sdk / future opensend PyPI package | Django, Flask, FastAPI, scripts, workers | First-party package; install from the repo until PyPI publishing is enabled |
| Go | github.com/namuh-eng/opensend/packages/go-sdk | API services, workers, CLIs | First-party module |
| Java / Kotlin | packages/jvm-sdk / future Maven package | Spring Boot, plain JVM services, Kotlin workers | First-party blocking SDK slice; install from the repo until Maven publishing is enabled |
| Ruby | packages/ruby-sdk / future opensend gem | Rails, Sinatra, Ruby jobs | First-party package; install from the repo until RubyGems publishing is enabled |
| PHP | packages/php-sdk / future opensend/opensend-php Composer package | PHP services, Laravel/Symfony apps, workers | First-party send-email slice; install from the repo until Packagist publishing is enabled |
| SMTP relay | @opensend/smtp-relay service | Apps that only speak SMTP | Self-hosted relay service |
| Other languages | /openapi.json | Generated clients | Generate from the OpenAPI contract |
Partial SDK surfaces
Each SDK has its own package-specific surface. The JVM and PHP packages are narrower than the full REST API and should be treated as explicit slices:
- Java / Kotlin (`packages/jvm-sdk`): blocking-only client for emails,
contacts, domains, and suppressions. It does not expose JVM methods for API keys, broadcasts, audiences, segments, topics, templates, webhooks, logs, contact properties, events, automations, receiving, dedicated IPs, or unsubscribe-page settings yet.
- PHP (`packages/php-sdk`): send-only client for
client->emails->send(...), idempotency options, typed send payloads/responses, and typed OpenSend API errors. It does not expose PHP resource clients for reads, batch sends, contacts, domains, suppressions, API keys, broadcasts, audiences, segments, topics, templates, webhooks, logs, contact properties, events, automations, receiving, dedicated IPs, or unsubscribe-page settings yet.
Use /openapi.json and the REST API docs for resources not listed in a package README. Do not assume every OpenAPI path has a handwritten JVM or PHP method.
TypeScript and JavaScript
Install the npm package:
npm install opensendSend an email:
import { Opensend } from "opensend";
const opensend = new Opensend(process.env.OPENSEND_API_KEY);
const { data, error } = await opensend.emails.send({
from: "OpenSend <onboarding@updates.example.com>",
to: ["user@example.com"],
subject: "Hello from OpenSend",
html: "<strong>It works.</strong>",
});
if (error) throw new Error(error.message);
console.log(data.id);The TypeScript SDK exports both Resend for migration-friendly code and Opensend as the first-party client name. It accepts replyTo, scheduled_at, attachments, tags, and template payloads that match the REST API. React email components are rendered locally by the SDK when you pass react and install react plus react-dom.
For self-hosting, pass baseUrl:
import { Opensend } from "opensend";
const opensend = new Opensend(process.env.OPENSEND_API_KEY, {
baseUrl: process.env.OPENSEND_BASE_URL,
});Python
Install from this repository until PyPI publishing is complete:
python -m pip install ./packages/python-sdkAfter the package is published, use the public package name:
python -m pip install opensendUse the instance client for services and tests:
import os
from opensend import OpenSend
client = OpenSend(
os.environ["OPENSEND_API_KEY"],
base_url=os.environ.get("OPENSEND_BASE_URL"),
)
email = client.emails.send({
"from": "OpenSend <onboarding@updates.example.com>",
"to": ["user@example.com"],
"subject": "Hello from OpenSend",
"html": "<strong>It works.</strong>",
})
print(email["id"])Python reserves from as a keyword, so the SDK accepts dictionaries using the JSON key ("from") and also normalizes from_ or from_email keys.
Go
Install the Go module from this repository:
go get github.com/namuh-eng/opensend/packages/go-sdk@v0.2.0Send one email:
package main
import (
"context"
"fmt"
"log"
"os"
opensend "github.com/namuh-eng/opensend/packages/go-sdk"
)
func main() {
opts := []opensend.Option{}
if baseURL := os.Getenv("OPENSEND_BASE_URL"); baseURL != "" {
opts = append(opts, opensend.WithBaseURL(baseURL))
}
client, err := opensend.NewClient(os.Getenv("OPENSEND_API_KEY"), opts...)
if err != nil {
log.Fatal(err)
}
email, err := client.Emails.Send(context.Background(), opensend.SendEmailRequest{
From: "OpenSend <onboarding@updates.example.com>",
To: []string{"user@example.com"},
Subject: "Hello from OpenSend",
HTML: "<strong>It works.</strong>",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(email.ID)
}Java and Kotlin
Support level: partial, blocking-only SDK. This package currently supports implemented email, contact, domain, and suppression routes only. Use the REST API and /openapi.json for other resources until matching JVM resource clients are added.
Install from this repository until Maven publishing is complete:
cd packages/jvm-sdk
mvn test
mvn installSend one email from Java:
import com.opensend.OpenSend;
import com.opensend.RequestOptions;
import com.opensend.models.EmailResponse;
import com.opensend.models.SendEmailRequest;
import java.util.List;
OpenSend client = OpenSend.builder(System.getenv("OPENSEND_API_KEY"))
.baseUrl(System.getenv().getOrDefault("OPENSEND_BASE_URL", OpenSend.DEFAULT_BASE_URL))
.build();
EmailResponse email = client.emails().send(
SendEmailRequest.builder()
.from("OpenSend <onboarding@updates.example.com>")
.to(List.of("user@example.com"))
.subject("Hello from OpenSend")
.html("<strong>It works.</strong>")
.build(),
RequestOptions.withIdempotencyKey("welcome-user-123"));
System.out.println(email.id());The JVM SDK exposes ApiException for OpenSend error envelopes plus rate-limit headers. See Send emails with Java and Kotlin for Kotlin and Spring Boot examples.
Ruby
Build and install locally until RubyGems publishing is complete:
cd packages/ruby-sdk
gem build opensend.gemspec
gem install ./opensend-0.1.0.gemAfter publication:
gem install opensendSend one email:
require "opensend"
OpenSend.api_key ENV.fetch("OPENSEND_API_KEY")
OpenSend.base_url ENV.fetch("OPENSEND_BASE_URL", OpenSend::DEFAULT_BASE_URL)
email = OpenSend.emails.send(
from: "OpenSend <onboarding@updates.example.com>",
to: "user@example.com",
subject: "Hello from OpenSend",
html: "<strong>It works.</strong>"
)
puts email.fetch("id")The Ruby package also exports Resend as a compatibility alias for migration-oriented code.
PHP
Support level: partial, send-only SDK. This package currently supports client->emails->send(...) for POST /emails, idempotency options, typed send payloads/responses, and typed OpenSend API errors only. Use the REST API and /openapi.json for other resources until matching PHP resource clients are added.
Install from this repository until Packagist publishing is complete:
composer config repositories.opensend path ../../packages/php-sdk
composer require opensend/opensend-php:dev-mainSend one email:
<?php
use OpenSend\Client;
use OpenSend\Errors\ApiException;
use OpenSend\ValueObjects\RequestOptions;
use OpenSend\ValueObjects\SendEmailRequest;
$client = new Client(
apiKey: getenv('OPENSEND_API_KEY') ?: '',
baseUrl: getenv('OPENSEND_BASE_URL') ?: null,
);
try {
$email = $client->emails->send(
new SendEmailRequest(
from: 'OpenSend <onboarding@updates.example.com>',
to: ['user@example.com'],
subject: 'Hello from OpenSend',
html: '<strong>It works.</strong>',
),
RequestOptions::withIdempotencyKey('welcome-user-123'),
);
echo $email->id;
} catch (ApiException $error) {
throw $error;
}The PHP SDK currently supports single-email sends plus shared request, response, idempotency, and error-envelope plumbing. Use the REST API for other resources until more PHP clients are added.
SMTP relay
Use the SMTP relay when an application cannot call the REST API or an SDK. The relay is a separate OpenSend service that authenticates with an OpenSend API key as the SMTP password, parses MIME, creates a queued email row, and publishes the normal delivery job.
- Default port:
2587 - Username: any non-empty value, commonly
apikey - Password: your OpenSend API key
- TLS: STARTTLS when you configure
SMTP_RELAY_TLS_CERT_PATHandSMTP_RELAY_TLS_KEY_PATH
See Send email with SMTP for deployment and client examples.
OpenAPI clients
If your language is not listed, generate a client from the OpenAPI contract:
https://opensend.namuh.co/openapi.jsonUse /openapi.json for exact schemas and route availability, then use these guides for application workflow, environment variables, and operational caveats.