Reference

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.

Key handling: server-side, keep the key in configuration or a secret store. In browser or mobile clients the key is visible to end users by design — use the project key intended for client use, and never place a server-only secret in public frontend code.

Canonical envelope (v1)

Required fields

FieldTypeNotes
eventIdstringClient-generated unique id (UUID recommended). Used for de-duplication.
timestampstring (ISO 8601)When the error occurred, with offset.
environmentstringRaw environment label (production, staging, …). Normalized server-side.
sdkobject{ "name": string, "version": string } identifying the sender, e.g. { "name": "custom-python", "version": "1.0.0" }.

Optional fields

FieldTypeNotes
releasestringRelease/version tag. Groups events by release. Correlation only — never causation.
serviceNamestring (≤256)Logical service name, e.g. checkout-api.
serviceVersionstring (≤128)Service build/version.
platformstring (≤32)e.g. dotnet, javascript, java, python, go. When supplied, this value is authoritative for the event.
levelstringSeverity level of the event, e.g. error, warning, fatal.
messagestringHuman-readable summary. Defaults to exception.message.
exceptionobjectSee below. Provide exception and/or message.
fingerprintstringExplicit issue-grouping key. If omitted, FaultLens derives one from the error shape.
tenantIdstring (≤256)Your own tenant/account id (opaque). Not the FaultLens workspace.
customerIdstring (≤256)Your own customer id (opaque).
accountIdstring (≤256)Your own account id (opaque). Falls back to tenantId if omitted.
userIdstringStable end-user id. Not an email or name.
anonymousIdstring (≤256)Unauthenticated/session identity. Do not send together with a known userId.
correlationIdstring (≤256)Correlates frontend/backend evidence.
breadcrumbsarrayDiagnostic trail. See below.
requestobjectHTTP request context: requestedUrl, method, route, queryString, referrer, requestId, correlationId.
pageobjectPage context for browser events.
clientobjectBrowser/runtime/user-agent context.
serviceContextobjectExtended service/host/runtime context.
customerContextobjectExtended customer/tenant context.
tagsobject (string→string)Custom key/value context. Reserved keys below.
contextobjectFree-form structured context.

Exception and breadcrumbs

exception

FieldTypeNotes
typestring (required)Exception class/type, e.g. System.InvalidOperationException.
messagestring (required)Exception message.
stacktracearrayFrames: { "method" (required), "file", "line", "column" }.
mechanismstringe.g. unhandled, handled.
sourceFile, line, columnstring / intOptional 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 tagMeaningConstraints
faultlens.capabilityBusiness capability, e.g. checkout, billing-sync.≤128 chars
faultlens.criticalityCapability criticality.critical | high | normal | low. Any other value is ignored.
faultlens.operationBusiness operation — may name a route, workflow, job, command, or background operation, e.g. payment-capture, nightly-billing-sync.≤128 chars
There is intentionally no separate workflow, job, or operation-criticality tag. Model those as the single 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

An HTTP 200 does not by itself mean the event was accepted. Every business outcome returns HTTP 200 with a JSON body — you must inspect 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:

statusMeaningidreasonCode
1 — IngestedEvent accepted and stored.event idnull
2 — DroppedAccepted by the endpoint but intentionally not stored (e.g. plan/entitlement limits).nullmachine-readable, e.g. billing_limit_exceeded
3 — RejectedWell-formed request but not processable (e.g. unknown organization).nullmachine-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

HTTPWhenRetry?
200 + status:1Ingested.No — success.
200 + status:2Dropped (e.g. billing limit).No — fix entitlement/plan; retrying will drop again.
200 + status:3Rejected (business rule).No — fix the request.
400Malformed envelope, missing required field, or failed validation.No — fix the payload.
401Missing or invalid X-API-Key.No — fix credentials/endpoint.
403Key is not permitted for this operation.No — fix credentials/permissions.
429Ingestion rate limit exceeded (rate-limited per project).Yes — back off and retry.
5xxTransient server error.Yes — retry with backoff.
Network failureConnection 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, or 200 + status:2/3 — they are deterministic and will recur.
  • Reuse the same eventId across 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:Authorization or Cookie header values, API keys, tokens, passwords, raw request or response bodies, payment card data, or unnecessary personal data.
  • Identity: send opaque ids for userId, tenantId, and accountId. Do not send a known userId and an anonymousId together.
  • Field caps: identity and context string fields are length-capped server-side; reserved capability/operation values are capped at 128 characters.
Direct integration is not permission to send secrets. You own redaction on this path.

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