Custom Connectors
Any system that can make an HTTP POST request can integrate with Humifortis. No SDK required.
Two Integration Patterns
Async — fire and forget. Send events to POST /events. The engine scores them asynchronously. No changes to your login flow. Ideal for evaluation and initial rollout.
Inline — enforce at authentication time. Call POST /evaluate during the login flow. The engine scores the event synchronously and returns a decision: ALLOW, CHALLENGE_MFA, or BLOCK.
Async Mode — Simplest Integration
import requests
def on_login_event(user_id, event_type, ip, user_agent):
requests.post(
"https://your-humifortis-instance/api/v1/events",
headers={
"X-API-Key": "YOUR_KEY",
"Content-Type": "application/json",
},
json={
"event": {
"event_id": str(uuid.uuid4()),
"entity_id": f"user:{user_id}",
"entity_type": "user",
"event_type": event_type, # e.g. "auth.login.failed"
"timestamp": datetime.utcnow().isoformat() + "Z",
"metadata": {
"ip_address": ip,
"user_agent": user_agent,
},
}
},
timeout=2,
)
# Fire-and-forget: POST /events returns 202 immediately
Inline Enforce Mode — Decision at Login Time
Use POST /evaluate to get a synchronous enforcement decision. The event is scored and the decision is returned in the same request.
import uuid
import requests
from datetime import datetime
def authenticate(user_id, ip, user_agent, enrolled_mfa_methods=None):
try:
resp = requests.post(
"https://your-humifortis-instance/api/v1/evaluate",
headers={
"X-API-Key": "YOUR_KEY",
"Content-Type": "application/json",
},
json={
"event": {
"event_id": str(uuid.uuid4()),
"entity_id": f"user:{user_id}",
"entity_type": "user",
"event_type": "auth.login.attempt",
"timestamp": datetime.utcnow().isoformat() + "Z",
"metadata": {
"ip_address": ip,
"user_agent": user_agent,
},
},
"user_mfa_profile": {
"enrolled_methods": enrolled_mfa_methods or [],
"email_verified": True,
"has_email": True,
},
},
timeout=3,
).json()
action = resp.get("action", "ALLOW")
if action == "BLOCK":
raise AuthenticationError("Login blocked by risk policy")
elif action == "CHALLENGE_MFA":
method = resp.get("recommended_mfa_method", "TOTP")
trigger_mfa_challenge(user_id, method)
# else ALLOW — proceed normally
except requests.Timeout:
pass # fail-open: allow if Humifortis is slow
Custom Event Mapping
If your system uses non-standard event names, map them in the Humifortis dashboard under Policies → Event Mappings → New mapping.
| Your event | Mapped to | Effect |
|---|---|---|
okta.user.session.start | AUTH_LOGIN_SUCCESS | +2.0 risk delta |
my-app.brute-force-detected | AUTH_BRUTE_FORCE | +30.0 risk delta |
ad.account.lockout | AUTH_ACCOUNT_LOCKED | +20.0 risk delta |
Once mapped, send the original event name — Humifortis translates it internally.
Pull Model — Query Risk Scores
Instead of (or in addition to) inline enforcement, you can query risk scores on demand:
curl https://your-humifortis-instance/api/v1/risk/user:alice@example.com \
-H "X-API-Key: YOUR_KEY"
Use this for:
- Pre-authorizing sensitive operations (admin panel access, data export)
- Building custom dashboards or SIEM integrations
- Periodic risk audits on your user base
Webhooks & CAEP
Humifortis can push risk events to your systems via webhooks or CAEP (Continuous Access Evaluation Protocol):
- Webhooks: POST a payload when a risk threshold is crossed or a playbook action fires
- CAEP SET tokens: signed Security Event Tokens that allow downstream systems (Keycloak, custom apps) to revoke active sessions in real time
Configure both under Settings → Integrations in the dashboard.
See Also
- Quick Start — your first event in 5 minutes
- Custom Event Mapping — map your event names to canonical signals
- API Reference — full endpoint docs