Webhooks integration
Webhooks let GStable notify your backend when something important happens (for example a payment session updates or a settlement completes). Instead of polling APIs, you expose a stable HTTPS URL, subscribe to event types, and process JSON payloads your server trusts after signature verification.
This page is a practical integration guide. It is split into:
- Management — create and maintain endpoints with
gstable-js(client.webhook). - Delivery — implement an HTTP handler that verifies, acknowledges quickly, and processes work asynchronously.
Payload shapes, headers, and signature math are fully specified in the API docs—see Verification & handling. Here we focus on what to build and in what order.
Prerequisites
- Node.js 18+ and
gstable-js(Package & module formats). - An API key that can manage webhooks on your merchant account.
- A public HTTPS endpoint (valid TLS certificate in production) that accepts POST requests and can read the raw request body before JSON parsing in your verification path.
- You picked which event types you need—use exact strings in
subscribedEvents.
Recommended integration sequence
- Design — List the business outcomes you need (e.g. mark an order paid, release inventory). Map each to one or more event types from the event list.
- Implement the receiver first (staging) — Build the route that will later run in production: verify signature + timestamp, parse envelope, return
2xxfast, enqueue work. - Register the endpoint — Call
client.webhook.createwith your HTTPS URL, human-readable name, andsubscribedEvents. - Protect the signing secret — The response includes a
key(signing secret). Store it in a secret manager or env var on the worker that verifies webhooks—never commit it, never log it. - Go live — Point production URL at the same handler, rotate keys on a schedule or incident response using
refreshKey, and disable the endpoint during maintenance if needed. - Operate — Monitor delivery health, dead-letter queue, and deduplicate using
eventId(at-least-once delivery).
Part 1 — Manage endpoints with gstable-js
Use client.webhook for everything GStable stores about your callback: URL, subscribed events, description, enable/disable, and signing key rotation.
| Goal | Call |
|---|---|
| Register URL & events | client.webhook.create(body) |
| Replace name, URL, events (full body) | client.webhook.update(body) |
| Audit / tooling | client.webhook.list() |
| Inspect one endpoint | client.webhook.detail(webhookId) |
| Temporarily stop delivery | client.webhook.disable(webhookId) |
| Resume delivery | client.webhook.enable(webhookId) |
| Rotate signing secret | client.webhook.refreshKey(webhookId) — previous secret invalid immediately |
| Remove configuration | client.webhook.remove(webhookId) |
Create is for new URLs; update replaces the whole subscription payload (typical “full replace” semantics—send every required field). See Webhooks (SDK API) for field tables.
Example — register a production endpoint
import { GStableClient } from 'gstable-js';
const client = new GStableClient({ apiKey: process.env.GSTABLE_API_KEY });
const hook = await client.webhook.create({
webhookName: 'Production ledger',
webhookUrl: 'https://api.example.com/v1/webhooks/gstable',
subscribedEvents: ['payment.completed', 'payment.failed'],
webhookDescription: 'Order + finance consumers',
});
// Persist hook.webhookId for later updates.
// Store hook.key ONLY in your secrets store — it verifies inbound requests.
Event names must match exactly
Use identifiers exactly as listed on Event list. Typos or unsupported names will not behave as expected.
Key rotation playbook
refreshKeyinvalidates the old secret immediately—in-flight deliveries may still use the old key for a short window.- Mitigations: accept two secrets during rotation if your architecture allows; or
disablethe endpoint briefly; or drain your queue before rotating. - After rotation, update the secret where your verifier runs (env / vault).
Part 2 — Receive and process callbacks
The SDK does not verify inbound HTTP callbacks for you. Your server must:
1. Expose the same URL you registered
- HTTPS only in production; certificate must be trusted by GStable’s delivery infrastructure.
- Respond to POST with a JSON body (see Verification & handling for envelope fields such as
eventId,eventType,payload).
2. Read the raw body for verification
Compute the signature over the exact bytes GStable sent. If a framework parses JSON before verification, you risk signature mismatch. Use x-gstable-timestamp and x-gstable-signature as documented.
3. Verify before doing business logic
Follow Verification & handling step by step (string-to-sign, HMAC, timing-safe compare, optional replay window on the timestamp).
Reject with 4xx only when you are sure the request is invalid; understand implications for retries (see below).
4. Acknowledge quickly
Return 200–299 promptly after verification and basic validation. Move heavy work (DB writes, third-party calls) to a queue or background worker so GStable does not hit your HTTP timeout on slow handlers.
5. Treat delivery as at-least-once
The same logical event may be delivered more than once. Use eventId (or another stable idempotent key) to dedupe before side effects.
6. Use payloads, not assumptions
Inspect eventType, businessType, and nested payload fields per the notification docs. Downstream session or payment data lives under the documented keys (for example sessionData for session-related events).
Retries and error responses
- GStable generally retries failed deliveries with backoff when your endpoint is down or returns
5xx—exact policy is documented with the Webhook product. - Returning
4xxfor “invalid signature” is appropriate after verification fails; returning5xxfor transient DB errors invites retries—make handlers idempotent.
Security checklist
- TLS: no self-signed certs in production.
- Secrets: webhook signing key only in vault/env on verifier hosts; rotate on team/offboarding policy.
- Logging: redact payloads and headers in shared logs; never print the signing secret.
- Replay: reject timestamps outside an allowed skew when the scheme requires it (see verification doc).
Troubleshooting
| Symptom | What to check |
|---|---|
| Signature never matches | Raw body vs parsed body, wrong secret, wrong string-to-sign, encoding. |
| Duplicate side effects | Missing idempotency on eventId or business key. |
| Timeouts / retries | Handler too slow—move work off the HTTP thread. |
| Silent drops | URL typo, TLS errors, or endpoint returning non-2xx consistently. |
Further reading
- Verification & handling — envelope, headers, signature algorithm.
- Event list — subscribe only to supported
eventTypevalues. - Webhooks (SDK API) — management methods and TypeScript types.
- Error codes — errors from management API calls (
client.webhook.*).