description: "Salesforce data access for reading, writing, and querying records via REST, GraphQL, Apex, or Platform SDK. Use when the user wants to fetch, search, filter, sort, display, create, update, delete, or attach files to Salesforce records (standard objects like Accounts, Contacts, Opportunities, Cases, Quotes, or any custom object) in a web app or UI component (React, Angular, Vue, etc.); call Chatter, Connect, or Apex REST APIs; or invoke AuraEnabled Apex methods from an external app. Does not apply to authentication/OAuth setup, schema changes (adding fields, relationships), Bulk/Tooling/Metadata API usage, declarative automation (Flows, Process Builder), general LWC/Apex coding guidance without a specific data operation, or Salesforce admin/configuration tasks."
---
# Salesforce Data Access
## When to Use
Use this skill when the user wants to:
- **Fetch or display Salesforce data** — Query records (Account, Contact, Opportunity, custom objects) to show in a component
- **Create, update, or delete records** — Perform mutations on Salesforce data
- **Add data fetching to a component** — Wire up a React component to Salesforce data
- **Call REST APIs** — Use Connect REST, Apex REST, or UI API endpoints
- **Explore the org schema** — Discover available objects, fields, or relationships
## Data SDK Requirement
> **All Salesforce data access MUST use the Data SDK** (`@salesforce/sdk-data`). The SDK handles authentication, CSRF, and base URL resolution. Never use `fetch()` or `axios` directly.
```typescript
import { createDataSDK, gql } from "@salesforce/sdk-data";
const sdk = await createDataSDK();
// GraphQL for record queries/mutations (PREFERRED)
| Einstein LLM | `sdk.fetch` | `/services/data/v{ver}/einstein/llm/prompt/generations` — AI text generation |
**Not supported:**
- **Enterprise REST query endpoint** (`/services/data/v*/query` with SOQL) — blocked at the proxy level. Use GraphQL for record reads; use Apex REST if server-side SOQL aggregates are required.
1.**Type definition** — all queryable fields and relationships
2.**Filter options** — available fields for `where:` conditions
3.**Sort options** — available fields for `orderBy:`
4.**Create input** — fields accepted by create mutations
5.**Update input** — fields accepted by update mutations
Use this output to determine exact field names before writing any query or mutation. **Maximum 2 script runs.** If the entity still can't be found, ask the user — the object may not be deployed.
### Step 3: Generate Query
Use the templates below. Every field name **must** be verified from the script output in Step 2.
**FLS Resilience**: Apply `@optional` to all record fields. The server omits inaccessible fields instead of failing. Consuming code must use optional chaining:
- Create: Include required fields, only `createable` fields, no child relationships
- Update: Include `Id`, only `updateable` fields
- Delete: Include `Id` only
#### Object Metadata & Picklist Values
Use `uiapi { objectInfos(...) }` to fetch field metadata or picklist values. Pass **either**`apiNames` or `objectInfoInputs` — never both in the same query.
**Object metadata** (field labels, data types, CRUD flags):
2.**Test**: Ask user before testing. For mutations, request input values — never fabricate data.
**If ESLint reports a GraphQL error** (e.g. `Cannot query field`, `Unknown type`, `Unknown argument`), the field or type name is wrong. Re-run the schema search script to find the correct name — do not guess:
```bash
# From project root — re-check the entity that caused the error