Skip to content

feat: align sdk with current convoy api and harden webhook verification#35

Merged
mekilis merged 3 commits into
mainfrom
oksmart/phase-a-refresh
Jul 7, 2026
Merged

feat: align sdk with current convoy api and harden webhook verification#35
mekilis merged 3 commits into
mainfrom
oksmart/phase-a-refresh

Conversation

@mekilis

@mekilis mekilis commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds endpoint pause, createBroadcastEvent, event replay, and event delivery forceResend. batchResend now posts an empty body with query filters, matching the server contract (previously PUT with a body the server ignored).
  • Client config now requires uri, rejects project-scoped URIs (prevents double-scoped URLs), and pins X-Convoy-Version to 2025-11-24. Transport errors (e.g. ECONNREFUSED) are rethrown as-is instead of being mislabelled as ServerException: Internal Server Error, and events.create throws a clear ConfigException when endpoint_id is missing instead of a raw TypeError.
  • Webhook verification hardening: advanced signature header pairs are classified by key (t= vs v1=) instead of value shape, so a purely numeric signature value is no longer mistaken for the timestamp and valid multi-signature headers verify correctly. Strict Number() parsing keeps malformed timestamps like t=2202-1-1 rejected.
  • ExpireSecret.secret is now optional (the server generates it when omitted). README updated for the current API.

Breaking changes

  • uri is a required config value and must be the instance base (e.g. https://us.getconvoy.cloud/api/v1), not a project path.
  • batchResend takes query filters only; use forceResend for id-based retries.

Test plan

  • npm test (33 tests: config, webhook vectors, route contracts via mocked axios, regression tests for header parsing and create validation), tsc --noEmit clean
  • Live smoke against a licensed QA instance: all routes (project, endpoint lifecycle, subscription, events, deliveries) pass
  • Edge matrix: bad key, invalid body, 404s, unreachable host, malformed signature headers; typed exceptions everywhere, no raw crashes
  • Delivered payload parity and signature verification against a real delivery captured from a webhook sink

Note

Medium Risk
Breaking uri requirement and batchResend signature affect all integrators; webhook parsing changes fix security bugs but alter verification outcomes for edge-case headers.

Overview
1.2.0 aligns the JS SDK with the current Convoy API and tightens client and webhook behavior, with breaking config and delivery-retry changes.

Client configuration now requires an instance uri (no default cloud URL), rejects URIs that already include /projects, and sends X-Convoy-Version: 2025-11-24. Transport failures without an HTTP response are rethrown as-is (with axios config/request stripped so auth does not leak into logs) instead of being wrapped as internal server errors.

New API surface: endpoint pause, events createBroadcastEvent and replay, and delivery forceResend. batchResend is a breaking change: it is now POST with an empty body and filters in query params only; ID-based force retries use forceResend. events.create validates endpoint_id as a non-empty string. ExpireSecret.secret is optional in types.

Webhook verification parses advanced headers by key (t= vs signatures), rejects non-finite timestamps, and fixes misclassification of numeric-looking signature values.

README and tests document the new setup URLs, broadcast example, and route contracts.

Reviewed by Cursor Bugbot for commit 2243b2f. Bugbot is set up for automated code reviews on this repo. Configure here.

adds endpoint pause, broadcast events, event replay, and event
delivery forceResend. batchResend now posts an empty body with query
filters to match the server contract (it previously used PUT with a
body the server ignored).

client config now requires uri, rejects project-scoped uris, and pins
X-Convoy-Version to 2025-11-24. transport errors are rethrown as-is
instead of being mislabelled as internal server errors, and
event.create rejects a missing endpoint_id with a clear
ConfigException instead of a raw TypeError.

webhook verification fix: advanced signature header pairs are now
classified by key instead of value shape, so a purely numeric
signature is no longer mistaken for the timestamp and valid
multi-signature headers verify.

adds route contract tests via mocked axios plus regression tests for
the header parsing and create-validation fixes.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Comment thread src/utils/helpers/response-helper.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 18f91af. Configure here.

Comment thread src/webhook.ts Outdated
Comment thread src/Api/event.ts Outdated
mekilis added 2 commits July 6, 2026 20:53
axios transport errors carry the request config, including the
Authorization header, so rethrowing them raw could leak the api key
into downstream exception logs. delete config and request from the
error before rethrowing; message and code are preserved. regression
test asserts the rethrown error has neither field.
t=Infinity passed the NaN check and made timestampAge -Infinity,
bypassing the expiry check; the timestamp must now be finite.
events.create now requires endpoint_id to be a non-empty string so an
empty array no longer slips past the falsy check. both from bugbot
review, with regression tests.
@mekilis mekilis merged commit 49df947 into main Jul 7, 2026
3 checks passed
@mekilis mekilis deleted the oksmart/phase-a-refresh branch July 7, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants