Authentication
Every API request carries a bearer token. This page covers the key shape, what each permission gates, test-mode keys, and the SMTP relay credential.
The bearer token
Send your API key as a bearer token on every request:
Authorization: Bearer <key>A key looks like zs_a1b2c3d4_5e6f...: a scheme (zs for a live key, zst for a test-mode one), an 8-character non-secret prefix used to look the key up, and a 48-character secret. The prefix is stored in plaintext, only to find the row; the database never stores the plaintext key itself: what's stored is a bcrypt hash of the full key (prefix and secret together), and that full key is what's compared against it on every request.
The plaintext key is shown exactly once, at creation. If you lose it, there is no way to retrieve it. Revoke the key and create a new one.
Permissions
A key carries one or more of three permissions. admin implicitly grants the other two on every check, so a key with admin can do everything below.
| Permission | Gates |
|---|---|
| send | POST /v1/emails/send. |
| read | Listing and reading messages, analytics, usage, domains, and suppressions. |
| admin | Account administration: renaming your account (PUT /api/tenants/:id), creating and revoking API keys, and the whole domain lifecycle: create, update, delete, and verify a domain. It does not gate sending or reading on its own; it gates the configuration surface around them. |
A common mistake: a key created with only send+read (the default a server-side integration usually wants) gets a 403 the moment you try to add or verify a domain with it: that needs admin. It is not, however, the case that every domain-adjacent action needs it: listing your domains (GET /v1/domains) only needs read.
Test-mode keys
A key prefixed zst_ instead of zs_ is a test-mode key. It authenticates and works identically over both HTTP and SMTP, and runs sends through the real pipeline (DKIM signing, tracking-link rewrite, header injection) but routes them to a sandbox that captures the message instead of delivering it. Test mode skips from-domain verification, your monthly quota, and suppression filtering.
A test-mode key is refused with 403 test_mode_restricted on the surfaces that only describe live traffic: analytics, usage, any suppression write, and all four GET /v1/emails/received* routes. Returning real numbers to a test key would make the sandbox look like production; inbound mail specifically has no test mode at all: a received message is always real, so there is no sandboxed version of it for a test key to read.
Using your key over SMTP
The same API key is also your password for the SMTP relay at smtp.zsender.io (ports 587 and 2525, STARTTLS). The username is the literal string apikey (it is not checked, only the password is) and a test-mode key works there too, for the same sandboxed send.
Example
Host: smtp.zsender.io
Port: 587 (or 2525)
Username: apikey
Password: <your API key>