RestoreCord API key scopes: least privilege in practice
A RestoreCord key can be allowed to read a server list or to pull members into a guild. Deciding which keys get which powers is the most important security choice in your integration.
Short answer
Create one key per integration in Account, API Keys. Grant only the permissions its endpoints check, set the shortest workable expiry, restrict it to your servers' IPs or CIDR ranges, and keep destructive permissions like SERVER_PULL on dedicated keys.
The key and the header
Send the full key as a Bearer token on every request:
curl https://restorecord.com/api/v3/servers \
-H "Authorization: Bearer $RESTORECORD_KEY"The full value is displayed once, at creation. Save it into your secret manager or environment before closing the dialog. An account can hold up to five active keys, which is plenty for one key per job.
The twelve permissions
Group the permissions by how much damage a leaked key could do:
| Risk | Permissions | Typical job |
|---|---|---|
| Read only | READ_ACCOUNT, READ_SERVERS, READ_MEMBERS, READ_BOTS, READ_ANALYTICS | Dashboards, reports, status checks |
| Configuration | WRITE_SERVERS, WRITE_BOTS | Provisioning servers and bot records |
| Backups | CREATE_BACKUPS, RESTORE_BACKUPS | Release pipelines, disaster recovery |
| Members and security | WRITE_MEMBERS, SERVER_PULL, SERVER_FIREWALL | Pulls, cleanup, firewall sync, ban imports |
READ_ACCOUNT is a safe baseline for testing. Add one permission at a time and let a 403 INSUFFICIENT_PERMISSIONS tell you when something is missing.
IP allowlists
Keys can be limited to known infrastructure with exact addresses or CIDR ranges, IPv4 or IPv6:
203.0.113.10
198.51.100.0/24
2001:db8::/32A request from anywhere else is rejected even with the correct secret. For CI runners with changing addresses, allowlist the provider's published range or route calls through a fixed egress IP.
Patterns that hold up
- One key per integration, named after it, so logs say who did what and revocation breaks one thing only.
- Destructive permissions (SERVER_PULL, WRITE_MEMBERS, WRITE_BOTS, RESTORE_BACKUPS) never share a key with reporting.
- Keys live on servers. Never in browser bundles, mobile apps, Discord messages or screenshots.
- Rotate on any exposure. If a key appears in a log or repository, revoke it first and investigate second.
When a key is rejected
Expired, revoked, inactive and IP-blocked keys get 401 UNAUTHORIZED. A valid key that lacks a permission, hits a plan gate or calls a dashboard-only route gets 403. Treat 401 as an alert for a human and 403 as a configuration bug, and never retry either in a loop.
Next: snapshot a server from CI, verify signed webhook events, or back to the developer overview.
Scope a key for one job
List what the job calls
Write down every endpoint the integration hits and look up the permission each one requires.
Create one key for that job
Give it a descriptive name, the shortest expiry that works and only those permissions.
Pin it to your infrastructure
Add the IPs or CIDR ranges of the machines that run the job to the key's allowlist.
Plan the rotation
Note the expiry date and replace the key before it lapses, or immediately if it shows up anywhere it shouldn't.
Starter permission sets
Four common integrations and the smallest set of permissions each one needs. Copy the column that matches your job.
| Reporting | CI snapshots | Firewall sync | Recovery | |
|---|---|---|---|---|
| READ_SERVERS | ||||
| READ_ANALYTICS | — | — | — | |
| CREATE_BACKUPS | — | — | — | |
| RESTORE_BACKUPS | — | — | — | |
| SERVER_FIREWALL | — | — | — | |
| Suggested expiry | 365 days | 90 days | 90 days | 30 days |
API key questions
Give every integration its own key
Create a key, grant one permission and expand only when a 403 says you must.