01.software Docs

SDK

Use the TypeScript SDK for the default implementation path.

Use the SDK when you are building a frontend, server route, or workflow that should stay aligned with 01.software conventions.

Setup Flow

Install the package

Add @01.software/sdk to the project package manager already used by the repository.

Create the browser client

Use the Publishable Key only from approved origins. The browser client supports public reads plus capability- or customer-authorized Cart, Checkout, and PaymentSession operations.

Create the server client

Use the Secret Key only in trusted server code for writes and privileged workflows.

Verify the slice

Run the target project's typecheck, lint, tests, and build before handoff.

Client Choice

ContextClientNotes
browser UIbrowser clientpublic reads and capability/customer-authorized commerce, origin-limited
server routeserver clientimport from @01.software/sdk/server for server-authoritative and privileged operations
React data fetchingquery helperskeep cache and loading states explicit
AI-generated codeexisting project patternsavoid adding framework layers

Collection reads (find/count) and server-only bulk mutations (updateMany/removeMany, via @01.software/sdk/server) share filter validation. They preserve filter meaning without silently dropping or rewriting values: equals: null and not_equals: null retain null through Payload REST. Other null or undefined values inside where, empty condition objects (including where: {}), empty arrays (including and/or), nesting beyond 10 levels, and arrays with more than 1000 elements throw ValidationError before a request. false, 0, empty strings, and Date conditions remain valid. This read-input restriction is a BREAKING (0.x minor) change.

Top-level where: undefined is equivalent to omitting where; undefined inside the filter is rejected. For an unfiltered read, omit where. For a dynamically empty ID list, return an empty result before calling the SDK. For bulk mutations, skip the call entirely when no conditions remain or the dynamic list is empty. Raw collection operations do not replace domain-specific SDK methods or bypass server-side access rules.

Review existing updateMany/removeMany callers before upgrading: calls that previously failed with HTTP 400 can now perform actual updates or deletions. Do not rely on the previous HTTP 400 as a mutation safeguard.

Large in/not_in lists can exceed URL length limits; use smaller batches where the complete selection can be preserved. For not_in, keep the full exclusion condition in every batch: splitting exclusions across separate mutations changes which records are excluded.

Server collection writes (create, update, updateMany) accept an optional locale (en or ko) for localized fields, sent as Payload's locale query parameter. Without it the request is unchanged and the server writes the platform default locale en; writes are never rewritten to the workspace default, so a workspace that enables only ko (the Korean onboarding default) must pass { locale: 'ko' }. An omitted or disabled write locale fails with HTTP 400 and apiReason content_locale_not_enabled.

Import Boundaries

Use @01.software/sdk for the browser-safe client, commerce helpers, and core types. Use @01.software/sdk/server for createServerClient, and use @01.software/sdk/query only when your app needs React Query helpers. Error guards are available from the client/server entry that creates the client and also work across the root and @01.software/sdk/errors entries.

Rows marked none do not need any extra packages beyond @01.software/sdk.

ImportFeature(s)Install when used
@01.software/sdkbrowser-safe createClient, commerce helpers, collection helpers, typesnone
@01.software/sdk/clientbrowser-safe createClient entry and SDK error guardsnone
@01.software/sdk/servercreateServerClient, server-only APIs, and SDK error guardsnone; keep secretKey code on the server
@01.software/sdk/errorsSDK error classes and guardsnone
@01.software/sdk/metadataSEO metadata extraction and generation helpersnone
@01.software/sdk/webhookwebhook handlers, event guards, and webhook typesnone
@01.software/sdk/queryReact Query hooks, cache helpers, getQueryClient@tanstack/react-query, react, react-dom
@01.software/sdk/realtimeRealtimeConnection, useRealtimeQuery@tanstack/react-query, react, react-dom
@01.software/sdk/storefront-cacheproduct storefront cache resource helpersnone
@01.software/sdk/embedded-adminembedded app browser handshake and protocol typesnone
@01.software/sdk/embedded-admin/serverassertion verification and JWKS loadingnone; keep receiver sessions on the server
@01.software/sdk/ui/rich-textRichTextContent, StyledRichTextContentreact, react-dom, @payloadcms/richtext-lexical
@01.software/sdk/ui/formFormRendererreact, react-dom
@01.software/sdk/ui/code-blockCodeBlock, highlightreact, react-dom, shiki, hast-util-to-jsx-runtime
@01.software/sdk/ui/canvasCanvasRenderer, CanvasFrame, useCanvas, prefetchCanvasreact, react-dom, @tanstack/react-query, @xyflow/react, quickjs-emscripten, postcss, sucrase
@01.software/sdk/ui/canvas/servercanvas server helperspostcss >=8 (optional peer)
@01.software/sdk/ui/videoVideoPlayerreact, react-dom, @mux/mux-player-react
@01.software/sdk/ui/imageImagereact, react-dom

Video playback

For VOD, authorize the viewer in your server application, then call createServerClient(...).video.playback(video.id) and pass its streamUrl to <VideoPlayer video={video} streamUrl={streamUrl} />. Renew this bearer URL before two hours for long playback or after a long pause. Free playback uses the metered gateway and may return 403 at the monthly delivery limit or 503 if the usage limit cannot be checked. Existing raw Mux URL helpers apply only to unmigrated paid assets; the stored public ID on a migrated asset remains for usage history.

Published SDK 0.67.0 supports the stored-ratio mapping below. The mapping is unavailable in published 0.65.1. Check support in the package version you use.

VideoPlayer displays the stored aspectRatio values 16_9, 9_16, 4_3, and 1_1 as CSS ratios in both the placeholder and ready player. An unset ratio defaults to 16/9. Override the ready player with style.aspectRatio, or the placeholder with placeholderStyle.aspectRatio; each override applies only to its own rendering path.

CanvasRenderer renders reserved shape nodes (terminator, process, decision, io, subprocess) with first-party SVG geometry, without a workspace catalog row or QuickJS template.

If a feature is not listed here, it does not need a separate peer install. For the full component-to-peer mapping, see the SDK package README.

Use client.content.galleryItems.list() in the browser to read a published gallery in curator order:

const gallery = await client.content.galleryItems.list({
  gallerySlug: 'spring-lookbook',
  limit: 24,
})

Each item has optional mediaType: 'image' | 'video'; treat an omitted value from an older response as image. Image items retain image media. Video items include video.availability: 'ready' | 'processing' | 'unavailable' and may include a video document id and safe uploaded thumbnail. Disabled or plan-blocked video access, missing/deleted targets, and failed videos return only { availability: 'unavailable' }, retaining the item's position and pagination. The image relationship is not used as a video poster.

ready describes preparation, not playback permission. Your application server must verify that the video belongs to the published gallery/item and apply its viewer policy before calling server.video.playback(video.id). Pass the returned streamUrl to your player; the server rechecks the current workspace, video state, and feature/plan. Keep server credentials on that server. Gallery DTOs omit playback URLs, provider IDs, tokens, and private storage fields.

Domain and integration references

  • Customers SDK: Customer identity, hosted sessions and source-aware groups.
  • Ecommerce SDK: Market context, product edits, orders and storefront caching.
  • Events SDK: Canonical event dates and paid-admission projections.
  • Community SDK: Browser-safe post reads and nullable detail results.
  • Payments: Payment action reuse, reconciliation and custom server bridges.
  • Membership: Prepare paid subscriptions, obtain server-owned billing custody context and deliver signed charge results.
  • Embedded Admin: Receive and verify an embedded app session behind fixed origins.
  • External Effects: Server-only effect claims, installation custody and customer links.

Continue at Membership.

Embedded Admin Apps

Continue at Embedded Admin.

Collection actions use receiveEmbeddedAdminExecution and the server-only verifyEmbeddedAdminExecution. Pin the full frameUrl and compare the actual execution inputs. The required consumeExecution callback claims only in shared durable atomic storage through expiresAt+60, with no business side effects. Verification checks the deadline again after await; false, timeout, uncertain commit or error denies approval. Begin business only after successful return and apply app-owned idempotency. V2 has explicit capability negotiation and a separate audience; it never falls back to v1 identity. Reload cannot extend its 60-second prepare deadline. Repeating an action creates a new execution, not a guaranteed retry of the same business result.

Error reasons

Canonical commerce failures keep their closed, typed reason on CommerceSDKError.reason. Other endpoints expose their open-ended machine reason on SDKError.apiReason. Shared handlers can import getSDKErrorReason from @01.software/sdk/errors to read either family without inspecting details.reason or details.body.reason; unknown commerce reasons are returned verbatim from rawReason.

Raw collection failures keep Payload's native body. When it carries a machine code in errors[0].data.code (or .reason) and no top-level reason, that code becomes apiReason, for example content_locale_not_enabled. The typed error class and code still follow the HTTP status.

PortOne Standard V2 cancellation and retry

Continue at Payments.

Server-only PortOne identity reconciliation

Continue at Payments.

Server-only custom payment bridge

Continue at Payments.

Idempotent mutation responses are not exactly-once gates

Continue at Payments.

Existing variant base prices

Continue at Ecommerce SDK.

Orders update compatibility

Continue at Ecommerce SDK.

External-effect claims (server only)

Continue at External Effects.

Installation credentials (server only)

Continue at External Effects.

Tenant Context Introspection

Trusted server workflows can read the resolved workspace features, active and inactive collections, and field configuration through the server-only client:

import { createServerClient } from '@01.software/sdk/server'

const server = createServerClient({
  publishableKey: process.env.SOFTWARE_PUBLISHABLE_KEY!,
  secretKey: process.env.SOFTWARE_SECRET_KEY!,
})

const context = await server.tenant.context()
const productSchema = await server.tenant.collectionSchema('products')

Use server.tenant.context({ includeCounts: true }) only when collection counts and webhook configuration are required. It performs additional reads and is slower than the default call. Keep this API and both credentials in trusted server code.

productSchema.collection.customFields is optional. When present, it describes active workspace-defined fields stored under customData using machine keys, types, optional required markers, and select option storage values. It excludes operator labels and stored document values; ordinary collection authorization still governs reads and writes.

Source-aware customer groups

Continue at Customers SDK.

Continue at External Effects.

Customer Auth

Continue at Customers SDK.

Self-withdrawal

Continue at Customers SDK.

Community public reads

Continue at Community SDK.

Event ranges and all-day dates

Continue at Events SDK.

Events Admission

Continue at Events SDK.

Market context

Continue at Ecommerce SDK.

Analytics

For website analytics, integrate an external tool such as GA4, Plausible, or Vercel Analytics in your own frontend. The SDK no longer provides analytics collection helpers.

Storefront Cache Resources

Continue at Ecommerce SDK.

Next.js Mapping

Continue at Ecommerce SDK.

Before Production

  • Confirm collection and feature availability for the workspace plan.
  • Confirm key storage and rotation ownership.
  • Confirm failure handling for customer-facing flows.

Do not put Secret Key values in browser bundles, public env vars, analytics events, or generated examples.

Errors, retries and request identity

Branch on machine reason, never localized error text. Preserve requestId for support and tolerate unknown reasons. Canonical commerce uses CommerceSDKError.reason (unknown values remain in rawReason); generic failures use SDKError.apiReason. getSDKErrorReason reads both. A malformed canonical envelope or mismatched body/header request ID is a protocol failure.

Automatic SDK failure retries apply only to safe methods (GET, HEAD, OPTIONS) after network or timeout failures and retry-eligible HTTP failures (default statuses: 408/500/502/503/504), within the SDK's bounded retry budget and with bounded backoff (exponential by default). GET already has these retries; avoid adding an outer retry loop that multiplies attempts. A terminal 429 is not automatically retried; honor Retry-After. Customer-token 401 triggers at most one refresh, only for token_expired; the original request is resent only for GET/HEAD/OPTIONS, while unsafe methods return the original authentication error. Never automatically replay token exchange or unsafe mutations. Reuse the original durable idempotencyKey after an interrupted supported mutation; a response flag does not deduplicate your own side effects.

After a successful refresh, the single safe resend is independent of the transient retry budget, including retry.maxRetries: 0 or expiry on the final attempt. It does not reset that budget. Another 401 returns its typed authentication error and request ID without a second refresh.

After refresh, a canonical commerce response with retryable: false or no retryable field, or a Retry-After beyond the automatic wait bound, returns its typed error and request ID without another automatic retry.

On endpoints using validateAuthenticatedCustomer, except refresh itself, token_expired means the signature, issuer, audience, tenant and active-customer checks passed and only the access token expiry elapsed. While revocation verification is enabled, generation, password watermark and JTI revocation checks must also pass. Expired tokens that are revoked or fail another validation remain 401 token_invalid and do not trigger refresh. Configure refresh with a valid refresh token; the refresh endpoint itself returns token_invalid for an expired legacy bearer.

The split examples use published SDK 0.65.1, Next.js 16.3.8 where shown, and Node 24.15.0. Follow the linked task guides for complete app sessions and deployment checks.

Customer credits

Use server.credits for template grants, grant lookups with getGrant(), account reads and revocation; browser client.credits reads only the logged-in Customer. See Customer credits for monthly grant recipes and exact Checkout funding negotiation.

Next Actions

Customer benefit vouchers

benefitVouchers is the API for Redemption coupons in Console. Tenant-admins configure them under Ecommerce → Redemption coupon definitions. Creating a definition and issuing a coupon to a customer are separate steps. Staff redeem these single-use benefits without an order; they have no Checkout discount or credit effect. Your server decides recipients and timing (for example from a membership webhook or your own cron); source uniqueness prevents duplicate effects only.

import { createServerClient } from '@01.software/sdk/server'

const server = createServerClient({ publishableKey, secretKey })
const { voucher, created } = await server.benefitVouchers.issue({
  definitionId,
  customerId,
  sourceNamespace: 'member-benefits',
  sourceRef: 'period:2030-01:member-opaque-id',
})
const redeemed = await server.benefitVouchers.redeem({
  customerId,
  voucherId: voucher.id,
  requestId,
  actorRef: 'staff:opaque-id',
})

server.benefitVouchers.get({ customerId, voucherId }) and list({ customerId, state?, definitionId?, limit?, cursor? }) require a read-scoped server key. issue, redeem, and voidVoucher({ customerId, voucherId, requestId, actorRef, reason }) require write scope, sk01 credentials and no browser Origin. Void reasons are issued_in_error, benefit_revoked, customer_request, and other. Issuing and redeeming require effective Ecommerce and Customers; server get/list, customer self-list and void remain available after feature loss. The Console panel lives inside Customer detail and is unavailable with that screen when Customers is disabled.

Reuse the same sourceNamespace/sourceRef and identical issue input on an unknown outcome. For redeem/void, create a request UUID once and reuse it on retries; these POSTs are not automatically retried. Reusing an identity with different input returns 409. A successful transition is irreversible. Expiry uses database time and is inclusive at expiresAt. Correct an issued benefit by voiding it and issuing a new source identity.

client.benefitVouchers.listMine({ status: 'available', limit: 20 }) uses the Customer JWT and returns only identity, customer-visible copy, state and timestamps. Use status: 'all' for history and the returned nextCursor for another page (maximum 100). The response is private, no-store. Server lists return the server DTO and require customerId; cross-customer/tenant targets are masked as 404. Console Customer detail also offers role-gated redeem and void confirmations.

The staff app server must verify the staff member and Customer before redeeming: voucherId is not a bearer capability. actorRef is app-attested evidence, never a platform-verified staff identity or an authorization input. Use opaque references without personal data in sourceRef and actorRef. Definitions snapshot name, description and expiry at issue; later edits do not change issued vouchers. Voucher history survives Customer erasure and blocks tenant hard deletion. Referenced definitions must be archived.

On this page