TL;DR — Admin API 2026-04 kills the metaobject consent dance, collapses
productUpdateto one round trip, and lets Shopify Functions read metaobjects at runtime. Anthropic ships Cowork to Pro plans and bundles Claude Code into Team seats.
The theme
Every item this week is a platform quietly removing a tax it had been charging. Shopify is removing permission prompts that punished apps for adding structure, removing round trips that punished sync jobs for using handles, and removing a recompile loop that punished Functions for having configurable rules. Anthropic is removing the tier gate that kept agentic Claude locked behind the Max plan and the second-SKU friction that kept Claude Code a separate purchase.
None of these are new features in the press-release sense. They are subtractions. The interesting pattern is how much of the "this is hard" story around both platforms turns out to be historical accident you can delete once someone at the vendor decides to clean it up. If you have a backlog item that starts with "we'd do this properly, but the permission/scope/round-trip situation is ugly" — read the four items below before you estimate it again.
1. App-Owned Metaobjects Drop Access Scopes in 2026-04 (original)
Overview
If you ship a Shopify app that stores its own structured data, you know the metaobjects scopes dance. Add a new definition, push an update, the merchant gets a "this app is requesting new permissions" prompt, and a chunk of your install base drops off because nobody enjoys re-consent. Admin API 2026-04 fixes this for the specific case of metaobjects owned by your app. Ownership now implies the access rights, so read_metaobjects and write_metaobjects come off your manifest entirely.
Public scopes still apply to shared metaobjects and to definitions owned by the merchant or another app. Storefront API access is also independent — if a Hydrogen theme needs to read entries, you still declare storefront: PUBLIC_READ on the definition. The drop is Admin scopes only, but that is the exact surface where merchants were seeing the consent screen.
Technical
Two mechanics matter. When you create the definition, set the admin access to PRIVATE and prefix the type with $app::
graphql
mutation CreateAppOwnedDefinition {
metaobjectDefinitionCreate(definition: {
type: "$app:loyalty_tier"
name: "Loyalty Tier"
access: { admin: PRIVATE, storefront: NONE }
fieldDefinitions: [
{ key: "label", name: "Label", type: "single_line_text_field" }
{ key: "threshold", name: "Threshold", type: "number_integer" }
]
}) {
metaobjectDefinition { id type }
userErrors { field message }
}
}
The $app: prefix scopes the namespace to your client ID, and the platform treats every entry under that namespace as app-owned. You can then delete both metaobject scopes from shopify.app.toml. Reads and writes from your app no longer touch the scope check.
The sharp edge is migration. Definitions you created under a plain namespace like loyalty_tier are not retroactively reclassified — there is no in-place conversion mutation. Either create a new definition under the prefixed type and copy entries over, or keep the scope in your manifest until the legacy data is drained. And pin to 2026-04: on 2025-10 or earlier, scopes are still enforced, and you will see Access denied for metaobject on mutations that look fine otherwise.
Takeaway
Audit your existing definitions this week, decide which are app-owned candidates, and migrate or rebuild. Pin to 2026-04 in dev, drop the metaobject scopes from shopify.app.toml, and run a fresh install flow. If the consent screen got shorter, you are done. If not, a legacy definition is still pinning the scope request.
2. productUpdate Mutation Gets an identifier Argument in 2026-04 (original)
Overview
Every Shopify-to-anything sync has the same prelude: query the product by handle to get the gid://shopify/Product/..., then send the real mutation. Two requests, two parses, two rate-limit hits, one nullable to handle. 2026-04 makes that prelude optional. productUpdate now takes an identifier argument that accepts a gid, a handle, or a customId metafield you stamp yourself — the same shape productSet and productCreateMedia have been using. One round trip saved per product, which adds up fast on a job processing 50,000 SKUs from an ERP feed.
Technical
ProductIdentifierInput is a oneOf. Pass exactly one of id, handle, or customId. Two is an error (Field identifier may only contain one identifier type), zero is an error (Argument identifier or input.id is required), and you cannot mix identifier with the legacy input: { id } in the same call.
graphql
mutation UpdateByHandle($identifier: ProductIdentifierInput!) {
productUpdate(
identifier: $identifier
product: { title: "Updated from ERP" }
) {
product { id title handle }
userErrors { field message }
}
}
json
{ "identifier": { "handle": "stainless-bottle-32oz" } }
Or, with a customId metafield on the product:
json
{ "identifier": { "customId": { "namespace": "erp", "key": "sku_id", "value": "ERP-99812" } } }
Note what it does not do. It does not loosen field permissions — no write_products, same access error as before. It does not upsert — a missing product returns Product not found in userErrors rather than creating a record. For upsert you still want productSet. The legacy input.id form stays supported in 2026-04 with no removal date announced, but the identifier shape is going to spread to other mutations, so building the muscle memory now pays off.
Takeaway
Find every place in your sync code that does a productByHandle followed by a productUpdate and collapse them. If you already stamp a stable external SKU as a customId metafield, even better — your job no longer needs Shopify's internal IDs at all. Bump to 2026-04, run the test suite, watch the request count drop.
3. Metaobject Access Lands in Shopify Functions (2026-04) (original)
Overview
Shopify Functions are pure, deterministic, and limited to whatever you stuff into the input query. For two years that meant rule tables either lived as hard-coded constants in the Wasm binary (recompile to update) or as a shop metafield full of parsed JSON (clumsy, unreviewable). 2026-04 changes the inputs schema to expose metaobjects directly. If you have a "loyalty tier" definition, a discount function can resolve it inline. The function still runs deterministically against the input snapshot — Shopify just hydrates the metaobject into the query before invoking your Wasm. This is the most useful Functions change since the discount targets refactor.
Technical
Define the metaobject the same way as item 1 (app-owned, $app:loyalty_tier), seed a few entries with metaobjectCreate, then add the connection at the top level of your function's input.graphql:
graphql
query Input {
cart {
cost { subtotalAmount { amount } }
buyerIdentity { customer { id } }
}
tiers: metaobjects(type: "$app:loyalty_tier", first: 10) {
nodes {
handle
minSpend: field(key: "min_spend") { value }
discountPct: field(key: "discount_pct") { value }
}
}
}
Available on purchase.product-discount.run, purchase.order-discount.run, purchase.shipping-discount.run, and the cart/checkout validation targets. Your Rust code iterates input.tiers.nodes and picks the best match for the current subtotal — normal for loop, no IO.
Two real constraints to design around. First, the connection caps at 250 entries per call, with no pagination because functions are single-shot. Size your rule tables to fit. Second, hydration is one level deep — you cannot follow references from one metaobject to another inside the function input, so flatten the data at definition time. The pre-2026-04 fallbacks (bundled constants, shop metafield JSON) still work on older versions, and they are both worse than this.
Takeaway
If you have a function with a hard-coded rule table, this is the week to extract it. Pin the extension to API 2026-04 in shopify.extension.toml, define the metaobject under $app:, and rebuild the input query. Test against a dev store with at least three tier entries so your sort and filter logic actually survives a non-trivial shape. The bonus round: the merchant editing experience becomes a metaobject form, which alone justifies the migration.
4. Cowork Lands on Pro Plans: Agentic Claude for Everyone (original)
Overview
On January 16, Anthropic expanded Cowork — the agentic Claude desktop experience — to Pro plan users on macOS, and folded Claude Code into the standard seat bundle on Team plans. Cowork had been a Max-plan research preview, which is a polite way of saying it lived behind the highest tier and the bumpiest edges. Pro is the tier most independent operators and small teams actually pay for, so a solo founder on a $20/month Claude plan now gets the same agent surface Max users have been talking about. That is the audience shift worth tracking.
Technical
Cowork on Pro is functionally the same product as Cowork on Max — local isolated VM, agent-thread interface, a Claude Code session running underneath — with two practical differences. First, Pro users get a smaller monthly Cowork agent-hours allotment than Max. You cannot run it as a fire-and-forget background worker without burning quota; treat it as a focused session tool. Second, the rollout is macOS only at launch, with Windows Pro users waiting for a follow-up.
The Team plan change is the more strategically interesting move. Claude Code used to be a separate SKU. Putting it on a developer's machine meant buying a Claude.ai seat and a Claude Code subscription, then reconciling two line items at renewal. Bundling collapses that into a single seat. New Team seats include Claude Code by default; existing teams with separate Claude Code subscriptions saw those merge at the next billing cycle. Enterprise was already bundled, so this is a Team-only change.
Shape of the shift:
text
Pre-Jan-16:
Pro = web Claude + mobile Claude
Cowork = Max only
Claude Code = separate purchase
Post-Jan-16:
Pro = web Claude + mobile Claude + Cowork (macOS)
Cowork = Pro and Max
Team seat includes Claude Code
A hardware note worth respecting: the Cowork VM runs on your machine, not Anthropic's cloud. On a 16GB M-series Mac you will feel it during heavy sessions. 32GB+ for sustained use.
Takeaway
Two actions. If you are on Pro and on macOS, install Claude Desktop and try Cowork on a real task this week — the capability you have been reading about for two months is in front of you. If you manage a Team plan and used to have separate Claude Code subscriptions, check your billing for the merge. The procurement win is real, but only if you actually claim it.
Original sources
- App-Owned Metaobjects Drop Access Scopes in 2026-04 — originally published 2026-01-13
- productUpdate Mutation Gets an identifier Argument in 2026-04 — originally published 2026-01-14
- Metaobject Access Lands in Shopify Functions (2026-04) — originally published 2026-01-15
- Cowork Lands on Pro Plans: Agentic Claude for Everyone — originally published 2026-01-16


