Google Sheets results export
Use this recipe when a club, creator, or operator wants a lightweight tournament results log in Google Sheets without polling.
Status: closed-beta runnable for accounts with webhooks enabled. The v0 event allowlist contains
tournament.completed.
Maintained sample: apps/developer-recipe-google-sheets-results.
What you build
- A server endpoint that receives PokerWorks webhook deliveries.
- Signature verification before any side effect.
- Event/delivery dedupe so retries and replays do not append duplicate rows.
- A Google Sheets append call to a sheet you own or manage.
Requirements
- A Console project.
- A service account token stored server-side for creating/managing the webhook endpoint.
- Management scopes:
webhook_endpoints:create,webhook_endpoints:read,webhook_deliveries:read,webhook_deliveries:replay. - A public HTTPS receiver URL.
- A Google account. A normal personal Google account is enough; Google Workspace is not required.
- A Google Cloud project with the Google Sheets API enabled.
- Google credentials stored server-side.
- A spreadsheet shared with the Google credential that will append rows.
1. Create the PokerWorks webhook endpoint
Use the Console Webhooks page, or call the management contract from trusted server code with a
pw_mgmt_… token:
Code
Store the reveal-once pwwhsec_… signing secret immediately. It is not shown again.
2. Connect Google Sheets
For deployed/server usage, create a Google Cloud service account, enable the Google Sheets API, and share the target spreadsheet with the service account email. For local personal-account testing, use an OAuth client and refresh token with the Sheets scope. Keep both credential forms server-side.
Set the sample env:
Code
RAW is the default value input option so result ids and timestamps are appended exactly as sent.
If you opt into USER_ENTERED, the maintained sample prefixes formula-like strings before append
so ids and labels are not evaluated as formulas.
3. Verify before appending
Your receiver must verify the raw request body before it appends a row. The signed input is:
Code
The event body is intentionally minimal in v0:
Code
Row shape
The maintained sample appends:
Code
Optional cells stay blank unless those fields already exist in the safe public payload. The v0 payload intentionally omits raw player identifiers, private player data, and winner identity.
Replay a failed delivery
Use the Console delivery log to inspect and replay failures. If you are automating from trusted server code, call the management delivery contracts:
Code
Duplicate events and deliveries are ignored after signature verification, so replay does not append a second row for the same event in the maintained single-process sample. The local JSON dedupe store also expires abandoned in-flight reservations after a bounded TTL so a crash before append can be replayed later. Processed ids are retained without automatic compaction; replace the local store with a shared durable store with explicit retention for long-lived or multi-instance deployments.
Security notes
- Keep
pwwhsec_…,pw_mgmt_…, Google credential JSON, OAuth refresh tokens, and spreadsheet ids from real users in server-side secrets. - Verify signatures before dedupe and before parsing event
data. - Dedupe on
PokerWorks-Event-IdandPokerWorks-Delivery-Id; deliveries are at-least-once. - Treat Google append timeouts and connection drops as ambiguous. The sample marks the event
processed before returning
503so retries do not append duplicate rows; reconcile byeventIdbefore clearing dedupe state or replaying to a fresh receiver. - Do not assume player names, winner details, standings, or payouts are present in v0.
- Rotate the PokerWorks webhook secret if it is exposed.