Security and API keys
Key types
Section titled “Key types”| Permission | Can do | Use for |
|---|---|---|
full_access |
Every endpoint | Your own tooling, CLI, MCP server, admin scripts |
sending_access |
Only POST /emails and POST /emails/batch |
Application servers that just send mail |
Calling any other endpoint with a sending_access key returns 401 restricted_api_key (“This API key is restricted to only send emails”).
Domain-restricted keys
Section titled “Domain-restricted keys”A sending_access key can additionally be bound to one domain with domain_id. It can then only send from addresses on that domain; any other from returns 401 restricted_api_key. Use it to give each product or client its own key.
import { SpacePost } from "@spacepost/node";
const spacepost = new SpacePost();
// A key that can only send, and only from one domain.const { data: key, error } = await spacepost.apiKeys.create({ name: "worker-prod", permission: "sending_access", domainId: "0192e1c4-0000-7000-8000-000000000001",});if (error) throw new Error(error.message);console.log(key.token); // sp_live_..., shown only once
const { data: keys } = await spacepost.apiKeys.list();console.log(keys?.data.map((k) => `${k.name} ${k.prefix}... ${k.permission}`));
await spacepost.apiKeys.remove(key.id);curl -X POST https://api.spacepost.dev/api-keys \ -H "Authorization: Bearer $SPACEPOST_API_KEY" -H "Content-Type: application/json" \ -d '{ "name": "worker-prod", "permission": "sending_access", "domain_id": "0192e1c4-0000-7000-8000-000000000001" }'{ "id": "0192e1c4-0000-7000-8000-0000000000e1", "token": "sp_live_Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56" }name is 1 to 50 characters. domain_id is only allowed with sending_access.
How keys are stored
Section titled “How keys are stored”- Keys look like
sp_live_followed by 32 random base62 characters. - SpacePost stores only a SHA-256 hash. The full key is shown once, at creation. If you lose it, create a new key.
- The dashboard and
GET /api-keysshow the prefix (sp_live_plus 4 characters), the permission, the domain andlast_used_at. - Deleting a key (
DELETE /api-keys/{id}) revokes it immediately.
Good habits
Section titled “Good habits”- Never put keys in client-side code, mobile apps or public repositories. The API allows cross-origin requests only so API playgrounds work; send email from your server.
- Use one key per service and environment, named clearly (
worker-prod,ci-staging). - Prefer
sending_access, restricted to a domain. - Rotate by creating a new key, deploying it, checking
last_used_atof the old one, then deleting the old one. - Keep keys in a secret manager or environment variables, not in code.
- Revoke immediately if a key leaks. If it was committed to GitHub, assume it is compromised.
- SMTP uses the same key as the password. See SMTP relay.
Transport
Section titled “Transport”All traffic uses TLS. The API is served at https://api.spacepost.dev, and the SMTP relay at smtp.spacepost.dev:25976 requires STARTTLS before authentication (implicit TLS on port 465 is not offered yet).
Other protections: failed SMTP authentication attempts are throttled per IP; webhook endpoints and attachment URLs must resolve to public addresses (private networks are refused); the unsubscribe links are signed per contact.
Where your data is stored
Section titled “Where your data is stored”SpacePost is operated by Studio 404 d.o.o., an EU company in Slovenia, and keeps customer data in the EU:
- Sending: Amazon SES in AWS
eu-central-1(Frankfurt, Germany). Every domain sends from this region. - Application and database: the API, dashboard, workers and Postgres database run on Railway in its EU region (Amsterdam, Netherlands).
- Isolation: each team sends through its own SES tenant, so one customer’s reputation problems don’t affect others.
- Website and docs are static pages served by Cloudflare’s global network; no customer data is stored there.
Some providers (AWS, Stripe, Railway) are US companies. They are listed with what they process and where on the sub-processor list. A GDPR data processing addendum is part of the Terms of Service, which are governed by Slovenian law.
Reporting a vulnerability
Section titled “Reporting a vulnerability”Email support@spacepost.dev with details. Please do not test against other customers’ data.