Aller au contenu principal
Version: Next đźš§

Authentication & API Keys

The Cert-IX Scan API uses API keys for programmatic access. API keys provide granular scopes, scan type restrictions, per-key rate limits, IP allowlisting, automatic expiration, and zero-downtime rotation.

Authentication Methods​

MethodUse CaseHeader
API KeyProgrammatic API access (scripts, CI/CD, integrations)X-API-Key
JWTDashboard operations (API key management)Authorization: Bearer <token>

This page covers API key authentication. JWT authentication is handled automatically by the Cert-IX Dashboard.

API Key Format​

Cert-IX API keys follow a deterministic format for easy identification:

cix_sk_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SegmentDescription
cix_Cert-IX platform prefix
sk_Secret key type identifier
XXX...40-character cryptographic random string
Security

API keys are hashed with SHA-256 before storage. The raw key is displayed only once at creation. Cert-IX cannot retrieve your key if lost — you must rotate.

Passing Your API Key​

Include your API key in the X-API-Key header on every request:

curl -X GET https://api.cert-ix.com/scan-api/api/v1/scans \
-H "X-API-Key: cix_sk_your_api_key_here"
Never pass API keys in URL query parameters

Query strings may be logged in server access logs, browser history, and proxy caches.

Creating an API Key​

API keys are created via the Cert-IX Dashboard (JWT authentication).

Endpoint​

POST /api/v1/api-keys

Request Body​

{
"name": "CI/CD Pipeline - Production",
"description": "Used by GitHub Actions for nightly vulnerability scans",
"scopes": [
"scans:create",
"scans:read",
"scans:list",
"results:read",
"webhooks:read"
],
"allowedScanTypes": ["nmap", "nuclei", "trivy", "zap"],
"allowedIpAddresses": ["203.0.113.50", "198.51.100.0/24"],
"rateLimitPerMinute": 30,
"rateLimitPerHour": 500,
"rateLimitPerDay": 5000,
"expiresInDays": 90
}

Request Parameters​

FieldTypeRequiredDescription
namestringYesHuman-readable key name (max 255 chars)
descriptionstringNoOptional usage description
scopesstring[]NoPermission scopes (defaults to all scopes)
allowedScanTypesstring[]NoScan engines this key can invoke (defaults to all)
allowedIpAddressesstring[]NoSource IP/CIDR ranges allowed to use this key
rateLimitPerMinuteintegerNoMax requests per minute
rateLimitPerHourintegerNoMax requests per hour
rateLimitPerDayintegerNoMax requests per day
expiresInDaysintegerNoKey expiration in days (0 or null = no expiration)

Response (201 Created)​

{
"success": true,
"data": {
"apiKey": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "CI/CD Pipeline - Production",
"keyPrefix": "cix_sk_001e3c",
"scopes": ["scans:create", "scans:read", "scans:list", "results:read", "webhooks:read"],
"allowedScanTypes": ["nmap", "nuclei", "trivy", "zap"],
"status": "active",
"expiresAt": "2026-06-04T10:00:00Z",
"createdAt": "2026-03-06T10:00:00Z"
},
"rawKey": "cix_sk_001e3c2d92ffb23344a943df2b6a001fb1028d002"
}
}
Critical

The rawKey field is returned only at creation. Copy it immediately and store it in a secure vault (e.g., HashiCorp Vault, AWS Secrets Manager, or your CI/CD secrets store).

Scopes & Permissions​

Scopes control what actions an API key is authorized to perform. Apply the principle of least privilege — only grant the scopes your integration needs.

Available Scopes​

ScopeDescription
scans:createSubmit new scans
scans:readView individual scan details and status
scans:listList all tenant scans
scans:cancelCancel running scans
results:readRetrieve scan results and findings
templates:createCreate scan templates
templates:readView scan templates
templates:updateModify scan templates
templates:deleteDelete scan templates
webhooks:createRegister and test webhooks
webhooks:readView webhook configurations and delivery logs
webhooks:updateModify webhook settings
webhooks:deleteDelete webhooks
usage:readView usage analytics and quota information

CI/CD Pipeline (scan read-write):

["scans:create", "scans:read", "scans:list", "results:read"]

Monitoring Dashboard (read-only):

["scans:read", "scans:list", "results:read", "usage:read"]

Full Automation (scans + webhooks + templates):

["scans:create", "scans:read", "scans:list", "scans:cancel", "results:read",
"templates:create", "templates:read", "templates:update",
"webhooks:create", "webhooks:read"]

Scope Enforcement​

If a request requires a scope the API key doesn't have:

{
"success": false,
"error": "Insufficient scope: requires scans:create",
"code": "INSUFFICIENT_SCOPE"
}

HTTP Status: 403 Forbidden

Allowed Scan Types​

Restrict which scan engines an API key can invoke:

  • Isolate CI/CD keys to container scans only (e.g., trivy)
  • Limit OSINT keys to passive reconnaissance only (e.g., harvester, sublist3r)
  • Restrict web keys to web scanners (e.g., zap, nikto, wapiti)

Available scan types: nmap, zap, trivy, nuclei, nikto, sqlmap, wapiti, harvester, sublist3r, sentinel

IP Allowlisting​

Lock an API key to specific source IP addresses or CIDR ranges. Requests from other IPs are rejected with 403 IP_NOT_ALLOWED.

Supported formats:

  • Single IP: "203.0.113.50"
  • CIDR range: "198.51.100.0/24"
  • IPv6: "2001:db8::1"
Dynamic IPs

For CI/CD runners with dynamic IPs (e.g., GitHub Actions), omit allowedIpAddresses or use the runner's published CIDR ranges.

Rate Limits​

Rate limits protect both your account and the platform. Limits are enforced across three windows:

WindowDefaultConfigurable Range
Per minute601 – 1,000
Per hour1,0001 – 50,000
Per day10,0001 – 500,000

Rate Limit Headers​

Every response includes rate limit information:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1709654460

Rate Limit Exceeded​

{
"success": false,
"error": "Rate limit exceeded. Retry in 23 seconds.",
"code": "RATE_LIMIT_EXCEEDED"
}

HTTP Status: 429 Too Many Requests

Implement exponential backoff in your client:

import time

def api_call_with_retry(func, max_retries=3):
for attempt in range(max_retries):
response = func()
if response.status_code != 429:
return response
wait = 2 ** attempt # 1s, 2s, 4s
time.sleep(wait)
raise Exception("Rate limit exceeded after retries")

Key Rotation​

Rotate API keys with zero downtime using the grace period mechanism. During the grace period, both old and new keys are valid.

Endpoint​

POST /api/v1/api-keys/:keyId/rotate

Request Body (optional)​

{
"gracePeriodHours": 24
}

Rotation Workflow​

1. POST /api-keys/:oldKeyId/rotate     → New key created, old key enters grace period
2. Update your secrets store with the new key
3. Deploy the new key to your services
4. Old key automatically expires after the grace period
Best Practice

Rotate keys every 90 days. Automate rotation in your infrastructure or set a calendar reminder.

Key Revocation​

Immediately and permanently disable an API key. Revocation is instant — the key stops working immediately with no grace period.

Endpoint​

DELETE /api/v1/api-keys/:keyId

Request Body​

{
"reason": "Key compromised — rotating to new key"
}

After revocation, any request using the revoked key returns 401 KEY_REVOKED.

Key Statuses​

StatusDescription
activeKey is fully operational
revokedKey has been permanently disabled
expiredKey has passed its expiresAt date
suspendedKey has been temporarily suspended by an admin

Only active keys can authenticate API requests.

Security Best Practices​

Do​

  • âś… Store keys in a secrets manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault)
  • âś… Use environment variables in your applications — never hardcode keys
  • âś… Apply least-privilege scopes — only grant what's needed
  • âś… Set expiration dates — rotate keys every 90 days
  • âś… Use IP allowlisting for static infrastructure
  • âś… Use per-key rate limits to prevent runaway automation
  • âś… Monitor usage via the usage analytics endpoints
  • âś… Revoke immediately if a key is compromised

Don't​

  • ❌ Never commit keys to source control (Git, SVN)
  • ❌ Never pass keys in URL parameters
  • ❌ Never share keys across teams or environments
  • ❌ Never log API keys in application logs
  • ❌ Never use a single key for all environments — create separate keys for dev, staging, production

Environment Variable Example​

# .env (never committed to Git)
CERTIX_API_KEY=cix_sk_your_api_key_here
import os
api_key = os.environ["CERTIX_API_KEY"]
apiKey := os.Getenv("CERTIX_API_KEY")
const apiKey = process.env.CERTIX_API_KEY;

Next Steps: