Skip to content
relyr/

Relyr / Information

A straightforward email API.

Verify your domain, create an API key, and send transactional messages from your application.

Pre-release documentation. Public signup and sending are not available yet. Examples require a future beta API URL and credentials; this website does not expose a sending API.

Before sending

  1. Obtain approved beta access.
  2. Add a sending domain and publish its workspace-specific ownership TXT record.
  3. Complete the sending-provider authentication records shown in the dashboard.
  4. Create an API key and keep it on your server.

A display name can be customized; the email address must still belong to a validated domain. DNS ownership alone is separate from sending-provider readiness.

curl

# Set the API base URL supplied with beta access (ends in /api/v1).
curl -X POST "$RELYR_API_URL/emails" \
  -H "Authorization: Bearer $RELYR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: welcome-user-123" \
  -d '{
    "from": "Your team <hello@your-domain.com>",
    "to": ["customer@example.com"],
    "subject": "Welcome aboard",
    "template": "welcome",
    "variables": { "name": "Ada" }
  }'

Node.js · fetch

const response = await fetch(process.env.RELYR_API_URL + '/emails', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.RELYR_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'welcome-user-123'
  },
  body: JSON.stringify({
    from: 'Your team <hello@your-domain.com>',
    to: ['customer@example.com'],
    subject: 'Welcome aboard',
    text: 'Good to have you here.'
  })
});
const result = await response.json();
if (!response.ok) throw new Error(result.error.message);
console.log(result.id);

Java 17+

import java.net.URI;
import java.net.http.*;

class SendEmail {
  public static void main(String[] args) throws Exception {
    var body = """
      {"from":"Your team <hello@your-domain.com>",
       "to":["customer@example.com"],
       "subject":"Welcome aboard","text":"Hello, Ada."}
      """;
    var request = HttpRequest.newBuilder()
      .uri(URI.create(System.getenv("RELYR_API_URL") + "/emails"))
      .header("Authorization", "Bearer " + System.getenv("RELYR_API_KEY"))
      .header("Content-Type", "application/json")
      .header("Idempotency-Key", "welcome-user-123")
      .POST(HttpRequest.BodyPublishers.ofString(body)).build();
    var response = HttpClient.newHttpClient().send(request,
      HttpResponse.BodyHandlers.ofString());
    if (response.statusCode() != 202) throw new RuntimeException(response.body());
    System.out.println(response.body());
  }
}

Responses and idempotency

POST /api/v1/emails accepts a JSON body and returns HTTP 202 with { "id": "email-id" } after queuing. Acceptance does not mean delivery. Reuse an Idempotency-Key only for retries of the same request. A conflicting payload returns HTTP 409.

Use GET /api/v1/emails/:id to retrieve the status and event timeline. Errors follow { "error": { "code": "…", "message": "…" } }. A revoked key returns 401; an unvalidated sender returns 422; rate limiting returns 429.

Content and templates

Supply html, text, or a built-in template: welcome or password-reset. Template variables are string values; password-reset requires an HTTPS reset_url. The API supports to, cc, bcc, reply_to, tags, and permitted custom X- headers, with at most 50 recipients per message.

Events and webhooks

Messages begin as queued and may progress through sent, delivered, bounced, complained, or failed. HTTPS webhook endpoints receive signed events. Verify HMAC-SHA256 over the timestamp, a period, and the raw request body using your endpoint secret. Check sendly-timestamp freshness and deduplicate sendly-id; delivery is at least once.

A successful transport handoff is not proof of inbox delivery. Provider-event handling and live sending will be validated before beta sending access opens.

Need access or have a question?

Tell us about your use case and review our acceptable-use requirements.