Froddy RCL — API Reference

API version: v1 · Base URL: https://froddy.io · Last updated: February 2026


Table of Contents

  1. Authentication
  2. Evaluate Transaction — the core endpoint
  3. Decision Log
  4. Policy Management
  5. Rules
  6. Statistics
  7. Alerting — Telegram (Optional)
  8. Alerting — Webhook
  9. Entity Overrides
  10. Sensitivity Analysis
  11. Pilot Report
  12. Health Check
  13. Tenant Management (Admin)
  14. Idempotency
  15. Error Handling
  16. Timeouts & Latency
  17. Rate Limits
  18. Versioning & Compatibility
  19. Webhook Delivery
  20. Access Level Summary

Authentication

All endpoints except /health and the demo tenant require the X-API-Key header.

X-API-Key: your_tenant_api_key

Each tenant receives a unique API key during provisioning. The key identifies both the caller and the tenant scope — all data returned is isolated to that tenant.

Demo tenant: The demo tenant is publicly accessible without an API key. It is intended for evaluation and interactive demos at froddy.io/demo. Do not use it for production data.

Admin endpoints (tenant management) require a separate admin key passed via the same X-API-Key header.

Authentication uses the X-API-Key header exclusively. Authorization: Bearer is not supported. Missing or invalid keys return HTTP 401 with body {"detail": "Invalid or missing API key"}. Admin endpoints return HTTP 501 if the admin key is not configured on the server.

Evaluate Transaction

The core endpoint. Call this before each payout to receive a verdict.

[TENANT] POST /v1/evaluate

Request

curl -X POST https://froddy.io/v1/evaluate \
  -H "X-API-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "payout_12345",
    "entity_id": "partner_42",
    "amount": 15000.00,
    "currency": "USD",
    "event_type": "payout",
    "device_hash": "abc123def456"
  }'

Request Schema

Field Type Required Description
event_id string yes Unique transaction identifier. Used for idempotency (see Idempotency).
entity_id string yes Identifier of the counterparty (partner, publisher, seller). Opaque to RCL.
amount number yes Transaction amount in the specified currency.
currency string yes Currency code (e.g. "USD").
event_type string yes Operation category (e.g. "payout").
device_hash string no Opaque source identifier used for deduplication grouping. Not a device fingerprint. If omitted, the R-DEDUP rule is skipped.
currency is a freeform string (max 3 characters, defaults to "USD"). event_type is a freeform string (defaults to "payout"); it is metadata only and does not affect rule evaluation. amount must be >= 0 (enforced via Pydantic ge=0); there is no upper bound. All amounts are treated as USD-equivalent for threshold comparison regardless of the currency field.

Response — ALLOW

{
  "event_id": "payout_12345",
  "verdict": "allow",
  "rule_id": null,
  "reason": "All rules passed",
  "evaluated_at": "2026-02-20T14:30:00"
}

Response — HOLD

{
  "event_id": "payout_12345",
  "verdict": "hold-for-review",
  "rule_id": "R-CEIL",
  "reason": "daily ceiling exceeded: $53,000 / $50,000",
  "evaluated_at": "2026-02-20T14:30:00"
}

Response — BLOCK

{
  "event_id": "payout_12345",
  "verdict": "block",
  "rule_id": "R-COHORT",
  "reason": "single transaction $150,000 >= block threshold $100,000",
  "evaluated_at": "2026-02-20T14:30:00"
}

Response Schema

Field Type Description
event_id string Echo of the submitted event_id. Serves as the decision identifier.
verdict string One of: "allow", "hold-for-review", "block"
rule_id string or null The rule that triggered the verdict. null if verdict is allow. One of: "R-COHORT", "R-CEIL", "R-VEL", "R-DEDUP"
reason string Human-readable explanation. "All rules passed" for allow verdicts.
evaluated_at string (ISO 8601) Timestamp of evaluation.

Note: The response does not include decision_id, policy_version, or shadow fields. The event_id serves as the decision identifier. Shadow mode status can be checked via the health endpoint.

Verdict Values

Verdict Meaning Recommended Client Action
allow Transaction within normal parameters Proceed with payout
hold-for-review Anomaly detected, review recommended Queue for manual review
block Clear anomaly, high confidence Reject or escalate

Rule Evaluation Order

Rules are evaluated in fixed priority: R-COHORT → R-CEIL → R-VEL → R-DEDUP. The first rule to trigger determines the verdict. If no rule triggers, the verdict is allow.

For rule parameters and default thresholds, see Policy Management and the Rules Reference in the product docs.


Decision Log

Query the log of all evaluation decisions for this tenant.

List Decisions

[TENANT] GET /v1/decisions

Returns a list of past evaluation decisions with filtering support.

Query Parameters:

Parameter Type Description
entity_id string Filter by entity
verdict string Filter by verdict: allow, hold-for-review, block
scenario string Filter by scenario / event type
Query parameters: limit (integer, default 100, max 1000), entity_id (string), verdict (string), tenant (string), scenario (string). Pagination is limit-based (no cursor, no offset). Date range filtering is not supported on this endpoint — use /v1/decisions/export for date filtering. Response: {"decisions": [...], "count": N} where each decision object contains: id, event_id, entity_id, amount, currency, event_type, event_ts, tenant, scenario, verdict, rule_id, rule_snapshot (JSON string), reason, evaluated_at, device_hash.

Example:

curl -X GET "https://froddy.io/v1/decisions?verdict=block&entity_id=partner_42" \
  -H "X-API-Key: your_key"

Example response:

{
  "decisions": [
    {
      "id": 42,
      "event_id": "payout_12345",
      "entity_id": "partner_42",
      "amount": 15000.0,
      "currency": "USD",
      "event_type": "payout",
      "event_ts": "2026-02-20T14:30:00",
      "tenant": "demo",
      "scenario": "default",
      "verdict": "hold-for-review",
      "rule_id": "R-CEIL",
      "rule_snapshot": "{\"daily_total\": 53000, \"ceiling_usd\": 50000}",
      "reason": "daily ceiling exceeded: $53,000 / $50,000",
      "evaluated_at": "2026-02-20T14:30:01",
      "device_hash": null
    }
  ],
  "count": 1
}

Export Decisions

[TENANT] GET /v1/decisions/export

Exports decisions in JSON format with date filters. Supports up to 50,000 records per request.

Query Parameters:

Parameter Type Description
from string Start date for export range
to string End date for export range
Date parameters (date_from, date_to) use ISO 8601 format (e.g. 2026-02-01). Additional filter: verdict (string) is supported. entity_id filtering is not available on export. Format parameter: format=json (default) returns {"tenant": "...", "count": N, "decisions": [...]}; format=csv returns a file download with Content-Disposition header. The response is not streamed — all rows are loaded in memory. The 50K limit is a silent truncation (rows beyond 50,000 are not returned; no error is raised).

Policy Management

Policy is a JSON object containing all rule thresholds for a tenant. It is versioned automatically — every update increments the version number and stores a snapshot.

Get Current Policy

[TENANT] GET /v1/policy

Returns the active policy, its version number, and the date of last update.

curl -X GET https://froddy.io/v1/policy \
  -H "X-API-Key: your_key"

Response:

{
  "version": 5,
  "updated_at": "2026-02-20T14:30:00Z",
  "policy": {
    "R-COHORT": {
      "hold_usd": 25000,
      "block_usd": 100000
    },
    "R-CEIL": {
      "daily_ceiling_usd": 50000,
      "block_multiplier": 1.5
    },
    "R-VEL": {
      "window_hours": 1,
      "max_count": 20,
      "block_multiplier": 2
    },
    "R-DEDUP": {
      "max_entities": 3,
      "block_entities": 6,
      "window_hours": 24
    },
    "entity_overrides": {
      "partner_vip": {
        "R-CEIL": { "daily_ceiling_usd": 200000 },
        "R-COHORT": { "hold_usd": 50000, "block_usd": 300000 }
      }
    }
  }
}
The response wraps the policy in a parent object: {"version": 3, "policy": {...}, "updated_at": "2026-02-20T14:30:00"}. The version is an integer that auto-increments on each update. updated_at is ISO 8601 format.

Policy Schema — Rule Parameters

Rule Parameter Type Default Description
R-COHORT hold_usd number 25,000 Single transaction ≥ this amount → HOLD
R-COHORT block_usd number 100,000 Single transaction ≥ this amount → BLOCK
R-CEIL daily_ceiling_usd number 50,000 Rolling 24h cumulative limit per entity
R-CEIL block_multiplier number 1.5 Ceiling × multiplier exceeded → BLOCK (otherwise HOLD)
R-VEL max_count number 20 Max transactions in window → HOLD
R-VEL window_hours number 1 Time window in hours
R-VEL block_multiplier number 2 max_count × multiplier exceeded → BLOCK
R-DEDUP max_entities number 3 ≥ N entities sharing the same source hash → HOLD
R-DEDUP block_entities number 6 ≥ N entities sharing the same source hash → BLOCK
R-DEDUP window_hours number 24 Observation window in hours

The entity_overrides object is optional. Keys are entity IDs; values are partial policy objects that override global thresholds for that specific entity.

Update Policy

[TENANT] PUT /v1/policy

Replaces the current policy. The version number auto-increments. A snapshot of the previous policy is stored in the history.

curl -X PUT https://froddy.io/v1/policy \
  -H "X-API-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "R-COHORT": { "hold_usd": 30000, "block_usd": 120000 },
    "R-CEIL": { "daily_ceiling_usd": 75000, "block_multiplier": 1.5 },
    "R-VEL": { "window_hours": 1, "max_count": 25, "block_multiplier": 2 },
    "R-DEDUP": { "max_entities": 3, "block_entities": 6, "window_hours": 24 }
  }'
PUT accepts a complete policy object (full replacement, not partial merge). The body must be a JSON object; non-object bodies return 400. Response: {"version": N, "policy": {...}, "updated_at": "..."} with the new version number. There is no server-side validation of rule parameter names or values within the policy — any JSON object is accepted. Invalid rule keys are only validated on the entity-overrides endpoint.

Policy History

[TENANT] GET /v1/policy/history

Returns all previous policy versions with their snapshots.

curl -X GET https://froddy.io/v1/policy/history \
  -H "X-API-Key: your_key"
Response: {"tenant": "...", "history": [...], "count": N}. Each history entry: {"version": 3, "policy": {...}, "changed_at": "2026-02-20T14:30:00"}. Ordered by version descending (newest first). Limited to the last 20 versions. No pagination — the limit is fixed server-side.

Policy Rollback

[TENANT] POST /v1/policy/rollback/{version}

Reverts the active policy to a specific historical version. This creates a new version (the version counter continues incrementing — it does not reset).

curl -X POST https://froddy.io/v1/policy/rollback/3 \
  -H "X-API-Key: your_key"
Response on success: {"tenant": "...", "rolled_back_to": 3, "new_version": 5, "policy": {...}, "updated_at": "..."}. Rollback creates a new version (increments the counter) with the content of the target version — it does not rewind the version number. If the specified version does not exist in history, returns HTTP 404 with {"detail": "Version N not found in history for tenant '...'"}.

Rules

Get Active Rules

[TENANT] GET /v1/rules

Returns the set of active rules and their current parameters, derived from the active policy. If the policy changes, this endpoint reflects the new state immediately.

curl -X GET https://froddy.io/v1/rules \
  -H "X-API-Key: your_key"
Response: {"rules": [...]}. Each rule object: {"rule_id": "R-CEIL", "name": "Daily exposure ceiling", "description": "...", "type": "ceiling", "params": {...}}. Rules R-COHORT, R-CEIL, and R-VEL are always included. R-DEDUP is only included if configured in the policy (i.e., if the policy contains an R-DEDUP or R-DEVICE key with non-empty config). There is no concept of "disabled" rules — a rule is either present in the policy or absent.

Statistics

Aggregated statistics for the current tenant.

Aggregate Stats

[TENANT] GET /v1/stats

Returns aggregated counters: total evaluations, count by verdict, total amounts.

curl -X GET https://froddy.io/v1/stats \
  -H "X-API-Key: your_key"
Response: {"total": 150, "allow_count": 120, "hold_count": 20, "block_count": 10, "blocked_amount": 45000.0, "held_amount": 32000.0}. Stats cover all-time (no window, no date range parameters). Filter parameters: tenant (string), scenario (string).

Verdict Timeseries

[TENANT] GET /v1/stats/timeseries

Returns verdict counts over time (for charting purposes). Supports hourly and daily buckets.

curl -X GET "https://froddy.io/v1/stats/timeseries" \
  -H "X-API-Key: your_key"
Query parameters: bucket ("hour" or "day", default "hour"), tenant (string), scenario (string). No date range filter — returns the last 168 buckets (7 days hourly, or ~24 weeks daily). Response: {"bucket": "hour", "data": [...]}. Each data entry: {"bucket": "2026-02-20T14:00:00", "allow_count": 10, "hold_count": 2, "block_count": 1, "total_amount": 25000.0, "blocked_amount": 5000.0}. Ordered by bucket descending (newest first).

Top Entities

[TENANT] GET /v1/stats/entities

Returns the top 20 entities ranked by the number of non-allow verdicts (hold + block triggers).

curl -X GET https://froddy.io/v1/stats/entities \
  -H "X-API-Key: your_key"
Response: {"entities": [...]}. Each entry: {"entity_id": "partner_42", "total": 50, "allow_count": 40, "hold_count": 7, "block_count": 3, "total_amount": 125000.0, "blocked_amount": 15000.0, "last_seen": "2026-02-20T14:30:00"}. Ranking: block_count DESC, hold_count DESC, total DESC. The limit is parameterized: limit query parameter (default 20, max 100). Additional filters: tenant, scenario.

Alerting — Telegram (Optional)

RCL can send real-time alerts to a Telegram group or channel on every HOLD or BLOCK verdict. Note: Webhook and Email are the primary notification channels. Telegram is an optional additional channel that may be deprecated in favor of other messaging integrations.

Get Telegram Settings

[TENANT] GET /v1/telegram

Returns the current Telegram alert configuration for this tenant.

Configure Telegram

[TENANT] PUT /v1/telegram

curl -X PUT https://froddy.io/v1/telegram \
  -H "X-API-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_token": "123456:ABC-DEF...",
    "chat_id": "-1001234567890"
  }'
Field Type Required Description
bot_token string yes Telegram Bot API token
chat_id string yes Target chat/group/channel ID

Remove Telegram Configuration

[TENANT] DELETE /v1/telegram

Disables Telegram alerts for this tenant.

Alert Format

Each alert includes: verdict emoji (🟡 hold / 🔴 block), rule name, entity ID, amount, human-readable reason, and timestamp.

Alert format is fixed (not customizable). Messages use HTML parse mode. Example:
🔴 RCL Alert: BLOCK

Entity: partner_42
Amount: $15,000.00
Rule: R-CEIL
Reason: daily ceiling exceeded: $53,000 / $50,000
Event: payout_12345
Time: 2026-02-20T14:30:01

Emoji mapping: 🔴 = block, 🟡 = hold-for-review.


Alerting — Webhook

RCL sends an HTTP POST request to a configured URL on every non-allow verdict.

Get Webhook Settings

[TENANT] GET /v1/webhook

Configure Webhook

[TENANT] PUT /v1/webhook

curl -X PUT https://froddy.io/v1/webhook \
  -H "X-API-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://your-system.com/rcl-alert"
  }'
Field Type Required Description
webhook_url string yes HTTPS URL that will receive POST requests on hold/block

Remove Webhook Configuration

[TENANT] DELETE /v1/webhook

For details on webhook delivery mechanics (payload format, retry policy, expected response), see Webhook Delivery.


Entity Overrides

Per-entity threshold overrides let you customize rule parameters for specific entities (e.g. VIP partners with legitimate high volumes) without changing the global policy.

Entity overrides can be managed both via the Policy API (entity_overrides field in the policy JSON) and via these dedicated endpoints.

Get Override

[TENANT] GET /v1/entity-overrides/{entity_id}

Returns the current threshold overrides for a specific entity.

Set Override

[TENANT] PUT /v1/entity-overrides/{entity_id}

curl -X PUT https://froddy.io/v1/entity-overrides/partner_vip \
  -H "X-API-Key: your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "R-CEIL": { "daily_ceiling_usd": 200000 },
    "R-COHORT": { "hold_usd": 50000, "block_usd": 300000 }
  }'

The override object is a partial policy — only include the rules and parameters you want to override.

Remove Override

[TENANT] DELETE /v1/entity-overrides/{entity_id}

Removes all custom thresholds for the entity. It will be evaluated against the global policy.

Entity overrides are stored inside the policy object under the entity_overrides key — they are the same store. Setting an override via this endpoint writes to policy.entity_overrides[entity_id] and increments the policy version. Responses:
GET /v1/entity-overrides: {"tenant": "...", "entity_overrides": {...}, "count": N}
GET /v1/entity-overrides/{id}: {"tenant": "...", "entity_id": "...", "overrides": {...}} (404 if not found)
PUT /v1/entity-overrides/{id}: {"tenant": "...", "entity_id": "...", "overrides": {...}, "policy_version": N}
DELETE /v1/entity-overrides/{id}: {"tenant": "...", "entity_id": "...", "deleted": true, "policy_version": N} (404 if not found)

Sensitivity Analysis

Re-evaluate historical decisions using alternative thresholds, without affecting the live policy. Use this to model the impact of threshold changes before committing them.

[TENANT] POST /v1/sensitivity

Request body:

{
  "configs": [
    {
      "label": "conservative",
      "R-COHORT": { "hold_usd": 15000, "block_usd": 50000 },
      "R-CEIL": { "daily_ceiling_usd": 30000 },
      "R-VEL": {}
    },
    {
      "label": "permissive",
      "R-COHORT": { "hold_usd": 50000, "block_usd": 200000 }
    }
  ],
  "scenario": "default"
}

Accepts 1–5 configs. Each config can include R-COHORT, R-CEIL, R-VEL thresholds. The scenario filter is optional. Currently, only R-COHORT (single-transaction size) is re-evaluated against historical data. R-CEIL and R-VEL require full state replay and are not re-simulated. Historical data is loaded up to 50,000 decisions.

Response:

{
  "tenant": "demo",
  "total_decisions": 1500,
  "results": [
    {
      "label": "conservative",
      "config": { "R-COHORT": { "hold_usd": 15000, "block_usd": 50000 }, ... },
      "verdicts": { "allow": 1200, "hold": 250, "block": 50 },
      "hold_rate": 16.67,
      "block_rate": 3.33,
      "note": "Only R-COHORT is re-evaluated..."
    }
  ]
}

Pilot Report

Aggregated data suitable for generating a pilot summary report.

[TENANT] GET /v1/report

Optional query parameter: scenario (string). No date range filter — returns all data for the tenant.

Response:

{
  "tenant": "acme_corp",
  "scenario": "default",
  "policy": { "version": 5, "policy": {...}, "updated_at": "..." },
  "report": {
    "summary": { "total": 1500, "allow": 1200, "hold": 250, "block": 50 },
    "rule_breakdown": [...],
    "top_entities": [...],
    "daily_timeline": [...]
  },
  "generated_at": "2026-02-20T15:00:00"
}

The data is structured for programmatic consumption (PDF generation, dashboards). The report object contains aggregated data from db.get_report_data().


Health Check

[PUBLIC] GET /health

Returns the service and database health status. No authentication required.

curl https://froddy.io/health
{
  "status": "ok",
  "db_healthy": true,
  "fail_open": true,
  "service": "rcl-proto",
  "mode": "shadow",
  "version": "1.0.0",
  "db_backend": "SQLite",
  "uptime_s": 3600
}

status is "ok" when the database is healthy, "degraded" otherwise. fail_open indicates the service recommends clients proceed (allow) if RCL is unreachable.


Tenant Management (Admin)

These endpoints require the admin API key and are used for provisioning and managing tenants. They are not available to regular tenant API keys.

Note for external integrators: Tenant provisioning is handled by the Froddy team during pilot onboarding. These endpoints are documented here for completeness. You do not need to call them directly.

Create Tenant

[ADMIN] POST /v1/tenants

curl -X POST https://froddy.io/v1/tenants \
  -H "X-API-Key: admin_key" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "acme_corp",
    "name": "Acme Corporation"
  }'

Response:

{
  "tenant_slug": "acme_corp",
  "api_key": "rcl_abc123..."
}
Field Type Required Description
slug string yes URL-safe unique identifier for the tenant
name string yes Human-readable tenant name

List Tenants

[ADMIN] GET /v1/tenants

Delete Tenant

[ADMIN] DELETE /v1/tenants/{slug}

Deletion is a hard delete. All decisions for the tenant are deleted from the decisions table, then the tenant row (including webhook URL and Telegram config) is deleted from the tenants table. Policy history snapshots in the policy_history table are not deleted (orphaned). The demo tenant cannot be deleted (returns 400). Nonexistent slug returns 404.
GET /v1/tenants: {"tenants": [{"tenant_slug": "...", "name": "...", "policy_version": N, "created_at": "..."}, ...]} (API keys are not returned in the list).
DELETE /v1/tenants/{slug}: {"deleted": "acme_corp"}.

Idempotency

The /v1/evaluate endpoint is idempotent. If the same transaction is submitted more than once — identified by the combination of event_id + tenant + scenario — RCL returns the original verdict without re-evaluating.

This means:

Recommended practice: Use your system's native payout identifier as event_id. This naturally ensures deduplication.

The idempotency scope is event_id + tenant + scenario. Decisions are stored indefinitely (no TTL) — an event_id that has been evaluated will always return the same verdict, even if the policy has changed since. The scenario field defaults to "default".


Error Handling

All errors return a JSON body with a detail field:

{
  "detail": "entity_id is required"
}

HTTP Status Codes

Status Meaning
200 Success
400 Bad request — invalid or missing fields
401 Unauthorized — missing or invalid API key
403 Forbidden — valid key but insufficient permissions (e.g. tenant key on admin endpoint)
404 Not found — endpoint or resource does not exist
409 Conflict — possible for duplicate resource creation
422 Unprocessable entity — valid JSON but semantically invalid
429 Rate limit exceeded
500 Internal server error

Timeouts & Latency

The /v1/evaluate endpoint is designed for synchronous, inline use in the payout execution path. Response times are typically in the low double-digit millisecond range.

Client-side recommendations:

No published latency metrics or SLA at this stage (pre-GA product). Observed latency during pilot testing is typically <50ms p50, <150ms p95. The API does not publish latency headers. Recommended client timeout: 1–2 seconds with fail-open fallback (if RCL is unreachable, proceed with the payout).

Rate Limits

The /v1/evaluate endpoint is rate-limited per tenant.

ParameterDefaultDescription
Limit100 requests/minutePer tenant, sliding window
Response on exceedHTTP 429{"detail": "Rate limit exceeded (100 req/min). Retry after a few seconds."}
ConfigurationRCL_RATE_LIMIT env varConfigurable at deployment

No rate limit headers are currently returned. The limit applies to /v1/evaluate only; other endpoints are not rate-limited.


Versioning & Compatibility

The API is versioned via URL path prefix: all current endpoints are under /v1/.

Response bodies may include additional fields in the future — clients should ignore unknown fields. Breaking changes (field removal, type changes, semantic changes) will be introduced under a new version prefix (e.g. /v2/). No formal deprecation timeline is defined at this stage. Clients integrating with /v1/ can expect stability for the duration of their pilot and production use.

Webhook Delivery

When a webhook URL is configured, RCL sends a POST request to that URL on every hold or block verdict.

Payload

The webhook receives a JSON POST with Content-Type: application/json:

{
  "event_id": "payout_12345",
  "entity_id": "partner_42",
  "amount": 15000.0,
  "verdict": "hold-for-review",
  "rule_id": "R-CEIL",
  "reason": "daily ceiling exceeded: $53,000 / $50,000",
  "evaluated_at": "2026-02-20T14:30:01"
}

The payload is identical for both webhook and Telegram alerts. Field rule_id (not rule) matches the evaluate response schema.

Delivery Expectations


Access Level Summary

Every endpoint falls into one of three access levels:

Level Authentication Who Uses It
[PUBLIC] None Anyone — health checks, demo
[TENANT] Tenant API key via X-API-Key Integrating systems, ops teams
[ADMIN] Admin API key via X-API-Key Froddy team — tenant provisioning

Full Endpoint Map

Method Endpoint Access Description
POST /v1/evaluate TENANT Evaluate a transaction
GET /v1/decisions TENANT Query decision log
GET /v1/decisions/export TENANT Export decisions (up to 50K)
GET /v1/policy TENANT Get current policy
PUT /v1/policy TENANT Update policy
GET /v1/policy/history TENANT List policy versions
POST /v1/policy/rollback/{ver} TENANT Rollback to a policy version
GET /v1/rules TENANT Get active rules
GET /v1/stats TENANT Aggregated statistics
GET /v1/stats/timeseries TENANT Verdict counts over time
GET /v1/stats/entities TENANT Top 20 entities by triggers
GET /v1/telegram TENANT Get Telegram config (optional)
PUT /v1/telegram TENANT Set Telegram config (optional)
DELETE /v1/telegram TENANT Remove Telegram config (optional)
GET /v1/webhook TENANT Get webhook config
PUT /v1/webhook TENANT Set webhook config
DELETE /v1/webhook TENANT Remove webhook config
GET /v1/entity-overrides/{id} TENANT Get entity override
PUT /v1/entity-overrides/{id} TENANT Set entity override
DELETE /v1/entity-overrides/{id} TENANT Remove entity override
POST /v1/sensitivity TENANT What-if analysis
GET /v1/report TENANT Pilot report data
GET /health PUBLIC Service health
POST /v1/tenants ADMIN Create tenant
GET /v1/tenants ADMIN List tenants
DELETE /v1/tenants/{slug} ADMIN Delete tenant

Froddy RCL API Reference · v1 · froddy.io · Product Docs · Interactive Demo