# 2026-10-05 — SDK for the stable API, with verifyWebhook (improvement · SDK · sdk 0.0.50 · BREAKING)

> The SDK follows the stable API. snake_case request fields, opt-in browser tokens, lowercase error codes, and webhook handlers built on Standard Webhooks events.

`@mynthio/sdk@0.0.50` follows the [stable API](/changelog/2026-10-05-stable-api).
Earlier versions stop working against it, so upgrade and update your code:

| Before                                          | Now                                                               |
| ----------------------------------------------- | ----------------------------------------------------------------- |
| `size: { type: "aspect_ratio", aspectRatio }`   | `size: { type: "aspect_ratio", aspect_ratio }`                    |
| `access: { pat: { enabled: false } }`           | Leave it out. Tokens are off by default                           |
| `taskAsync.access.publicAccessToken` always set | Set only with `generate_public_access_token: true` on the request |
| `webhook: { dashboard: false }`                 | `webhook: { registered: false }`                                  |
| `error.code === "INSUFFICIENT_BALANCE"`         | `error.code === "insufficient_balance"`                           |
| `MynthSDKTypes.WebhookPayload`                  | `MynthSDKTypes.WebhookEvent`                                      |
| `(result, { deliveryId })` in webhook callbacks | `(result, { event })`. Deduplicate on `event.id`                  |
| `wbs_...` in `MYNTH_WEBHOOK_SECRET`             | The endpoint's new `whsec_...` secret, from the dashboard         |

Results from polling and webhook callbacks keep their shape: `result.taskId`,
`result.images`, `image.mynthUrl`. Raw API data the SDK passes through is
snake_case now: `raw.request`, the model catalog (`display_name`,
`per_image`), and `video.estimate()` (`estimated_cost`, `estimate_kind`). A
video's `url` can be `null`, and `result.urls` skips it.

`verifyWebhook()` verifies a delivery outside the framework helpers and
returns the typed event:

```ts
import { verifyWebhook } from "@mynthio/sdk";

const event = await verifyWebhook({ body: await request.text(), headers: request.headers });

if (event.type === "task.image.generate.completed") {
  console.log(event.id, event.data.result.images);
}
```

The helpers take `onEvent` for every event, including types newer than the
SDK. They refuse unsigned deliveries to a `webhook.custom` URL unless you pass
`{ unsigned: { verify } }`, which checks a token you put in the URL instead.

See [webhooks](/docs/concepts/webhooks) and
[webhook payloads](/docs/api-reference/webhook-payloads).

Permalink: https://mynth.io/changelog/2026-10-05-sdk-stable-api · Markdown: https://mynth.io/changelog/2026-10-05-sdk-stable-api.md
