Documentation
One policy surface. Real-time or batch.
PromptGuard screens text and MediaGuard screens images against policies you define. Use scalar checks in a request path or asynchronous batches for bulk moderation and backfills. Python SDK aetherlab 0.5.0, REST underneath, x-api-key auth.
Scalar quickstart
Install the SDK (Python 3.9+), set your API key, and screen your first output. Keys are issued per environment at app.aetherlab.co.
pip install aetherlab
export AETHERLAB_API_KEY="your-api-key"from aetherlab import AetherLabClient
client = AetherLabClient() # reads AETHERLAB_API_KEY
# An AI response you want screened before it ships
ai_response = "Invest all your money in crypto! Guaranteed 10x returns!"
result = client.check_prompt(
ai_response,
blacklisted_keywords=["guaranteed returns", "financial advice"],
)
print(result.compliance_status) # "Non-Compliant"
print(result.is_compliant) # False
print(result.avg_threat_level) # probability of policy violation
print(result.rationale) # why it was flaggedAt least one policy is required per check: configure standing policies in Policy Controls at app.aetherlab.co, or pass whitelisted_keywords / blacklisted_keywords per request.
import asyncio
from aetherlab import AsyncAetherLabClient
async def main():
async with AsyncAetherLabClient() as client:
result = await client.check_prompt(
"Hello, how can I help you today?",
blacklisted_keywords=["violence", "weapons"],
)
print(result.compliance_status) # "Compliant"
asyncio.run(main())Batch quickstart
Batches run on AetherLab's servers after submission, so your process does not need to stay open. The recommended guardrail-specific routes infer the endpoint and execution window: send prompt strings or media URL/file-ID strings in items, with policy values shared by the batch in settings.
curl -sS -X POST https://api.aetherlab.co/v1/guardrails/prompt/batches \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
"Guaranteed returns with no risk.",
"Your funds may lose value."
],
"settings": {
"blacklisted_keyword": "guaranteed returns",
"reasoning_mode": "medium",
"risk_tolerance": "medium"
}
}'curl -sS -X POST https://api.aetherlab.co/v1/guardrails/media/batches \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
"https://assets.example.com/campaign.png",
"50fd109f-4c3a-42b7-92be-14c1d8f89111"
],
"settings": {
"blacklisted_keyword": "regulated product claim",
"reasoning_mode": "medium"
}
}'# Copy the "id" from the creation response.
BATCH_ID="33333333-3333-4333-8333-333333333333"
# Poll every 5–10 seconds until status is completed, failed, cancelled, or expired.
curl -sS "https://api.aetherlab.co/v1/batches/${BATCH_ID}" \
-H "x-api-key: YOUR_API_KEY"
# A terminal status describes processing. Fetch results for item-level verdicts.
curl -sS "https://api.aetherlab.co/v1/batches/${BATCH_ID}/results" \
-H "x-api-key: YOUR_API_KEY"The creation response is queued job metadata, not compliance verdicts. Small batches commonly complete in about 1–2 minutes; larger batches can take longer depending on item count, reasoning mode, and service load. The supported 24-hour processing window is not a completion-time SLA.
custom_id and Idempotency-Key are optional advanced controls on these routes. AetherLab generates correlation IDs when omitted. Supply your own item IDs when results must join directly to customer records; supply one concrete stable retry key before the first POST only when an uncertain submission may need to be replayed.
SDK helpers
from aetherlab import AetherLabClient
client = AetherLabClient()
batch = client.check_prompt_batch(
[
"Guaranteed returns with no risk.",
"Your funds may lose value.",
],
blacklisted_keywords=["guaranteed returns"],
)
batch = client.wait_for_batch(batch) # polls the server in v1
for item in client.iter_batch_results(batch.id):
print(item.custom_id, item.result or item.error)uploaded = client.upload_file(
"requests.jsonl",
purpose="batch",
)
batch = client.create_batch(
"/v1/guardrails/prompt",
idempotency_key="docs-jsonl-backfill-001",
input_file_id=uploaded.id,
completion_window="24h",
)media_file = client.upload_file(
"campaign.png",
purpose="guardrail_media",
)
media_batch = client.check_media_batch(
[
{"custom_id": "media-url-001",
"url": "https://assets.example.com/campaign.png"},
{"custom_id": "media-file-001",
"file_id": media_file.id},
],
idempotency_key="docs-media-review-001",
blacklisted_keywords=["regulated product claim"],
)from aetherlab import AsyncAetherLabClient
async with AsyncAetherLabClient() as client:
batch = await client.check_prompt_batch(
prompts,
idempotency_key="docs-async-backfill-001",
blacklisted_keywords=["guaranteed returns"],
)
batch = await client.wait_for_batch(batch)
page = await client.get_batch_results(batch.id)
for item in page.items:
print(item.custom_id, item.result or item.error)SDK 0.5.0 exposes matching sync and async resource methods on AetherLabClient and AsyncAetherLabClient: upload_file, create_batch, check_prompt_batch, check_media_batch, list_batches, retrieve_batch, wait_for_batch, get_batch_results, cancel_batch, and delete_batch. The lower-level generic create method requires an idempotency key; the recommended REST routes above do not.
Authentication
All requests authenticate with an x-api-key header against https://api.aetherlab.co. The SDK reads AETHERLAB_API_KEY from the environment, or accepts api_key= explicitly.
- ·Never expose keys in client-side code; keep them in server environment variables.
- ·Use separate keys for development and production, and rotate them periodically.
PromptGuard · POST /v1/guardrails/prompt
Screens text against your guardrail policies and returns a compliance verdict with a threat level, confidence, and rationale. This endpoint backs the SDK's check_prompt().
| Parameter | Type | Required | Description |
|---|---|---|---|
| user_prompt | string | Yes | The text to check |
| whitelisted_keyword | string | No* | Comma-separated topics/keywords that are allowed |
| blacklisted_keyword | string | No* | Comma-separated topics/keywords that are not allowed |
| reasoning_mode | string | No | Reasoning effort: low (default), medium, or high |
| risk_tolerance | string | No | low, medium, or high |
| environment | string | No | Environment tag (default: production) |
* At least one policy is required: standing policies from Policy Controls, or a whitelist/blacklist sent with the request. Otherwise the API returns ERR_0202.
curl -X POST https://api.aetherlab.co/v1/guardrails/prompt \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_prompt": "Invest all your money in crypto! Guaranteed 10x returns!",
"blacklisted_keyword": "guaranteed returns,financial advice"
}'The SDK method test_prompt() is a deprecated 0.3.x alias. Use check_prompt() in new integrations.
MediaGuard · POST /v1/guardrails/media
Screens an image against your guardrail policies. Accepts multipart form data with input_type set to file, url, or base64, plus the same policy and tuning fields as the prompt endpoint. Backs the SDK's check_media() and returns the same response shape.
result = client.check_media(
"photo.png",
input_type="file",
blacklisted_keywords=["violence"],
)
print(result.compliance_status)Batch resources
Batch support is additive: the scalar endpoints above remain available. Use the guardrail-specific routes for normal inline submissions. The generic resource API remains available for provider-compatible envelopes and uploaded JSONL workflows.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/files | Upload JSONL (purpose=batch) or media (purpose=guardrail_media) |
| POST | /v1/guardrails/prompt/batches | Recommended prompt strings plus shared settings |
| POST | /v1/guardrails/media/batches | Recommended media URL/file-ID strings plus shared settings |
| POST | /v1/batches | Advanced generic inline or JSONL creation |
| GET | /v1/batches | List batches |
| GET | /v1/batches/{batch_id} | Poll batch status and item counts |
| GET | /v1/batches/{batch_id}/results | Read item results |
| POST | /v1/batches/{batch_id}/cancel | Request cancellation |
| DELETE | /v1/batches/{batch_id} | Delete a terminal batch resource |
Advanced provider-compatible creation
POST /v1/batches preserves the generic envelope for interoperability. Unlike the recommended routes, it requires an endpoint, the 24-hour completion window, batch-unique correlation IDs, and a concrete idempotency key.
curl -X POST https://api.aetherlab.co/v1/batches \
-H "x-api-key: YOUR_API_KEY" \
-H "Idempotency-Key: prompt-backfill-001" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "/v1/guardrails/prompt",
"completion_window": "24h",
"requests": [
{
"custom_id": "prompt-001",
"method": "POST",
"url": "/v1/guardrails/prompt",
"body": {
"user_prompt": "Guaranteed returns with no risk.",
"blacklisted_keyword": "guaranteed returns"
}
}
]
}'curl -X POST https://api.aetherlab.co/v1/files \
-H "x-api-key: YOUR_API_KEY" \
-F "purpose=batch" \
-F "file=@requests.jsonl"
# Then POST /v1/batches with Idempotency-Key and:
# {"endpoint":"/v1/guardrails/prompt",
# "input_file_id":"FILE_ID","completion_window":"24h"}{"custom_id":"prompt-001","method":"POST","url":"/v1/guardrails/prompt","body":{"user_prompt":"Guaranteed returns.","blacklisted_keyword":"guaranteed returns"}}[
{
"custom_id": "media-url-001",
"body": {
"input_type": "url",
"image": "https://assets.example.com/campaign.png"
}
},
{
"custom_id": "media-file-001",
"body": {
"input_type": "file",
"file_id": "MEDIA_FILE_ID"
}
}
]curl https://api.aetherlab.co/v1/batches/BATCH_ID \
-H "x-api-key: YOUR_API_KEY"curl https://api.aetherlab.co/v1/batches/BATCH_ID/results \
-H "x-api-key: YOUR_API_KEY"curl -X POST https://api.aetherlab.co/v1/batches/BATCH_ID/cancel \
-H "x-api-key: YOUR_API_KEY"
curl -X DELETE https://api.aetherlab.co/v1/batches/BATCH_ID \
-H "x-api-key: YOUR_API_KEY"Batch semantics, limits & retention
Correlation and order
The recommended routes generate a deterministic custom_id when you omit one; supplied IDs must be unique. The advanced generic API requires them. Results are unordered, so correlate every result by its returned custom_id.
Partial failures
Items are independent. A terminal batch can contain successful and failed items; each result carries its own response or error. Inspect every item instead of treating batch completion as universal success.
Media input
MediaGuard batch items reference an HTTPS media URL or a file ID returned by POST /v1/files. Base64 media is not accepted in batches; scalar check_media remains available for that input type.
Window and polling
v1 supports a 24h completion window and uses status polling. Small batches commonly complete in about 1–2 minutes; larger batches can take longer. Poll every 5–10 seconds with backoff, then fetch results after the status becomes terminal.
Documented service limits
- Inline: up to 1,000 items and a 10 MiB request body.
- JSONL: up to 50,000 items and a 200 MiB file.
- These are accepted-input limits, not throughput, latency, or completion guarantees.
{
"object": "list",
"batch_id": "BATCH_ID",
"data": [
{
"custom_id": "prompt-001",
"status": "succeeded",
"response": {
"status": 200,
"message": "Prompt Guard Response",
"data": {"compliance_status": "Non-Compliant"}
}
},
{
"custom_id": "prompt-002",
"status": "failed",
"error": {
"message": "This item could not be processed."
}
}
],
"has_more": false
}Batch inputs use encrypted private staging. Results remain available for seven days. Staged media is removed promptly after processing and no later than 24 hours; downstream model-provider retention remains provider-dependent.
Scalar responses
Both endpoints return a data object with the verdict. The SDK exposes it as ComplianceResult (compliance_status, is_compliant, avg_threat_level, confidence, rationale, full body as raw).
{
"status": 200,
"message": "Prompt Guard Response",
"data": {
"compliance_status": "Compliant",
"avg_threat_level": 0.0,
"confidence": 1.0,
"rationale": "No violating content."
}
}{
"status": 200,
"message": "Prompt Guard Response",
"data": {
"compliance_status": "Non-Compliant",
"avg_threat_level": 1.0,
"confidence": 1.0,
"rationale": "Guaranteed returns violate policy."
}
}Timing expectations
Every check runs a multi-model compliance jury plus your policy engine: the content is evaluated by several models against your rules, and the verdict is adjudicated, scored, and explained. That is substantially more work per request than a single-classifier moderation ping, and the production medians reflect it: roughly 1.4s for text and 1.8s for images (median, across all reasoning modes).
- ·Budget ~2 seconds for a synchronous check in the request path; where your flow allows, run the check concurrently with other work.
- ·
reasoning_modecontrols the depth/latency trade-off per request. Talk to us about tuning it for latency-sensitive paths. - ·The response includes the full verdict, threat level, and rationale in one round trip, so no follow-up call is needed to explain a block.
Those medians describe scalar checks only. Small batches commonly complete in about 1–2 minutes, but batch timing scales with item count, reasoning mode, and service load. Poll every 5–10 seconds with backoff. The documented 24-hour processing window is not a completion-time SLA.
Errors
Standard HTTP status codes, plus an error_code field the SDK maps to a typed exception hierarchy (all inherit from AetherLabError).
| Status | Meaning | SDK exception |
|---|---|---|
| 200 | Success | n/a |
| 400 · ERR_0200 / ERR_0201 | Malformed request | InvalidRequestError |
| 400 · ERR_0202 | No guardrail policy configured | MissingPolicyError |
| 401 | Invalid or missing API key | AuthenticationError |
| 429 | Rate limit exceeded (honours Retry-After) | RateLimitError |
| 5xx | Server error (retried automatically) | APIError |
| Network failure | Unreachable after all retries | APIConnectionError |
Resources
PyPI ↗
aetherlab 0.5.0, the Python SDK
GitHub ↗
Community repo, examples, issues
Support
support@aetherlab.co
Security overview
Architecture, data handling, controls, and operations
Deploying at scale, on-prem, or with bespoke policies? Talk to us, or see how engagements work.
Ship with guardrails this week.
Start with scalar checks, or submit a batch for bulk moderation and backfills. If you need bespoke policies, image workflows at scale, or an assessment first, that's an email away.
Ask about the Evidence Pack
Leave your email and we'll walk you through what an Evidence Pack contains for your use case: severity-scored findings, business-impact mapping, and the approval record.