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: beta runnable for projects with webhooks configured. The v0 event allowlist contains
tournament.completed.
Maintained sample: apps/developer-recipe-google-sheets-results.
Public-clean example: examples/developer-platform/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 tournament result verification read after the webhook arrives.
- 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,tournament_results:read,playground:writefor test-mode fixture emission. - 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. Trigger the playground fixture
After your receiver is deployed, Sheets is configured, and the test endpoint is active, emit the
playground completion fixture. PokerWorks queues a signed tournament.completed delivery to the
endpoint you just created, so you can prove the append path without waiting for a real tournament.
Code
The fixture is test-only and uses synthetic player display names and public participant ids.
4. 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 and includes a tournament result verification link:
Code
After verification and dedupe reservation, call the required links.results.href with the same
server-side pw_mgmt_… token. Treat deliveries without the link as contract-invalid instead of
deriving a URL from data.tournamentId.
If the result projection returns 503, return a retryable 503 without marking the event processed
so PokerWorks can retry later.
Row shape
The maintained sample appends:
Code
The maintained sample appends only fields from the public-safe tournament result DTO. Raw player identifiers, private player data, webhook secrets, OAuth tokens, and management tokens never go into the sheet.
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. - Fetch the tournament result verification read from the required
links.results.href; do not derive fallback URLs fromdata.tournamentId. - 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. - Read winner details, standings, payouts, replay status, and proof status only from the public-safe tournament result DTO.
- Rotate the PokerWorks webhook secret if it is exposed.