Skip to main content

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:

  1. Management — create and maintain endpoints with gstable-js (client.webhook).
  2. 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.
  1. 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.
  2. Implement the receiver first (staging) — Build the route that will later run in production: verify signature + timestamp, parse envelope, return 2xx fast, enqueue work.
  3. Register the endpoint — Call client.webhook.create with your HTTPS URL, human-readable name, and subscribedEvents.
  4. 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.
  5. 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.
  6. 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.

GoalCall
Register URL & eventsclient.webhook.create(body)
Replace name, URL, events (full body)client.webhook.update(body)
Audit / toolingclient.webhook.list()
Inspect one endpointclient.webhook.detail(webhookId)
Temporarily stop deliveryclient.webhook.disable(webhookId)
Resume deliveryclient.webhook.enable(webhookId)
Rotate signing secretclient.webhook.refreshKey(webhookId)previous secret invalid immediately
Remove configurationclient.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

  • refreshKey invalidates 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 disable the 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 4xx for “invalid signature” is appropriate after verification fails; returning 5xx for 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

SymptomWhat to check
Signature never matchesRaw body vs parsed body, wrong secret, wrong string-to-sign, encoding.
Duplicate side effectsMissing idempotency on eventId or business key.
Timeouts / retriesHandler too slow—move work off the HTTP thread.
Silent dropsURL typo, TLS errors, or endpoint returning non-2xx consistently.

Further reading