Work with Data SDK
The Data SDK handles authentication, CSRF tokens, and base path resolution internally. To work with Data SDK, import the functions from @salesforce/platform-sdk/data.
With the Data SDK, you can query and update Salesforce records extensively from your web app by using simple bindings for running GraphQL queries and mutations.
| Export | Type | Description |
|---|---|---|
createDataSDK | async function | Factory that creates a new DataSDK instance |
gql | template tag | Identity template literal for inline GraphQL queries, which also enables editor syntax highlighting and codegen detection |
DataSDK | interface | The SDK surface type with an optional apiVersion and graphql and fetch methods |
SDKOptions | interface | Base options type with optional surface override |
GraphQLRequest | interface | The raw GraphQL request shape (query, variables, operationName, and headers) sent to the transport |
GraphQLResponse<T> | interface | The raw GraphQL response envelope with data and optional errors |
GraphQLRawDocument | type alias | The type of the query and mutation fields; an alias for string |
GraphQLRequestHeaders | type alias | Type of the per-request headers option; an alias for the standard HeadersInit |
QuerySubscriber<T> | type alias | The callback type passed to QueryResult.subscribe(); receives a QuerySnapshot<T> |
NodeOfConnection<T> | utility type | Extracts the node type from a GraphQL connection with edges and node response |
Creates a new DataSDK instance.
| Property | Type | Description |
|---|---|---|
surface | Surface | Overrides the auto-detected surface. When set, the SDK uses this value instead of running surface detection. Supported values are WebApp, Micro-Frontend, and OpenAI. See Data SDK Support. |
webapp | WebAppDataSDKOptions | Options specific to the web app surface, such as for React or Angular. |
extensions | ExtensionsFor<DataSDK> | Extensions to attach as sdk.ext.<name>. See Data SDK Extensions. |
| Property | Type | Description |
|---|---|---|
basePath | string | Base URL prefix for Salesforce API calls, for example /services/data/v64.0. |
apiVersion | string | Salesforce API version to target, for example 64.0. The SDK uses this version in the resolved ui-api, graphql, and CSRF request paths. If omitted, the SDK uses the runtime environment’s default API version. |
onStatus | Partial<Record<number, () => Promise<unknown> | void>> | Optional map of per-HTTP-status callbacks that the host invokes for a given response status. Each callback can be synchronous or asynchronous. For example, pass { 401: () => reauthenticate() } to re-authenticate on a 401 response. |
The return type for createDataSDK(options?), which resolves to a promise with the DataSDK object.
The GraphQL cache is shared across all DataSDK instances that target the same base URL and API version, which improves performance and consistency when multiple components query the same data. Multiple calls to createDataSDK() that resolve to the same base URL and API version share the same GraphQL cache, and cache updates from one SDK instance are visible to all other instances that share that cache. Instances that target different API versions get isolated caches, so a query response cached under one version is never served to an instance on another version.
The gql tag is a template literal for inline GraphQL query definitions. When GraphQL queries are defined with TypeScript code, the Data SDK requires the use of gql to understand and apply special processing to your GraphQL queries at different stages of the component lifecycle. The use of the gql tag enables org-aware GraphQL syntax highlighting when using Agentforce Vibes.
See GraphQL Queries in Data SDK.
Defines the top-level SDK surface that exposes an optional API version along with optional GraphQL and fetch APIs. The apiVersion, graphql, and fetch members are all optional as they’re supported in specific environments only.
apiVersion:string—Read-only. The Salesforce API version the SDK resolved for the current environment, such as64.0. Set it with theapiVersionoption oncreateDataSDK(). It’s absent in environments that don’t resolve to a versioned API path.
GraphQL is the preferred way to work with record data.
To account for the lack of availability of GraphQL in some environments, use optional chaining (graphql?). See GraphQL Queries in Data SDK.
Pass options in several ways:
- Use
graphql.query()based on the QueryOptions Interface. - Use
graphql.mutate()based on the MutateOptions Interface.
Use dataSdk.fetch?.() for Salesforce REST endpoints that aren’t covered by GraphQL. Use optional chaining to account for environments that don’t support fetch().
The fetch wrapper handles:
- CSRF token management
- Base path resolution
- 401/403 callback hooks
- Language and locale preferences
When the runtime environment provides an active language, the SDK adds an Accept-Language header to REST requests so responses are localized. If you set Accept-Language yourself, the SDK preserves your value. Response localization for GraphQL isn’t currently supported.
Consider using the dataSdk.fetch() call for:
- Apex REST endpoints (e.g. /services/apexrest/auth/…)
- Salesforce REST endpoints (e.g. /services/data/v{version}/…)
Defines the GraphQL methods available on the Data SDK, including queries and mutations.
Describes the raw GraphQL request that the SDK sends to the transport. QueryOptions and MutateOptions are the method-specific options. GraphQLRequest is the underlying request shape they resolve to.
Describes the raw GraphQL response envelope that the transport returns, before the SDK wraps it in a reactive QueryResult<T> or a MutationResult<T>.
Describes the options for graphql.query(). See GraphQL Query Parameters.
Describes the options for graphql.mutate(). See GraphQL Mutate Parameters.
The type of the per-request headers option on QueryOptions, MutateOptions, and GraphQLRequest. It’s an alias for the standard HeadersInit, so you can pass a plain object, an array of [name, value] tuples, or a Headers instance.
For more information, see Per-Request Headers.
Describes the reactive query result that’s returned by graphql.query(). It extends QuerySnapshot<T>, so it carries the same data and errors fields and adds subscribe() and refresh().
data:T | undefined—The resolved query data, orundefinedwhen the query didn’t resolve data.errors:GraphQLError[]—Optional. Any GraphQL or transport errors.subscribe(cb):(cb: QuerySubscriber<T>) => Unsubscribe—Registers a callback that receives aQuerySnapshot<T>on each subsequent resolution. Returns anUnsubscribefunction.refresh():() => Promise<void>—Re-issues the underlying request and propagates the result to subscribers.
The callback type passed to QueryResult.subscribe(). It receives a QuerySnapshot<T> on each new resolution.
Describes the one-shot result returned by graphql.mutate().
Describes the snapshot object passed to subscribe() callbacks.
Defines the shape of GraphQL error objects returned by the Data SDK. See Error Handling in Data SDK.
message:string—The error message.locations:{ line: number, column: number }[]—Optional. Where in the query the error occurred.path:string[]—Optional. The response path to the field that errored.extensions:Record<string, unknown>—Optional. Free-form error metadata, the GraphQLextensionsslot. Server-returned errors carry whateverextensionsthe resolver attached, verbatim.
Describes supported cache control values for graphql.query(). See Cache Control in Data SDK.
These API endpoints are supported.
- /services/apexrest
- /services/data/v{version}/ui-api/records
- /services/data/v{version}/ui-api/search-info
- /services/data/v{version}/ui-api/layout
- /services/data/v{version}/ui-api/session/csrf
- /services/data/v{version}/connect/file/upload/config
- /services/data/v{version}/connect/proxy/ui-telemetry
- /services/data/v{version}/chatter/users/me
- /services/data/v{version}/chatter/users/{userId}
- /sfsites/c/_nc_external/system/security/session/SessionTimeServlet
- /secur/logout.jsp
We recommend that you use optional chaining fetch?.() instead of a non-null assertion fetch!.(). Optional chaining is useful when you want to use fetch in a shared or cross-surface utility. If you’re not sure where your code is run, use optional chaining and handle the response appropriately.
The read-data examples in the Multi-framework recipes repo demonstrate how to call Chatter Connect API, Apex REST, and UI API REST.
Extracts the node type from a UIAPI connection response shape with the edges and node pattern.
Use NodeOfConnection when your GraphQL response uses the Salesforce connection shape (edges and node) and you want a clean, strongly-typed node type. For example:
- Query returns:
Account { edges { node { ... } } } - You define:
type AccountNode = NodeOfConnection<MyQuery["uiapi"]["query"]["Account"]> - Use
AccountNodefor transforms, props, and list rendering
If your query doesn’t use connection fields or you already have simple flat generated types, you don’t need to use NodeOfConnection.
When using the Data SDK to access Salesforce data use standard web APIs and npm packages only. These functionalities aren’t supported:
@salesforcescoped modules, except@salesforce/platform-sdk/data- Lightning base components and
lightning/*modules @wireservice
If you’re familiar with Lightning Web Components (LWC), here’s what to use instead in Multi-Framework.
| Don’t use (LWC-only) | Use instead in Multi-Framework |
|---|---|
@salesforce/apex/Class.method | dataSdk.fetch?.() against /services/apexrest/... |
@salesforce/schema/Object.Field | Hardcode the API name as a string in your GraphQL query |
@salesforce/user/Id, /CurrentUserId | GraphQL uiapi.currentUser query via dataSdk.graphql?.query(...) |
lightning/uiRecordApi: get* calls such as getRecord and getListUi | dataSdk.graphql?.query(...) |
lightning/uiRecordApi: mutation calls such as createRecord, updateRecord, and deleteRecord | dataSdk.graphql?.mutate(...) |
@wire decorator | React useEffect hook and dataSdk.graphql?.query(...); QueryResult.subscribe for reactive updates |
@salesforce/label/* (custom label imports such as @salesforce/label/c.Greeting) | The labels Data SDK extension: sdk.ext.labels.get?.(...) or getAll?.(...). See Get Custom Labels. |
Use @salesforce/platform-sdk/data for all Salesforce API calls. The SDK handles authentication and CSRF validation. Follow these data access guidelines in order of preference.
- Use GraphQL queries and mutations as the preferred way to access data.
dataSdk.graphql?.query()anddataSdk.graphql?.mutate()send a POST request to Salesforce GraphQL. - Use UI API via
sdk.fetch?.()for data access that calls/services/data/v{version}/ui-api/*or another Salesforce REST endpoint, such as an Apex controller that’s exposed via Apex REST. - Use GraphQL with
sdk.fetch?.()if GET request is required, such as when your query and variables are small enough to fit in URL constraints. Or use a GraphQL GET request if you have a dependency on a roundtrip fetch of a CSRF token. - Use Apex REST when you want custom logic that GraphQL doesn’t support.
- Don’t call
fetch()oraxiosdirectly for Salesforce endpoints.
Data SDK support differs by surface. Data SDK supports web apps, such as those built using React or Angular. It also fully support micro-frontends.
| Data SDK Support | WebApp | Micro-Frontend | OpenAI |
|---|---|---|---|
| GraphQL queries | ✅ | ✅ | ✅ |
| GraphQL mutations | ✅ | ✅ | ✅ |
GraphQL response caching (cacheControl) | ✅ | ✅ | ❌ |
fetch() for Salesforce REST endpoints | ✅ | ✅ | ❌ |
apiVersion on the SDK instance | ✅ | ✅ | ❌ |
Per-request headers on a query or mutation | ✅ | ✅ | ❌ |
webapp options (basePath, apiVersion, onStatus) | ✅ | ✅ | ❌ |
Because Data SDK support varies, use optional chaining (sdk.graphql?., sdk.fetch?.) so your code stays portable across surfaces.
On the OpenAI surface, graphql is uncached, so a query result’s subscribe() callback receives new snapshots only when you call refresh(). On the WebApp and Micro-Frontend surfaces, subscribe() also receives cache-driven updates. See Cache Control in Data SDK.
Review the examples in the React App Recipes GitHub repo. Install the app in a scratch org and explore each recipe to understand how to complete a specific task, whether it’s querying data with GraphQL or handling loading, an empty state, or error responses.