HTTP ingestion API
FaultLens works with any application stack. Use an official SDK for streamlined setup, or integrate directly through the documented HTTP ingestion API. This is the canonical, language-neutral event contract — the official SDKs are convenience layers over exactly this endpoint.
Any platform that can make an authenticated HTTPS request can send events: Java, Python, Go, PHP, Ruby, Rust, C++, serverless functions, proprietary runtimes, and legacy systems. Both paths use the same project API key and the same event contract.
Two first-class integration methods
Use an official SDK where one exists — today .NET, TypeScript / JavaScript, React, and Angular. The SDK builds the envelope, authenticates, adds context, and handles retries for you.
Use the Direct HTTP API from any other language or runtime. You own envelope construction, retries, redaction, and context collection. Everything on this page is the same contract the SDKs use, so nothing about this path is second-class or reduced.
Additional SDKs are prioritised based on customer demand and ecosystem feedback.
Endpoint
POST https://YOUR-WORKSPACE.faultlens.in/api/events/ingest
Send to your own tenant ingestion host — the host shown in your FaultLens project setup. There is no shared central ingestion host; substitute the workspace host your project was issued.
- Method:
POST - Content-Type:
application/json - Field names are camelCase. Unknown fields are accepted and ignored, so additions will not break older senders.
Authentication
X-API-Key: YOUR_PROJECT_API_KEY
The project API key is scoped to a single project; FaultLens resolves the project and its organization from the key. The project is not part of the payload. Do not send a workspace or user JWT to this endpoint — it authenticates by API key only.
Canonical envelope (v1)
Required fields
| Field | Type | Notes |
|---|---|---|
eventId | string | Client-generated unique id (UUID recommended). Used for de-duplication. |
timestamp | string (ISO 8601) | When the error occurred, with offset. |
environment | string | Raw environment label (production, staging, …). Normalized server-side. |
sdk | object | { "name": string, "version": string } identifying the sender, e.g. { "name": "custom-python", "version": "1.0.0" }. |
Optional fields
| Field | Type | Notes |
|---|---|---|
release | string | Release/version tag. Groups events by release. Correlation only — never causation. |
serviceName | string (≤256) | Logical service name, e.g. checkout-api. |
serviceVersion | string (≤128) | Service build/version. |
platform | string (≤32) | e.g. dotnet, javascript, java, python, go. When supplied, this value is authoritative for the event. |
level | string | Severity level of the event, e.g. error, warning, fatal. |
message | string | Human-readable summary. Defaults to exception.message. |
exception | object | See below. Provide exception and/or message. |
fingerprint | string | Explicit issue-grouping key. If omitted, FaultLens derives one from the error shape. |
tenantId | string (≤256) | Your own tenant/account id (opaque). Not the FaultLens workspace. |
customerId | string (≤256) | Your own customer id (opaque). |
accountId | string (≤256) | Your own account id (opaque). Falls back to tenantId if omitted. |
userId | string | Stable end-user id. Not an email or name. |
anonymousId | string (≤256) | Unauthenticated/session identity. Do not send together with a known userId. |
correlationId | string (≤256) | Correlates frontend/backend evidence. |
breadcrumbs | array | Diagnostic trail. See below. |
request | object | HTTP request context: requestedUrl, method, route, queryString, referrer, requestId, correlationId. |
page | object | Page context for browser events. |
client | object | Browser/runtime/user-agent context. |
serviceContext | object | Extended service/host/runtime context. |
customerContext | object | Extended customer/tenant context. |
tags | object (string→string) | Custom key/value context. Reserved keys below. |
context | object | Free-form structured context. |
Exception and breadcrumbs
exception
| Field | Type | Notes |
|---|---|---|
type | string (required) | Exception class/type, e.g. System.InvalidOperationException. |
message | string (required) | Exception message. |
stacktrace | array | Frames: { "method" (required), "file", "line", "column" }. |
mechanism | string | e.g. unhandled, handled. |
sourceFile, line, column | string / int | Optional top-frame hints. |
breadcrumbs[]
Required per breadcrumb: timestamp, type, level, message. Optional: sequence, layer, category, source, entityType, entityId, data.
Reserved metadata (business severity)
FaultLens classifies severity from observed impact — affected accounts, event rate, regressions. It never infers business criticality from routes, URLs, messages, or stack traces. To mark an event as belonging to a business-critical capability, send explicit metadata under these reserved tags keys. FaultLens consumes exactly three:
| Reserved tag | Meaning | Constraints |
|---|---|---|
faultlens.capability | Business capability, e.g. checkout, billing-sync. | ≤128 chars |
faultlens.criticality | Capability criticality. | critical | high | normal | low. Any other value is ignored. |
faultlens.operation | Business operation — may name a route, workflow, job, command, or background operation, e.g. payment-capture, nightly-billing-sync. | ≤128 chars |
faultlens.operation value and the single faultlens.criticality. Any other faultlens.* key is not consumed and is treated as an ordinary custom tag at most. Response contract
status. { "status": 1, "id": "b1e5c0de-0000-0000-0000-000000000000", "message": "Event ingested successfully", "timestamp": "2026-07-15T12:34:56.789Z", "reasonCode": null }
status is a numeric enum:
status | Meaning | id | reasonCode |
|---|---|---|---|
1 — Ingested | Event accepted and stored. | event id | null |
2 — Dropped | Accepted by the endpoint but intentionally not stored (e.g. plan/entitlement limits). | null | machine-readable, e.g. billing_limit_exceeded |
3 — Rejected | Well-formed request but not processable (e.g. unknown organization). | null | machine-readable, e.g. organization_id_not_exists |
A robust integration checks status === 1 before considering an event stored, and surfaces 2 / 3 with their reasonCode. Branch on status first, then on reasonCode; the set of reason codes may grow over time.
Errors and retries
| HTTP | When | Retry? |
|---|---|---|
200 + status:1 | Ingested. | No — success. |
200 + status:2 | Dropped (e.g. billing limit). | No — fix entitlement/plan; retrying will drop again. |
200 + status:3 | Rejected (business rule). | No — fix the request. |
400 | Malformed envelope, missing required field, or failed validation. | No — fix the payload. |
401 | Missing or invalid X-API-Key. | No — fix credentials/endpoint. |
403 | Key is not permitted for this operation. | No — fix credentials/permissions. |
429 | Ingestion rate limit exceeded (rate-limited per project). | Yes — back off and retry. |
5xx | Transient server error. | Yes — retry with backoff. |
| Network failure | Connection reset, DNS, or timeout. | Yes — retry with backoff; do not block the application. |
Recommended retry policy
- Retry on
429,5xx, and network failures with exponential backoff and jitter (e.g. 3 attempts). - Do not retry
400,401,403, or200 + status:2/3— they are deterministic and will recur. - Reuse the same
eventIdacross retries of one event. It is the de-duplication key, so a retry is treated as the same logical event. There is no separate idempotency header. - Never let ingestion failures crash or block the host application.
Privacy and redaction
FaultLens sanitizes URLs, query strings, and breadcrumb data server-side, and redacts sensitive query parameters and known sensitive keys. Treat that as a safety net, not a substitute for client-side care.
- Never send:
AuthorizationorCookieheader values, API keys, tokens, passwords, raw request or response bodies, payment card data, or unnecessary personal data. - Identity: send opaque ids for
userId,tenantId, andaccountId. Do not send a knownuserIdand ananonymousIdtogether. - Field caps: identity and context string fields are length-capped server-side; reserved capability/operation values are capped at 128 characters.
Examples
curl
curl -sS -X POST "https://YOUR-WORKSPACE.faultlens.in/api/events/ingest" \ -H "Content-Type: application/json" \ -H "X-API-Key: $FAULTLENS_API_KEY" \ -d '{ "eventId": "3f6c1a52-0000-4000-8000-000000000001", "timestamp": "2026-07-15T12:34:56.000Z", "environment": "production", "sdk": { "name": "custom-python", "version": "1.0.0" }, "release": "checkout@2026.07.15.1", "serviceName": "checkout-api", "platform": "python", "level": "error", "exception": { "type": "TimeoutError", "message": "Payment authorization timed out", "mechanism": "unhandled", "stacktrace": [ { "method": "authorize_payment", "file": "checkout/payments.py", "line": 142 } ] }, "tags": { "faultlens.capability": "checkout", "faultlens.criticality": "critical", "faultlens.operation": "payment-capture" } }'
Generic JSON envelope
{ "eventId": "3f6c1a52-0000-4000-8000-000000000002", "timestamp": "2026-07-15T12:34:56.000Z", "environment": "production", "sdk": { "name": "custom-go", "version": "1.0.0" }, "release": "orders@2026.07.15.2", "serviceName": "orders-service", "serviceVersion": "2.4.0", "platform": "go", "level": "error", "message": "Inventory reservation failed", "fingerprint": "orders:reservation:deadlock", "userId": "user_opaque_123", "accountId": "acct_opaque_456", "correlationId": "corr-9f2a", "exception": { "type": "DeadlockError", "message": "Deadlock detected while committing reservation", "stacktrace": [ { "method": "Commit", "file": "repo/reservation.go", "line": 88 } ] }, "breadcrumbs": [ { "timestamp": "2026-07-15T12:34:55.100Z", "type": "http", "level": "info", "message": "POST /api/orders/import" } ], "request": { "requestedUrl": "https://app.example.com/api/orders/import", "method": "POST", "route": "/api/orders/import", "requestId": "req-7781" }, "tags": { "faultlens.capability": "orders", "faultlens.criticality": "high", "faultlens.operation": "bulk-import" }, "context": { "batchSize": 500 } }
Server-side example (Python)
import os, uuid, json, urllib.request from datetime import datetime, timezone FAULTLENS_HOST = os.environ["FAULTLENS_HOST"] # e.g. https://YOUR-WORKSPACE.faultlens.in FAULTLENS_API_KEY = os.environ["FAULTLENS_API_KEY"] # keep in a secret store def send_event(exc: BaseException) -> None: envelope = { "eventId": str(uuid.uuid4()), "timestamp": datetime.now(timezone.utc).isoformat(), "environment": "production", "sdk": {"name": "custom-python", "version": "1.0.0"}, "platform": "python", "level": "error", "exception": {"type": type(exc).__name__, "message": str(exc)}, "tags": { "faultlens.capability": "checkout", "faultlens.criticality": "critical", "faultlens.operation": "payment-capture", }, } req = urllib.request.Request( f"{FAULTLENS_HOST}/api/events/ingest", data=json.dumps(envelope).encode(), headers={"Content-Type": "application/json", "X-API-Key": FAULTLENS_API_KEY}, method="POST", ) # HTTP 200 is not acceptance: branch on status. with urllib.request.urlopen(req, timeout=5) as resp: body = json.loads(resp.read()) if body.get("status") != 1: # 2 = dropped (e.g. billing_limit_exceeded), 3 = rejected. print("not ingested:", body.get("status"), body.get("reasonCode"))
Reporting should never block or crash your application: send on a background path, cap the time you wait, and treat delivery failures as non-fatal.
Next steps
- Integration docs overview — official SDK setup for .NET, TypeScript / JavaScript, React, and Angular.
- Payload reference on the main docs page.
- Frontend sample apps and .NET sample app.
