Skip to content

Email DLP API

The Email DLP API provides admin endpoints for managing email quarantine, per-org relay configuration, and compliance templates. All endpoints require admin authentication (Authorization: Bearer <admin-token>).

For setup instructions, see Email DLP Setup. For configuration guidance, see Email DLP Configuration. For quarantine workflows, see Email Quarantine Management.


Method Path Description
GET /v1/admin/email/quarantine List quarantined emails
GET /v1/admin/email/quarantine/stats Aggregated quarantine statistics
GET /v1/admin/email/quarantine/{scan_id} Get quarantine detail
GET /v1/admin/email/quarantine/{scan_id}/eml Download raw .eml file
POST /v1/admin/email/quarantine/{scan_id}/release Release and re-deliver
DELETE /v1/admin/email/quarantine/{scan_id} Soft-delete
Method Path Description
GET /v1/admin/email/config List all org configs
GET /v1/admin/email/config/defaults Get default config values
GET /v1/admin/email/config/{org_id} Get org config
PUT /v1/admin/email/config/{org_id} Create or update org config
DELETE /v1/admin/email/config/{org_id} Delete org config (revert to defaults)
Method Path Description
GET /v1/admin/email/overview Per-org dashboard summary

The QuarantineItemResponse returned in list results:

Field Type Description
scan_id string Unique DLP scan ID (max 64 chars)
org_id int | null Owning organization ID
sender string | null Envelope sender address (RFC 5321)
recipients list[string] | null Recipient addresses
subject string | null Email subject line
risk_level string DLP risk: none, low, medium, high, critical
action string Disposition taken: quarantine, reject
entity_count int Number of detected sensitive entities
quarantined_at datetime | null When the email was quarantined
released_at datetime | null When (if) released for delivery
released_by uuid | null Admin user ID who released

The QuarantineDetailResponse extends the above with:

Field Type Description
entities list[object] Full list of detected entity dicts (entity_type, confidence, detection_tier, span offsets)
attachment_findings list[object] Per-attachment scan results (filename, status, findings)
eml_path string | null Filesystem path to the raw .eml file

List quarantined emails with pagination, filtering, and sorting.

Query parameters:

Parameter Type Default Description
page int 1 Page number (1-indexed)
page_size int 25 Results per page (1–100)
offset int Legacy offset override (takes precedence over page)
limit int Legacy limit override (1–200, takes precedence over page_size)
org_id int Exact-match filter on organization
risk_level string Exact-match filter: none, low, medium, high, critical
action string Exact-match filter: quarantine, reject
sender_domain string Match sender domain (SQL LIKE %@{domain})
date_from datetime quarantined_at >= date_from
date_to datetime quarantined_at <= date_to
has_attachments bool Filter by whether attachment_findings is non-empty
sort_by string quarantined_at Sort column: quarantined_at, risk_level, sender
sort_order string desc Sort direction: asc, desc

Response (200 OK):

{
"items": [
{
"scan_id": "scan_01HXYZ",
"org_id": 42,
"sender": "[email protected]",
"recipients": ["[email protected]"],
"subject": "Patient update - urgent",
"risk_level": "high",
"action": "quarantine",
"entity_count": 2,
"quarantined_at": "2026-03-20T09:14:22Z",
"released_at": null,
"released_by": null
}
],
"total_count": 1,
"page": 1,
"page_size": 25,
"total": 1,
"offset": 0,
"limit": 25
}

The total/offset/limit fields are legacy compatibility aliases for total_count/computed offset/effective limit.


Aggregated statistics for all non-deleted quarantined emails. All aggregation is performed server-side.

Response (200 OK):

{
"total_quarantined": 842,
"by_risk_level": {
"critical": 12,
"high": 187,
"medium": 501,
"low": 142
},
"by_action": {
"quarantine": 700,
"reject": 142
},
"by_org": {
"42": 412,
"58": 430
},
"time_series_7d": [
{"date": "2026-03-17", "count": 98},
{"date": "2026-03-18", "count": 115},
{"date": "2026-03-19", "count": 107},
{"date": "2026-03-20", "count": 143},
{"date": "2026-03-21", "count": 132},
{"date": "2026-03-22", "count": 119},
{"date": "2026-03-23", "count": 128}
],
"time_series_30d": ["..."],
"top_entity_types": [
{"entity_type": "ssn", "count": 234},
{"entity_type": "health_info", "count": 198},
{"entity_type": "credit_card", "count": 87}
],
"avg_scan_latency_ms": 108.4
}
Field Type Description
total_quarantined int Total non-deleted quarantine records
by_risk_level dict[string, int] Count grouped by risk level
by_action dict[string, int] Count grouped by action
by_org dict[int, int] Count grouped by organization ID
time_series_7d list[object] Daily counts for the last 7 days
time_series_30d list[object] Daily counts for the last 30 days
top_entity_types list[object] Most frequently detected entity types
avg_scan_latency_ms float | null Average DLP scan duration in milliseconds

Get full detail for a single quarantined email, including entities and attachment findings.

Path parameters:

Parameter Type Description
scan_id string DLP scan ID

Response (200 OK):

Returns QuarantineDetailResponse — see Quarantine object above.

Errors:

Status Condition
404 Quarantined email not found

GET /v1/admin/email/quarantine/{scan_id}/eml

Section titled “GET /v1/admin/email/quarantine/{scan_id}/eml”

Download the raw .eml file for a quarantined email.

Path parameters:

Parameter Type Description
scan_id string DLP scan ID

Response: application/octet-stream

The response body is the raw .eml bytes. The Content-Disposition header is set to attachment; filename="{scan_id}.eml".

Terminal window
curl -s "https://platform.arbitex.ai/v1/admin/email/quarantine/scan_01HXYZ/eml" \
-H "Authorization: Bearer <admin-token>" \
-o scan_01HXYZ.eml

Errors:

Status Condition
404 Quarantined email not found, no .eml path stored, or .eml file missing from disk

POST /v1/admin/email/quarantine/{scan_id}/release

Section titled “POST /v1/admin/email/quarantine/{scan_id}/release”

Release a quarantined email — re-deliver via SMTP to the downstream MTA. The original .eml is transmitted with X-Arbitex-DLP-Released headers appended. An audit event (email_quarantine_released) is recorded.

Path parameters:

Parameter Type Description
scan_id string DLP scan ID to release

No request body required.

Response (200 OK):

{
"status": "released",
"scan_id": "scan_01HXYZ"
}

Errors:

Status Condition
404 Quarantined email not found or already released
502 SMTP delivery to downstream MTA failed — email remains quarantined

DELETE /v1/admin/email/quarantine/{scan_id}

Section titled “DELETE /v1/admin/email/quarantine/{scan_id}”

Soft-delete a quarantined email. Sets deleted_at on the record. The email is excluded from list queries and stats. An audit event (email_quarantine_deleted) is recorded.

Path parameters:

Parameter Type Description
scan_id string DLP scan ID to delete

Response (200 OK):

{
"status": "deleted",
"scan_id": "scan_01HXYZ"
}

Errors:

Status Condition
404 Quarantined email not found

Per-org email relay configuration stored in the email_relay_config table:

Field Type Default Validation Description
id int Auto-increment PK Config record ID
org_id int FK to organizations.id, unique Organization this config applies to
enabled bool true Enable email DLP scanning for this org
allowed_sender_domains list[string] [] Regex-validated domain format Sender domain allowlist. Empty = all domains accepted
quarantine_policy string "quarantine" quarantine, reject, tag Action on high-risk findings
max_attachment_size_mb int 10 1–50 Max per-attachment size in MB
custom_risk_thresholds object | null null Per-entity-type confidence overrides
rate_limit_per_minute int 60 1–10,000 Sustained message rate limit
rate_limit_burst int 120 1–20,000 Burst capacity above sustained rate

The response also includes:

Field Type Description
applied_templates list[object] Active compliance templates — each has template_id (string) and rule_count (int)

List all per-org email relay configurations.

Response (200 OK): Array of EmailRelayConfigResponse objects.


Return the default email relay configuration values. These are the values used for any organization without a per-org config record. The response is static — no database query needed.

Response (200 OK):

{
"enabled": true,
"allowed_sender_domains": [],
"quarantine_policy": "quarantine",
"max_attachment_size_mb": 10,
"custom_risk_thresholds": null,
"rate_limit_per_minute": 60,
"rate_limit_burst": 120
}

Get email relay configuration for a specific organization.

Path parameters:

Parameter Type Description
org_id int Organization ID

Response (200 OK): EmailRelayConfigResponse including applied_templates.

Errors:

Status Condition
404 No email config exists for org_id

Create or update email relay configuration for an organization. Idempotent: creates if no config exists, updates otherwise. Returns 422 on validation failure.

Path parameters:

Parameter Type Description
org_id int Organization ID

Request body:

{
"enabled": true,
"allowed_sender_domains": ["acme.com", "partner.org"],
"quarantine_policy": "quarantine",
"max_attachment_size_mb": 20,
"custom_risk_thresholds": null,
"rate_limit_per_minute": 200,
"rate_limit_burst": 400
}

All fields have defaults, so you only need to include fields you want to override.

Domain validation: Each domain in allowed_sender_domains is validated against the pattern ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$.

Response (200 OK): Updated EmailRelayConfigResponse including applied_templates.

Errors:

Status Condition
404 Organization org_id does not exist
422 Validation failure (invalid domain format, out-of-range values, invalid quarantine_policy)

Delete email relay configuration for an organization, reverting to system defaults.

Path parameters:

Parameter Type Description
org_id int Organization ID

Response: 204 No Content

Errors:

Status Condition
404 No email config exists for org_id

Per-org email DLP summary for the admin dashboard. Returns all organizations with relay config status, active quarantine counts, 24-hour scan volume, and applied compliance templates.

Response (200 OK):

{
"orgs": [
{
"org_id": 42,
"org_name": "Acme Corp",
"enabled": true,
"quarantine_policy": "quarantine",
"templates_applied": ["hipaa", "pci_dss"],
"quarantine_count": 23,
"scan_volume_24h": 412
}
],
"global_enabled": true,
"total_quarantine_count": 23
}
Field Type Description
orgs list[OrgEmailOverview] Per-org summary (all orgs, defaults applied where no config row)
global_enabled bool System-wide email_dlp.enabled toggle
total_quarantine_count int Sum of active quarantine records across all orgs

OrgEmailOverview fields:

Field Type Description
org_id int Organization ID
org_name string Organization display name
enabled bool Whether email DLP scanning is enabled for this org
quarantine_policy string Active quarantine policy
templates_applied list[string] Compliance template IDs active for this org
quarantine_count int Active (non-deleted, non-released) quarantine records
scan_volume_24h int Quarantine records created in the last 24 hours