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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc0545f89aad5c76ed2be58bcf99621e794a2de0cfb6da40e032a8ee6ba61ff5
|
|
| MD5 |
a5d8738fa7eaf6b3fc5c0a9d3bcaf076
|
|
| BLAKE2b-256 |
7a18af48aad7c19ef55b6e2aaf04b16dcc6e76dbbaca25551576cbd17602c710
|
Provenance
The following attestation bundles were made for logseal-0.1.0.tar.gz:
Publisher:
publish-python.yml on LogSeal/logseal-sdks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
logseal-0.1.0.tar.gz -
Subject digest:
cc0545f89aad5c76ed2be58bcf99621e794a2de0cfb6da40e032a8ee6ba61ff5 - Sigstore transparency entry: 1050362088
- Sigstore integration time:
-
Permalink:
LogSeal/logseal-sdks@c3f83420bd613f79506a4bc1cb90678206f72c87 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/LogSeal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@c3f83420bd613f79506a4bc1cb90678206f72c87 -
Trigger Event:
workflow_dispatch
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10f29b8e28c40e34b2f4020bcace323dab8408984069d0c5b790120883231b86
|
|
| MD5 |
93a132425b8a63fbc295dc0527dbde12
|
|
| BLAKE2b-256 |
07af409783c60b4089391f5a709254d6bbc72cccfd0a1265276de0ab48b4d045
|
Provenance
The following attestation bundles were made for logseal-0.1.0-py3-none-any.whl:
Publisher:
publish-python.yml on LogSeal/logseal-sdks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
logseal-0.1.0-py3-none-any.whl -
Subject digest:
10f29b8e28c40e34b2f4020bcace323dab8408984069d0c5b790120883231b86 - Sigstore transparency entry: 1050362099
- Sigstore integration time:
-
Permalink:
LogSeal/logseal-sdks@c3f83420bd613f79506a4bc1cb90678206f72c87 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/LogSeal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@c3f83420bd613f79506a4bc1cb90678206f72c87 -
Trigger Event:
workflow_dispatch
-
Statement type: