Resend has two API key permission levels: full access and sending access. Full access is admin-level: it can create, read, update, and delete any resource in the account, including domains and other API keys. Sending access can only send emails. For almost everything that runs in production, sending access is the key you want, and this guide covers why, plus the domain restriction and rotation practices that go with it.
Full access vs sending access.
The split is about blast radius. A full-access key is effectively the keys to the account, so if it leaks, an attacker can delete domains, mint new keys, and lock you out. A sending-access key can do exactly one thing: send. That is the whole point of the level, and it is why it belongs in your application runtime.
| Capability | Full access | Sending access |
|---|---|---|
| Send emails | Yes | Yes |
| Manage domains (create, update, delete) | Yes | No |
| Manage API keys (create, delete) | Yes | No |
| Read and manage other account resources | Yes | No |
| Restrict the key to a single domain | No | Yes (optional at creation) |
| Intended use | Admin and automation tooling | Application runtime sending |
Restrict a sending key to one domain.
Sending access has a second lever that full access does not: you can attach the key to a single domain when you create it. A key scoped that way can only send from that one domain, so even a leaked credential cannot be used to send from anything else in your account. Full-access keys cannot be domain-restricted at all, which is one more reason to keep them out of runtime. If a given service only ever sends from one domain, scope its key to that domain and close the door on the rest.
The same restriction is available when you mint keys programmatically: the create-key endpoint takes a permission of sending_access or full_access, and a domain_id that pins the key to one verified domain. The domain_id field only applies to a sending-access key, so a full-access key stays account-wide no matter how you create it.
Least privilege in practice.
The rule of thumb is to give each credential the least it needs. In practice that means sending access for anything that sends mail as part of normal operation, and full access only for the narrow set of admin or developer tooling that genuinely manages domains or keys. Resend's own guidance lines up with this: sending access plus a domain restriction for production, full access reserved for tooling.
Two more habits keep the blast radius small. Use a separate key per environment, so a dev, staging, and production key each stand alone and revoking one never takes down another. And rotate a key the moment you suspect it has leaked: because Resend shows a key value only once at creation, rotation means minting a fresh key, swapping it in, and deleting the old one, which is a clean operation when each environment already has its own key.
Store the key as an environment variable.
Whatever level you pick, the key is a secret, so it never belongs in source control. The convention is a RESEND_API_KEY environment variable, read at runtime from your platform's secret store or a local env file that is git-ignored.
# .env.local (never commit this file) RESEND_API_KEY=re_your_sending_key
Keep the env file out of your repository, load the value at startup, and hand it to the Resend SDK from there. If a key ever lands in a commit, treat it as leaked: rotate it, do not just remove the line, because the value stays in your git history.
Resend API key permissions, answered.
What is the difference between full access and sending access in Resend?
Resend offers two API key permission levels. Full access can create, read, update, and delete any resource in the account, including domains and other API keys, which makes it an admin-level credential. Sending access can only send emails. It cannot touch domains, keys, or other resources. Because most application code only ever needs to send, sending access is the right default for anything running in production.
Can I limit a Resend API key to one domain?
Yes, but only for a sending-access key. When you create a sending-access key you can attach it to a single domain, so a leaked key can only send from that one domain and nowhere else. Full-access keys cannot be domain-restricted. That is one more reason to prefer sending access with a domain restriction for runtime credentials.
Which Resend API key type should production use?
Sending access, ideally restricted to the one domain that environment sends from. That matches Resend's own guidance: use sending access with a domain restriction in production, and reserve full access for admin or developer tooling that genuinely needs to manage domains or keys. Use a separate key per environment, and rotate any key the moment you suspect it has leaked.
A scoped sending key is also all GetFluxly needs from Resend. When you connect Resend to GetFluxly, you paste a sending-access key and a verified from address, and GetFluxly handles the automation and analytics on top. If you are still getting the domain itself to verify, start with the Resend DKIM selector guide, and if you want to consume delivery and engagement events from your own backend, see Resend webhooks.