For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Apply for AccessDashboard
Guides
Guides
  • Get Started
    • Introduction
    • Quickstart
  • Agent Identity
    • Overview
    • Create Auth Intent
    • Exchange for JWT
    • Sessions
    • JWKS
  • Agent Checkout
    • Overview
    • Create an Invoice
    • List Invoices
    • Get Invoice
    • Cancel Invoice
  • Integration Patterns
    • Overview
    • Shared SDK Client
    • Wallet Auth
    • JWT Verification
    • Subscription Checkout
    • Webhook Verification
  • Concepts
    • Two Invoice IDs
    • Wallet Identity
    • Session vs Token
    • Webhook-Driven State
  • Webhooks
    • Overview
    • Verify Signatures
  • Reliability
    • Errors
    • SDK Reference
Apply for AccessDashboard
On this page
  • Webhook events
  • Headers
  • Payload
  • invoice.paid data fields
  • Next step
Webhooks

Webhooks

Receive real-time notifications for invoice events

||View as Markdown|
Was this page helpful?
Edit this page
Previous

Webhook-Driven State

Next

Verify Webhooks

Built with

Webhook events

Gwop sends webhook events when invoice status changes:

EventTrigger
invoice.paidInvoice settled and funds received
invoice.expiredOpen invoice reached TTL without payment
invoice.canceledMerchant canceled an open invoice

Headers

Every webhook request includes these headers:

HeaderDescription
X-Gwop-SignatureHMAC-SHA256 signature: t={timestamp},v1={hmac}
X-Gwop-Event-IdUnique event ID for deduplication
X-Gwop-Event-TypeEvent type string (invoice.paid, etc.)

Payload

1{
2 "event_type": "invoice.paid",
3 "event_id": "evt_abc123",
4 "data": {
5 "invoice_id": "ba7bc94a-5468-42f4-9f04-2502e50c7501",
6 "public_invoice_id": "inv_7dbeeaad8ebf4f5298c380c90e4b3576",
7 "merchant_id": "9e9c9ba5-3bab-4172-8a79-336f9ca0f163",
8 "status": "PAID",
9 "amount_usdc": "1025000",
10 "currency": "USDC",
11 "tx_hash": "0xcd2688e1636de50f283933bd08b849dc6aef51ea9600521bc5f2de409897ad47",
12 "payment_chain": "base",
13 "payment_chain_caip2": "eip155:8453",
14 "paid_at": "2026-03-24T00:48:31.602Z",
15 "payer_wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bA16"
16 }
17}

Webhook payloads use snake_case field names (the wire format), not the camelCase used in SDK responses.

invoice.paid data fields

FieldTypeDescription
invoice_idstringMerchant-side UUID
public_invoice_idstringPayer-facing inv_* identifier
merchant_idstringYour merchant ID
statusstringAlways "PAID"
amount_usdcstringAmount settled (atomic units, as string)
currencystringAlways "USDC"
tx_signaturestringSolana tx signature (present when payment_chain is solana)
tx_hashstringEVM tx hash (present when payment_chain is base)
payment_chainstring"solana" or "base"
payment_chain_caip2stringCAIP-2 chain ID
paid_atstringISO 8601 settlement timestamp
payer_walletstringThe wallet that paid

amount_usdc in webhooks is a string, not a number. This is different from REST API responses where it’s a number. Parse it: parseInt(data.amount_usdc, 10).

Next step

Verify Signatures

Validate the raw request body and headers before trusting the event

Webhook-Driven State

Learn why signed webhook delivery is the durable trigger for fulfillment