PristineSend
Get started
Guides

Test mode (sandbox)

A ps_test_ key runs every request through the full pipeline — auth, validation, sender checks, the suppression list — but captures the send instead of delivering it. No real email goes out, nothing hits your sending reputation, and it's free. Build and test your integration with confidence, then swap to a ps_live_ key.

How it works

Create a test key in Settings → API keys. Send exactly as you would in production — the API returns 200 with a synthetic test_… id, writes a log row you can read back, but makes no provider call.

"color:#ff7b72">import { PristineSend } "color:#ff7b72">from "pristinesend"

// A ps_test_ key — sends are captured, not delivered.
"color:#ff7b72">const ps = "color:#ff7b72">new PristineSend(process.env.PRISTINESEND_TEST_KEY!)

"color:#ff7b72">const { id } = "color:#ff7b72">await ps.emails.send({
  to: "anyone@example.com",
  subject: "Sandbox send",
  html: "<p>Captured — never delivered.</p>",
})
// id looks like test_… — no SES call, no charge, no reputation impact.

Test vs live keys

ps_test_ps_live_
Delivers via the email providerNo — capturedYes
Costs / consumes quotaFreeCounts toward your plan
Counts toward the send cap / rate limitNo (rate limit still applies per key)Yes
Honors the suppression listYesYes
Validation (sender, fields, suppression)YesYes
Appears in logs / GET /emailsYes (environment=test)Yes (environment=live)

Identifying test sends

Every email row carries an environment field — "live" or "test" — and GET /api/v1/emails accepts an ?environment=test filter. In the dashboard, test sends show a Test badge.

// Read back only test sends:
for "color:#ff7b72">await ("color:#ff7b72">const e of "color:#ff7b72">await ps.emails.list({ environment: "test" })) {
  console.log(e.id, e.environment) // "test"
}

What's the same

Because validation runs identically, the sandbox is a faithful rehearsal: a send to a suppressed recipient still returns 403 recipient_suppressed, an unverified from still returns 403 sender_not_verified, and captured rows are reported as sent. The only difference is that nothing is delivered. Captured sends never receive delivery/open/bounce events (there was no real message).