Skip to content

API introduction

The SpacePost API is a JSON REST API that is compatible with the Resend API. The complete endpoint list is in the API reference, generated from the OpenAPI spec.

https://api.spacepost.dev

Paths are at the root (/emails, /domains, …). A /v1 prefix is also accepted: https://api.spacepost.dev/v1/emails is the same endpoint. Use whichever your client prefers.

Send your API key as a bearer token on every request:

Terminal window
curl https://api.spacepost.dev/emails -H "Authorization: Bearer sp_live_YOUR_API_KEY"

Keys start with sp_live_. full_access keys can use every endpoint; sending_access keys can only send emails, optionally from one domain. See Security and API keys.

Problem Response
No Authorization header 401 missing_api_key
Unknown, revoked or malformed key (including Resend re_ keys) 403 invalid_api_key
sending_access key on a non-sending endpoint 401 restricted_api_key
  • Send JSON with Content-Type: application/json. Invalid JSON returns 422 validation_error.
  • Fields are snake_case (reply_to, scheduled_at). For convenience replyTo and scheduledAt are also accepted when sending.
  • IDs are UUIDv7 strings; they sort by creation time, which is how pagination works.
  • Timestamps are ISO 8601 in UTC (2026-10-23T14:02:09.512Z).
  • Unknown fields on a request are ignored.

Successful responses are JSON with status 200. Resources carry an object field naming their type ("email", "domain", …). Lists look like { "object": "list", "has_more": false, "data": [] }.

Errors always have the same shape:

{ "statusCode": 422, "name": "validation_error", "message": "`to`: Invalid email address" }

See Errors for every name.

POST /emails and POST /emails/batch accept an Idempotency-Key header (1 to 256 characters, remembered for 24 hours): the same key and body returns the first response instead of sending again. See Idempotency keys.

Per team: 10 requests per second (25 on Scale), returned in ratelimit-* headers. See Rate limits.

The API follows Resend’s current shapes and does not use dated versions. We only make backward-compatible changes to existing endpoints (new optional fields, new fields in responses, new event types and error names), so write clients that ignore unknown fields and handle unknown error names. Anything breaking would ship under a new path prefix with advance notice in the changelog.

The API sends permissive CORS headers so API explorers can call it, but never call it from a browser with a real key. Keys belong on servers.