everydeck (Python SDK)
The Python server SDK of everydeck: it reports the signals, errors and logs of your app's flows to everydeck.
pip install everydeck
import os
from everydeck import Everydeck
everydeck = Everydeck(
endpoint=os.environ["EVERYDECK_URL"],
credential="<server key of the environment>",
release_key="auto",
manifest_digest="<digest of the approved manifest>",
heartbeat_interval=300,
instance_id="api",
)
everydeck.signal("job.created", operation_id)
signal(),error()andlog()never block and never raise: they enqueue into a bounded in-memory buffer; a background thread sends batches (at most 50 events, 64 KiB, gzip-compressed).- Retries only on 429, 5xx, timeout and network errors;
Retry-Afteris honoured; final rejections are dropped and counted, never reported as sent. - A buffer overflow is reported as a
gapevent, so everydeck shows a known data gap instead of silence. heartbeat_intervalsendseverydeck.sdk.heartbeatfrom the sender thread. Give each component a stableinstance_id(for example"api","worker").release_key="auto"derives the version from the deployment commit (EVERYDECK_RELEASE_KEY,GITHUB_SHA,VERCEL_GIT_COMMIT_SHA,RENDER_GIT_COMMIT, …) or local git.- Server errors without a hand-written signal (0.5.0; FastAPI, Starlette, any ASGI app):
app.add_middleware(EverydeckMiddleware, everydeck=everydeck)withfrom everydeck.asgi import EverydeckMiddleware. Every unhandled exception while answering a request (re-raised, the app answers as before) and every answer with status 500 to 599 becomes oneserver.request_failedevent with method, route as a pattern (/orders/:order_id), status, duration, error class, the message scrubbed withscrub_text, frames and the run ids of a browser action. Never a body, a query, a cookie or any other header. 4xx is the app's answer and is not reported. Scrubbing runs in linear time and covers at most 8 192 characters (SCRUB_INPUT_MAX); a longer message is cut first and ends with…. - Counts per type (0.5.0): the read bridge answers
GET /everydeck/read/counts(rows per table of the read scope,count(*)read-only;psycopg_count,PsycopgReadOnly.count,SupabaseReadOnly.countwith PostgRESTcount=exact) and namescount: trueper type, so everydeck's data loss watch does not wait for a full read of a large table. Update everydeck first. - A date column as a calendar day (0.5.0): the read bridge sends a
date(also inside a list) as midnight UTC of that day (2026-10-19T00:00:00Z), like the TypeScript SDK, in every time zone of the server. Before, it sent2026-10-19without a time, which everydeck does not take for a date field. Timestamps (datetime) are unchanged. - When a record was created (0.5.2): the read bridge also delivers
created_at(ISO) from the column the database sets when a record is created (createdin the read scope, per object type and for people), so everydeck can show the app's past from before it was connected. - Several refunds and failed attempts of one order (0.5.1):
everydeck.payment("order_refunded", order_id=..., refund_id=...)with the provider's id of this one refund (Stripere_…) andpayment_failedwithattempt_id(Stripech_…): two partial refunds of 20 and 30 on 100 count as 50, retries count each, a refund delivered twice counts once. Without these ids everything stays as before.provider=(the name in money.providers of the app map, such asstripe) says which provider a payment came from. Update everydeck first. - Image and audio calls (0.5.1):
wrap_openaialso measuresimages.generate,images.edit,audio.transcriptions.create,audio.translations.createandaudio.speech.create(operationimage_generation,audio_transcription,audio_speech). everydeck's price list prices text tokens only; these calls show their cost as unknown unless you set a price of your own. Update everydeck first. - Payments (0.5.0, server only):
everydeck.payment(event, order_id=..., total=..., currency=..., product=..., quantity=..., checkout_id=..., reason=..., subject_ref=..., account_ref=..., object_type=..., object_ref=...)where the app itself talks to its payment provider, in the code that opens a checkout and in the webhook it receives (for example a FastAPI route/webhooks/stripe). The same five events and fields as the TS SDK, named after the Segment e-commerce spec and Stripe:checkout_started,order_completed,payment_failed,order_refunded,checkout_abandoned.totalis in the main unit of the currency (divide Stripe's cents by 100, except for zero decimal currencies),currencyan ISO 4217 code;order_id(orcheckout_idfor a checkout) is required and counts once per event, so a webhook delivered twice is safe. When the webhook stores the purchase as a row of a purchases table of the app map, pass that row's id asorder_id(several rows for one payment: the first row's id andquantitythe number of rows), so everydeck counts the purchase once. Never card data: an event with a value that looks like a card number is not sent. No key of the provider ever goes to everydeck. Update everydeck first. - AI calls (0.5.0, server only):
openai_client = everydeck.wrap_openai(OpenAI())andeverydeck.wrap_anthropic(Anthropic())(alsoAsyncOpenAI,AsyncAnthropic) return the same client (isinstancestays true), like PostHog'sposthog.ai.openaiand Langfuse'slangfuse.openai. The same eventeverydeck.ai.generationand fields as the TS SDK (OpenTelemetry GenAI names: model, tokens in and out with cached tokens, duration,error.type,everydeck.flow). Never the prompt, the answer, a system text or a key. Name the flow, the person and the organization at the wrapper (wrap_openai(client, flow="cv_analysis", subject_ref=..., account_ref=...)) or around the work (with everydeck.ai_context(flow="cv_analysis", account_ref=org_id):; the calls inside belong to one run).everydeck.ai_call(provider=..., request_model=..., input_tokens=..., output_tokens=...)sends a call the app measured itself. everydeck prices the tokens; the app sends no money and no key of the provider. Update everydeck first. - Sending time (0.5.0): every batch carries
X-Everydeck-Sent-At, so everydeck can correct a server clock that is off by an hour or more (like Sentry'ssent_at);error()takessession_id. - Settings read again while running (0.5.0):
Everydeck.from_supabasereadspublic.everydeck_server_config()again every 5 minutes (refresh_seconds, 0 = only at start), the way PostHog polls its flag definitions. A new approval in everydeck (manifest digest) or a new server key reaches a long-running server without a restart; batches built after the read carry the new values. A failed read keeps the last settings (one warning that names the function, never a value). A client switched off at start because the function was not there yet switches itself on once the values arrive. Environment variables stay fixed. - A server next to a hosted Supabase project (0.4.1):
Everydeck.from_supabase(supabase_admin, instance_id="api", heartbeat_interval=300)reads endpoint, server key and manifest digest once at start frompublic.everydeck_server_config()through the server's own Supabase client (service key). everydeck adds that function after the owner's approval; onlyservice_rolemay call it. Nothing to copy into the hosting dashboard. WhenEVERYDECK_ENDPOINT,EVERYDECK_SERVER_KEYandEVERYDECK_MANIFEST_DIGESTare all set, they win. If the call fails, the SDK switches itself off with a warning that names the function, never a value. everydeck.verify.verify_everydeck_requestchecks everydeck's signature on bridge calls.- Read bridge (0.5.0, pull):
from everydeck.read_route import mount_read_bridge, SupabaseReadOnlyandmount_read_bridge(app, SupabaseReadOnly(supabase_admin))in the module that createsappstart a background thread that fetches the bridge's requests from everydeck with a long poll (GET <EVERYDECK_URL>/v1/read-bridge/next) and sends the answers back, outbound only, like a CI runner: no route on the app, everydeck needs no address. Every request it answers must carry everydeck's signature. Other frameworks callstart_read_bridge(db)once at start. It readsEVERYDECK_URLandEVERYDECK_READ_BRIDGE_TOKENfrom the environment and waits while they are not set. - Read bridge (0.3.0):
everydeck.read_route.EverydeckReadBridge(endpoint, key, db)is the ready-made route for other frameworks. It fetches its read scope from everydeck (GET <endpoint>/v1/read-scopewith the bridge key) and uses it only with everydeck's signature; no read-scope file, no read role, no views.dbis the connection the app already has:PsycopgReadOnly(conninfo)runs every query inBEGIN READ ONLY,SupabaseReadOnly(client)reads through the app's Supabase client withselect()only (GET requests, which PostgREST runs read-only; only tables in schemas the Supabase API exposes).
No dependencies. Python 3.11 or newer. License: MIT.
Metadata
Release files for everydeck 0.5.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| everydeck-0.5.2.tar.gz | 49.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| everydeck-0.5.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 98.6 kB
Release files / everydeck-0.5.2.tar.gz
| Download URL | everydeck-0.5.2.tar.gz |
|---|---|
| Size | 49.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4fceb1e8bce00a6aab52ddb58ca66e8b446ef43f7cbd1281b661f0a5237e4d6f
|
|
BLAKE2b-256 checksum How to use checksums |
3b387a867a6986a13dfef35eed681dad78570eeb6a0729cc449332627fba9bc8
|
| 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 Oct 27, 2026.
Transparency logRelease files / everydeck-0.5.2-py3-none-any.whl
| Download URL | everydeck-0.5.2-py3-none-any.whl |
|---|---|
| Size | 49.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2721400ab419687d4442f85821f25967faa29fe0fe96ca8daf182e758e6a534f
|
|
BLAKE2b-256 checksum How to use checksums |
4d624c062c120250b9e99c17e89adfcd1ac3906480736111ec2a603c6727555c
|
| 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 Oct 27, 2026.
Transparency logSecurity for everydeck 0.5.2
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
All 2 files in this release have been uploaded with provenance metadata.
Attestation for everydeck-0.5.2.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 Oct 27, 2026.
Transparency logA 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.