WhatsApp client for Python, powered by Rust. A thin PyO3 wrapper over whatsapp-rust.
Project description
wars
WhatsApp client for Python, powered by Rust. A thin PyO3 wrapper over whatsapp-rust (vendored as a submodule). Drop it into any Python app to send and receive WhatsApp messages — no Node.js sidecar, no separate server, no IPC.
warsis an unofficial library — it is not built by, affiliated with, endorsed by, or sponsored by WhatsApp / Meta. "WhatsApp" and related trademarks belong to their respective owners.
pip install wars
Why
- No Node.js required. A single
pip installships native code; the WhatsApp Web protocol (Noise handshake, Signal Protocol, protobuf) runs in Rust inside your Python process. - Sync API. Call
wa.send(...)from any Flask handler. Noasyncio, no background server, no IPC. - No files by default. In-memory session out of the box — zero
filesystem permissions to set. When you're ready, dump the session as
bytesand stash it in your existing database. - One unified
send(). Same call for text, images, documents, groups, and broadcasts. Bot mode with an@on_messagedecorator.
Quick start
1. Pair your phone (one-time)
In a Jupyter notebook — one cell, end-to-end:
from wars import WhatsApp
wa = WhatsApp()
wa.pair() # QR shows inline; scan it
wa.send("Hello from wars") # works after pair
wa.pair() blocks until the device is paired or 5 minutes elapse,
displays a fresh QR image each time WhatsApp rotates it (~every 30s),
and prints any pair code WhatsApp issues. In a terminal it falls back
to an ASCII QR automatically.
From the command line — useful for headless setup:
curl -O https://raw.githubusercontent.com/marketcalls/wars/main/examples/pair.py
python pair.py --phone 919876543210
Use either:
- QR: WhatsApp on phone → Linked devices → Link a device → scan.
- Code: Linked devices → Link with phone number → type the code.
By default nothing is written to disk — the session is in-memory and will be lost when the script exits. For persistence pick one:
python pair.py --phone 919876543210 --db whatsapp.db # SQLite file
python pair.py --phone 919876543210 --save-png qr.png # also dump QR PNG
For the cleanest production flow, leave the script in-memory and stash the session bytes into your own DB — see Persist the session below.
2. Send a message
One unified send() for every pattern. Single-arg send("text")
automatically routes to your own number after pairing — perfect for
personal alerts.
from wars import WhatsApp
# No db_path → in-memory session. Re-pair if the process restarts.
wa = WhatsApp()
wa.connect()
wa.wait_until_ready()
# Single-arg send → goes to owner (yourself)
wa.send("Hello from wars")
wa.send(f"Build #{build_id} finished in {elapsed:.1f}s")
# Send to a specific contact
wa.send("14155550199", "Are you free for a quick call?")
# Image with caption
wa.send("14155550100", image="screenshot.png", caption="Latest dashboard")
# Document
wa.send("14155550100", document="report.pdf")
# Group message
wa.send_group("120363012345678901@g.us", "Daily standup in 5 minutes")
# Broadcast the same body to many recipients
wa.send([(n, "Server maintenance starting now") for n in oncall])
3. Persist the session in your own database
In-memory is simplest but you re-pair on every restart. For production,
keep the paired session as bytes inside your existing app database, an
encrypted column in a secret store, or anywhere you already keep API keys.
import os, sqlite3, tempfile
# First run — pair to a short-lived temp file, then dump bytes once.
# (export_session() needs a file-backed DB; Rust + Python use separate
# SQLite library instances so an in-memory DB can't be snapshotted from
# Python. The temp file is 0600 and deleted as soon as we have the bytes.)
fd, pair_db = tempfile.mkstemp(suffix=".db", prefix="wars_pair_")
os.close(fd); os.chmod(pair_db, 0o600)
wa = WhatsApp(pair_db)
wa.connect(); wa.wait_until_ready() # scan QR
blob = wa.export_session() # ~300 KB bytes
wa.disconnect()
os.unlink(pair_db) # clean up
# Stash wherever — example: a tiny table in your app's SQLite
db = sqlite3.connect("app.db")
db.execute("CREATE TABLE IF NOT EXISTS wa (id INTEGER PRIMARY KEY, blob BLOB)")
db.execute("INSERT OR REPLACE INTO wa VALUES (1, ?)", (blob,)); db.commit()
# Every run after — load and resume. No QR.
blob = db.execute("SELECT blob FROM wa WHERE id = 1").fetchone()[0]
wa = WhatsApp.from_bytes(blob)
wa.connect() # instant reconnect
See examples/webapp_integration.py
for the full pattern including a pair CLI subcommand, lazy singleton,
and Flask integration.
4. Show the pairing QR in a browser (no files)
For a browser-based pairing screen, convert the QR to a base64 data URL and embed it in HTML — no PNG ever touches the disk:
from wars import WhatsApp, qr_to_data_url
wa = WhatsApp()
latest_qr = {"data_url": None}
@wa.on_qr
def cache(code):
latest_qr["data_url"] = qr_to_data_url(code)
wa.connect()
# Flask route
@app.get("/pair-qr")
def pair_qr():
return {"img": latest_qr["data_url"]} # JSON for SPAs
# Or render directly:
# <img src="{{ qr.data_url }}" /> # works because it's a data URL
Also available: qr_to_base64(code) for the raw base64 string without the
data: prefix.
5. Or: just use a file path
If you want SQLite-on-disk (simpler than DB-stored bytes for solo runs), pass a path:
wa = WhatsApp("whatsapp.db")
The file lives wherever the path points. Treat it like any other secret
(restrict permissions, exclude from git — .gitignore already covers
*.db).
6. Receive messages (bot mode)
from wars import WhatsApp, Message
wa = WhatsApp("whatsapp.db")
@wa.on_message
def handle(msg: Message):
if msg.is_from_me:
return # ignore echoes of our own sends
if msg.text == "/ping":
wa.send(msg.chat, "pong")
elif msg.text == "/status":
wa.send(msg.chat, f"Uptime: {get_uptime()}")
elif msg.text.startswith("/echo "):
wa.send(msg.chat, msg.text.removeprefix("/echo "))
wa.connect()
wa.run_forever()
7. Integrate into a web app
Singleton pattern — one connection per process, send from any route. See
examples/webapp_integration.py for the
full sketch.
# yourapp/whatsapp.py
import atexit
from threading import Lock
from wars import WhatsApp
_wa: WhatsApp | None = None
_lock = Lock()
OWNER = "14155550100"
def wa() -> WhatsApp:
"""Lazy singleton — first call pairs/connects, rest are free."""
global _wa
if _wa is not None:
return _wa
with _lock:
if _wa is not None:
return _wa
client = WhatsApp("whatsapp.db")
client.connect()
client.wait_until_ready(timeout=60)
atexit.register(client.disconnect)
_wa = client
return _wa
# any Flask blueprint
from yourapp.whatsapp import wa
@app.post("/webhook/build")
def build_done():
data = request.json
wa().send(f"Build #{data['id']} {data['status']} in {data['duration']}s")
return "ok"
Works the same way under Django (call from AppConfig.ready()), FastAPI
(wrap blocking calls with asyncio.to_thread(wa().send, ...)), Streamlit,
Dash, etc.
⚠️ One process only. WhatsApp Web is one-device-per-session. Run
gunicorn -w 1 --threads 8or equivalent — don't fork multiple workers all using the samewhatsapp.db, or Meta will unlink the device.
API
WhatsApp(db_path=None, log_level=None)
Construct a client. Does not connect.
db_path=None(default) — in-memory session, no filesystem touched.db_path="path.db"— SQLite on disk, session survives restarts.
Single-arg send("text") defaults to the device's own phone number
(read from the paired-device record). No explicit owner is needed —
just call wa.pair() first.
WhatsApp.from_bytes(blob)
Class method. Restore a session previously exported with export_session().
Use this to load a paired session from your own database.
| Method | Returns | Notes |
|---|---|---|
pair(phone=None, timeout=300) |
None |
One-call interactive pairing helper. Renders QR inline in Jupyter, ASCII in a terminal. Blocks until paired. |
connect(phone=None) |
None |
Start background run loop. Optional E.164 digits enable pair-code auth. |
wait_until_ready(timeout=120) |
None |
Block until paired+online. Raises TimeoutError. |
is_connected() |
bool |
|
disconnect() |
None |
Idempotent. |
export_session() |
bytes |
Dump session for safe storage in your own DB / secret manager. |
send(*args, image=, document=, caption=, filename=) |
message_id or list |
Unified API — see shapes below. |
send_group(group_id, text) |
message_id: str |
Convenience for groups. group_id accepts "…@g.us" or bare digits. |
send_text(to, text) |
message_id: str |
Explicit form. to accepts "919876543210", "+91 98765 43210", full JID, or group JID. |
send_image(to, data, caption=None) |
message_id: str |
Explicit form. data: file path or bytes. MIME auto-sniffed. |
send_document(to, data, filename=None, mimetype=None) |
message_id: str |
Explicit form. |
on_qr(fn) |
decorator | fn(qr_data: str) |
on_pair_code(fn) |
decorator | fn(code: str) |
on_message(fn) |
decorator | fn(msg: Message) |
on_connected(fn) / on_disconnect(fn) |
decorator | fn() |
messages(timeout=1.0) |
iterator | yields Message |
events(timeout=1.0) |
iterator | yields raw dicts |
run_forever() |
None |
Block until Ctrl-C |
print_qr(code) (static) |
None |
Render QR to stdout (terminal). |
show_qr(code) (module fn) |
None |
Render QR inline in Jupyter (PNG), or ASCII in a terminal. |
qr_to_base64(code) (static) |
str |
QR → base64 PNG. No filesystem I/O. |
qr_to_data_url(code) (static) |
str |
QR → data:image/png;base64,… URL. |
send() shapes
wa.send("alert text") # → owner
wa.send("919876543210", "alert text") # → recipient
wa.send("919876543210", image="screenshot.png", caption="Dashboard")
wa.send("919876543210", document="report.pdf")
wa.send("120363…@g.us", "group msg") # group JIDs work as-is
wa.send([(n, "msg") for n in subscribers]) # broadcast
Message (dataclass)
chat: str # JID of the chat (1:1 or group)
sender: str # JID of the person who sent it
is_group: bool
is_from_me: bool
id: str # message ID
push_name: str # sender's display name
timestamp: int # unix seconds
text: str | None # plain text content if any
media_type: str # "" / "image" / "document" / ...
Building from source
git clone --recursive https://github.com/marketcalls/wars
cd wars
uv venv && source .venv/bin/activate
uv pip install maturin
maturin develop --release # build + install into current venv
--recursive is required because wars vendors the upstream Rust crate
as a submodule at vendor/whatsapp-rust. If you forgot it, run
git submodule update --init --recursive after cloning.
The first build takes ~5 min (compiles the whole workspace); incremental builds are seconds.
To produce a wheel:
maturin build --release # wheel lands in target/wheels/
To publish to PyPI:
maturin publish # needs PYPI_TOKEN
Wheels target Python 3.8+ via abi3 — one wheel per OS+arch covers every Python version from 3.8 onwards.
What's in v0.1
- ✅ QR + pair-code auth, persistent SQLite session
- ✅ Unified
send()— text, image, document, groups, broadcast - ✅
send_group(),send_text(),send_image(),send_document()(explicit forms) - ✅ Receive messages via
@on_messagecallback orwa.messages()iterator - ✅ All connection events:
on_qr,on_pair_code,on_connected,on_disconnect - ✅ Built-in JID normalization (digits, +91 …, full JIDs, group JIDs)
Not in v0.1 (the Rust crate supports them; bindings to be added):
- ❌ Group create/manage, reactions, edit/revoke, status, polls
- ❌ Voice notes, video, contact lookup, presence
- ❌ Async/await API (use
asyncio.to_threadfor now)
PRs welcome.
Credits
wars is a thin Python binding layer. The protocol work — Noise handshake,
Signal Protocol, binary stanza encoding, media encryption, every byte that
goes on the wire — is done by the projects below. If wars is useful to
you, please go support them:
- whatsapp-rust
(originally by @jlucaso1)
— the Rust client that this package wraps, vendored here as a fork
for stable supply-chain. Without it,
warsis nothing. - Baileys by the
WhiskeySockets maintainers — the
TypeScript reference implementation that
whatsapp-rustlearns from for protocol quirks, edge cases, and behavior parity. - whatsmeow by @tulir — the Go implementation that pioneered much of the multi-device protocol reverse-engineering.
- @pokearaujo and @Sigalor for early observations of the WhatsApp Multi-Device and WhatsApp Web protocols that the above projects were built on.
The Python bindings layer (this package) is by Rajendran R / Marketcalls.
License
Copyright (c) 2026 Rajendran R / Marketcalls
Licensed under the MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Thus, the maintainers of the project can't be held liable for any potential misuse of this project.
wars also bundles and statically links the upstream
whatsapp-rust crate
(a fork of @jlucaso1's original),
also
distributed under the MIT License (Copyright (c) 2025 João Lucas de
Oliveira Lopes). See LICENSE for the full combined notice.
Disclaimer
This is an unofficial, open-source reimplementation. Using custom WhatsApp clients may violate Meta's Terms of Service and could result in account suspension. Use at your own risk.
This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at whatsapp.com. "WhatsApp" and related marks are registered trademarks of their respective owners.
The maintainers of wars do not in any way condone the use of this
package in practices that violate the Terms of Service of WhatsApp. We
call upon the personal responsibility of users to use this package fairly,
as it is intended to be used. Do not spam people with this. We discourage
any stalkerware, bulk, or automated mass-messaging usage.
WhatsApp Terms of Service — practical risk note
Unofficial WhatsApp clients can get the linked device unlinked or the entire account banned by Meta's automation. The dominant trigger is send volume and pattern, not the client itself:
- Low risk (typical personal/automation usage) — a handful of
notifications a day, the occasional
/statusreply to your own number or a small private group. This pattern is indistinguishable from a person using WhatsApp normally and stays well under Meta's automated thresholds. - Medium risk — sending to dozens of distinct contacts who haven't messaged you first, frequent broadcast lists, sending the same message body to many recipients in a short window.
- High risk (don't) — bulk marketing, cold outreach to numbers you scraped, lookalike-spam patterns, evading rate limits. This is what triggers bans. Use the official WhatsApp Business / Cloud API for those use cases.
Treat your paired session file (whatsapp.db) as sensitive — it contains the
private keys for your linked device. Anyone who gets a copy can impersonate
that session.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
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 wars-0.1.3-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: wars-0.1.3-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 7.0 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
612d5bdf5a0d934d064ae4c0d8c549dbd065afac6a039f816a5a5d6fb7f122bd
|
|
| MD5 |
73f92191f54eef397a0964ceeae17adf
|
|
| BLAKE2b-256 |
78cbd0820994018014527f048b8f321d3064dd1c0a261e4f257ed9ff136b4810
|
Provenance
The following attestation bundles were made for wars-0.1.3-cp38-abi3-win_amd64.whl:
Publisher:
release.yml on marketcalls/wars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wars-0.1.3-cp38-abi3-win_amd64.whl -
Subject digest:
612d5bdf5a0d934d064ae4c0d8c549dbd065afac6a039f816a5a5d6fb7f122bd - Sigstore transparency entry: 1555362534
- Sigstore integration time:
-
Permalink:
marketcalls/wars@16790619b3d7472f38de441e6e58a624e6c510a0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/marketcalls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@16790619b3d7472f38de441e6e58a624e6c510a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wars-0.1.3-cp38-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: wars-0.1.3-cp38-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 6.7 MB
- Tags: CPython 3.8+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fd4a40822a301f727b620c2e59ef04c86e65b6d36a80c446e6a0718244a112a
|
|
| MD5 |
18e361e6a043c5b7cf19a2214cdd317e
|
|
| BLAKE2b-256 |
536a18852e5159004246b00f836b3481e2a028aba50e02d6c3f71b63b746ede6
|
Provenance
The following attestation bundles were made for wars-0.1.3-cp38-abi3-manylinux_2_28_x86_64.whl:
Publisher:
release.yml on marketcalls/wars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wars-0.1.3-cp38-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
3fd4a40822a301f727b620c2e59ef04c86e65b6d36a80c446e6a0718244a112a - Sigstore transparency entry: 1555362580
- Sigstore integration time:
-
Permalink:
marketcalls/wars@16790619b3d7472f38de441e6e58a624e6c510a0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/marketcalls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@16790619b3d7472f38de441e6e58a624e6c510a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wars-0.1.3-cp38-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: wars-0.1.3-cp38-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 6.2 MB
- Tags: CPython 3.8+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aba35e9331bc0644ea535e0e2a99f169d8fce467680ccde89fa0823f79dfc44a
|
|
| MD5 |
9d1b38c9310c4fe805a71c74186afe67
|
|
| BLAKE2b-256 |
4401024d3898c6bc6c895f243e900fe431bbe5bbffa4a0e401bc3d75be279f77
|
Provenance
The following attestation bundles were made for wars-0.1.3-cp38-abi3-manylinux_2_28_aarch64.whl:
Publisher:
release.yml on marketcalls/wars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wars-0.1.3-cp38-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
aba35e9331bc0644ea535e0e2a99f169d8fce467680ccde89fa0823f79dfc44a - Sigstore transparency entry: 1555362506
- Sigstore integration time:
-
Permalink:
marketcalls/wars@16790619b3d7472f38de441e6e58a624e6c510a0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/marketcalls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@16790619b3d7472f38de441e6e58a624e6c510a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wars-0.1.3-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: wars-0.1.3-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 6.1 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf5f827106b9ca575e910eaf9542d95ffc8429ab14eb7f419e4409aeb0ceba56
|
|
| MD5 |
1a3d8861774107ff12b312387c594e8d
|
|
| BLAKE2b-256 |
a1dc28ddb0ccff13f34864ebbf57bacf3a703f03171f8628b44ce219ecc320e2
|
Provenance
The following attestation bundles were made for wars-0.1.3-cp38-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on marketcalls/wars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wars-0.1.3-cp38-abi3-macosx_11_0_arm64.whl -
Subject digest:
bf5f827106b9ca575e910eaf9542d95ffc8429ab14eb7f419e4409aeb0ceba56 - Sigstore transparency entry: 1555362566
- Sigstore integration time:
-
Permalink:
marketcalls/wars@16790619b3d7472f38de441e6e58a624e6c510a0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/marketcalls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@16790619b3d7472f38de441e6e58a624e6c510a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wars-0.1.3-cp38-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: wars-0.1.3-cp38-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 6.5 MB
- Tags: CPython 3.8+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31b261f52a8df71a3888f0c600bf577e195035ebcb2f2ab3cdf933de2d7520a1
|
|
| MD5 |
34ab4b7edf6fd75a7ce07d172f918da4
|
|
| BLAKE2b-256 |
529cc801518ec5b3edd5695601cccaac9eabcd4d702f111839072da2c4e97b3e
|
Provenance
The following attestation bundles were made for wars-0.1.3-cp38-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on marketcalls/wars
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wars-0.1.3-cp38-abi3-macosx_10_12_x86_64.whl -
Subject digest:
31b261f52a8df71a3888f0c600bf577e195035ebcb2f2ab3cdf933de2d7520a1 - Sigstore transparency entry: 1555362484
- Sigstore integration time:
-
Permalink:
marketcalls/wars@16790619b3d7472f38de441e6e58a624e6c510a0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/marketcalls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@16790619b3d7472f38de441e6e58a624e6c510a0 -
Trigger Event:
push
-
Statement type: