Skip to main content

Official Python SDK for LogSeal — Audit logging for B2B SaaS

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

logseal-0.1.0.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

logseal-0.1.0-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file logseal-0.1.0.tar.gz.

File metadata

  • Download URL: logseal-0.1.0.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for logseal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cc0545f89aad5c76ed2be58bcf99621e794a2de0cfb6da40e032a8ee6ba61ff5
MD5 a5d8738fa7eaf6b3fc5c0a9d3bcaf076
BLAKE2b-256 7a18af48aad7c19ef55b6e2aaf04b16dcc6e76dbbaca25551576cbd17602c710

See more details on using hashes here.

Provenance

The following attestation bundles were made for logseal-0.1.0.tar.gz:

Publisher: publish-python.yml on LogSeal/logseal-sdks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file logseal-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: logseal-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for logseal-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 10f29b8e28c40e34b2f4020bcace323dab8408984069d0c5b790120883231b86
MD5 93a132425b8a63fbc295dc0527dbde12
BLAKE2b-256 07af409783c60b4089391f5a709254d6bbc72cccfd0a1265276de0ab48b4d045

See more details on using hashes here.

Provenance

The following attestation bundles were made for logseal-0.1.0-py3-none-any.whl:

Publisher: publish-python.yml on LogSeal/logseal-sdks

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page