Skip to main content

logseal

Official Python SDK for LogSeal — Audit logging for B2B SaaS.

Installation

pip install logseal

Quick Start

import asyncio
from logseal import LogSeal, ActorInput, EmitEventInput, TargetInput

async def main():
    async with LogSeal(api_key="sk_test_...") as client:
        # Emit an event (batched, non-blocking)
        await client.emit(EmitEventInput(
            action="document.published",
            organization_id="org_acme",
            actor=ActorInput(id="user_123", name="Jane Smith", email="jane@acme.com"),
            targets=[TargetInput(type="document", id="doc_456", name="Q3 Report")],
            metadata={"previous_status": "draft"},
        ))

        # Emit and wait for confirmation
        event = await client.emit_sync(EmitEventInput(
            action="user.deleted",
            organization_id="org_acme",
            actor=ActorInput(id="admin_1"),
            targets=[TargetInput(type="user", id="user_123")],
        ))
        print(f"Event ID: {event.id}")

asyncio.run(main())

The async with block automatically starts the background flush loop and calls shutdown() on exit, ensuring all queued events are delivered before your process ends.

Configuration

client = LogSeal(
    api_key="sk_live_...",       # Required
    base_url="https://api.logseal.io",  # Optional override
    batch_size=100,              # Events to buffer before auto-flushing
    flush_interval=5.0,          # Seconds between automatic flushes
    max_retries=3,               # Retry attempts on 429 / 5xx responses
    timeout=30,                  # HTTP request timeout in seconds
)

Querying Events

from logseal.types import ListEventsParams

# Paginated list
page = await client.events.list(ListEventsParams(
    organization_id="org_acme",
    action="document.published",
    limit=50,
))

for event in page.data:
    print(event.action, event.actor.name)

# Auto-paginate through all results
async for event in client.events.list_all(organization_id="org_acme"):
    print(event.action, event.actor.name)

Organizations

from logseal.types import CreateOrganizationInput

orgs = await client.organizations.list()
org = await client.organizations.create(CreateOrganizationInput(
    external_id="acme",
    name="Acme Corp",
))
org = await client.organizations.get("org_123")

Event Schemas

from logseal.types import CreateSchemaInput, UpdateSchemaInput

schemas = await client.schemas.list()
schema = await client.schemas.create(CreateSchemaInput(
    action="document.updated",
    description="Fired when a document is modified",
    target_types=["document"],
))
schema = await client.schemas.update("sch_123", UpdateSchemaInput(description="Updated desc"))
await client.schemas.delete("sch_123")

Viewer Tokens

from logseal.types import CreateViewerTokenInput

token = await client.viewer_tokens.create(CreateViewerTokenInput(
    organization_id="org_acme",
    expires_in=3600,  # 1 hour
))
# Pass token.token to your frontend for the embeddable viewer

Webhooks

from logseal.types import CreateWebhookInput, UpdateWebhookInput

webhooks = await client.webhooks.list()
webhook = await client.webhooks.create(CreateWebhookInput(
    url="https://example.com/webhooks/logseal",
    events=["*"],
))
print(f"Secret: {webhook.secret}")  # Only returned on creation

await client.webhooks.update("whk_123", UpdateWebhookInput(enabled=False))
await client.webhooks.delete("whk_123")

Exports

from logseal.types import CreateExportInput, ExportFilters

export_job = await client.exports.create(CreateExportInput(
    organization_id="org_acme",
    format="csv",
    filters=ExportFilters(after="2024-01-01"),
))

# Poll until complete
completed = await client.exports.poll(export_job.id, timeout=120.0)
print(f"Download: {completed.download_url}")

Verification

from logseal.types import VerifyParams

result = await client.events.verify(VerifyParams(organization_id="org_acme"))
print(result.status)  # "valid", "broken", or "tampered"

Error Handling

from logseal import LogSeal, LogSealError

try:
    await client.emit_sync(...)
except LogSealError as e:
    print(f"[{e.type}] {e.code}: {e}")
    print(f"HTTP status: {e.status_code}")

All API errors are raised as LogSealError with structured fields:

Field Description
type Error category (authentication_error, validation_error, etc.)
code Machine-readable code (invalid_api_key, missing_required_field, etc.)
message Human-readable description
param Request parameter that caused the error (if applicable)
status_code HTTP status code

Type Safety

This package ships with py.typed and full type annotations. Works out of the box with mypy, pyright, and IDE autocompletion.

License

MIT

Release files for logseal 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for logseal 0.1.0
File Size Uploaded
logseal-0.1.0.tar.gz 10.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for logseal 0.1.0
File Interpreter ABI Platform
logseal-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.6 kB

Release files / logseal-0.1.0.tar.gz

Download URL logseal-0.1.0.tar.gz
Size 10.5 kB
Tags Source
SHA-256 checksum
How to use checksums
cc0545f89aad5c76ed2be58bcf99621e794a2de0cfb6da40e032a8ee6ba61ff5
BLAKE2b-256 checksum
How to use checksums
7a18af48aad7c19ef55b6e2aaf04b16dcc6e76dbbaca25551576cbd17602c710
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 6, 2026.

Transparency log

Release files / logseal-0.1.0-py3-none-any.whl

Download URL logseal-0.1.0-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
10f29b8e28c40e34b2f4020bcace323dab8408984069d0c5b790120883231b86
BLAKE2b-256 checksum
How to use checksums
07af409783c60b4089391f5a709254d6bbc72cccfd0a1265276de0ab48b4d045
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page