@atproto/api 0.14: stricter types, $type required in records, is* helpers no longer cast
What changed
On February 13, 2025 Bluesky released version 0.14 of the @atproto/api TypeScript SDK. Generated interfaces now declare $type explicitly (optional on objects, required on records, and required inside open unions such as a post's embed via the new $Typed helper). The is* helpers no longer type-cast their input, validate* returns a precise type, a new asPredicate turns a validator into a type guard, and the [k: string]: unknown index signature was removed so typos in field names are caught.
What it means
TypeScript tools that build Bluesky posts with @atproto/api may get new compile errors on upgrade, because union members such as embeds need an explicit $type and is* helpers no longer narrow types unsafely.
Who is affected
Developers of Bluesky posting, scheduling and bot tools written in TypeScript with @atproto/api.
What to do by 13 Feb 2025
When upgrading to 0.14, add $type to embeds and other union values (use $Typed where required), switch to validate* or asPredicate where data is untrusted, mark intentional extra fields, and pin all @atproto packages to one version.
What this means for you
In February 2025 Bluesky made its free code toolkit stricter about the shape of a post. Apps that are updated now catch mistakes, like a video attached the wrong way, before the post is sent. You do not need to do anything. App makers may need a short round of fixes when they update.
The details
- Explicit
$type: generated interfaces now include$type, for example$type?: 'app.bsky.embed.video'. It is optional on plain objects and required on interfaces generated fromrecorddefinitions. - Open unions: a post's
embedis now typed as$Typed<AppBskyEmbedImages.Main> | $Typed<AppBskyEmbedVideo.Main> | ..., so an embed without$typeis a type error. is*helpers: they no longer cast based only on$type, and the old check that accepted a#mainsuffix was invalid under the spec. The post says they remain fine for data returned by Bluesky's APIs, which is "guaranteed" valid.validate*andasPredicate:validate*now returns a typedvalueon success;asPredicate(validateX)turns it into a type guard for untrusted data.- No index signature:
[k: string]: unknownwas removed, so a typo such asatlinstead ofaltis caught. Mark intentional extra fields explicitly. - Dependencies: do not mix versions of
@atproto/*packages; pin them with overrides or resolutions. - Source note: the post was on docs.bsky.app, which now redirects to bsky.network and no longer serves it. The text is in Bluesky's own
bluesky-social/bsky-docsrepository. - Later: in 2026 the packages moved to ESM and dropped Node 18 and 20; see TypeScript SDK upgrades.
What to do next
- Business owners: Nothing.
- Marketers and agencies: Nothing.
- Developers: Upgrade in a branch, fix
$typeand$Typederrors on embeds and other union fields, usevalidate*for untrusted input, and pin one version of every@atproto/*package.
Primary sources
Get an email when a new API change is added
Follow new entries with the RSS feed. Each platform also has its own feed, for example X or Meta.