Skip to main content

SeatLayer Python Server SDK for Reserved Seating

CI PyPI Python License: MIT

The official Python client for the SeatLayer API. The seatlayer package lets a Python backend inspect seat holds, price orders from server data, book reserved seats and verify webhooks, with no runtime dependencies. SeatLayer is seating chart and reserved-seat ticketing software built for venues up to stadium scale.

SeatLayer's official Python server SDK is the trusted side of its reserved seating and seat booking API. Inspect what a hold really contains, price from server-owned seating-chart data, and book with a stable booking_ref, while managing charts, events, inventory, allocations, and webhooks through one typed ticketing API client.

seatlayer on PyPI · Python server SDK guide · SeatLayer SDK and API overview · SeatLayer JavaScript seat map SDK · Server API reference

Server-side only. This package authenticates with your secret key. Never run it anywhere a ticket buyer can reach. Browser surfaces get short-lived, origin-bound tokens that you mint here.

Two-step shape: the buyer picks and holds seats in the client with your public key, then this SDK confirms the booking from your server with your secret key while your platform keeps checkout and its own payment provider.

Start here: Quickstart · Holds and checkout · Python server SDK guide · SDK catalog · Pricing: $0 entry, 100 free confirmed-sold-seat credits per organization each month, then $0.10 down to $0.05 a credit, and credits never expire.

Scale evidence

Benchmarked on public 100,000-, 150,000- and 200,000-seat venue fixtures on 15 September 2026: 200,000 seats chart-ready in 1.95 s, desktop, local production build. Fixtures, method and run logs: https://github.com/seatlayer/seatlayer-performance. Live 200,000-seat stadium demo: https://app.seatlayer.io/demo/play/century-stadium-200k. This is renderer evidence, not a concurrent-buyer claim.

Install the Python seat booking SDK

pip install seatlayer

Requires Python 3.10 or newer. No runtime dependencies.

Quick start

import os
from seatlayer import SeatLayer

seatlayer = SeatLayer(os.environ["SEATLAYER_SECRET_KEY"])

# 1. Provision a venue from the public template catalog as a new draft chart.
# Replace this placeholder with a template id from your catalog.
chart = seatlayer.templates.instantiate_template("your-published-template")["meta"]
seatlayer.charts.publish(chart["id"])

# 2. Create an event on it.
event = seatlayer.events.create(
    chart_id=chart["id"], name="Spring Gala",
    currency="EUR",  # omit to inherit the workspace currency
    region="western-europe",  # India: "asia-pacific"
)["meta"]

# 3. Sell four seats over the phone.
held = seatlayer.inventory.hold_best_available(event["key"], qty=4)
# … take payment against held["items"], which carry authoritative prices …
seatlayer.inventory.book(event["key"], hold_id=held["holdId"], booking_ref="order-8842")

Event hosting region

Pass region to events.create based on the event venue, not your API server or office. It controls the initial placement of the Event's live inventory; an existing Event cannot be moved later. Omit it to inherit the workspace default (western-europe for new accounts). Set that default with workspaces.create(..., default_region=...) or workspaces.update(workspace_id, default_region=...); changing it affects only future Events.

  • western-europe, eastern-europe, north-america-east, north-america-west, south-america
  • asia-pacific, northeast-asia, southeast-asia, oceania, africa, middle-east

The hint is best effort, not a data-residency guarantee. See the full Event region guide.

Nullable event-create fields distinguish omission from an explicit reset: passing, for example, venue=None sends JSON null; leaving venue out sends no field.

Test vs live

Keys carry their own mode. sk_test_… keys can only touch test-mode events and sk_live_… only live ones; crossing them returns 403 mode_mismatch, surfaced as SeatLayerAuthError with is_mode_mismatch.

Fixed Renewable Seasons

seatlayer.seasons exposes all 87 trusted organizer operations: catalogue and packages, performances, package prices (per price type: adult, child, concession, senior, student), sales, checkout tests, buyer access and booking, holder imports, holders, season orders, renewals, hosted renewals and renewal checkouts, occurrences (postpone and cancel a date), bulk refunds of a cancelled date, the release of lapsed renewal offers and their jobs, reports, CSV exports, audit, outbox, and support export.

After the test hold/book/cancel journey and matching webhook deliveries, validate_season_buyer_rehearsal(season_key) sends no evidence body; SeatLayer discovers the retained chain automatically. Retrieved Season holds contain inventory identity, not an authoritative amount. When you run your own checkout, your platform owns package price, payment, order, tax, refunds, benefits, and ticket or pass delivery.

checked = seatlayer.seasons.validate_season(
    source_performance_group_keys=["pg_subscription_run"],
)
draft = seatlayer.seasons.create_season(
    "2027 subscription",
    source_performance_group_keys=["pg_subscription_run"],
    idempotency_key="season-create-2027",
)["season"]
activation = seatlayer.seasons.activate_season(draft["key"], draft["revision"])

Treat 202 as accepted work: retain the returned lifecycleOperation.operationId and poll retrieve_season_lifecycle. Buyer sessions are show-once and never retried invisibly. Booking, cancellation, and renewal actions require caller-stable identities. Only header-replay mutations retry automatically.

seatlayer = SeatLayer(os.environ["SEATLAYER_SECRET_KEY"])
if os.environ.get("ENV") == "production" and seatlayer.mode != "live":
    raise RuntimeError("Refusing to boot production against test-mode seating data.")

When SeatLayer takes the season's payments, renew a holder with no hosted page: read the price with retrieve_season_renewal_quote, then start a checkout and send the holder to payment["url"]. For a renewal taken by phone or at the box office, record the holder's intent with create_season_renewal_intent before you commit the offer. A decline can carry the holder's reason.

quote = seatlayer.seasons.retrieve_season_renewal_quote(season_key, offer_id)
if quote["problem"] is None:
    started = seatlayer.seasons.create_season_renewal_checkout(
        season_key,
        offer_id,
        "https://tickets.yourclub.example/renewed",
        idempotency_key=f"renew-{offer_id}",
    )
    redirect(started["payment"]["url"])

seatlayer.holders.decline_holder_renewal_offer("holder_123", offer_id, reason="Moving away")

Season seats

Season seats are the seats a season sets aside on every date before its sales open. A season buyer's hold then doesn't have to ask each date, and single-ticket buyers see those seats as unavailable. They are off for every season until you pass inventory_mode="block" to create_season or update_season. The season needs one package, and its sales must not have opened.

seatlayer.seasons.update_season(season_key, expected_revision=revision, inventory_mode="block")

job = seatlayer.seasons.set_aside_season_block(
    season_key,
    expected_revision=revision,
    keep_for_single_tickets={"sectionIds": ["sec_family"]},
)["job"]
while job["state"] in ("planning", "running"):
    time.sleep(2)
    job = seatlayer.seasons.retrieve_season_bulk_job(season_key, job["jobId"])["job"]
block = seatlayer.seasons.retrieve_season_block(season_key)["block"]

# Release unsold season seats to single sale. Leave out `at` to release now.
seatlayer.seasons.release_season_block(
    season_key,
    expected_revision=block["revision"],
    scope={"all": True},
    at="2026-12-01T09:00:00Z",
)
  • On an active season, block mode turns on by itself once every date has the seats, and season.block.ready is sent once. On a draft, publish_season turns it on. season.block.released is sent once a release has run.
  • In block mode, a date cancel (create_season_amendment, kind "cancel") or mark_season_performance_past first takes the date off every season seat. Until that finishes the answer is a 202: check it with seatlayer.is_season_date_leave_pending(answer), then send the same request again after Retry-After.
  • Refusals come through SeatLayerError with code, and nothing changes. For example 409 season_block_packages (more than one package), 409 season_block_on_sale (sales have opened), or 409 block_not_ready from open_season_sales before block mode is on.
  • A partner's seat on a date (one a sales channel sells there) stays out of the block. It is listed in block["notFreeOnEveryDate"] with reason channel.

The Season seats docs list every refusal.

Holders, orders, sales settings and event series

Three more resources sit next to seasons: holders (season ticket holders, their tickets and transfers, and list_customers), orders (orders SeatLayer took through its own checkout, across events and seasons, and one event's orders), and event_series (runs of dated events made from one schedule). An event's sales settings (checkout choice, payment gateway, sales readiness and transitions, booking fee, discount codes) are on events. Method names are the snake_case operation ids, as on seasons.

holders = seatlayer.seasons.list_season_holders("sea_2027", status="active", limit=50)
tickets = seatlayer.holders.list_holder_tickets("holder_123", season_key="sea_2027")

orders = seatlayer.orders.list_orders(season_key="sea_2027", status="confirmed")
seatlayer.orders.refund_event_order("ev_1", "ord_1", idempotency_key="refund-ord_1")
csv_text = seatlayer.orders.export_event_orders_csv("ev_1")   # the CSV as a str

series = seatlayer.event_series.create_event_series(
    "Hamlet",
    "chart_1",
    {"rule": "weekly", "from": "2026-11-03", "count": 6, "times": ["19:30"]},
    timezone="Europe/London",
    dry_run=True,   # answer the dates, create nothing
)

The three CSV exports (seasons.export_season_holders_csv, seasons.export_season_orders_csv, orders.export_event_orders_csv) return the CSV text. seasons.delete_season_plan and events.delete_event_discount_code return None. If you run your own checkout, your store stays the order record; these order operations cover sales SeatLayer took.

Book reserved seats from Python

Buyer picks seats in the browser. Your frontend holds them; your backend confirms the price and books. Never price from what the browser sent you: retrieve_hold is authoritative.

hold = seatlayer.inventory.retrieve_hold(event_key, hold_id)
currencies = {item["currency"] for item in hold["items"]}
if len(currencies) != 1:
    raise ValueError("A hold must use one currency")
currency = currencies.pop()
total = sum(item["unitPrice"] * item.get("quantity", 1) for item in hold["items"])
# … charge `total` in `currency` …
seatlayer.inventory.book(event_key, hold_id=hold_id, booking_ref=charge.id)

Your backend picks the seats. Phone orders, box office, comps.

# Payment already taken: book outright, so nothing is stranded if a second call fails.
seatlayer.inventory.book_best_available(event_key, qty=2, booking_ref="phone-1183")

# Or name the seats yourself.
seatlayer.inventory.box_office_book(event_key, labels=["A-1", "A-2"], booking_ref="comp-14")

Private and partner sales

Channels split event inventory into explicit allocations. A channel id is reporting/routing metadata, not browser authority. Authenticate the buyer in your backend and mint a short-lived token restricted to the event, origin, and allowed allocations:

access = seatlayer.channels.create_buyer_access_session(
    event_key,
    channel_ids=["chn_partner_a"],
    include_public=False,
    allowed_origin="https://tickets.example",
)
# Return access["token"] to the in-memory buyerAccessTokenProvider only.

Never log or persist the returned bse_… bearer. Allocation setup, previews, pause/archive controls, audit-safe session listing, and channel reports are on seatlayer.channels.

Listing and pagination

list() returns one page plus a nextCursor. When you want everything, list_all() pages for you and yields as it goes. It is a generator rather than a list, because the point of paginating is to not hold an unbounded result set in memory.

# One page, your own paging.
page = seatlayer.events.list(limit=50)
page["events"]
page.get("nextCursor")   # absent once exhausted

# Or let the SDK walk it.
for event in seatlayer.events.list_all():
    sync(event)

Listing events includes live availability counts by default, which costs the server one round-trip per event. list_all() turns them off automatically, since walking a whole catalogue is exactly when you don't want that, and you can control it explicitly:

seatlayer.events.list(limit=50, counts=False)

To list only the dates of one event series, pass series_key="ser_1" to list() or list_all().

Keeping a hold alive

When an order takes longer than the checkout window (an invoice, a phone sale), extend rather than release and re-hold. Releasing first hands the seats to whoever is racing for them in between.

from seatlayer import SeatLayerConflictError

try:
    seatlayer.inventory.extend_hold(event_key, hold_id, ttl_ms=10 * 60_000)
except SeatLayerConflictError:
    # Gone, expired, or at its renewal cap: the buyer has to re-pick.
    ...

Embedding the control room

Your secret key never reaches a browser. Mint a scoped token instead.

session = seatlayer.sessions.create_manage_session(
    event_key,
    allowed_origin="https://box-office.yourplatform.com",
    capabilities=["event:view", "event:block"],
    expires_in_seconds=3600,
)

capabilities is required by this SDK even though the raw API safely defaults an omitted list to view-only (event:view). Keeping the argument required makes browser authority visible at every call site. Grant the smallest set the page needs.

The full set, all opt-in:

Capability Grants
event:view Read the seat map and its live states
event:block Block and unblock seats
event:cancel Cancel a Platform/SDK booking by reference and return its inventory to sale; does not move gateway money
event:reports Read sales and availability reports
event:channels:view Read sales channels and their allocations
event:channels:manage Create, pause and archive channels; rotate access links
event:orders:read Read SeatLayer-managed orders
event:refund Refund an eligible Managed Ticketing order through its connected gateway
event:tickets:send Send SeatLayer-managed tickets
event:door:view Read the door list
event:door:checkin Check tickets in and out
event:boxoffice Use the managed box-office surface

The two event:channels:* capabilities are not in the default (a token minted before sales channels existed must not silently acquire channel authority), so ask for them explicitly if the page manages channels.

The same pattern embeds the Designer in your own UI:

chart = seatlayer.charts.create(name="Riverside Theatre")["meta"]
designer = seatlayer.sessions.create_designer_session(
    workspace_id=workspace_id,
    chart_id=chart["id"],
    allowed_origin="https://app.yourplatform.com",
    authority="edit",
)
# The API response is an envelope; hand designer["session"]["token"] to the embed.

For safe-mode embeds, pass mode="safe" with safe_mode_options; feature policy is passed with features and the returned settings live under designer["session"].

Webhooks

Subscription responses use the API envelopes exactly: list() returns {"subs": [...]}, create() returns {"sub": ..., "secret": ...} (the secret is shown once), and update() returns {"sub": ...}. Supported event names are seat.booked, seat.released, seat.blocked, hold.expired, hold.created, hold.extended, event.created, event.soldout, series.created, series.dates_added, order.paid, order.refunded, order.cancelled, customer.created, customer.email_changed, season.ticket.transfer_sent, season.ticket.transferred, and season.ticket.transfer_cancelled.

Verify every delivery against the raw body. Re-serialising it changes the bytes and verification will fail.

from flask import request
from seatlayer import verify_webhook, WebhookVerificationError

@app.post("/webhooks/seatlayer")
def seatlayer_webhook():
    try:
        event = verify_webhook(
            request.get_data(),                                 # raw bytes, not request.json
            request.headers.get("X-SeatLayer-Signature"),
            os.environ["SEATLAYER_WEBHOOK_SECRET"],
        )
    except WebhookVerificationError:
        return "", 400

    # The signed body carries `at`, but nothing enforces a freshness window, so
    # a captured delivery stays valid indefinitely. Deduplicate on occurrenceId:
    # this is your replay protection, not an optimisation.
    if already_processed(event["occurrenceId"]):
        return "", 200

    handle(event)
    return "", 200

Errors

from seatlayer import SeatLayerAuthError, SeatLayerConflictError, SeatLayerRateLimitError

try:
    seatlayer.inventory.hold_best_available(event_key, qty=6)
except SeatLayerConflictError as error:
    if error.is_sold_out:
        return show_alternative_dates()      # a business outcome, not a bug
    raise
except SeatLayerRateLimitError as error:
    return retry_after(error.retry_after_seconds)
except SeatLayerAuthError as error:
    if error.is_mode_mismatch:
        raise RuntimeError("Test key pointed at a live event (or the reverse.)") from error
    raise

Every error carries status, code, body, and request_id. Quote the request id in support requests.

Reliability

Retries and idempotency. Reads retry 408, 429 and 5xx responses with backoff. Forty-one mutations opt into exact header replay: charts.create, charts.copy, templates.instantiate_template, events.create, workspaces.create, performance_groups.create; on seasons, create_season, update_season, delete_season, create_season_plan, update_season_plan, delete_season_plan, publish_season, replace_season_package_prices, attach_season_plan_performance, delete_season_plan_performance, create_season_performances, attach_season_performances, delete_season_performance, mark_season_performance_past, create_season_checkout_test, duplicate_season_to_live, create_season_holder_import, create_season_holder_import_from_season, create_season_renewal_offers, create_season_amendment, refund_season_order, cancel_season_order, cancel_season_order_date, refund_season_performance, release_season_lapsed_offers, and create_season_renewal_checkout; holders.update_holder, holders.create_holder_transfer, holders.create_holder_return, and holders.create_holder_renewal_checkout; orders.refund_event_order and orders.cancel_event_order; and event_series.create_event_series, event_series.add_event_series_dates, and event_series.update_event_series. The SDK generates one Idempotency-Key (or uses yours) and reuses it for every attempt. All remaining SDK mutations are sent once; some have a server-side domain idempotency contract, but the SDK does not retry them automatically.

Booking safety. Direct and box-office bookings have the server's exact-selection plus booking_ref safeguard, but the SDK still sends them once. Holds, best-available operations, show-once secret creation and raw mutations are also single-attempt; reconcile an unknown outcome before trying again.

SeatLayer(
    os.environ["SEATLAYER_SECRET_KEY"],
    max_retries=3,   # attempts for reads and the 41 exact-header-replay mutations
    timeout=30.0,    # seconds, per attempt
)

Escape hatch

For surface this SDK does not wrap yet. Raw reads retain retries; raw mutations are single-attempt because the SDK cannot prove that an unknown operation supports exact replay:

seatlayer.request("POST", "/v1/events/ev_1/some-new-route", body={...})

API surface

The client exposes these resources. Performance Groups cover runs, sessions, holds, and bookings; Seasons cover catalogue, plan, performance, price, sales, checkout-test, buyer-session, booking, holder, order, renewal, occurrence, reporting, export, outbox, and support operations.

Resource Methods
charts list list_all create retrieve update delete copy archive unarchive publish
templates instantiate_template
events list list_all create retrieve retrieve_configuration_binding update_configuration_binding update delete update_poster delete_poster update_chart close reopen archive list_ticket_releases update_ticket_releases close_ticket_release retrieve_hold_ttl update_hold_ttl retrieve_report retrieve_log retrieve_event_buyer_checkout replace_event_buyer_checkout retrieve_event_payment_gateway replace_event_payment_gateway retrieve_event_sales_readiness preflight_event_sales transition_event_sales retrieve_event_booking_fee replace_event_booking_fee list_event_discount_codes create_event_discount_code update_event_discount_code end_event_discount_code delete_event_discount_code
inventory hold hold_best_available book_best_available extend_hold retrieve_hold release book box_office_book unbook list_bookings retrieve_booking block unblock unblock_all retrieve_availability update_availability
channels list_channels create_channel update_channel update_assignments list_allocation retrieve_access_preview retrieve_report pause unpause archive create_buyer_access_session list_buyer_access_sessions revoke_buyer_access_session create_access_link list_access_links rotate_access_link revoke_access_link
sessions create_manage_session revoke_manage_session create_designer_session revoke_designer_session
webhooks list create update delete list_deliveries
workspaces list create retrieve update
performance_groups list create retrieve delete activate close retrieve_lifecycle create_buyer_access_session list_buyer_access_sessions revoke_buyer_access_session retrieve_hold book_hold retrieve_booking
seasons 87 operations for catalogue and Plan lifecycle, performances, package prices, sales windows, checkout tests, buyer access and booking, holder imports, holders, season orders, renewals, hosted renewals and renewal checkouts, occurrence amendments, returns and reclaims, bulk refunds, lapsed offer release and jobs, reports, CSV exports, audit, outbox, and support export
holders list_customers retrieve_holder update_holder revoke_holder_sessions list_holder_seasons list_holder_tickets retrieve_holder_ticket create_holder_transfer list_holder_transfers cancel_holder_transfer accept_holder_transfer create_holder_return create_holder_renewal_checkout decline_holder_renewal_offer
orders list_orders retrieve_order list_order_tickets list_event_orders retrieve_event_order export_event_orders_csv refund_event_order cancel_event_order resend_event_order_tickets
event_series create_event_series list_event_series retrieve_event_series add_event_series_dates update_event_series

Full reference: SeatLayer server API events

Deliberately not in this SDK

Some API surface is intentionally unwrapped, not merely pending:

  • Connecting payment gateways. Connecting one is a dashboard flow. Once a gateway is connected, events.replace_event_payment_gateway assigns it to an event.
  • Realtime seat updates. Live seat state reaches the browser through the widget's own socket. There is no server-side subscribe; a secret-key caller gets authoritative state from events.retrieve_report() and inventory.retrieve_availability().

None of these are reachable through request() as a supported path either; they are excluded from the public manifest, not just from the wrapper.

Frequently asked questions

How do I book seats from Python?

Create a client with your secret key, obtain a hold id (either from the buyer's browser session or by holding server-side) and call inventory.book(event_key, hold_id=..., booking_ref=...). booking_ref is your own stable order id and is the join between SeatLayer inventory and your commercial order, so the same reference identifies the booking in Booking History and when you later cancel it. For phone orders, box office, and comps, inventory.book_best_available books outright with no browser involved.

What does the server SDK do compared with the buyer SDK?

The buyer SDK runs where the ticket buyer is: it renders the interactive seating chart, handles seat selection, and creates temporary holds. This server SDK is the trusted side. It authenticates with your secret key, inspects what a hold actually contains, prices from server-owned data, and books. Never bundle the secret key into a browser or a mobile app. Browser surfaces get short-lived, origin-bound tokens that you mint here.

How do temporary holds work server-side?

A hold reserves seats against concurrent buyers for a limited window. inventory.retrieve_hold(event_key, hold_id) is the authoritative answer for what is held and at what price, so charge from its items rather than from anything the browser sent you. When an order runs longer than the checkout window, inventory.extend_hold renews the hold instead of releasing and re-holding, which would hand the seats to whoever is racing for them. Bookings carry the server's exact-selection plus booking_ref safeguard, but the SDK sends each booking once; reconcile an unknown outcome before trying again.

Can I use my own payment provider?

Yes. This server SDK does not process payment in a Platform/SDK integration. Inspect the hold, compute the charge from each returned item's authoritative unitPrice, quantity, and currency, take the money through whichever provider you already use, and then book the hold with your order id as booking_ref. SeatLayer owns seating state, holds, booking concurrency, and the inventory ledger in this integration; your platform owns payments, commercial orders, tickets, delivery, and refunds. Managed Ticketing is a separate product path with organizer-connected payments.

Continue your Python integration

Other SeatLayer SDKs

Surface Package or source
JavaScript @seatlayer/js
React @seatlayer/react
React Native @seatlayer/react-native
iOS seatlayer-ios
Flutter seatlayer
Android seatlayer-android
Node.js (server) @seatlayer/server
Python (server) seatlayer (this package)
PHP (server) seatlayer/seatlayer-php
Ruby (server) seatlayer
.NET (server) SeatLayer
Java (server) io.seatlayer:seatlayer-java
Go (server) github.com/seatlayer/seatlayer-go

Development

pip install -e ".[dev]"
ruff check src tests && mypy && pytest -q

License

MIT

Metadata

Release files for seatlayer 0.9.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 seatlayer 0.9.0
File Size Uploaded Provenance Actions
seatlayer-0.9.0.tar.gz 78.3 kB With provenance Details for seatlayer-0.9.0.tar.gz

Built distribution (wheel)

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

Total release size: 124.9 kB

Release files / seatlayer-0.9.0.tar.gz

Download URL seatlayer-0.9.0.tar.gz
Size 78.3 kB
Tags Source
SHA-256 checksum
How to use checksums
95282765fabf63f8d3908ac20043ad54df905c67925895d185a56be03a05a903
BLAKE2b-256 checksum
How to use checksums
29b0a6b548b21c4aadc79966cf163685f6ac9f15fe9c9436c3e1ec22644ef057
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 11, 2026.

Transparency log

Release files / seatlayer-0.9.0-py3-none-any.whl

Download URL seatlayer-0.9.0-py3-none-any.whl
Size 46.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b00a21a2f4122bfb11ad56c0a4249a7dfb93b8a36eb09b981f80d789ee8a041e
BLAKE2b-256 checksum
How to use checksums
8662c62cbe1ae4133a14420b66af040a36e145a6b8499599fdd13af551c2960c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 11, 2026.

Transparency log

Security for seatlayer 0.9.0

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for seatlayer-0.9.0.tar.gz

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 Nov 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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