Skip to content

v0.14.6

Latest

Choose a tag to compare

@rmyndharis rmyndharis released this 08 Aug 08:52
· 2 commits to main since this release

Added

  • The SDKs can now read and change a running session's config, and read the webhook diagnosticsGET/PATCH /sessions/{id}/config (0.14.5's headline feature), the cross-session GET /webhooks, and GET /webhooks/delivery-failures were absent from all five SDKs while sdk/README.md claimed every user-facing resource was exposed; that claim is now scoped to the exclusion list the SDK design doc actually states.

Fixed

  • The Go and Java SDKs can now send the explicit null the session-config route needs — that route takes three states per field (an absent key leaves the value unchanged, null clears it to the default, a value sets it), and neither SDK could emit the middle one: Go's omitempty omits a nil pointer and Gson drops nulls by default, so restoring maxReconnectAttempts to unlimited — the one thing no in-range number can express — was unreachable. Both now carry explicit clear* flags.

  • Three SDK response types dropped fields the API sends — the per-participant group result omitted message, the product-send response omitted timestamp, and Python's new 503 error class was not exported from the package root, so the documented import failed for exactly the class that was added.

  • A running gateway now serves the same schema-valid OpenAPI document as the committed snapshot — the validity pass was added to the export script only, so /api/docs kept serving a document that fails validation while openapi.json was clean; a test now holds both producers to the same passes in the same order.

  • Two statements in the codebase that were not true — a load-bearing comment justified skipping a lookup on the grounds that PostgreSQL would raise a 500 against a uuid column, when sessions.id is varchar on both dialects and a malformed id simply matches nothing; and the webhook event table stated all 22 events are actively dispatched by the engines without saying that four of them fire on Baileys only, which the same document states 2 200 lines later.

  • All five SDKs now give the retryable status a type of its own — every one classified 401, 403, 404, 409, 429 and 501 into a dedicated error and let 503 fall through to the base class, which inverted the mapping against usefulness: 501 Not Implemented is permanent and never worth retrying, while 503 is the transport failure a caller should retry — and 0.14.5 made it the standard answer for "WhatsApp never confirmed" across 47 of the 189 operations.

  • ⚠️ Breaking (SDK types only, no gateway change). Creating a group returns the summary shape, and the SDKs said otherwisePOST /groups answers {id, name, participantsCount, isAdmin?, linkedParentJID?}, but the four typed SDKs declared the DETAIL type get() returns, so participants, description, owner and createdAt were typed as present on a response that never carries them.

  • Four SDKs could not paginate the session listGET /api/sessions takes limit and offset, and only the Go SDK exposed them; the other four sent a bare path and pinned the caller to the server default.

  • A post-connect group-name hydration WhatsApp never answered no longer finishes without a word — the read shared the ambiguity GET /sessions/{id}/groups was bounded against in 0.14.5, where an unanswered query and an account with no groups both yield an empty result, but only the REST caller got a clock: the hydration step logged neither its success line nor its failure line, so group chats stayed unnamed with nothing to explain it.

  • The published OpenAPI document is schema-valid again@nestjs/swagger expands an @All() route over its own method list, which includes search, and the 3.0 Path Item Object has no field for it, so the ingress route contributed a key that made strict validators reject the whole 150-path document rather than just that route; the export now drops operations the specification cannot express, and nothing in the repository validated the document to catch it.

  • ⚠️ Breaking (SDK types only, no gateway change). Three response shapes the SDKs decoded into the wrong type — the four group membership writes answer with a per-participant results array that a partial refusal is reported in, and all four typed SDKs declared only {success, message}, so a rejected member was indistinguishable from a fully applied batch; ContactRecord declared pushname where both engines emit pushName (which left Java's case-sensitive binder returning null for every contact), carried an isBusiness the API never sends, and omitted isBlocked and profilePicUrl; and send-product answers with id while the SDKs decoded messageId.
    Migration. addParticipants/removeParticipants/promoteParticipants/demoteParticipants now return ParticipantsResult — a superset of the old type, so existing reads of success/message keep compiling. ContactRecord.pushname becomes pushName and isBusiness is gone; both were always empty. sendProduct returns ProductMessageResponse { id }.

  • A webhook a smart filter drops now leaves a trace — a condition on a field the event's payload does not carry cannot match, so a sender filter suppressed every message.ack, message.failed and message.reaction while the dispatch logged nothing, emitted no metric and recorded nothing in the delivery-failure table, which only tracks deliveries that were attempted; suppression is now logged at debug with the payload fields that were actually available, and the interaction is documented.

  • Two webhook payload descriptions did not match what is sentsession.qr was documented as carrying the raw QR string when both engines render it to a PNG data URL before the event is dispatched, and the filter field list did not say that its fields exist on only some message events.

  • Ten gaps where the published contract described less than the API actually accepts or returns — eleven operations carried a path template with no parameter to fill it, the plugin upload published no request body at all so the file it exists for was invisible, the statistics window selector was undocumented, the archived-media download and the config-UI route published a 200 with no media type while every sibling binary route declares one, five plugin operations returned a PluginDto the contract never named, and six nullable properties published as type: object — which also made the ranges declared beside two of them inert, since JSON Schema ignores minimum/maximum on a non-numeric type.