feat: add baselinker-webhooks skill - #181
Merged
Merged
Conversation
BaseLinker (rebranded Base.com), a Polish multichannel e-commerce, warehouse and order-management platform. Added to Hookdeck's source-type enum ~2026-08-10. BaseLinker publishes NO webhook documentation at all, so this skill was authored from primary evidence rather than provider docs: - api.baselinker.com is 195 request/response methods over connector.php, with change tracking by polling (getJournalList). No webhook registration method. - Neither the English nor Polish Help Centre documents an outbound webhook or a "send HTTP request" automatic action. Every "webhook" hit is an inbound marketplace/courier integration. Two properties make it unlike any other skill here, and both drive the examples: 1. Deliveries are HTTP HEAD, never POST. A HEAD request has no body, so handlers use app.head() / an exported HEAD / @app.head and never read req.body. 2. The entire payload is in the query string. Values are always strings, so order_id is coerced and validated; nothing is assumed present. There is NO signature verification: no HMAC, no secret, no timestamp, no handshake. This is confirmed by Hookdeck's own spec, where SourceConfigBaselinkerAuth is an empty object accepting no properties, while every HMAC source there carries webhook_secret_key. No verifier is fabricated. The only auth shown is an OPTIONAL token the user appends to their own endpoint URL, labelled throughout as not being provider authentication. Responses stay bodyless per RFC 9110 section 9.3.2, including the 400/401 paths (hence Response(status_code=...) rather than HTTPException in FastAPI). Hedged honestly: order_id and state are presented as observed examples, not a documented or exhaustive parameter list, and state is treated as an opaque string rather than an event-type discriminator. See TODO.md. Testing: validate-provider.sh passes; 23 express + 19 nextjs + 22 fastapi tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VcD5gC7udDGBQD8Ko97q8i
Self-review caught two claims that ran past the evidence. Both were assertions about the BaseLinker panel, which was never inspected: this skill was written without account access, so only the documentation was ever searched. - setup.md claimed the panel "has no Webhooks settings page" and that no endpoint registry, secret screen or test button "exists". Rewritten to claim only what was checked (both Help Centre locales, exhaustively), with an explicit note that the panel was not inspected and beats any inference here. - setup.md step 2 presented Automatic Actions as the place to wire the outbound call, hedging the placeholder syntax but not the capability. BaseLinker documents no URL-calling action at all, so the step now says plainly that it cannot be specified, and points at getJournalList polling as the supported path if the panel offers no such action. - verification.md said there is "nowhere in the panel to create" a signing secret. Replaced with the citable form: none is documented, and Hookdeck's source config accepts no secret. Also records in TODO.md that no account was available, since that is the root cause of the whole class. Verified while reviewing, both now confirmed verbatim against the live docs and left unchanged: the 100 requests/minute rate limit, and getJournalList's 3-day window, last_log_id cursor and account-settings prerequisite. No code changes. validate-provider.sh passes; 23 express + 19 nextjs + 22 fastapi tests still pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VcD5gC7udDGBQD8Ko97q8i
garethx
marked this pull request as ready for review
August 14, 2026 10:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the
baselinker-webhooksskill for BaseLinker (rebranded Base.com), a Polish multichannel e-commerce / warehouse / order-management platform.BASELINKERwas added to the Hookdeck source-type enum ~2026-08-10.Why this one is unusual
BaseLinker publishes no webhook documentation at all. Before authoring I confirmed:
api.baselinker.com(=api.base.com) is 195 request/response methods overconnector.php. No webhook registration/subscription method exists; change tracking is polling (getJournalList,getOrderReturnJournalList,getInventoryProductLogs).developers.baselinker.com/shops_api"shops data exchange protocol" is BaseLinker calling merchant-hosted PHP scripts with a shared password — RPC polling, not signed event delivery.webhookhit is an inbound marketplace/courier integration (Heureka, Fruugo, ClickPost, Blue Dart, Myntra).base.com/*/developers404s).hookdeck.com/docs/sourceslistsBASELINKERwith no documentation link.So the skill is authored from primary evidence rather than provider prose.
The scheme
Two properties make this unlike any other skill in the repo, and both drive every example:
HEAD, never POST. A HEAD request has no body — handlers useapp.head()/ an exportedHEAD/@app.head, and never readreq.body. No JSON body parser is mounted on the route.order_idis coerced and validated and nothing is assumed present.There is no signature verification — no HMAC, no secret, no timestamp/replay check, no handshake. Confirmed in Hookdeck's own API spec, where
SourceConfigBaselinkerAuthis{properties: {}, additionalProperties: false}(accepts no secret), while every HMAC source there carrieswebhook_secret_key. BaseLinker sits in the zero-property-auth cohort with AWS SNS, Microsoft Graph, Microsoft SharePoint, Monday, Strava, Tikkie, Ethoca and Zift.No verifier is fabricated. The only auth shown is an optional token the user appends to their own endpoint URL, labelled throughout as not provider authentication.
X-BLTokenis documented as the outbound request header for your own API calls and explicitly not a webhook signature.Responses stay bodyless per RFC 9110 §9.3.2, including the
400/401paths — henceResponse(status_code=...)rather thanHTTPExceptionin FastAPI. Worth knowing: because a HEAD response can't carry a body, Hookdeck returns the request id in thex-hookdeck-request-idheader instead.Things a reviewer may otherwise re-flag
hmac.compare_digest/crypto.timingSafeEqualappear in the examples. These are constant-time comparisons of the user's own URL token, not a provider signature check. Please don't read them as a fabricated verifier.order_id/stateare hedged deliberately. They are presented as observed examples, never as a documented or exhaustive parameter list.stateis treated as an opaque string, not an enum and not an event-type discriminator — there is noswitchover state values anywhere, by design.TODO.md.Testing
./scripts/validate-provider.sh baselinker-webhooks— passesrequirements.txt)Open items are tracked honestly in
skills/baselinker-webhooks/TODO.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01VcD5gC7udDGBQD8Ko97q8i