Sign in to fill these examples with your own keys. Sign in Start free trial

Send emails with Java

Install the Java SDK from GitHub and call emails.send.

What you'll build

A Java program that sends a receipt email with the com.postshiba client and prints the queued message.

Before you start

  • An API key with Send only access. Full access also works. See Create an API key. Support keys cannot send.
  • A verified sending domain. See Add and verify a domain. from must be an address on it.
  • A cluster that is ready to send (sending_ready is true). See Clusters.
  • Java 17 or later.

Install

The artifact is not on Maven Central. Clone postshiba/postshiba-java and install it to your local Maven repository.

install.sh
1git clone https://github.com/postshiba/postshiba-java 2cd postshiba-java 3./mvnw install

Then add the dependency to your pom.xml.

pom.xml
1<dependency> 2 <groupId>com.postshiba</groupId> 3 <artifactId>postshiba</artifactId> 4 <version>0.1.0</version> 5</dependency>

Send your first email

Pass your API key to PostShiba, then call emails.send with a Map. teamId is only needed for team-scoped calls such as listing clusters, and those calls need a Full access key that stays out of your deployed app. It is on the API keys page.

Send.java
1import com.fasterxml.jackson.databind.JsonNode; 2import com.postshiba.PostShiba; 3 4import java.util.List; 5import java.util.Map; 6 7public class Send { 8 public static void main(String[] args) { 9 PostShiba client = new PostShiba("YOUR_API_KEY", new PostShiba.Options().teamId("KjkAJW")); 10 11 JsonNode sent = client.emails.send(Map.of( 12 "from", "hello@mail.example.com", 13 "to", List.of("you@example.com"), 14 "reply_to", "support@example.com", 15 "subject", "Your receipt", 16 "text", "Thanks for your order.", 17 "html", "<p>Thanks for your order.</p>", 18 "unique_args", Map.of("order_id", "ord_123") 19 )); 20 System.out.println(sent); 21 } 22}

emails.send returns the JSON body of the 201 response as a Jackson JsonNode. The message then shows under Events in the dashboard.

response.json
1{ 2 "queued": true, 3 "message_id": "abc@capsule.test", 4 "from": "hello@mail.example.com", 5 "to": ["you@example.com"], 6 "subject": "Your receipt", 7 "unique_args": {"order_id": "ord_123"} 8}

Pin a cluster

Without a pin, PostShiba uses your first cluster that is ready to send. Pass SendOptions with clusterId to choose one.

Pin.java
1client.emails.send(message, new PostShiba.SendOptions().clusterId("NmQpXr"));

Attachments and templates

Attach a file

Add attachments with filename, content_type, and base64 content. Up to 10 files, 18 MB in total. See Attachments for allowed types.

Attachment.java
1String pdf = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("invoice.pdf"))); 2 3client.emails.send(Map.of( 4 "from", "hello@mail.example.com", 5 "to", List.of("you@example.com"), 6 "subject", "Your invoice", 7 "text", "Your invoice is attached.", 8 "attachments", List.of(Map.of( 9 "filename", "invoice.pdf", 10 "content_type", "application/pdf", 11 "content", pdf 12 )) 13));

Send a published template

Pass template with the alias or public id and its variables. Leave out html and text.

Template.java
1client.emails.send(Map.of( 2 "from", "hello@mail.example.com", 3 "to", List.of("you@example.com"), 4 "template", Map.of("id", "welcome", "variables", Map.of("name", "Ada")) 5));

Keep the key safe

Use a Send only key in your app. It can send email and call GET /api/v1/users/me. Every other request returns 403 forbidden.

If this key leaks Send only Full access
Send mail from your verified domains Yes Yes
Read events, recipients, templates, and sent messages No Yes
See SMTP passwords and webhook secrets No Yes
Change clusters, domains, credentials, webhooks, and suppressions No Yes
  • Keep Full access keys for setup scripts, the CLI, and MCP. Don't deploy one with your app.
  • Read the key with System.getenv("POSTSHIBA_API_KEY") instead of a string in your code. Don't commit it, log it, or put it in a URL.
  • Send from your server. Never put a key, even a Send only key, in browser or mobile code.
  • Create one key per app and environment. If a key leaks, delete it on API keys and create a new one. Deleting stops it straight away.

Troubleshooting

A response outside 2xx throws com.postshiba.ApiError with the public fields error, field, and message.

Errors.java
1try { 2 client.emails.send(message); 3} catch (ApiError e) { 4 System.err.println(e.error + " " + e.field + " " + e.message); 5 throw e; 6}
Status error What to do
401 Invalid token or no user signed in The API key is missing, mistyped, or deleted. Copy it again from API keys.
403 forbidden Support keys cannot send. A Send only key gets this on any call other than sending.
403 domain_unverified from is not on a verified domain.
403 kyc_required Your team is pending production approval. Until then, send only to team members, live inbox addresses, and inbox forward-to addresses.
422 invalid field names the problem, such as a missing to, an unpublished template, or a rejected attachment.
429 throttled The cluster hit its hourly throttle or 24-hour cap. The client does not retry, and retrying right away hits the same cap. See What happens at your cap.
429 rate_limited More than 300 send requests in one minute on one API key. Slow down.

Every other status is on Errors.

Next steps