Authentication
All requests to the S4E API must be authenticated. The platform supports multiple authentication mechanisms depending on your use case: API keys for server-to-server integrations, OAuth 2.0 client credentials for automated systems, and session tokens for browser-based access.
API Keys
API keys are the simplest and most common way to authenticate with the S4E REST API. They are long-lived credentials tied to a specific user and workspace.
Creating an API Key
- Log in to the S4E console.
- Open the account menu (user avatar, top-right) and click API Token.
- Click Generate Token.
- Enter a descriptive name (e.g., "CI/CD Pipeline", "SIEM Connector").
- Toggle Apply All Assets or select specific assets to scope the token's access.
- Check Read and/or Write to set the token's permissions.
- Click Save.
- Copy the key immediately -- it will not be displayed again.
Warning
Store your API key in a secure secrets manager (e.g., HashiCorp Vault, AWS Secrets Manager, or your CI/CD platform's secret store). Never hard-code keys in source files or commit them to version control.
Using the API Key
Include the token in the JSON request body as the token field:
Example: curl
curl -X POST "https://api.s4e.io/asset/handler/bulk-asset-add" \
-H "Content-Type: application/json" \
-d '{
"assets": ["example.com"],
"token": "YOUR_API_TOKEN"
}'
Example: Python (requests)
import requests
API_TOKEN = "YOUR_API_TOKEN"
BASE_URL = "https://api.s4e.io"
response = requests.post(
f"{BASE_URL}/asset/handler/bulk-asset-add",
json={"assets": ["example.com"], "token": API_TOKEN},
)
response.raise_for_status()
result = response.json()
print(result["message"])
Example: Python (S4E SDK)
from s4e import S4EClient
client = S4EClient(api_key="YOUR_API_KEY")
assets = client.assets.list()
for asset in assets:
print(asset.hostname, asset.security_score)
OAuth 2.0 Client Credentials
For machine-to-machine integrations that require short-lived tokens and fine-grained access control, S4E supports the OAuth 2.0 client credentials grant (RFC 6749, Section 4.4).
Obtaining Client Credentials
- Navigate to Settings > OAuth Applications in the S4E console.
- Register a new application.
- Record the Client ID and Client Secret.
Requesting an Access Token
Exchange your client credentials for an access token by sending a POST request to the token endpoint:
curl -X POST "https://api.s4e.io/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=assets:read scans:write"
A successful response returns a JSON object:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "assets:read scans:write"
}
Use the access_token in the Authorization header the same way you would use an API key:
Note
OAuth access tokens have a limited lifetime (typically 1 hour). Your integration must handle token expiration and request a new token before the current one expires. See Token Expiration and Refresh below.
Session Tokens (Cookie-Based)
Session tokens are used by the S4E web console and are primarily relevant if you are building browser-based extensions or single-page applications that interact with the S4E API directly from the browser.
How Session Authentication Works
- The user submits credentials to the login endpoint.
- The server returns a
Set-Cookieheader containing the session token. - Subsequent requests include the cookie automatically (handled by the browser).
curl -X POST "https://api.s4e.io/api/user/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "your_password",
"captcha_response": "string",
"bypass_captcha": false,
"vendor": "googlev3"
}'
The response includes a token in the body and/or a Set-Cookie header. For subsequent API calls, pass the token as a cookie:
Tip
Session-based authentication is intended for interactive browser sessions. For programmatic integrations, prefer API keys or OAuth 2.0 client credentials instead.
API Key Scopes
Scopes control what an API key or OAuth token is authorized to do. Always follow the principle of least privilege -- grant only the scopes your integration requires.
| Scope | Description |
|---|---|
assets:read |
List and retrieve asset details. |
assets:write |
Create, update, and delete assets. |
scans:read |
View scan definitions, results, and history. |
scans:write |
Create, modify, trigger, and cancel scans. |
findings:read |
Access vulnerability findings and their metadata. |
findings:write |
Update finding status, severity, and annotations. |
reports:read |
Generate and download reports. |
actions:execute |
Trigger custom actions and playbooks. |
webhooks:manage |
Create, update, and delete webhook subscriptions. |
admin:full |
Full administrative access. Use with extreme caution. |
Warning
The admin:full scope grants unrestricted access to all resources in the workspace, including user management and billing. Only assign this scope to keys used by trusted, audited automation.
Token Expiration and Refresh
Different authentication methods have different token lifetimes:
| Method | Default Lifetime | Renewable |
|---|---|---|
| API Key | No expiration | Revoke and reissue manually. |
| OAuth Access Token | 1 hour | Request a new token using client credentials. |
| Session Token | 24 hours | Automatically extended on activity; re-login required after idle timeout. |
Handling OAuth Token Expiration
Your integration should proactively refresh tokens before they expire. A common pattern:
import time
import requests
class S4EAuth:
def __init__(self, client_id, client_secret, base_url="https://api.s4e.io"):
self.client_id = client_id
self.client_secret = client_secret
self.base_url = base_url
self._token = None
self._expires_at = 0
def get_token(self):
if time.time() < self._expires_at - 60:
return self._token
response = requests.post(
f"{self.base_url}/oauth/token",
data={
"grant_type": "client_credentials",
"client_id": self.client_id,
"client_secret": self.client_secret,
},
)
response.raise_for_status()
data = response.json()
self._token = data["access_token"]
self._expires_at = time.time() + data["expires_in"]
return self._token
def auth_header(self):
return {"Authorization": f"Bearer {self.get_token()}"}
Security Best Practices
Follow these guidelines to protect your credentials and minimize risk:
-
Use secrets management. Store API keys and client secrets in a dedicated secrets manager, not in environment variables on developer machines or in configuration files.
-
Rotate keys regularly. Establish a rotation schedule (e.g., every 90 days) and revoke old keys promptly.
-
Apply least-privilege scopes. Only request the scopes your integration actually needs. Avoid
admin:fullunless absolutely necessary. -
Use short-lived tokens for automation. Prefer OAuth client credentials over long-lived API keys for automated pipelines, so tokens expire automatically.
-
Audit key usage. Monitor the API key activity log in Settings > API Keys > Activity to detect unauthorized or anomalous usage.
-
Restrict network access. If your S4E instance supports IP allowlisting, configure it to accept API requests only from known source addresses.
-
Never log tokens. Ensure your application does not write API keys or access tokens to log files, error reports, or monitoring systems.
Tip
The S4E console provides an API key activity dashboard that shows request counts, last-used timestamps, and source IP addresses for each key. Review this regularly as part of your security posture management.