Introducing the Postscale Ruby SDK
Send email and verify Postscale webhooks from Ruby and Rails with the official RubyGems package.
Postscale now has an official Ruby SDK on RubyGems:
postscale.
The first release is built for server-side Ruby 3.0+ applications. It wraps the public Postscale API, keeps the same request fields you see in the REST docs, and adds the pieces Ruby and Rails teams otherwise write by hand: result objects, attachment helpers, retry handling for idempotent requests, and webhook signature verification.
Install
gem install postscale
Or add it to your Gemfile:
gem "postscale"
Set your API key in the environment:
POSTSCALE_API_KEY=ps_live_your_api_key
API keys should only be used from trusted server-side code. Do not ship them in browser bundles or mobile applications.
Send Your First Email
require "postscale"
postscale = Postscale::Client.new(api_key: ENV.fetch("POSTSCALE_API_KEY"))
result = postscale.emails.send(
from: "hello@yourdomain.com",
to: ["user@example.com"],
subject: "Welcome to Postscale",
html_body: "<strong>It works.</strong>"
)
if result.error
raise result.error.message
end
puts result.data["message_id"]
Before production sending, add and verify your sending domain in Postscale so SPF, DKIM, DMARC, and return-path bounce tracking are configured correctly. The Getting Started guide covers that flow end to end.
API-Native by Design
The SDK keeps Postscale request fields in snake_case.
That is intentional. The same payload works across SDK examples, REST examples, OpenAPI tooling, logs, and support conversations:
postscale.emails.send(
from: "orders@yourdomain.com",
to: ["customer@example.com"],
subject: "Receipt",
html_body: "<p>Thanks for your order.</p>",
text_body: "Thanks for your order.",
metadata: {
order_id: "ord_123",
}
)
There is less translation layer to learn, and fewer edge cases where a field name differs between SDK and HTTP usage.
Result Objects Instead of Throw-Only Flows
Resource methods return result objects with data, error, and headers:
result = postscale.emails.send(
from: "hello@yourdomain.com",
to: ["user@example.com"],
subject: "Welcome",
html_body: "<strong>Hello</strong>"
)
if result.error
warn "#{result.error.code}: #{result.error.message}"
warn result.headers.request_id
exit 1
end
puts result.data["status"]
The SDK does not automatically retry non-idempotent email sends. That keeps applications from accidentally duplicating customer email until the send API has an explicit idempotency contract.
Attachments
For file attachments, use the helper instead of manually base64-encoding the file:
attachment = Postscale.attachment_from_file(
"./invoice-1234.pdf",
"application/pdf"
)
result = postscale.emails.send(
from: "billing@yourdomain.com",
to: ["customer@example.com"],
subject: "Invoice #1234",
html_body: "<p>Your invoice is attached.</p>",
attachments: [attachment]
)
if result.error
raise result.error.message
end
The SDK checks the documented attachment limits before sending: 10 attachments, 25 MB per attachment, and 50 MB total decoded attachment payload.
Webhook Verification
Postscale signs webhook deliveries with X-Postscale-Signature. The SDK
verifies the timestamped t=...,v1=... format and supports multiple secrets
during rotation windows:
result = Postscale.verify_webhook_signature(
request.raw_post,
request.get_header("HTTP_X_POSTSCALE_SIGNATURE"),
[current_secret, previous_secret]
)
unless result.valid?
return head :unauthorized
end
Use the raw request body bytes for verification. Do not parse JSON and re-serialize it before verifying the signature.
What Is Included
The initial Ruby SDK covers public product APIs:
emailsdomainsdkimaliasesinboundstatswarmingsuppressionswebhookstemplatesusagetrust
It intentionally does not include billing, invoices, onboarding, browser auth, MFA, API-key management, admin routes, Stripe webhooks, unsubscribe endpoints, or contact forms.
What Is Next
Ruby joins the official Node.js, TypeScript, and Python SDKs. The roadmap continues with PHP/Laravel, Go, Java/Kotlin, .NET, and Rust once the public OpenAPI contract is ready for each ecosystem.
Start with the SDKs and HTTP Clients guide, or install the package from RubyGems.