Extensions

Extension Scopes

Extensions operate within a strict scope ceiling. Only scopes marked extensionAllowed may appear in an extension manifest. Human, admin, and management scopes are never grantable to extensions.

How scopes flow

Scopes are declared in the extension manifest, snapshotted into a published version, and issued to an install. At each stage Throttle enforces the extensionAllowed ceiling:

  1. Manifest declaration. You list the scopes your extension needs in POST /api/v1/extensions or PATCH /api/v1/extensions/:id. validateScopesForExtension runs immediately — any scope with extensionAllowed: false (or an unknown scope) returns 400 invalid_scope.
  2. Version snapshot. When you publish a version, the manifest scopes are frozen into the version record. Subsequent manifest edits do not change the published version.
  3. Install. POST /api/v1/extensions/:id/install pins the install to a version. The install's API key is granted exactly the version's scopes — no more, no less.
  4. Iframe JWT. The launch-token endpoint mints a JWT whose scopes claim is the pinned version's scope list. Every bridge.api.* call is authorized against those scopes.
Manifest with scopes
// Extension manifest with scopes
{
  "name": "Order Inspector",
  "iframeUrl": "https://extensions.example.com/orders",
  "webhookUrl": "https://extensions.example.com/webhooks",
  "eventSubscriptions": ["order.created", "order.updated", "payment.captured"],
  "scopes": [
    "orders:read",     // required for order.* events + GET /api/v1/orders
    "payments:read",   // required for payment.* events + GET /api/v1/payments
    "customers:read"   // optional — allows reading customer records
  ]
}
Scope ceiling in practice
// The extension's JWT token carries the scopes from the pinned version.
// Calling a route that requires a scope not in that list returns:
// HTTP 403 { error: { code: "insufficient_scopes", ... } }

// Good — orders:read is in the manifest scopes:
const orders = await bridge.api.get('/api/v1/orders?limit=10');

// Bad — payment_refunds:write is NOT extensionAllowed; the manifest
// would have been rejected at registration time:
// await bridge.api.post('/api/v1/payments/pay_xxx/refund', { amount: 500 });
// → 400 invalid_scope at extension create/update time

Scope implication rules

The same implication rules that apply to API keys apply to extension scopes:

  • * covers all scopes — but * is never extensionAllowed and cannot appear in an extension manifest.
  • resource:write implies resource:read on the same resource. For example, orders:write covers orders:read.
  • Read never implies write. orders:read does NOT grant orders:write.
  • No cross-resource implication. orders:read does not grant customers:read.

Management scopes for extensions

The management scopes (extensions:read, extensions:write, extensions:install) control who can author and install extensions. These are Taxonomy B (human) scopes — they are not extensionAllowed. Extensions cannot manage other extensions.

Management scope summary

  • extensions:read — view the extension catalog and installation list. Required for GET /api/v1/extensions, GET /api/v1/extensions/:id, GET /api/v1/extensions/:id/versions, GET /api/v1/installations, GET /api/v1/installations/:id/deliveries.
  • extensions:write — author, version, and publish extensions. Required for POST /api/v1/extensions, PATCH /api/v1/extensions/:id, POST /api/v1/extensions/:id/versions, POST /api/v1/extensions/:id/versions/:vid/publish, POST /api/v1/extensions/:id/lifecycle (draft/private).
  • extensions:install — install, configure, and manage installs. Required for POST /api/v1/extensions/:id/install, POST /api/v1/extensions/:id/uninstall, PATCH /api/v1/installations/:id/config, POST /api/v1/installations/:id/upgrade, POST /api/v1/installations/:id/launch-token, POST /api/v1/installations/:id/deliveries/:deliveryId/replay, POST /api/v1/installations/:id/test.
install does not imply write or read
The extensions:install scope is a custom action — it is independent of extensions:write and extensions:read. Granting only extensions:install to a key lets it manage installations without being able to author or list the catalog.

Team RBAC for extension management

Dashboard (Clerk) callers are additionally gated by RBAC permissions, not just scopes. The relevant RBAC keys are:

  • application:extensions:read — all app roles (admin | developer | finance | viewer).
  • application:extensions:write — app admin and developer.
  • application:extensions:install — app admin and developer.
  • application:extensions:admin — required to promote an extension to public or to delete a catalog entry. Only admin role.

Workspace owners and workspace admins have implicit admin role on every application. See the Permissions reference for the full role-capability matrix.

Extension-allowed scope catalog

The following scopes may appear in an extension manifest. They are all extensionAllowed: true and sourced directly from the live scope registry — they update automatically when new scopes are added.

Applications

  • applications:readView applications
  • applications:writeManage applications

Carts

  • carts:readView carts
  • carts:writeManage carts
  • cart_items:readView line items
  • cart_items:writeManage line items
  • checkout_sessions:readView checkout sessions
  • checkout_sessions:writeManage checkout sessions

Connectors

  • connectors:readView connectors
  • connectors:writeManage connectors
  • connector_activations:writeActivate/deactivate connectors

Customers

  • customers:readView customers
  • customers:writeManage customers
  • customer_pii:readView customer PII (sensitive)
  • customer_addresses:readView addresses
  • customer_addresses:writeManage addresses
  • customer_payment_methods:readView stored cards (sensitive)
  • customer_payment_methods:writeManage stored cards (sensitive)

Discounts

  • discounts:readView discounts
  • discounts:writeManage discounts

Fulfillments

  • fulfillments:readView fulfillments
  • fulfillments:writeManage fulfillments
  • fulfillment_shipments:writeUpdate shipments
  • fulfillment_digital:readView digital delivery
  • fulfillment_digital:writeManage digital delivery
  • fulfillment_access:writeManage access credentials
  • fulfillment_services:writeManage service fulfillment

Invoices / AR

  • invoices:readView invoices & aging
  • invoice_payments:writeMark invoices paid (sensitive)
  • invoice_dunning:writeSend dunning notices

Orders

  • orders:readView orders
  • orders:writeManage orders
  • order_cancellations:writeCancel orders
  • order_returns:writeProcess returns

Payments

  • payments:readView payments
  • payments:writeCreate payments
  • payment_authorizations:writeAuthorize payments
  • payment_captures:writeCapture payments
  • payment_refunds:readView refunds (sensitive)
  • payment_refunds:writeRefund payments (sensitive)
  • payment_voids:writeVoid payments (sensitive)
  • payment_disputes:readView disputes (sensitive)
  • payment_disputes:writeHandle disputes (sensitive)
  • payment_methods:readView payment methods (sensitive)
  • payment_methods:writeTokenize payment methods (sensitive)

Shipping & Tax

  • shipping_tax:readView shipping/tax config
  • shipping_tax:writeEdit shipping/tax config
  • shipping_tax_publications:writePublish shipping/tax config
  • shipping_quotes:writeRequest shipping quotes
  • tax_calculations:writeCalculate tax
  • shipping_tax_quote_tokens:readView quote tokens
  • shipping_tax_quote_tokens:writeManage quote tokens
  • shipping_tax_snapshots:writeAccept external snapshots

Subscriptions

  • subscriptions:readView subscriptions
  • subscriptions:writeManage subscriptions
  • subscription_pauses:writePause/resume subscriptions
  • subscription_cancellations:writeCancel subscriptions

Webhooks & Events

  • webhooks:readView webhooks
  • webhooks:writeManage webhooks
  • webhook_deliveries:readView deliveries
  • webhook_deliveries:writeRetry deliveries
  • events:readView events
  • audit_logs:readView audit log

Workspace

  • merchant:readView workspace settings
  • merchant:writeEdit workspace settings
  • embed_config:readView embed config
  • embed_config:writeEdit embed config
  • branding:writeUpload branding assets
Full scope catalog
The complete scope catalog, including non-extension scopes, is at API key scopes and served live at GET /api/v1/scopes.