API Reference: API Keys
Manage the full API key lifecycle: list, create, update, rotate, and revoke keys for your team.
Overview
API keys provide long-lived authentication for server-to-server integrations. The API Keys endpoints let you manage the full lifecycle: creation, listing, inspection, updating, rotation, and revocation. The full key value is only returned once, at creation or rotation time — store it immediately. All endpoints require the TEAM_ADMIN_API_KEYS feature permission.
Key Concepts
- Format — All API keys start with
s360_live_. There is no test/sandbox prefix. - Feature permissions — Each key can be scoped to specific feature/admin API permissions, such as schema, wizard, messaging, or integration administration.
- Data Role — Record and MCP data access comes from the selected Team Role (
teamRoleSimplyId). A key without a Data Role has no record data access. Full data access requires the selected role to grantDATA_FULL_ACCESS; write bypass requires an edit-level grant. - Rate limit — Each key has a configurable
rateLimitRequestsPerMinutequota; keys created through this endpoint default to 60. - Allowed IPs — Optionally restrict the key to specific source IP addresses.
- Rotation — Generate a new secret for an existing key; the old secret stops working immediately.
- Revocation — Deactivate a key. Takes effect immediately.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /v1/api-keys | List key metadata (secrets never listed). |
POST | /v1/api-keys | Create a key; returns the full secret once. |
GET | /v1/api-keys/{apiKeySimplyId} | Get one key's metadata. |
PUT / PATCH | /v1/api-keys/{apiKeySimplyId} | Update key settings (both methods behave identically). |
DELETE | /v1/api-keys/{apiKeySimplyId} | Revoke (deactivate) a key. |
POST | /v1/api-keys/{apiKeySimplyId}/rotate | Rotate the key secret; returns the new secret once. |
List API Keys
Returns metadata only — the full key values are not included.
const keys = await s360.apiKeys.list();
for (const key of keys.data) {
console.log(`${key.id}: ${key.name} (prefix: ${key.keyPrefix})`);
console.log(` Permissions: ${key.featurePermissions.join(', ')}`);
console.log(` Data role: ${key.teamRoleSimplyId ?? 'none'}`);
console.log(` Last used: ${key.lastUsedAt ?? 'never'}`);
}
curl -s "https://api.simply360.app/v1/api-keys" \
-H "Authorization: Bearer $S360_API_KEY"
Create an API Key
The full key value is in response.data.fullApiKey — store it now. Creating a key requires a user bearer token with admin-level permissions because creation is audited to an authenticated user; API-key-authenticated calls are rejected with 400 VALIDATION_ERROR.
import { Simply360 } from '@simply360/sdk';
const adminClient = new Simply360({
getToken: async () => process.env.S360_USER_ACCESS_TOKEN!,
teamSimplyId: process.env.S360_TEAM_SIMPLY_ID!,
});
const created = await adminClient.apiKeys.create({
name: 'CRM Integration',
teamRoleSimplyId: 'TROL-0000-0001',
featurePermissions: ['TEAM_ADMIN_DC_SCHEMA'],
rateLimitRequestsPerMinute: 600,
allowedIpAddresses: ['203.0.113.10'],
expiresAt: '2027-01-01T00:00:00Z', // optional
});
console.log(`Key ID: ${created.data.id}`);
console.log(`Secret (save now): ${created.data.fullApiKey}`);
curl -s -X POST "https://api.simply360.app/v1/api-keys" \
-H "Authorization: Bearer $S360_USER_ACCESS_TOKEN" \
-H "X-Team-Id: $S360_TEAM_SIMPLY_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "CRM Integration",
"teamRoleSimplyId": "TROL-0000-0001",
"featurePermissions": ["TEAM_ADMIN_DC_SCHEMA"],
"rateLimitRequestsPerMinute": 600
}'
Get an API Key
const key = await s360.apiKeys.get('AKEY-1234-ABCD');
console.log(key.data.isActive, key.data.expiresAt);
curl -s "https://api.simply360.app/v1/api-keys/AKEY-1234-ABCD" \
-H "Authorization: Bearer $S360_API_KEY"
Update an API Key
Change name, featurePermissions, Data Role, allowedIpAddresses, rateLimitRequestsPerMinute, expiresAt, or isActive without rotating the secret, via PUT or PATCH. Set teamRoleSimplyId to null to remove the Data Role. Changing the Data Role requires a user bearer token; API-key credentials can update other key metadata but cannot assign role-backed data access.
await adminClient.apiKeys.update('AKEY-1234-ABCD', {
teamRoleSimplyId: 'TROL-0000-0001',
rateLimitRequestsPerMinute: 1000,
allowedIpAddresses: ['203.0.113.10', '198.51.100.5'],
});
Rotate a Key
Generate a new secret. The old secret is invalidated immediately. Rotating a revoked key returns 404.
const rotated = await s360.apiKeys.rotate('AKEY-1234-ABCD');
console.log(`New secret: ${rotated.data.fullApiKey}`); // store now
curl -s -X POST "https://api.simply360.app/v1/api-keys/AKEY-1234-ABCD/rotate" \
-H "Authorization: Bearer $S360_API_KEY"
Revoke a Key
Deactivates the key. Subsequent requests using it return 401 UNAUTHENTICATED.
await s360.apiKeys.revoke('AKEY-1234-ABCD');
curl -s -X DELETE "https://api.simply360.app/v1/api-keys/AKEY-1234-ABCD" \
-H "Authorization: Bearer $S360_API_KEY"
Best Practices
- Rotate regularly. Set a calendar reminder to rotate every 90 days as a security best practice.
- Least privilege. Assign the narrowest Team Role data permissions and feature permissions each integration actually needs.
- One key per integration. So you can revoke one without affecting the rest.
- Monitor
lastUsedAt. Identify and remove unused keys. - Restrict allowed IPs for keys whose callers operate from known network ranges.
Usage Notes
- Revoking a key takes effect immediately (the key is marked inactive). Treat revocation as final for external integrations; a team admin can re-enable a key by updating
isActive, but rotating to a fresh secret is the safer recovery path. - API key secrets are hashed server-side. If you lose a key, rotate or create a new one — the original is unrecoverable.
- API key operations require the
TEAM_ADMIN_API_KEYSpermission. Setting or changingteamRoleSimplyIdalso requires an authenticated user context with Team Admin/sysadmin access or edit access to user-role administration (TEAM_ADMIN_USER_ROLES).